This commit is contained in:
parent
c8c5b5ad86
commit
3b7fa25cd2
22 changed files with 199 additions and 193 deletions
|
@ -45,7 +45,8 @@ fn main() {
|
||||||
);
|
);
|
||||||
// End checks
|
// End checks
|
||||||
|
|
||||||
// Configuration name used when a config is required but should always evaluate to true
|
// Configuration name used when a config is required but should always evaluate
|
||||||
|
// to true
|
||||||
println!(r#"cargo:rustc-check-cfg=cfg(NONE, values("false", none()))"#);
|
println!(r#"cargo:rustc-check-cfg=cfg(NONE, values("false", none()))"#);
|
||||||
|
|
||||||
for (var, val) in env {
|
for (var, val) in env {
|
||||||
|
|
15
kernel/rustfmt.toml
Normal file
15
kernel/rustfmt.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
unstable_features = true
|
||||||
|
binop_separator = "Back"
|
||||||
|
wrap_comments = true
|
||||||
|
edition = "2024"
|
||||||
|
style_edition = "2024"
|
||||||
|
fn_single_line = true
|
||||||
|
format_code_in_doc_comments = true
|
||||||
|
format_macro_matchers = true
|
||||||
|
match_block_trailing_comma = true
|
||||||
|
imports_granularity = "Module"
|
||||||
|
newline_style = "Unix"
|
||||||
|
normalize_comments = true
|
||||||
|
trailing_comma = "Vertical"
|
||||||
|
trailing_semicolon = true
|
||||||
|
use_try_shorthand = true
|
|
@ -9,8 +9,10 @@
|
||||||
#![feature(cfg_match)]
|
#![feature(cfg_match)]
|
||||||
#![feature(formatting_options)]
|
#![feature(formatting_options)]
|
||||||
|
|
||||||
|
use core::arch::asm;
|
||||||
|
use core::ffi::CStr;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
use aphrodite::arch::egatext;
|
use aphrodite::arch::egatext;
|
||||||
use aphrodite::arch::output::*;
|
use aphrodite::arch::output::*;
|
||||||
|
@ -65,9 +67,11 @@ static mut MAGIC: u32 = 0xFFFFFFFF;
|
||||||
extern "C" fn _start() -> ! {
|
extern "C" fn _start() -> ! {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Copy values provided by the bootloader out
|
// Copy values provided by the bootloader out
|
||||||
// Aphrodite bootloaders pass values in eax and ebx, however rust doesn't know that it can't overwrite those.
|
// Aphrodite bootloaders pass values in eax and ebx, however rust doesn't know
|
||||||
// (if necessary, we'll store all of the registers for other bootloaders and identify which one it is later)
|
// that it can't overwrite those. (if necessary, we'll store all of the
|
||||||
// we force using ebx and eax as the output of an empty assembly block to let it know.
|
// registers for other bootloaders and identify which one it is later)
|
||||||
|
// we force using ebx and eax as the output of an empty assembly block to let it
|
||||||
|
// know.
|
||||||
asm!(
|
asm!(
|
||||||
"", out("ebx") O, // Bootloader-specific data(ebx)
|
"", out("ebx") O, // Bootloader-specific data(ebx)
|
||||||
out("eax") MAGIC, // Magic number(eax)
|
out("eax") MAGIC, // Magic number(eax)
|
||||||
|
@ -128,21 +132,21 @@ extern "C" fn _start() -> ! {
|
||||||
panic!("size of ending tag != 8");
|
panic!("size of ending tag != 8");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
},
|
||||||
4 => {
|
4 => {
|
||||||
// Basic memory information
|
// Basic memory information
|
||||||
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");
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
5 => {
|
5 => {
|
||||||
// BIOS boot device, ignore
|
// BIOS boot device, ignore
|
||||||
if current_tag.tag_len != 20 {
|
if current_tag.tag_len != 20 {
|
||||||
// Unexpected size, something is probably up
|
// Unexpected size, something is probably up
|
||||||
panic!("size of bios boot device tag != 20");
|
panic!("size of bios boot device tag != 20");
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
1 => {
|
1 => {
|
||||||
// Command line
|
// Command line
|
||||||
if current_tag.tag_len < 8 {
|
if current_tag.tag_len < 8 {
|
||||||
|
@ -154,7 +158,7 @@ extern "C" fn _start() -> ! {
|
||||||
|
|
||||||
BI.cmdline = Some(cstring.to_str().unwrap());
|
BI.cmdline = Some(cstring.to_str().unwrap());
|
||||||
// ...before the BootInfo's commandline is set.
|
// ...before the BootInfo's commandline is set.
|
||||||
}
|
},
|
||||||
6 => {
|
6 => {
|
||||||
// Memory map tag
|
// Memory map tag
|
||||||
if current_tag.tag_len < 16 {
|
if current_tag.tag_len < 16 {
|
||||||
|
@ -165,11 +169,14 @@ extern "C" fn _start() -> ! {
|
||||||
ptr as *mut u8,
|
ptr as *mut u8,
|
||||||
(current_tag.tag_len / *((ptr + 8usize) as *const u32)) as usize,
|
(current_tag.tag_len / *((ptr + 8usize) as *const u32)) as usize,
|
||||||
);
|
);
|
||||||
// The end result of the above is creating a *const RawMemoryMap that has the same address as current_tag
|
// The end result of the above is creating a *const RawMemoryMap that
|
||||||
// and has all of the [aphrodite::multiboot2::MemorySection]s for the memory map
|
// has the same address as current_tag
|
||||||
|
// and has all of the [aphrodite::multiboot2::MemorySection]s for the
|
||||||
|
// memory map
|
||||||
|
|
||||||
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 rawmemorymap's sections into a pointer to those sections.
|
// Above is a bit hard to understand, but what it does is transmute
|
||||||
|
// rawmemorymap's sections into a pointer to those sections.
|
||||||
|
|
||||||
for ele in &mut *memorysections {
|
for ele in &mut *memorysections {
|
||||||
(*ele) = core::mem::transmute(Into::<MemoryMapping>::into(*ele))
|
(*ele) = core::mem::transmute(Into::<MemoryMapping>::into(*ele))
|
||||||
|
@ -188,7 +195,7 @@ extern "C" fn _start() -> ! {
|
||||||
idx: 0,
|
idx: 0,
|
||||||
};
|
};
|
||||||
BI.memory_map = Some(mm2);
|
BI.memory_map = Some(mm2);
|
||||||
}
|
},
|
||||||
2 => {
|
2 => {
|
||||||
// Bootloader name
|
// Bootloader name
|
||||||
if current_tag.tag_len < 8 {
|
if current_tag.tag_len < 8 {
|
||||||
|
@ -200,7 +207,7 @@ extern "C" fn _start() -> ! {
|
||||||
|
|
||||||
BI.bootloader_name = Some(cstring.to_str().unwrap());
|
BI.bootloader_name = Some(cstring.to_str().unwrap());
|
||||||
// ...before the BootInfo's bootloader_name is set.
|
// ...before the BootInfo's bootloader_name is set.
|
||||||
}
|
},
|
||||||
8 => {
|
8 => {
|
||||||
// Framebuffer info
|
// Framebuffer info
|
||||||
if current_tag.tag_len < 32 {
|
if current_tag.tag_len < 32 {
|
||||||
|
@ -213,16 +220,16 @@ extern "C" fn _start() -> ! {
|
||||||
0 => {
|
0 => {
|
||||||
// Indexed
|
// Indexed
|
||||||
panic!("Indexed color is unimplemented");
|
panic!("Indexed color is unimplemented");
|
||||||
}
|
},
|
||||||
1 => {
|
1 => {
|
||||||
// RGB
|
// RGB
|
||||||
panic!("RGB color is unimplemented");
|
panic!("RGB color is unimplemented");
|
||||||
}
|
},
|
||||||
2 => { // EGA Text
|
2 => { // EGA Text
|
||||||
}
|
},
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unknown color info type")
|
panic!("unknown color info type")
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
let framebuffer_info = (*framebufferinfo).clone();
|
let framebuffer_info = (*framebufferinfo).clone();
|
||||||
|
|
||||||
|
@ -235,12 +242,12 @@ extern "C" fn _start() -> ! {
|
||||||
change_cursor: false,
|
change_cursor: false,
|
||||||
};
|
};
|
||||||
BI.output = Some(&FBI)
|
BI.output = Some(&FBI)
|
||||||
}
|
},
|
||||||
_ => {
|
_ => {
|
||||||
// Unknown/unimplemented tag type, ignore
|
// Unknown/unimplemented tag type, ignore
|
||||||
swarnings("Unknown tag type ");
|
swarnings("Unknown tag type ");
|
||||||
swarningbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
|
swarningbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
sinfounp(b'\n');
|
sinfounp(b'\n');
|
||||||
ptr = (ptr + current_tag.tag_len as usize + 7) & !7;
|
ptr = (ptr + current_tag.tag_len as usize + 7) & !7;
|
||||||
|
@ -266,11 +273,11 @@ extern "C" fn _start() -> ! {
|
||||||
}
|
}
|
||||||
current_tag = core::ptr::read_volatile(ptr as *const Tag);
|
current_tag = core::ptr::read_volatile(ptr as *const Tag);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
_ => {
|
_ => {
|
||||||
// Unknown bootloader, panic
|
// Unknown bootloader, panic
|
||||||
panic!("unknown bootloader");
|
panic!("unknown bootloader");
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sdebugsln("Bootloader information has been successfully loaded");
|
sdebugsln("Bootloader information has been successfully loaded");
|
||||||
|
|
|
@ -11,9 +11,7 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
/// Returns the most specific architecture available.
|
/// Returns the most specific architecture available.
|
||||||
pub const fn get_arch() -> super::Architecture {
|
pub const fn get_arch() -> super::Architecture { super::Architecture::ExampleDummy }
|
||||||
super::Architecture::ExampleDummy
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod interrupts {
|
pub mod interrupts {
|
||||||
//! Interrupt-related functions.
|
//! Interrupt-related functions.
|
||||||
|
@ -26,9 +24,7 @@ pub mod interrupts {
|
||||||
|
|
||||||
/// Returns whether interrupts are enabled or not.
|
/// Returns whether interrupts are enabled or not.
|
||||||
#[aphrodite_proc_macros::kernel_item(InterruptsCheck)]
|
#[aphrodite_proc_macros::kernel_item(InterruptsCheck)]
|
||||||
fn interrupts_enabled() -> bool {
|
fn interrupts_enabled() -> bool { false }
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enables interrupts.
|
/// Enables interrupts.
|
||||||
#[aphrodite_proc_macros::kernel_item(InterruptsEnable)]
|
#[aphrodite_proc_macros::kernel_item(InterruptsEnable)]
|
||||||
|
@ -41,9 +37,7 @@ pub mod interrupts {
|
||||||
/// Disables interrupts and a value that can be used to restore them
|
/// Disables interrupts and a value that can be used to restore them
|
||||||
/// with [restore_irq].
|
/// with [restore_irq].
|
||||||
#[aphrodite_proc_macros::kernel_item(InterruptsPop)]
|
#[aphrodite_proc_macros::kernel_item(InterruptsPop)]
|
||||||
fn pop_irq() -> u64 {
|
fn pop_irq() -> u64 { 0 }
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Restores interrupts after a [pop_irq] call.
|
/// Restores interrupts after a [pop_irq] call.
|
||||||
#[aphrodite_proc_macros::kernel_item(InterruptsRestore)]
|
#[aphrodite_proc_macros::kernel_item(InterruptsRestore)]
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
//! Arch-specific code. This module re-exports all code from the architecture being used.
|
//! Arch-specific code. This module re-exports all code from the architecture
|
||||||
|
//! being used.
|
||||||
//!
|
//!
|
||||||
//! See [example_impl] for everything that has to be implemented by an architecture module.
|
//! See [example_impl] for everything that has to be implemented by an
|
||||||
|
//! architecture module.
|
||||||
|
|
||||||
pub mod example_impl;
|
pub mod example_impl;
|
||||||
mod x86;
|
mod x86;
|
||||||
|
@ -10,8 +12,8 @@ pub use x86::*;
|
||||||
/// The enum returned by arch::*::get_arch.
|
/// The enum returned by arch::*::get_arch.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||||
pub enum Architecture {
|
pub enum Architecture {
|
||||||
/// Returned by [example_impl]. If this is returned by arch::*::get_arch, something
|
/// Returned by [example_impl]. If this is returned by arch::*::get_arch,
|
||||||
/// is incredibly wrong and a panic should occur immediately.
|
/// something is incredibly wrong and a panic should occur immediately.
|
||||||
#[default]
|
#[default]
|
||||||
ExampleDummy,
|
ExampleDummy,
|
||||||
/// 32-bit x86.
|
/// 32-bit x86.
|
||||||
|
|
|
@ -45,7 +45,7 @@ impl crate::display::TextDisplay for FramebufferInfo {
|
||||||
match clr {
|
match clr {
|
||||||
0 => clr = 0,
|
0 => clr = 0,
|
||||||
1 => clr = 0b00000111,
|
1 => clr = 0b00000111,
|
||||||
_ => {}
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let color = clr;
|
let color = clr;
|
||||||
|
@ -68,9 +68,7 @@ impl crate::display::TextDisplay for FramebufferInfo {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn get_size(&self) -> (u32, u32) {
|
fn get_size(&self) -> (u32, u32) { (self.width, self.height) }
|
||||||
(self.width, self.height)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FramebufferInfo {
|
impl FramebufferInfo {
|
||||||
|
|
|
@ -5,7 +5,8 @@ use core::alloc::Layout;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
/// Writes a series of GDT entries to an allocated section of memory and returns a pointer.
|
/// Writes a series of GDT entries to an allocated section of memory and returns
|
||||||
|
/// a pointer.
|
||||||
pub unsafe fn write_gdt_entries(
|
pub unsafe fn write_gdt_entries(
|
||||||
entries: Vec<GDTEntry>,
|
entries: Vec<GDTEntry>,
|
||||||
) -> Result<*const [u8], crate::Error<'static>> {
|
) -> Result<*const [u8], crate::Error<'static>> {
|
||||||
|
@ -33,7 +34,8 @@ pub struct GDTEntry {
|
||||||
pub flags: u8,
|
pub flags: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An error returned by [GDTEntry::write_to_addr] when the limit is greater than 0xFFFFF.
|
/// An error returned by [GDTEntry::write_to_addr] when the limit is greater
|
||||||
|
/// than 0xFFFFF.
|
||||||
const GDT_WRITE_ADDR_INVALID_LIMIT: i16 = -1;
|
const GDT_WRITE_ADDR_INVALID_LIMIT: i16 = -1;
|
||||||
|
|
||||||
impl GDTEntry {
|
impl GDTEntry {
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
#![cfg(target_arch = "x86")]
|
#![cfg(target_arch = "x86")]
|
||||||
#![allow(static_mut_refs)]
|
#![allow(static_mut_refs)]
|
||||||
|
|
||||||
use core::{
|
use core::alloc::{Allocator, Layout};
|
||||||
alloc::{Allocator, Layout},
|
use core::arch::asm;
|
||||||
arch::asm,
|
use core::mem::MaybeUninit;
|
||||||
mem::MaybeUninit,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The syscall vector.
|
/// The syscall vector.
|
||||||
pub const USER_SYSCALL_VECTOR: u16 = 0xA0;
|
pub const USER_SYSCALL_VECTOR: u16 = 0xA0;
|
||||||
|
@ -26,20 +24,17 @@ pub fn interrupts_enabled() -> bool {
|
||||||
|
|
||||||
/// Disables interrupts.
|
/// Disables interrupts.
|
||||||
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
|
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
|
||||||
pub fn disable_interrupts() {
|
pub fn disable_interrupts() { unsafe { asm!("cli") } }
|
||||||
unsafe { asm!("cli") }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// PoppedInterrupts implements drop and restores the interrupts upon being dropped.
|
/// PoppedInterrupts implements drop and restores the interrupts upon being
|
||||||
/// This is useful in functions where you need interrupts disabled during it but also
|
/// dropped. This is useful in functions where you need interrupts disabled
|
||||||
/// want to use functions like [Result::unwrap] or [Option::unwrap].
|
/// during it but also want to use functions like [Result::unwrap] or
|
||||||
|
/// [Option::unwrap].
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PoppedInterrupts(u32);
|
pub struct PoppedInterrupts(u32);
|
||||||
|
|
||||||
impl Drop for PoppedInterrupts {
|
impl Drop for PoppedInterrupts {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) { restore_irq(self.clone()); }
|
||||||
restore_irq(self.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disables interrupts and returns the value of them.
|
/// Disables interrupts and returns the value of them.
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
//! Hardware-level memory sections. Unimplemented for certain hardware, x86 implements with GDT.
|
//! Hardware-level memory sections. Unimplemented for certain hardware, x86
|
||||||
|
//! implements with GDT.
|
||||||
#![cfg(target_arch = "x86")]
|
#![cfg(target_arch = "x86")]
|
||||||
|
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
|
|
||||||
use alloc::{vec, vec::Vec};
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use crate::memsections::*;
|
use crate::memsections::*;
|
||||||
|
|
||||||
|
@ -26,7 +28,8 @@ unsafe impl crate::memsections::MemorySections for MemorySections {
|
||||||
|
|
||||||
for section in self.sections {
|
for section in self.sections {
|
||||||
let mut section: MemorySection = section;
|
let mut section: MemorySection = section;
|
||||||
// rust-analyzer doesn't want to cooperate and recognize that section is already MemorySection, so I'm telling it here.
|
// rust-analyzer doesn't want to cooperate and recognize that section is already
|
||||||
|
// MemorySection, so I'm telling it here.
|
||||||
fn make_entry(section: &mut MemorySection, entries: &mut Vec<GDTEntry>) {
|
fn make_entry(section: &mut MemorySection, entries: &mut Vec<GDTEntry>) {
|
||||||
if section.length == 0 {
|
if section.length == 0 {
|
||||||
return;
|
return;
|
||||||
|
@ -39,13 +42,13 @@ unsafe impl crate::memsections::MemorySections for MemorySections {
|
||||||
match section.owner {
|
match section.owner {
|
||||||
Owner::Kernelspace => {
|
Owner::Kernelspace => {
|
||||||
access |= 0b0000000;
|
access |= 0b0000000;
|
||||||
}
|
},
|
||||||
Owner::Modulespace => {
|
Owner::Modulespace => {
|
||||||
access |= 0b0100000;
|
access |= 0b0100000;
|
||||||
}
|
},
|
||||||
Owner::Userspace => {
|
Owner::Userspace => {
|
||||||
access |= 0b1100000;
|
access |= 0b1100000;
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
if let SectionType::TaskSection { busy } = section.section_type {
|
if let SectionType::TaskSection { busy } = section.section_type {
|
||||||
access |= 0b00000;
|
access |= 0b00000;
|
||||||
|
@ -159,9 +162,7 @@ pub struct MemorySectionBuilder {
|
||||||
|
|
||||||
impl MemorySectionBuilder {
|
impl MemorySectionBuilder {
|
||||||
/// Create a new MemorySectionBuilder.
|
/// Create a new MemorySectionBuilder.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self { MemorySectionBuilder { sections: vec![] } }
|
||||||
MemorySectionBuilder { sections: vec![] }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds a section to this MemorySectionBuilder.
|
/// Adds a section to this MemorySectionBuilder.
|
||||||
pub fn add_section(&mut self, section: MemorySection) -> &mut Self {
|
pub fn add_section(&mut self, section: MemorySection) -> &mut Self {
|
||||||
|
|
|
@ -18,9 +18,7 @@ use interrupts::{pop_irq, restore_irq};
|
||||||
use ports::{inb, outb};
|
use ports::{inb, outb};
|
||||||
|
|
||||||
/// Returns the most specific architecture available.
|
/// Returns the most specific architecture available.
|
||||||
pub const fn get_arch() -> super::Architecture {
|
pub const fn get_arch() -> super::Architecture { super::Architecture::X86 }
|
||||||
super::Architecture::X86
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns information from the CPUID command in the form
|
/// Returns information from the CPUID command in the form
|
||||||
/// (ebx, edx, ecx).
|
/// (ebx, edx, ecx).
|
||||||
|
@ -65,29 +63,19 @@ pub fn test_a20() -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Waits for a keyboard command to complete.
|
/// Waits for a keyboard command to complete.
|
||||||
pub fn wait_for_keyboard_cmd() {
|
pub fn wait_for_keyboard_cmd() { while inb(0x64) & 0b10 > 1 {} }
|
||||||
while inb(0x64) & 0b10 > 1 {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Waits for there to be data to read from the keyboard.
|
/// Waits for there to be data to read from the keyboard.
|
||||||
pub fn wait_for_keyboard_data() {
|
pub fn wait_for_keyboard_data() { while inb(0x64) & 0b1 == 0 {} }
|
||||||
while inb(0x64) & 0b1 == 0 {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sends a keyboard command.
|
/// Sends a keyboard command.
|
||||||
pub fn send_keyboard_cmd(byte: u8) {
|
pub fn send_keyboard_cmd(byte: u8) { outb(0x64, byte); }
|
||||||
outb(0x64, byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets data from the keyboard.
|
/// Gets data from the keyboard.
|
||||||
pub fn get_keyboard_data() -> u8 {
|
pub fn get_keyboard_data() -> u8 { inb(0x60) }
|
||||||
inb(0x60)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sends data to the keyboard.
|
/// Sends data to the keyboard.
|
||||||
pub fn send_keyboard_data(data: u8) {
|
pub fn send_keyboard_data(data: u8) { outb(0x60, data); }
|
||||||
outb(0x60, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to enable the a20 gate via the keyboard controller method.
|
/// Tries to enable the a20 gate via the keyboard controller method.
|
||||||
pub fn enable_a20_keyboard() {
|
pub fn enable_a20_keyboard() {
|
||||||
|
@ -128,9 +116,7 @@ pub fn enable_a20_fasta20() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to enable the a20 gate by reading from port 0xee.
|
/// Tries to enable the a20 gate by reading from port 0xee.
|
||||||
pub fn enable_a20_ee_port() {
|
pub fn enable_a20_ee_port() { inb(0xee); }
|
||||||
inb(0xee);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to enable the a20 gate by trying many different methods
|
/// Tries to enable the a20 gate by trying many different methods
|
||||||
/// and seeing what sticks.
|
/// and seeing what sticks.
|
||||||
|
|
|
@ -5,7 +5,8 @@ use core::arch::asm;
|
||||||
|
|
||||||
use aphrodite_proc_macros::kernel_item;
|
use aphrodite_proc_macros::kernel_item;
|
||||||
|
|
||||||
/// One page directory entry. Use [PageDirectoryEntry::create_fourmb] or [PageDirectoryEntry::create_other] to make these.
|
/// One page directory entry. Use [PageDirectoryEntry::create_fourmb] or
|
||||||
|
/// [PageDirectoryEntry::create_other] to make these.
|
||||||
pub enum PageDirectoryEntry {
|
pub enum PageDirectoryEntry {
|
||||||
/// A four megabyte page.
|
/// A four megabyte page.
|
||||||
FourMb(u32),
|
FourMb(u32),
|
||||||
|
|
|
@ -34,6 +34,4 @@ pub fn inb(port: u16) -> u8 {
|
||||||
|
|
||||||
/// Wait a short, indeterminable time
|
/// Wait a short, indeterminable time
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn io_wait() {
|
pub fn io_wait() { outb(0x80, 0); }
|
||||||
outb(0x80, 0);
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,7 +27,8 @@ pub enum MemoryType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryType {
|
impl MemoryType {
|
||||||
/// Outputs the contents of this to the debug port with [crate::arch::output::sdebugsnp].
|
/// Outputs the contents of this to the debug port with
|
||||||
|
/// [crate::arch::output::sdebugsnp].
|
||||||
pub fn output(&self) {
|
pub fn output(&self) {
|
||||||
match self {
|
match self {
|
||||||
MemoryType::Free => crate::arch::output::sdebugsnp("Free"),
|
MemoryType::Free => crate::arch::output::sdebugsnp("Free"),
|
||||||
|
@ -41,7 +42,7 @@ impl MemoryType {
|
||||||
} else {
|
} else {
|
||||||
crate::arch::output::sdebugsnp(", unallocatable");
|
crate::arch::output::sdebugsnp(", unallocatable");
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
MemoryType::Kernel => crate::arch::output::sdebugsnp("Kernel loaded"),
|
MemoryType::Kernel => crate::arch::output::sdebugsnp("Kernel loaded"),
|
||||||
MemoryType::Permanent => crate::arch::output::sdebugsnp("Flash"),
|
MemoryType::Permanent => crate::arch::output::sdebugsnp("Flash"),
|
||||||
MemoryType::Reserved => crate::arch::output::sdebugsnp("Reserved"),
|
MemoryType::Reserved => crate::arch::output::sdebugsnp("Reserved"),
|
||||||
|
@ -92,9 +93,7 @@ pub struct MemoryMap {
|
||||||
|
|
||||||
impl MemoryMap {
|
impl MemoryMap {
|
||||||
/// Resets the index of the iterator (sets self.idx to 0).
|
/// Resets the index of the iterator (sets self.idx to 0).
|
||||||
pub fn reset_iter(&mut self) {
|
pub fn reset_iter(&mut self) { self.idx = 0; }
|
||||||
self.idx = 0;
|
|
||||||
}
|
|
||||||
/// The size of allocatable memory in bytes.
|
/// The size of allocatable memory in bytes.
|
||||||
pub fn mem_size(&mut self) -> u64 {
|
pub fn mem_size(&mut self) -> u64 {
|
||||||
let curr_idx = self.idx;
|
let curr_idx = self.idx;
|
||||||
|
@ -117,9 +116,7 @@ impl MemoryMap {
|
||||||
impl core::ops::Index<usize> for MemoryMap {
|
impl core::ops::Index<usize> for MemoryMap {
|
||||||
type Output = MemoryMapping;
|
type Output = MemoryMapping;
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Self::Output {
|
fn index(&self, index: usize) -> &Self::Output { &self.sections[index] }
|
||||||
&self.sections[index]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::iter::Iterator for MemoryMap {
|
impl core::iter::Iterator for MemoryMap {
|
||||||
|
@ -141,7 +138,8 @@ pub struct BootInfo<'a> {
|
||||||
/// See <https://aphrodite-os.github.io/book/command-line.html> for the format.
|
/// 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 attempt to generate it.
|
/// The memory map provided by the bootloader. If None, the kernel will
|
||||||
|
/// attempt to generate it.
|
||||||
pub memory_map: Option<MemoryMap>,
|
pub memory_map: Option<MemoryMap>,
|
||||||
|
|
||||||
/// The name of the bootloader(for example, "GRUB 2.12").
|
/// The name of the bootloader(for example, "GRUB 2.12").
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
/// A value of an argument.
|
/// A value of an argument.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum ArgumentValue {
|
pub enum ArgumentValue {
|
||||||
/// A string argument with the preceeding and following single quotes removed, and any \' replaced with '.
|
/// A string argument with the preceeding and following single quotes
|
||||||
|
/// removed, and any \' replaced with '.
|
||||||
Str(&'static str),
|
Str(&'static str),
|
||||||
/// A float argument.
|
/// A float argument.
|
||||||
Float(f128),
|
Float(f128),
|
||||||
|
@ -37,12 +38,14 @@ pub struct Cmdline {
|
||||||
/// The flags of the Cmdline.
|
/// The flags of the Cmdline.
|
||||||
pub flags: &'static [Flag],
|
pub flags: &'static [Flag],
|
||||||
|
|
||||||
/// The argument validators. When using [CmdlineValidator], it will check all of them
|
/// The argument validators. When using [CmdlineValidator], it will check
|
||||||
/// and if ALL of them report ANY of the arguments incorrect, then it will return an error.
|
/// all of them and if ALL of them report ANY of the arguments
|
||||||
|
/// incorrect, then it will return an error.
|
||||||
pub argument_validators: &'static [&'static dyn ArgumentValidator],
|
pub argument_validators: &'static [&'static dyn ArgumentValidator],
|
||||||
|
|
||||||
/// The flag validators. When using [CmdlineValidator], it will check all of them
|
/// The flag validators. When using [CmdlineValidator], it will check all of
|
||||||
/// and if ALL of them report ANY of the flags incorrect, then it will return an error.
|
/// them and if ALL of them report ANY of the flags incorrect, then it
|
||||||
|
/// will return an error.
|
||||||
pub flag_validators: &'static [&'static dyn FlagValidator],
|
pub flag_validators: &'static [&'static dyn FlagValidator],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
//! Types, constants and traits for displaying text. Mostly implemented in arch/.
|
//! Types, constants and traits for displaying text. Mostly implemented in
|
||||||
|
//! arch/.
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
|
@ -86,23 +87,18 @@ impl dyn TextDisplay + '_ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An implementation of [TextDisplay]. Returns (1,1) for the size and always returns Ok(()) for all functions.
|
/// An implementation of [TextDisplay]. Returns (1,1) for the size and always
|
||||||
|
/// returns Ok(()) for all functions.
|
||||||
pub struct NoneTextDisplay {}
|
pub struct NoneTextDisplay {}
|
||||||
|
|
||||||
impl TextDisplay for NoneTextDisplay {
|
impl TextDisplay for NoneTextDisplay {
|
||||||
fn get_size(&self) -> (u32, u32) {
|
fn get_size(&self) -> (u32, u32) { (1, 1) }
|
||||||
(1, 1)
|
|
||||||
}
|
|
||||||
fn write_char(&self, _: (u32, u32), _: u8, _: Color) -> Result<(), crate::Error<'static>> {
|
fn write_char(&self, _: (u32, u32), _: u8, _: Color) -> Result<(), crate::Error<'static>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Write for NoneTextDisplay {
|
impl Write for NoneTextDisplay {
|
||||||
fn write_char(&mut self, _: char) -> core::fmt::Result {
|
fn write_char(&mut self, _: char) -> core::fmt::Result { Ok(()) }
|
||||||
Ok(())
|
fn write_str(&mut self, _: &str) -> core::fmt::Result { Ok(()) }
|
||||||
}
|
|
||||||
fn write_str(&mut self, _: &str) -> core::fmt::Result {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,7 @@ pub struct Error<'a> {
|
||||||
|
|
||||||
impl<'a> Error<'a> {
|
impl<'a> Error<'a> {
|
||||||
/// Creates a new error.
|
/// Creates a new error.
|
||||||
pub const fn new(message: &'a str, code: i16) -> Self {
|
pub const fn new(message: &'a str, code: i16) -> Self { Error { message, code } }
|
||||||
Error { message, code }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error<'_> {
|
impl Error<'_> {
|
||||||
|
|
|
@ -5,16 +5,15 @@
|
||||||
|
|
||||||
use core::alloc::{Allocator, Layout};
|
use core::alloc::{Allocator, Layout};
|
||||||
|
|
||||||
use crate::{
|
use crate::display::{COLOR_DEFAULT, NoneTextDisplay};
|
||||||
display::{COLOR_DEFAULT, NoneTextDisplay},
|
use crate::output::*;
|
||||||
output::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
use aphrodite_proc_macros::*;
|
use aphrodite_proc_macros::*;
|
||||||
|
|
||||||
const MEM_TEST_SIZES: [usize; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
|
const MEM_TEST_SIZES: [usize; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
|
||||||
|
|
||||||
/// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files eventually call this.
|
/// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files
|
||||||
|
/// eventually call this.
|
||||||
#[kernel_item(IndepBootEntry)]
|
#[kernel_item(IndepBootEntry)]
|
||||||
fn indep_boot_entry(
|
fn indep_boot_entry(
|
||||||
display: Option<&dyn crate::display::TextDisplay>,
|
display: Option<&dyn crate::display::TextDisplay>,
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
//! Memory allocation.
|
//! Memory allocation.
|
||||||
|
|
||||||
use core::{
|
use core::alloc::{Allocator, GlobalAlloc};
|
||||||
alloc::{Allocator, GlobalAlloc},
|
use core::fmt::Debug;
|
||||||
fmt::Debug,
|
use core::mem::MaybeUninit;
|
||||||
mem::MaybeUninit,
|
use core::num::NonZero;
|
||||||
num::NonZero,
|
use core::ops::Range;
|
||||||
ops::Range,
|
use core::ptr::{NonNull, null_mut};
|
||||||
ptr::{NonNull, null_mut},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::boot::{MemoryMap, MemoryType};
|
use crate::boot::{MemoryMap, MemoryType};
|
||||||
|
|
||||||
|
@ -27,7 +25,8 @@ struct Allocation {
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
struct AllocationHeader {
|
struct AllocationHeader {
|
||||||
/// Whether this allocation table is used. Kept for parity with [Allocation]s.
|
/// Whether this allocation table is used. Kept for parity with
|
||||||
|
/// [Allocation]s.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub used: bool,
|
pub used: bool,
|
||||||
/// The starting address of the allocation table.
|
/// The starting address of the allocation table.
|
||||||
|
@ -76,13 +75,14 @@ fn get_allocator() -> Option<&'static MemoryMapAlloc<'static>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The unsafe counterpart of [MemMapAlloc()]. Doesn't check if the allocator is initalized.
|
/// The unsafe counterpart of [MemMapAlloc()]. Doesn't check if the allocator is
|
||||||
/// Internally, uses [MaybeUninit::assume_init_ref].
|
/// initalized. Internally, uses [MaybeUninit::assume_init_ref].
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Calling this instead of [MemMapAlloc] or when the allocator is uninitalized causes
|
/// Calling this instead of [MemMapAlloc] or when the allocator is uninitalized
|
||||||
/// undefined behavior; check [MaybeUninit::assume_init_ref] for safety guarantees.
|
/// causes undefined behavior; check [MaybeUninit::assume_init_ref] for safety
|
||||||
|
/// guarantees.
|
||||||
pub unsafe fn get_allocator_unchecked() -> &'static MemoryMapAlloc<'static> {
|
pub unsafe fn get_allocator_unchecked() -> &'static MemoryMapAlloc<'static> {
|
||||||
#[allow(static_mut_refs)]
|
#[allow(static_mut_refs)]
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -110,7 +110,8 @@ fn memory_map_alloc_init(memmap: crate::boot::MemoryMap) -> Result<(), crate::Er
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A implementation of a physical memory allocator that uses a [crate::boot::MemoryMap].
|
/// A implementation of a physical memory allocator that uses a
|
||||||
|
/// [crate::boot::MemoryMap].
|
||||||
pub struct MemoryMapAlloc<'a> {
|
pub struct MemoryMapAlloc<'a> {
|
||||||
/// The memory map to use to allocate memory.
|
/// The memory map to use to allocate memory.
|
||||||
pub memory_map: &'a mut crate::boot::MemoryMap,
|
pub memory_map: &'a mut crate::boot::MemoryMap,
|
||||||
|
@ -120,7 +121,8 @@ pub struct MemoryMapAlloc<'a> {
|
||||||
max_allocations_size: u64,
|
max_allocations_size: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Too many allocations have been created, pushing the size of [MemoryMapAlloc::allocations] over [MemoryMapAlloc::max_allocations_size].
|
/// Too many allocations have been created, pushing the size of
|
||||||
|
/// [MemoryMapAlloc::allocations] over [MemoryMapAlloc::max_allocations_size].
|
||||||
pub const TOO_MANY_ALLOCATIONS: i16 = -2;
|
pub const TOO_MANY_ALLOCATIONS: i16 = -2;
|
||||||
|
|
||||||
/// There isn't enough space for 32 allocations(the minimum available).
|
/// There isn't enough space for 32 allocations(the minimum available).
|
||||||
|
@ -132,7 +134,8 @@ pub const EXTEND_ALLOCATION_INVALID_INDEX: i16 = -4;
|
||||||
/// The allocation provided to [MemoryMapAlloc::extend_allocation] is unused.
|
/// The allocation provided to [MemoryMapAlloc::extend_allocation] is unused.
|
||||||
pub const EXTEND_ALLOCATION_ALLOCATION_UNUSED: i16 = -5;
|
pub const EXTEND_ALLOCATION_ALLOCATION_UNUSED: i16 = -5;
|
||||||
|
|
||||||
/// The allocation provided to [MemoryMapAlloc::extend_allocation], if extended, would extend into another allocation.
|
/// The allocation provided to [MemoryMapAlloc::extend_allocation], if extended,
|
||||||
|
/// would extend into another allocation.
|
||||||
pub const EXTEND_ALLOCATION_OTHER_ALLOCATION: i16 = -6;
|
pub const EXTEND_ALLOCATION_OTHER_ALLOCATION: i16 = -6;
|
||||||
|
|
||||||
impl<'a> Debug for MemoryMapAlloc<'a> {
|
impl<'a> Debug for MemoryMapAlloc<'a> {
|
||||||
|
@ -150,12 +153,14 @@ impl<'a> Debug for MemoryMapAlloc<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MemoryMapAlloc<'a> {
|
impl<'a> MemoryMapAlloc<'a> {
|
||||||
/// Creates a new [MemoryMapAlloc]. Please call this method instead of creating it manually!
|
/// Creates a new [MemoryMapAlloc]. Please call this method instead of
|
||||||
|
/// creating it manually!
|
||||||
///
|
///
|
||||||
/// This method internally stores the memory map in the outputted MemoryMapAlloc.
|
/// This method internally stores the memory map in the outputted
|
||||||
|
/// MemoryMapAlloc.
|
||||||
///
|
///
|
||||||
/// Note that this function will return an error only if there isn't enough allocatable space
|
/// Note that this function will return an error only if there isn't enough
|
||||||
/// for at least 32 allocations.
|
/// allocatable space for at least 32 allocations.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
memory_map: &'a mut crate::boot::MemoryMap,
|
memory_map: &'a mut crate::boot::MemoryMap,
|
||||||
) -> Result<MemoryMapAlloc<'a>, crate::Error<'a>> {
|
) -> Result<MemoryMapAlloc<'a>, crate::Error<'a>> {
|
||||||
|
@ -223,9 +228,7 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of allocations.
|
/// Returns the number of allocations.
|
||||||
pub fn number_of_allocations(&self) -> u64 {
|
pub fn number_of_allocations(&self) -> u64 { unsafe { *self.allocationheader }.num_allocations }
|
||||||
unsafe { *self.allocationheader }.num_allocations
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a [AllocationIter] to iterate over the current allocations.
|
/// Creates a [AllocationIter] to iterate over the current allocations.
|
||||||
fn allocations_iter(&self) -> AllocationIter {
|
fn allocations_iter(&self) -> AllocationIter {
|
||||||
|
@ -236,13 +239,14 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check to see if any allocations contain the given address. Returns true if so.
|
/// Check to see if any allocations contain the given address. Returns true
|
||||||
|
/// if so.
|
||||||
fn check_addr(&self, addr: u64) -> bool {
|
fn check_addr(&self, addr: u64) -> bool {
|
||||||
if cfg!(CONFIG_MEMORY_UNION_ALL = "true") {
|
if cfg!(CONFIG_MEMORY_UNION_ALL = "true") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if addr >= (self.allocationheader as u64)
|
if addr >= (self.allocationheader as u64) &&
|
||||||
&& addr < (self.allocationheader as u64 + unsafe { *self.allocationheader }.len)
|
addr < (self.allocationheader as u64 + unsafe { *self.allocationheader }.len)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +259,8 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check to see if a range of addresses have any allocations within. Returns true if so.
|
/// Check to see if a range of addresses have any allocations within.
|
||||||
|
/// Returns true if so.
|
||||||
fn check_range(&self, addr: Range<u64>) -> bool {
|
fn check_range(&self, addr: Range<u64>) -> bool {
|
||||||
if cfg!(CONFIG_MEMORY_UNION_ALL = "true") {
|
if cfg!(CONFIG_MEMORY_UNION_ALL = "true") {
|
||||||
return false;
|
return false;
|
||||||
|
@ -339,7 +344,8 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds a free block of memory that can fit the requested size and alignment
|
/// Finds a free block of memory that can fit the requested size and
|
||||||
|
/// alignment
|
||||||
fn find_free_block(&self, size: u64, align: usize) -> Option<u64> {
|
fn find_free_block(&self, size: u64, align: usize) -> Option<u64> {
|
||||||
for mapping in self.memory_map.clone() {
|
for mapping in self.memory_map.clone() {
|
||||||
if mapping.len < size {
|
if mapping.len < size {
|
||||||
|
@ -452,9 +458,7 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
|
|
||||||
/// Merge contiguous free memory blocks to reduce fragmentation.
|
/// Merge contiguous free memory blocks to reduce fragmentation.
|
||||||
/// This should be called periodically to keep memory efficient.
|
/// This should be called periodically to keep memory efficient.
|
||||||
pub fn merge_contiguous_allocations(&self) {
|
pub fn merge_contiguous_allocations(&self) { self.merge_free_blocks(); }
|
||||||
self.merge_free_blocks();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
||||||
|
@ -485,7 +489,7 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
return Err(core::alloc::AllocError);
|
return Err(core::alloc::AllocError);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Track the allocation
|
// Track the allocation
|
||||||
|
@ -663,5 +667,6 @@ unsafe impl<'a> GlobalAlloc for MemoryMapAlloc<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The last status of memory allocation or deallocation for a [MemoryMapAlloc].
|
/// The last status of memory allocation or deallocation for a [MemoryMapAlloc].
|
||||||
/// This can be used for more insight to why an allocation or deallocation failed.
|
/// This can be used for more insight to why an allocation or deallocation
|
||||||
|
/// failed.
|
||||||
pub static mut LAST_MEMMAP_ERR: Result<(), crate::Error<'static>> = Ok(());
|
pub static mut LAST_MEMMAP_ERR: Result<(), crate::Error<'static>> = Ok(());
|
||||||
|
|
|
@ -52,14 +52,15 @@ pub struct MemorySection {
|
||||||
/// The base address.
|
/// The base address.
|
||||||
pub address: u64,
|
pub address: u64,
|
||||||
/// The length. If the implementation has a maximum length of
|
/// The length. If the implementation has a maximum length of
|
||||||
/// sections, it should be automatically split into however many sections are necessary.
|
/// sections, it should be automatically split into however many sections
|
||||||
|
/// are necessary.
|
||||||
pub length: u64,
|
pub length: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implemented by arch::*::memory::MemorySections. Note to implementers:
|
/// Implemented by arch::*::memory::MemorySections. Note to implementers:
|
||||||
/// Copy should NOT be implemented. That would lead to issues where a
|
/// Copy should NOT be implemented. That would lead to issues where a
|
||||||
/// struct implementing this trait could be used after [write](MemorySections::write)
|
/// struct implementing this trait could be used after
|
||||||
/// is called, which is not supposed to happen.
|
/// [write](MemorySections::write) is called, which is not supposed to happen.
|
||||||
pub unsafe trait MemorySections {
|
pub unsafe trait MemorySections {
|
||||||
/// Write the sections to an allocated region and then activate them.
|
/// Write the sections to an allocated region and then activate them.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
//! This provides raw methods for internal kernel usage for the Aphrodite kernel. See aphrodite_user for userspace.
|
//! This provides raw methods for internal kernel usage for the Aphrodite
|
||||||
|
//! kernel. See aphrodite_user for userspace.
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(clippy::missing_docs_in_private_items)]
|
#![warn(clippy::missing_docs_in_private_items)]
|
||||||
|
@ -51,11 +52,7 @@ pub use util::*;
|
||||||
pub use traits::*;
|
pub use traits::*;
|
||||||
|
|
||||||
/// Returns the version of aphrodite.
|
/// Returns the version of aphrodite.
|
||||||
pub const fn version() -> &'static str {
|
pub const fn version() -> &'static str { env!("VERSION") }
|
||||||
env!("VERSION")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the version of the config for aphrodite.
|
/// Returns the version of the config for aphrodite.
|
||||||
pub const fn cfg_version() -> &'static str {
|
pub const fn cfg_version() -> &'static str { env!("CFG_VERSION") }
|
||||||
env!("CFG_VERSION")
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
//! Definitions of structs for multiboot2 information. Mostly used during pre-userspace.
|
//! Definitions of structs for multiboot2 information. Mostly used during
|
||||||
|
//! pre-userspace.
|
||||||
|
|
||||||
use crate::boot::MemoryMapping;
|
use crate::boot::MemoryMapping;
|
||||||
|
|
||||||
/// Used for Multiboot2 tags. This shouldn't be used after a [crate::boot::BootInfo] struct has been initalized, but it still can be used.
|
/// Used for Multiboot2 tags. This shouldn't be used after a
|
||||||
|
/// [crate::boot::BootInfo] struct has been initalized, but it still can be
|
||||||
|
/// used.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Tag {
|
pub struct Tag {
|
||||||
|
@ -12,7 +15,8 @@ pub struct Tag {
|
||||||
pub tag_len: u32,
|
pub tag_len: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The root tag. The official Multiboot2 name is literally the "fixed part" of the tags, so I made a better name.
|
/// The root tag. The official Multiboot2 name is literally the "fixed part" of
|
||||||
|
/// the tags, so I made a better name.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RootTag {
|
pub struct RootTag {
|
||||||
|
@ -30,8 +34,8 @@ pub struct Module {
|
||||||
pub mod_start: *const u8,
|
pub mod_start: *const u8,
|
||||||
/// A pointer to the end of the module
|
/// A pointer to the end of the module
|
||||||
pub mod_end: *const u8,
|
pub mod_end: *const u8,
|
||||||
/// A string that should be in the format `module_name (command line arguments)`.
|
/// A string that should be in the format `module_name (command line
|
||||||
/// See <https://aphrodite-os.github.io/book/bootloader-modules.html>.
|
/// arguments)`. See <https://aphrodite-os.github.io/book/bootloader-modules.html>.
|
||||||
pub mod_str: &'static core::ffi::CStr,
|
pub mod_str: &'static core::ffi::CStr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +47,8 @@ pub struct MemorySection {
|
||||||
pub base_addr: u64,
|
pub base_addr: u64,
|
||||||
/// The length of the section.
|
/// The length of the section.
|
||||||
pub length: u64,
|
pub length: u64,
|
||||||
/// The type of the section. Name is changed from the one provided in the Multiboot2 docs
|
/// The type of the section. Name is changed from the one provided in the
|
||||||
/// as "type" is a keyword in rust.
|
/// Multiboot2 docs as "type" is a keyword in rust.
|
||||||
pub mem_type: u32,
|
pub mem_type: u32,
|
||||||
/// Reserved space. Should be ignored.
|
/// Reserved space. Should be ignored.
|
||||||
reserved: u32,
|
reserved: u32,
|
||||||
|
@ -78,7 +82,8 @@ pub struct RawMemoryMap {
|
||||||
pub entry_size: u32,
|
pub entry_size: u32,
|
||||||
/// The version of the memory map. Should be disregarded as it's 0.
|
/// The version of the memory map. Should be disregarded as it's 0.
|
||||||
pub entry_version: u32, // currently is 0, future Multiboot2 versions may increment
|
pub entry_version: u32, // currently is 0, future Multiboot2 versions may increment
|
||||||
/// The sections. This is the reason that [Clone] can't be implemented for [RawMemoryMap].
|
/// The sections. This is the reason that [Clone] can't be implemented for
|
||||||
|
/// [RawMemoryMap].
|
||||||
pub sections: [MemorySection],
|
pub sections: [MemorySection],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +92,8 @@ pub struct RawMemoryMap {
|
||||||
pub struct MemoryMap {
|
pub struct MemoryMap {
|
||||||
/// The version of the memory map. Should be disregarded as it's 0.
|
/// The version of the memory map. Should be disregarded as it's 0.
|
||||||
pub version: u32, // currently is 0, future Multiboot2 versions may increment
|
pub version: u32, // currently is 0, future Multiboot2 versions may increment
|
||||||
/// Size of one entry(one [MemorySection] for Aphrodite's Multiboot2 support)
|
/// Size of one entry(one [MemorySection] for Aphrodite's Multiboot2
|
||||||
|
/// support)
|
||||||
pub entry_size: u32,
|
pub entry_size: u32,
|
||||||
/// All sections.
|
/// All sections.
|
||||||
pub sections: &'static [crate::boot::MemoryMapping],
|
pub sections: &'static [crate::boot::MemoryMapping],
|
||||||
|
@ -186,37 +192,42 @@ pub struct Multiboot2BootInfo {
|
||||||
/// See above
|
/// See above
|
||||||
pub mem_upper: Option<u32>,
|
pub mem_upper: Option<u32>,
|
||||||
|
|
||||||
// Multiboot2 bootloaders may provide us with the BIOS device and partition, but we're not interested.
|
// Multiboot2 bootloaders may provide us with the BIOS device and partition, but we're not
|
||||||
// To ensure future developers don't get any ideas, I'm leaving it out here.
|
// interested. To ensure future developers don't get any ideas, I'm leaving it out here.
|
||||||
// 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 should contain the original pointer provided by
|
/// We're provided with a C-style UTF-8(null-terminated UTF-8) string. This
|
||||||
/// the bootloader.
|
/// should contain the original pointer provided by the bootloader.
|
||||||
/// See <https://aphrodite-os.github.io/book/command-line.html> for the format.
|
/// 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 modules.
|
// Due to the way modules work, it's not easily possible to make a struct that contains all the
|
||||||
// Therefore, they are loaded on the fly.
|
// modules. Therefore, they are loaded on the fly.
|
||||||
|
|
||||||
// Multiboot2 bootloaders may provide us with ELF symbols, but I'm feeling lazy and right now it's mostly
|
// Multiboot2 bootloaders may provide us with ELF symbols, but I'm feeling lazy and right now
|
||||||
// unnecessary, so I don't care. Sorry if you are affected by this.
|
// it's mostly unnecessary, so I don't care. Sorry if you are affected by this.
|
||||||
/// The memory map provided by the bootloader.
|
/// The memory map provided by the bootloader.
|
||||||
pub memory_map: Option<MemoryMap>,
|
pub memory_map: Option<MemoryMap>,
|
||||||
|
|
||||||
/// The name of the bootloader(for example, "GRUB 2.12"). C-style UTF-8(null-terminated UTF-8) string.
|
/// The name of the bootloader(for example, "GRUB 2.12"). C-style
|
||||||
/// This should contain the original pointer provided by the bootloader.
|
/// UTF-8(null-terminated UTF-8) string. This should contain the
|
||||||
|
/// original pointer provided by the bootloader.
|
||||||
pub bootloader_name: Option<&'static core::ffi::CStr>,
|
pub bootloader_name: Option<&'static core::ffi::CStr>,
|
||||||
|
|
||||||
// APM table is ignored as APM has been superseded by ACPI. If your system doesn't support ACPI, good luck.
|
// APM table is ignored as APM has been superseded by ACPI. If your system doesn't support
|
||||||
|
// ACPI, good luck.
|
||||||
|
|
||||||
// VBE table is ignored for a similar reason to above: it's deprecated. Good luck if you need it.
|
// VBE table is ignored for a similar reason to above: it's deprecated. Good luck if you need
|
||||||
|
// 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 for it ourselves.
|
// Even though SMBIOS is documented for Multiboot2, we're not using it and will instead search
|
||||||
// This is because right now I cannot figure out what format it provides the SMBIOS table in.
|
// for it ourselves. This is because right now I cannot figure out what format it provides
|
||||||
|
// 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.
|
||||||
|
|
||||||
// "Image load base physical address" is not included as at the moment the kernel is not relocatable.
|
// "Image load base physical address" is not included as at the moment the kernel is not
|
||||||
|
// relocatable.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::{ToTokens, quote};
|
use quote::{ToTokens, quote};
|
||||||
use syn::{
|
use syn::parse::{Parse, ParseStream};
|
||||||
ItemFn, Signature, Token,
|
use syn::{ItemFn, Signature, Token};
|
||||||
parse::{Parse, ParseStream},
|
|
||||||
};
|
|
||||||
|
|
||||||
struct KernelItemNameInput {
|
struct KernelItemNameInput {
|
||||||
item: syn::Ident,
|
item: syn::Ident,
|
||||||
|
|
Loading…
Add table
Reference in a new issue