worked on stuff
This commit is contained in:
parent
ded4ea603e
commit
d5f31ecce7
10 changed files with 250 additions and 127 deletions
|
@ -15,7 +15,6 @@ use core::fmt::Debug;
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
use aphrodite::arch::egatext;
|
use aphrodite::arch::egatext;
|
||||||
use aphrodite::arch::enable_a20;
|
|
||||||
use aphrodite::arch::output::*;
|
use aphrodite::arch::output::*;
|
||||||
use aphrodite::boot::{BootInfo, MemoryMapping};
|
use aphrodite::boot::{BootInfo, MemoryMapping};
|
||||||
use aphrodite::display::COLOR_DEFAULT;
|
use aphrodite::display::COLOR_DEFAULT;
|
||||||
|
@ -27,11 +26,20 @@ use aphrodite::output::*;
|
||||||
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
|
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
|
||||||
#[unsafe(link_section = ".bootheader")]
|
#[unsafe(link_section = ".bootheader")]
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
static MULTIBOOT2_HEADER: [u8; 24] = [
|
static MULTIBOOT2_HEADER: [u8; 48] = [
|
||||||
0xd6, 0x50, 0x52, 0xe8, // Magic number
|
0xd6, 0x50, 0x52, 0xe8, // Magic number
|
||||||
0x00, 0x00, 0x00, 0x00, // Architecture
|
0x00, 0x00, 0x00, 0x00, // Architecture
|
||||||
0x18, 0x00, 0x00, 0x00, // Size
|
0x18, 0x00, 0x00, 0x00, // Size
|
||||||
0x12, 0xaf, 0xad, 0x17, // Checksum
|
0x12, 0xaf, 0xad, 0x17, // Checksum
|
||||||
|
|
||||||
|
0x0A, 0x00, // Relocatable tag
|
||||||
|
0x00, 0x00, // Flags,
|
||||||
|
0x18, 0x00, 0x00, 0x00, // Size of tag
|
||||||
|
0x00, 0x00, 0x00, 0xB0, // Starting minimum location
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, // Ending maximum location: End of 32-bit address space
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Image alignment
|
||||||
|
0x01, 0x00, 0x00, 0x00, // Loading preference: lowest possible
|
||||||
|
|
||||||
0x00, 0x00, // End tag
|
0x00, 0x00, // End tag
|
||||||
0x00, 0x00, // Flags
|
0x00, 0x00, // Flags
|
||||||
0x08, 0x00, 0x00, 0x00, // Size
|
0x08, 0x00, 0x00, 0x00, // Size
|
||||||
|
@ -85,6 +93,7 @@ extern "C" fn _start() -> ! {
|
||||||
memory_map: None,
|
memory_map: None,
|
||||||
bootloader_name: None,
|
bootloader_name: None,
|
||||||
output: None,
|
output: None,
|
||||||
|
load_base: None,
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
match MAGIC {
|
match MAGIC {
|
||||||
|
@ -135,7 +144,7 @@ extern "C" fn _start() -> ! {
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
4 => {
|
4 => {
|
||||||
// Basic memory information
|
// Basic memory information, ignore
|
||||||
if current_tag.tag_len != 16 {
|
if current_tag.tag_len != 16 {
|
||||||
// Unexpected size, something is probably up
|
// Unexpected size, something is probably up
|
||||||
panic!("size of basic memory information tag != 16");
|
panic!("size of basic memory information tag != 16");
|
||||||
|
@ -177,7 +186,7 @@ extern "C" fn _start() -> ! {
|
||||||
|
|
||||||
let memorysections: &'static mut [aphrodite::multiboot2::MemorySection] = &mut *core::ptr::from_raw_parts_mut((&mut (*rawmemorymap).sections[0]) as &mut MemorySection, (*rawmemorymap).sections.len());
|
let memorysections: &'static mut [aphrodite::multiboot2::MemorySection] = &mut *core::ptr::from_raw_parts_mut((&mut (*rawmemorymap).sections[0]) as &mut MemorySection, (*rawmemorymap).sections.len());
|
||||||
// Above is a bit hard to understand, but what it does is transmute
|
// Above is a bit hard to understand, but what it does is transmute
|
||||||
// rawmemorymap's sections into a pointer to those sections.
|
// rawmemorymap's sections into a pointer to those sections
|
||||||
|
|
||||||
for ele in &mut *memorysections {
|
for ele in &mut *memorysections {
|
||||||
(*ele) = core::mem::transmute::<
|
(*ele) = core::mem::transmute::<
|
||||||
|
@ -252,6 +261,20 @@ extern "C" fn _start() -> ! {
|
||||||
};
|
};
|
||||||
BI.output = Some(&FBI)
|
BI.output = Some(&FBI)
|
||||||
},
|
},
|
||||||
|
21 => {
|
||||||
|
// Image load base physical address
|
||||||
|
if current_tag.tag_len != 12 {
|
||||||
|
panic!("size of image load base physical address tag != 12");
|
||||||
|
}
|
||||||
|
let ptr = (ptr + size_of::<Tag>()) as *const u32;
|
||||||
|
|
||||||
|
sdebugs("ptr: ");
|
||||||
|
sdebugbnp(&aphrodite::usize_as_u8_slice(ptr as usize));
|
||||||
|
sdebugsnp(" value: ");
|
||||||
|
sdebugbnpln(&aphrodite::u32_as_u8_slice(*ptr));
|
||||||
|
|
||||||
|
BI.load_base = Some(*ptr);
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
// Unknown/unimplemented tag type, ignore
|
// Unknown/unimplemented tag type, ignore
|
||||||
swarnings("Unknown tag type ");
|
swarnings("Unknown tag type ");
|
||||||
|
@ -292,10 +315,7 @@ extern "C" fn _start() -> ! {
|
||||||
sdebugsln("Bootloader information has been successfully loaded");
|
sdebugsln("Bootloader information has been successfully loaded");
|
||||||
sdebugunp(b'\n');
|
sdebugunp(b'\n');
|
||||||
|
|
||||||
if !enable_a20() {
|
aphrodite::arch::initalize_rtc();
|
||||||
panic!("failed to enable a20 gate");
|
|
||||||
}
|
|
||||||
initalize_rtc();
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if BI.output.clone().is_some() {
|
if BI.output.clone().is_some() {
|
||||||
|
@ -318,7 +338,7 @@ extern "C" fn _start() -> ! {
|
||||||
|
|
||||||
let ega: &dyn aphrodite::display::TextDisplay = &framebuffer_info;
|
let ega: &dyn aphrodite::display::TextDisplay = &framebuffer_info;
|
||||||
framebuffer_info.disable_cursor();
|
framebuffer_info.disable_cursor();
|
||||||
ega.clear_screen(COLOR_DEFAULT);
|
ega.clear_screen(COLOR_DEFAULT).unwrap();
|
||||||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||||
|
|
|
@ -2,9 +2,25 @@
|
||||||
#![cfg(target_arch = "x86")]
|
#![cfg(target_arch = "x86")]
|
||||||
|
|
||||||
use core::alloc::Layout;
|
use core::alloc::Layout;
|
||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
/// The GDTR. Used internally in [activate_gdt].
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct Gdtr {
|
||||||
|
base: *const u8,
|
||||||
|
size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn activate_gdt(ptr: *const [u8]) {
|
||||||
|
let gdtr = Gdtr {
|
||||||
|
base: ptr as *const u8,
|
||||||
|
size: ptr.len(),
|
||||||
|
};
|
||||||
|
unsafe { asm!("lgdt {}", in(reg) (&gdtr) as *const Gdtr as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes a series of GDT entries to an allocated section of memory and returns
|
/// Writes a series of GDT entries to an allocated section of memory and returns
|
||||||
/// a pointer.
|
/// a pointer.
|
||||||
pub unsafe fn write_gdt_entries(
|
pub unsafe fn write_gdt_entries(
|
||||||
|
@ -34,6 +50,13 @@ pub struct GDTEntry {
|
||||||
pub flags: u8,
|
pub flags: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const GDT_NULL_ENTRY: GDTEntry = GDTEntry {
|
||||||
|
limit: 0,
|
||||||
|
base: 0,
|
||||||
|
access: 0,
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
|
||||||
/// An error returned by [GDTEntry::write_to_addr] when the limit is greater
|
/// An error returned by [GDTEntry::write_to_addr] when the limit is greater
|
||||||
/// than 0xFFFFF.
|
/// than 0xFFFFF.
|
||||||
const GDT_WRITE_ADDR_INVALID_LIMIT: i16 = -1;
|
const GDT_WRITE_ADDR_INVALID_LIMIT: i16 = -1;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#![cfg(target_arch = "x86")]
|
#![cfg(target_arch = "x86")]
|
||||||
#![allow(static_mut_refs)]
|
#![allow(static_mut_refs)]
|
||||||
|
|
||||||
use core::alloc::{Allocator, Layout};
|
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use core::mem::MaybeUninit;
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
@ -70,29 +69,125 @@ struct Idtr {
|
||||||
size: usize,
|
size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Idtr {}
|
|
||||||
unsafe impl Sync for Idtr {}
|
|
||||||
|
|
||||||
/// Loads an interrupt descriptor table.
|
/// Loads an interrupt descriptor table.
|
||||||
fn load_idt(base: *const u8, size: usize) {
|
unsafe fn load_idt(base: *const u8, size: usize) {
|
||||||
static mut IDTR: MaybeUninit<Idtr> = MaybeUninit::uninit();
|
let idtr = Idtr { base, size };
|
||||||
unsafe {
|
unsafe { asm!("lidt {}", in(reg) (&idtr) as *const Idtr as usize) }
|
||||||
IDTR.write(Idtr { base, size });
|
|
||||||
}
|
|
||||||
unsafe { asm!("lidt {}", in(reg) IDTR.as_ptr() as usize) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Activate an IDT.
|
#[derive(Clone, Copy)]
|
||||||
|
pub(super) struct IdtEntry {
|
||||||
|
pub offset_high: u16,
|
||||||
|
pub data: u16,
|
||||||
|
pub segment: u16,
|
||||||
|
pub offset_low: u16,
|
||||||
|
pub vector: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct RawIdtEntry {
|
||||||
|
pub offset_high: u16,
|
||||||
|
pub data: u16,
|
||||||
|
pub segment: u16,
|
||||||
|
pub offset_low: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IdtEntry> for RawIdtEntry {
|
||||||
|
fn from(value: IdtEntry) -> Self {
|
||||||
|
RawIdtEntry {
|
||||||
|
offset_high: value.offset_high,
|
||||||
|
data: value.data,
|
||||||
|
segment: value.segment,
|
||||||
|
offset_low: value.offset_low,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Activate an IDT. Requires that all handlers can properly handle the calling
|
||||||
|
/// convention and are in GDT segment 1.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// Panics if the global allocator has not been setup
|
||||||
#[aphrodite_proc_macros::kernel_item(ActivateIDT)]
|
#[aphrodite_proc_macros::kernel_item(ActivateIDT)]
|
||||||
fn activate_idt(idt: Idt, alloc: crate::mem::MemoryMapAlloc) {
|
fn activate_idt(idt: Idt) {
|
||||||
let mem = alloc
|
let mut entries = alloc::vec::Vec::new();
|
||||||
.allocate(unsafe { Layout::from_size_align_unchecked(8 * idt.len, 1) })
|
|
||||||
.unwrap()
|
|
||||||
.as_mut_ptr();
|
|
||||||
for i in 0..idt.len {
|
for i in 0..idt.len {
|
||||||
let _vector = idt.vectors[i];
|
if idt.using_raw[i] {
|
||||||
let _func = unsafe { idt.funcs[i].assume_init() } as usize as u64;
|
entries.push(idt.raw_entries[i]);
|
||||||
let _user_callable = idt.user_callable[i];
|
continue;
|
||||||
|
}
|
||||||
|
let vector = idt.vectors[i];
|
||||||
|
let func = unsafe { idt.funcs[i].assume_init() } as usize as u32;
|
||||||
|
let user_callable = idt.user_callable[i];
|
||||||
|
let exception = idt.exception[i];
|
||||||
|
|
||||||
|
let mut entry = IdtEntry {
|
||||||
|
offset_high: (func & 0xFFFF0000) as u16,
|
||||||
|
data: 0b1000000000000000,
|
||||||
|
segment: 1,
|
||||||
|
offset_low: (func & 0xFFFF) as u16,
|
||||||
|
vector,
|
||||||
|
};
|
||||||
|
if user_callable {
|
||||||
|
entry.data |= 0b110000000000000;
|
||||||
|
}
|
||||||
|
if exception {
|
||||||
|
entry.data |= 0b111100000000;
|
||||||
|
} else {
|
||||||
|
entry.data |= 0b111000000000;
|
||||||
|
}
|
||||||
|
entries.push(entry);
|
||||||
|
}
|
||||||
|
entries.sort_by(|ele1: &IdtEntry, ele2: &IdtEntry| ele1.vector.cmp(&ele2.vector));
|
||||||
|
let mut last_vector = 0u16;
|
||||||
|
let mut start = true;
|
||||||
|
|
||||||
|
let mut entries2 = alloc::vec::Vec::new();
|
||||||
|
|
||||||
|
for entry in &entries {
|
||||||
|
if start {
|
||||||
|
let mut vector = entry.vector;
|
||||||
|
while vector > 0 {
|
||||||
|
entries2.push(IdtEntry {
|
||||||
|
offset_high: 0,
|
||||||
|
data: 0,
|
||||||
|
segment: 0,
|
||||||
|
offset_low: 0,
|
||||||
|
vector: 0,
|
||||||
|
});
|
||||||
|
vector -= 1;
|
||||||
|
}
|
||||||
|
last_vector = entry.vector;
|
||||||
|
entries2.push(*entry);
|
||||||
|
start = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if entry.vector - last_vector > 0 {
|
||||||
|
let mut vector = entry.vector - last_vector;
|
||||||
|
while vector > 0 {
|
||||||
|
entries2.push(IdtEntry {
|
||||||
|
offset_high: 0,
|
||||||
|
data: 0,
|
||||||
|
segment: 0,
|
||||||
|
offset_low: 0,
|
||||||
|
vector: 0,
|
||||||
|
});
|
||||||
|
vector -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_vector = entry.vector;
|
||||||
|
entries2.push(*entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut raw_entries: alloc::vec::Vec<RawIdtEntry, _> = alloc::vec::Vec::new();
|
||||||
|
for entry in &entries2 {
|
||||||
|
raw_entries.push(RawIdtEntry::from(*entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
let raw_entries = raw_entries.into_raw_parts();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
load_idt(raw_entries.0 as *const u8, (idt.len * 8) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +197,9 @@ pub struct Idt {
|
||||||
vectors: [u16; 256],
|
vectors: [u16; 256],
|
||||||
funcs: [MaybeUninit<fn()>; 256],
|
funcs: [MaybeUninit<fn()>; 256],
|
||||||
user_callable: [bool; 256],
|
user_callable: [bool; 256],
|
||||||
|
exception: [bool; 256],
|
||||||
|
raw_entries: [IdtEntry; 256],
|
||||||
|
using_raw: [bool; 256],
|
||||||
len: usize,
|
len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +209,9 @@ pub struct IdtBuilder {
|
||||||
vectors: [u16; 256],
|
vectors: [u16; 256],
|
||||||
funcs: [MaybeUninit<fn()>; 256],
|
funcs: [MaybeUninit<fn()>; 256],
|
||||||
user_callable: [bool; 256],
|
user_callable: [bool; 256],
|
||||||
|
exception: [bool; 256],
|
||||||
|
raw_entries: [IdtEntry; 256],
|
||||||
|
using_raw: [bool; 256],
|
||||||
idx: usize,
|
idx: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,14 +222,38 @@ impl IdtBuilder {
|
||||||
vectors: [0; 256],
|
vectors: [0; 256],
|
||||||
funcs: [MaybeUninit::uninit(); 256],
|
funcs: [MaybeUninit::uninit(); 256],
|
||||||
user_callable: [false; 256],
|
user_callable: [false; 256],
|
||||||
|
exception: [false; 256],
|
||||||
|
raw_entries: [IdtEntry {
|
||||||
|
offset_high: 0,
|
||||||
|
data: 0,
|
||||||
|
segment: 0,
|
||||||
|
offset_low: 0,
|
||||||
|
vector: 0,
|
||||||
|
}; 256],
|
||||||
|
using_raw: [false; 256],
|
||||||
idx: 0,
|
idx: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Add a function to this IdtBuilder.
|
/// Add a function to this IdtBuilder.
|
||||||
pub fn add_fn(&mut self, vector: u16, func: fn(), user_callable: bool) -> &mut Self {
|
pub fn add_fn(
|
||||||
|
&mut self,
|
||||||
|
vector: u16,
|
||||||
|
func: fn(),
|
||||||
|
user_callable: bool,
|
||||||
|
exception: bool,
|
||||||
|
) -> &mut Self {
|
||||||
self.vectors[self.idx] = vector;
|
self.vectors[self.idx] = vector;
|
||||||
self.funcs[self.idx].write(func);
|
self.funcs[self.idx].write(func);
|
||||||
self.user_callable[self.idx] = user_callable;
|
self.user_callable[self.idx] = user_callable;
|
||||||
|
self.exception[self.idx] = exception;
|
||||||
|
self.using_raw[self.idx] = false;
|
||||||
|
self.idx += 1;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn add_raw(&mut self, vector: u16, raw_entry: IdtEntry) -> &mut Self {
|
||||||
|
self.vectors[self.idx] = vector;
|
||||||
|
self.raw_entries[self.idx] = raw_entry;
|
||||||
|
self.using_raw[self.idx] = true;
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -138,18 +263,14 @@ impl IdtBuilder {
|
||||||
vectors: self.vectors,
|
vectors: self.vectors,
|
||||||
funcs: self.funcs,
|
funcs: self.funcs,
|
||||||
user_callable: self.user_callable,
|
user_callable: self.user_callable,
|
||||||
|
raw_entries: self.raw_entries,
|
||||||
|
using_raw: self.using_raw,
|
||||||
|
exception: self.exception,
|
||||||
len: self.idx,
|
len: self.idx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for IdtBuilder {
|
impl Default for IdtBuilder {
|
||||||
fn default() -> Self {
|
fn default() -> Self { Self::new() }
|
||||||
IdtBuilder {
|
|
||||||
vectors: [0; 256],
|
|
||||||
funcs: [MaybeUninit::uninit(); 256],
|
|
||||||
user_callable: [false; 256],
|
|
||||||
idx: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,9 @@ pub mod ports;
|
||||||
|
|
||||||
mod constants;
|
mod constants;
|
||||||
|
|
||||||
|
use alloc::vec;
|
||||||
use constants::*;
|
use constants::*;
|
||||||
|
use gdt::GDTEntry;
|
||||||
use interrupts::{pop_irq, restore_irq};
|
use interrupts::{pop_irq, restore_irq};
|
||||||
use ports::{inb, outb};
|
use ports::{inb, outb};
|
||||||
|
|
||||||
|
@ -77,83 +79,6 @@ pub fn get_keyboard_data() -> u8 { inb(0x60) }
|
||||||
/// Sends data to the keyboard.
|
/// Sends data to the keyboard.
|
||||||
pub fn send_keyboard_data(data: u8) { outb(0x60, data); }
|
pub fn send_keyboard_data(data: u8) { outb(0x60, data); }
|
||||||
|
|
||||||
/// Tries to enable the a20 gate via the keyboard controller method.
|
|
||||||
pub fn enable_a20_keyboard() {
|
|
||||||
let irq = pop_irq();
|
|
||||||
|
|
||||||
wait_for_keyboard_cmd();
|
|
||||||
send_keyboard_cmd(0xAD); // disable keyboard
|
|
||||||
|
|
||||||
wait_for_keyboard_cmd();
|
|
||||||
send_keyboard_cmd(0xD0); // read from input
|
|
||||||
|
|
||||||
wait_for_keyboard_cmd();
|
|
||||||
wait_for_keyboard_data();
|
|
||||||
let a = get_keyboard_data();
|
|
||||||
|
|
||||||
wait_for_keyboard_cmd();
|
|
||||||
send_keyboard_cmd(0xD1); // write to output
|
|
||||||
|
|
||||||
wait_for_keyboard_cmd();
|
|
||||||
send_keyboard_data(a | 2);
|
|
||||||
|
|
||||||
wait_for_keyboard_cmd();
|
|
||||||
send_keyboard_cmd(0xAE); // enable keyboard
|
|
||||||
|
|
||||||
restore_irq(irq);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to enable the a20 gate via fast a20.
|
|
||||||
/// Note that this may not work or do something unexpected.
|
|
||||||
pub fn enable_a20_fasta20() {
|
|
||||||
let mut a = inb(0x92);
|
|
||||||
if a & 0b10 > 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
a |= 0b10;
|
|
||||||
a &= 0xFE;
|
|
||||||
outb(0x92, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to enable the a20 gate by reading from port 0xee.
|
|
||||||
pub fn enable_a20_ee_port() { inb(0xee); }
|
|
||||||
|
|
||||||
/// Tries to enable the a20 gate by trying many different methods
|
|
||||||
/// and seeing what sticks.
|
|
||||||
pub fn enable_a20() -> bool {
|
|
||||||
if test_a20() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
enable_a20_keyboard();
|
|
||||||
let mut i = 0u32;
|
|
||||||
while (!test_a20()) && i < 10000 {
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if test_a20() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
enable_a20_ee_port();
|
|
||||||
let mut i = 0u32;
|
|
||||||
while (!test_a20()) && i < 10000 {
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if test_a20() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
enable_a20_fasta20();
|
|
||||||
let mut i = 0u32;
|
|
||||||
while (!test_a20()) && i < 10000 {
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return test_a20();
|
|
||||||
}
|
|
||||||
|
|
||||||
static mut RTC_INITALIZED: bool = false;
|
static mut RTC_INITALIZED: bool = false;
|
||||||
|
|
||||||
pub fn initalize_rtc() {
|
pub fn initalize_rtc() {
|
||||||
|
@ -167,10 +92,27 @@ pub fn initalize_rtc() {
|
||||||
unsafe { RTC_INITALIZED = true }
|
unsafe { RTC_INITALIZED = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(seconds: u32) {
|
pub fn sleep(seconds: u32) { initalize_rtc(); }
|
||||||
initalize_rtc();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn alloc_available_boot() {
|
pub fn alloc_available_boot() {
|
||||||
|
let irq = pop_irq();
|
||||||
|
let mut entries = vec![];
|
||||||
|
entries.push(gdt::GDT_NULL_ENTRY);
|
||||||
|
entries.push(GDTEntry {
|
||||||
|
limit: 0,
|
||||||
|
base: 0,
|
||||||
|
access: 0b10011011,
|
||||||
|
flags: 0b1100,
|
||||||
|
}); // kernel code segment
|
||||||
|
entries.push(GDTEntry {
|
||||||
|
limit: 0,
|
||||||
|
base: 0,
|
||||||
|
access: 0b10010011,
|
||||||
|
flags: 0b1100,
|
||||||
|
}); //
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gdt::activate_gdt(gdt::write_gdt_entries(entries).unwrap());
|
||||||
|
}
|
||||||
|
restore_irq(irq);
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,6 @@ impl core::iter::Iterator for MemoryMap {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct BootInfo<'a> {
|
pub struct BootInfo<'a> {
|
||||||
/// The commandline of the kernel.
|
/// The commandline of the kernel.
|
||||||
/// See <https://aphrodite-os.github.io/book/command-line.html> for the format.
|
|
||||||
pub cmdline: Option<&'static str>,
|
pub cmdline: Option<&'static str>,
|
||||||
|
|
||||||
/// The memory map provided by the bootloader. If None, the kernel will
|
/// The memory map provided by the bootloader. If None, the kernel will
|
||||||
|
@ -147,4 +146,7 @@ pub struct BootInfo<'a> {
|
||||||
|
|
||||||
/// Provides a way to display text.
|
/// Provides a way to display text.
|
||||||
pub output: Option<&'a dyn crate::display::TextDisplay>,
|
pub output: Option<&'a dyn crate::display::TextDisplay>,
|
||||||
|
|
||||||
|
/// The base address of the kernel
|
||||||
|
pub load_base: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#![allow(unexpected_cfgs)]
|
#![allow(unexpected_cfgs)]
|
||||||
#![allow(static_mut_refs)]
|
#![allow(static_mut_refs)]
|
||||||
|
|
||||||
|
use crate::arch::output::*;
|
||||||
use crate::display::{COLOR_DEFAULT, NoneTextDisplay};
|
use crate::display::{COLOR_DEFAULT, NoneTextDisplay};
|
||||||
use crate::output::*;
|
use crate::output::*;
|
||||||
|
|
||||||
|
@ -37,5 +38,14 @@ fn indep_boot_entry(
|
||||||
tinfosln("Successfully ran all configured power on tests", display).unwrap();
|
tinfosln("Successfully ran all configured power on tests", display).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cfg!(CONFIG_PREUSER_OUTPUT_DEBUG = "true") {
|
||||||
|
if let Some(load_base) = BI.load_base {
|
||||||
|
sdebugs("Image load base address is ");
|
||||||
|
sdebugbnpln(&crate::u32_as_u8_slice(load_base));
|
||||||
|
} else {
|
||||||
|
sdebugsln("Image load base address was not provided");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,9 +69,9 @@ static mut ALLOCATOR_INITALIZED: bool = false;
|
||||||
pub fn get_allocator() -> Option<&'static MemoryMapAlloc<'static>> {
|
pub fn get_allocator() -> Option<&'static MemoryMapAlloc<'static>> {
|
||||||
if unsafe { ALLOCATOR_INITALIZED } {
|
if unsafe { ALLOCATOR_INITALIZED } {
|
||||||
#[allow(static_mut_refs)]
|
#[allow(static_mut_refs)]
|
||||||
return Some(unsafe { ALLOCATOR.assume_init_ref() });
|
Some(unsafe { ALLOCATOR.assume_init_ref() })
|
||||||
} else {
|
} else {
|
||||||
return None;
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#![feature(ptr_as_uninit)]
|
#![feature(ptr_as_uninit)]
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(vec_into_raw_parts)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,6 @@ pub struct Multiboot2BootInfo {
|
||||||
// If you need it, good luck.
|
// If you need it, good luck.
|
||||||
/// We're provided with a C-style UTF-8(null-terminated UTF-8) string. This
|
/// We're provided with a C-style UTF-8(null-terminated UTF-8) string. This
|
||||||
/// should contain the original pointer provided by the bootloader.
|
/// should contain the original pointer provided by the bootloader.
|
||||||
/// See <https://aphrodite-os.github.io/book/command-line.html> for the format.
|
|
||||||
pub cmdline: Option<&'static core::ffi::CStr>,
|
pub cmdline: Option<&'static core::ffi::CStr>,
|
||||||
|
|
||||||
// Due to the way modules work, it's not easily possible to make a struct that contains all the
|
// Due to the way modules work, it's not easily possible to make a struct that contains all the
|
||||||
|
@ -220,14 +219,16 @@ pub struct Multiboot2BootInfo {
|
||||||
// it.
|
// it.
|
||||||
/// Provides information on the framebuffer.
|
/// Provides information on the framebuffer.
|
||||||
pub framebuffer_info: Option<FramebufferInfo>,
|
pub framebuffer_info: Option<FramebufferInfo>,
|
||||||
|
|
||||||
/// Color info, stored separately from [FramebufferInfo] because rust
|
/// Color info, stored separately from [FramebufferInfo] because rust
|
||||||
pub color_info: Option<ColorInfo>,
|
pub color_info: Option<ColorInfo>,
|
||||||
|
|
||||||
// Even though SMBIOS is documented for Multiboot2, we're not using it and will instead search
|
// Even though SMBIOS is documented for Multiboot2, we're not using it and will instead search
|
||||||
// for it ourselves. This is because right now I cannot figure out what format it provides
|
// for it ourselves. This is because right now I cannot figure out what format it provides
|
||||||
// the SMBIOS table in.
|
// the SMBIOS table in.
|
||||||
|
|
||||||
// EFI memory map and image handle pointers are not included for portability.
|
// EFI memory map and image handle pointers are not included for portability. Yeah, that's what
|
||||||
|
// I'm calling it.
|
||||||
// "Image load base physical address" is not included as at the moment the kernel is not
|
/// Base address of the kernel
|
||||||
// relocatable.
|
pub load_base: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#![cfg(all(not(CONFIG_POWERON_TESTS = "false"), not(CONFIG_POWERON_TEST_ALLOC = "false")))]
|
#![cfg(all(
|
||||||
|
not(CONFIG_POWERON_TESTS = "false"),
|
||||||
|
not(CONFIG_POWERON_TEST_ALLOC = "false")
|
||||||
|
))]
|
||||||
|
|
||||||
use crate::display::TextDisplay;
|
use crate::display::TextDisplay;
|
||||||
use crate::output::*;
|
use crate::output::*;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue