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
|
||||
|
||||
// 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()))"#);
|
||||
|
||||
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(formatting_options)]
|
||||
|
||||
use core::arch::asm;
|
||||
use core::ffi::CStr;
|
||||
use core::fmt::Debug;
|
||||
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
use aphrodite::arch::egatext;
|
||||
use aphrodite::arch::output::*;
|
||||
|
@ -65,9 +67,11 @@ static mut MAGIC: u32 = 0xFFFFFFFF;
|
|||
extern "C" fn _start() -> ! {
|
||||
unsafe {
|
||||
// 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.
|
||||
// (if necessary, we'll store all of the 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.
|
||||
// Aphrodite bootloaders pass values in eax and ebx, however rust doesn't know
|
||||
// that it can't overwrite those. (if necessary, we'll store all of the
|
||||
// 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!(
|
||||
"", out("ebx") O, // Bootloader-specific data(ebx)
|
||||
out("eax") MAGIC, // Magic number(eax)
|
||||
|
@ -128,21 +132,21 @@ extern "C" fn _start() -> ! {
|
|||
panic!("size of ending tag != 8");
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
4 => {
|
||||
// Basic memory information
|
||||
if current_tag.tag_len != 16 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of basic memory information tag != 16");
|
||||
}
|
||||
}
|
||||
},
|
||||
5 => {
|
||||
// BIOS boot device, ignore
|
||||
if current_tag.tag_len != 20 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of bios boot device tag != 20");
|
||||
}
|
||||
}
|
||||
},
|
||||
1 => {
|
||||
// Command line
|
||||
if current_tag.tag_len < 8 {
|
||||
|
@ -154,7 +158,7 @@ extern "C" fn _start() -> ! {
|
|||
|
||||
BI.cmdline = Some(cstring.to_str().unwrap());
|
||||
// ...before the BootInfo's commandline is set.
|
||||
}
|
||||
},
|
||||
6 => {
|
||||
// Memory map tag
|
||||
if current_tag.tag_len < 16 {
|
||||
|
@ -165,11 +169,14 @@ extern "C" fn _start() -> ! {
|
|||
ptr as *mut u8,
|
||||
(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
|
||||
// and has all of the [aphrodite::multiboot2::MemorySection]s for the memory map
|
||||
// The end result of the above is creating a *const RawMemoryMap that
|
||||
// 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());
|
||||
// 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 {
|
||||
(*ele) = core::mem::transmute(Into::<MemoryMapping>::into(*ele))
|
||||
|
@ -188,7 +195,7 @@ extern "C" fn _start() -> ! {
|
|||
idx: 0,
|
||||
};
|
||||
BI.memory_map = Some(mm2);
|
||||
}
|
||||
},
|
||||
2 => {
|
||||
// Bootloader name
|
||||
if current_tag.tag_len < 8 {
|
||||
|
@ -200,7 +207,7 @@ extern "C" fn _start() -> ! {
|
|||
|
||||
BI.bootloader_name = Some(cstring.to_str().unwrap());
|
||||
// ...before the BootInfo's bootloader_name is set.
|
||||
}
|
||||
},
|
||||
8 => {
|
||||
// Framebuffer info
|
||||
if current_tag.tag_len < 32 {
|
||||
|
@ -213,16 +220,16 @@ extern "C" fn _start() -> ! {
|
|||
0 => {
|
||||
// Indexed
|
||||
panic!("Indexed color is unimplemented");
|
||||
}
|
||||
},
|
||||
1 => {
|
||||
// RGB
|
||||
panic!("RGB color is unimplemented");
|
||||
}
|
||||
},
|
||||
2 => { // EGA Text
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
panic!("unknown color info type")
|
||||
}
|
||||
},
|
||||
}
|
||||
let framebuffer_info = (*framebufferinfo).clone();
|
||||
|
||||
|
@ -235,12 +242,12 @@ extern "C" fn _start() -> ! {
|
|||
change_cursor: false,
|
||||
};
|
||||
BI.output = Some(&FBI)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// Unknown/unimplemented tag type, ignore
|
||||
swarnings("Unknown tag type ");
|
||||
swarningbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
|
||||
}
|
||||
},
|
||||
}
|
||||
sinfounp(b'\n');
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// Unknown bootloader, panic
|
||||
panic!("unknown bootloader");
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
sdebugsln("Bootloader information has been successfully loaded");
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
/// Returns the most specific architecture available.
|
||||
pub const fn get_arch() -> super::Architecture {
|
||||
super::Architecture::ExampleDummy
|
||||
}
|
||||
pub const fn get_arch() -> super::Architecture { super::Architecture::ExampleDummy }
|
||||
|
||||
pub mod interrupts {
|
||||
//! Interrupt-related functions.
|
||||
|
@ -26,9 +24,7 @@ pub mod interrupts {
|
|||
|
||||
/// Returns whether interrupts are enabled or not.
|
||||
#[aphrodite_proc_macros::kernel_item(InterruptsCheck)]
|
||||
fn interrupts_enabled() -> bool {
|
||||
false
|
||||
}
|
||||
fn interrupts_enabled() -> bool { false }
|
||||
|
||||
/// Enables interrupts.
|
||||
#[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
|
||||
/// with [restore_irq].
|
||||
#[aphrodite_proc_macros::kernel_item(InterruptsPop)]
|
||||
fn pop_irq() -> u64 {
|
||||
0
|
||||
}
|
||||
fn pop_irq() -> u64 { 0 }
|
||||
|
||||
/// Restores interrupts after a [pop_irq] call.
|
||||
#[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;
|
||||
mod x86;
|
||||
|
@ -10,8 +12,8 @@ pub use x86::*;
|
|||
/// The enum returned by arch::*::get_arch.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
pub enum Architecture {
|
||||
/// Returned by [example_impl]. If this is returned by arch::*::get_arch, something
|
||||
/// is incredibly wrong and a panic should occur immediately.
|
||||
/// Returned by [example_impl]. If this is returned by arch::*::get_arch,
|
||||
/// something is incredibly wrong and a panic should occur immediately.
|
||||
#[default]
|
||||
ExampleDummy,
|
||||
/// 32-bit x86.
|
||||
|
|
|
@ -45,7 +45,7 @@ impl crate::display::TextDisplay for FramebufferInfo {
|
|||
match clr {
|
||||
0 => clr = 0,
|
||||
1 => clr = 0b00000111,
|
||||
_ => {}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
let color = clr;
|
||||
|
@ -68,9 +68,7 @@ impl crate::display::TextDisplay for FramebufferInfo {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
fn get_size(&self) -> (u32, u32) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
fn get_size(&self) -> (u32, u32) { (self.width, self.height) }
|
||||
}
|
||||
|
||||
impl FramebufferInfo {
|
||||
|
|
|
@ -5,7 +5,8 @@ use core::alloc::Layout;
|
|||
|
||||
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(
|
||||
entries: Vec<GDTEntry>,
|
||||
) -> Result<*const [u8], crate::Error<'static>> {
|
||||
|
@ -33,7 +34,8 @@ pub struct GDTEntry {
|
|||
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;
|
||||
|
||||
impl GDTEntry {
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
#![cfg(target_arch = "x86")]
|
||||
#![allow(static_mut_refs)]
|
||||
|
||||
use core::{
|
||||
alloc::{Allocator, Layout},
|
||||
arch::asm,
|
||||
mem::MaybeUninit,
|
||||
};
|
||||
use core::alloc::{Allocator, Layout};
|
||||
use core::arch::asm;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
/// The syscall vector.
|
||||
pub const USER_SYSCALL_VECTOR: u16 = 0xA0;
|
||||
|
@ -26,20 +24,17 @@ pub fn interrupts_enabled() -> bool {
|
|||
|
||||
/// Disables interrupts.
|
||||
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
|
||||
pub fn disable_interrupts() {
|
||||
unsafe { asm!("cli") }
|
||||
}
|
||||
pub fn disable_interrupts() { unsafe { asm!("cli") } }
|
||||
|
||||
/// PoppedInterrupts implements drop and restores the interrupts upon being dropped.
|
||||
/// This is useful in functions where you need interrupts disabled during it but also
|
||||
/// want to use functions like [Result::unwrap] or [Option::unwrap].
|
||||
/// PoppedInterrupts implements drop and restores the interrupts upon being
|
||||
/// dropped. This is useful in functions where you need interrupts disabled
|
||||
/// during it but also want to use functions like [Result::unwrap] or
|
||||
/// [Option::unwrap].
|
||||
#[derive(Clone)]
|
||||
pub struct PoppedInterrupts(u32);
|
||||
|
||||
impl Drop for PoppedInterrupts {
|
||||
fn drop(&mut self) {
|
||||
restore_irq(self.clone());
|
||||
}
|
||||
fn drop(&mut self) { restore_irq(self.clone()); }
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
use alloc::{vec, vec::Vec};
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::memsections::*;
|
||||
|
||||
|
@ -26,7 +28,8 @@ unsafe impl crate::memsections::MemorySections for MemorySections {
|
|||
|
||||
for section in self.sections {
|
||||
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>) {
|
||||
if section.length == 0 {
|
||||
return;
|
||||
|
@ -39,13 +42,13 @@ unsafe impl crate::memsections::MemorySections for MemorySections {
|
|||
match section.owner {
|
||||
Owner::Kernelspace => {
|
||||
access |= 0b0000000;
|
||||
}
|
||||
},
|
||||
Owner::Modulespace => {
|
||||
access |= 0b0100000;
|
||||
}
|
||||
},
|
||||
Owner::Userspace => {
|
||||
access |= 0b1100000;
|
||||
}
|
||||
},
|
||||
}
|
||||
if let SectionType::TaskSection { busy } = section.section_type {
|
||||
access |= 0b00000;
|
||||
|
@ -159,9 +162,7 @@ pub struct MemorySectionBuilder {
|
|||
|
||||
impl MemorySectionBuilder {
|
||||
/// Create a new MemorySectionBuilder.
|
||||
pub fn new() -> Self {
|
||||
MemorySectionBuilder { sections: vec![] }
|
||||
}
|
||||
pub fn new() -> Self { MemorySectionBuilder { sections: vec![] } }
|
||||
|
||||
/// Adds a section to this MemorySectionBuilder.
|
||||
pub fn add_section(&mut self, section: MemorySection) -> &mut Self {
|
||||
|
|
|
@ -18,9 +18,7 @@ use interrupts::{pop_irq, restore_irq};
|
|||
use ports::{inb, outb};
|
||||
|
||||
/// Returns the most specific architecture available.
|
||||
pub const fn get_arch() -> super::Architecture {
|
||||
super::Architecture::X86
|
||||
}
|
||||
pub const fn get_arch() -> super::Architecture { super::Architecture::X86 }
|
||||
|
||||
/// Returns information from the CPUID command in the form
|
||||
/// (ebx, edx, ecx).
|
||||
|
@ -65,29 +63,19 @@ pub fn test_a20() -> bool {
|
|||
}
|
||||
|
||||
/// Waits for a keyboard command to complete.
|
||||
pub fn wait_for_keyboard_cmd() {
|
||||
while inb(0x64) & 0b10 > 1 {}
|
||||
}
|
||||
pub fn wait_for_keyboard_cmd() { while inb(0x64) & 0b10 > 1 {} }
|
||||
|
||||
/// Waits for there to be data to read from the keyboard.
|
||||
pub fn wait_for_keyboard_data() {
|
||||
while inb(0x64) & 0b1 == 0 {}
|
||||
}
|
||||
pub fn wait_for_keyboard_data() { while inb(0x64) & 0b1 == 0 {} }
|
||||
|
||||
/// Sends a keyboard command.
|
||||
pub fn send_keyboard_cmd(byte: u8) {
|
||||
outb(0x64, byte);
|
||||
}
|
||||
pub fn send_keyboard_cmd(byte: u8) { outb(0x64, byte); }
|
||||
|
||||
/// Gets data from the keyboard.
|
||||
pub fn get_keyboard_data() -> u8 {
|
||||
inb(0x60)
|
||||
}
|
||||
pub fn get_keyboard_data() -> u8 { inb(0x60) }
|
||||
|
||||
/// 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() {
|
||||
|
@ -128,9 +116,7 @@ pub fn enable_a20_fasta20() {
|
|||
}
|
||||
|
||||
/// Tries to enable the a20 gate by reading from port 0xee.
|
||||
pub fn enable_a20_ee_port() {
|
||||
inb(0xee);
|
||||
}
|
||||
pub fn enable_a20_ee_port() { inb(0xee); }
|
||||
|
||||
/// Tries to enable the a20 gate by trying many different methods
|
||||
/// and seeing what sticks.
|
||||
|
|
|
@ -5,7 +5,8 @@ use core::arch::asm;
|
|||
|
||||
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 {
|
||||
/// A four megabyte page.
|
||||
FourMb(u32),
|
||||
|
|
|
@ -34,6 +34,4 @@ pub fn inb(port: u16) -> u8 {
|
|||
|
||||
/// Wait a short, indeterminable time
|
||||
#[inline(always)]
|
||||
pub fn io_wait() {
|
||||
outb(0x80, 0);
|
||||
}
|
||||
pub fn io_wait() { outb(0x80, 0); }
|
||||
|
|
|
@ -27,7 +27,8 @@ pub enum 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) {
|
||||
match self {
|
||||
MemoryType::Free => crate::arch::output::sdebugsnp("Free"),
|
||||
|
@ -41,7 +42,7 @@ impl MemoryType {
|
|||
} else {
|
||||
crate::arch::output::sdebugsnp(", unallocatable");
|
||||
}
|
||||
}
|
||||
},
|
||||
MemoryType::Kernel => crate::arch::output::sdebugsnp("Kernel loaded"),
|
||||
MemoryType::Permanent => crate::arch::output::sdebugsnp("Flash"),
|
||||
MemoryType::Reserved => crate::arch::output::sdebugsnp("Reserved"),
|
||||
|
@ -92,9 +93,7 @@ pub struct MemoryMap {
|
|||
|
||||
impl MemoryMap {
|
||||
/// Resets the index of the iterator (sets self.idx to 0).
|
||||
pub fn reset_iter(&mut self) {
|
||||
self.idx = 0;
|
||||
}
|
||||
pub fn reset_iter(&mut self) { self.idx = 0; }
|
||||
/// The size of allocatable memory in bytes.
|
||||
pub fn mem_size(&mut self) -> u64 {
|
||||
let curr_idx = self.idx;
|
||||
|
@ -117,9 +116,7 @@ impl MemoryMap {
|
|||
impl core::ops::Index<usize> for MemoryMap {
|
||||
type Output = MemoryMapping;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self.sections[index]
|
||||
}
|
||||
fn index(&self, index: usize) -> &Self::Output { &self.sections[index] }
|
||||
}
|
||||
|
||||
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.
|
||||
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>,
|
||||
|
||||
/// The name of the bootloader(for example, "GRUB 2.12").
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
/// A value of an argument.
|
||||
#[derive(Clone, Copy)]
|
||||
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),
|
||||
/// A float argument.
|
||||
Float(f128),
|
||||
|
@ -37,12 +38,14 @@ pub struct Cmdline {
|
|||
/// The flags of the Cmdline.
|
||||
pub flags: &'static [Flag],
|
||||
|
||||
/// The argument validators. When using [CmdlineValidator], it will check all of them
|
||||
/// and if ALL of them report ANY of the arguments incorrect, then it will return an error.
|
||||
/// The argument validators. When using [CmdlineValidator], it will check
|
||||
/// 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],
|
||||
|
||||
/// The flag validators. When using [CmdlineValidator], it will check all of them
|
||||
/// and if ALL of them report ANY of the flags incorrect, then it will return an error.
|
||||
/// The flag validators. When using [CmdlineValidator], it will check all of
|
||||
/// 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],
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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 {}
|
||||
|
||||
impl TextDisplay for NoneTextDisplay {
|
||||
fn get_size(&self) -> (u32, u32) {
|
||||
(1, 1)
|
||||
}
|
||||
fn get_size(&self) -> (u32, u32) { (1, 1) }
|
||||
fn write_char(&self, _: (u32, u32), _: u8, _: Color) -> Result<(), crate::Error<'static>> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for NoneTextDisplay {
|
||||
fn write_char(&mut self, _: char) -> core::fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
fn write_str(&mut self, _: &str) -> core::fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
fn write_char(&mut self, _: char) -> 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> {
|
||||
/// Creates a new error.
|
||||
pub const fn new(message: &'a str, code: i16) -> Self {
|
||||
Error { message, code }
|
||||
}
|
||||
pub const fn new(message: &'a str, code: i16) -> Self { Error { message, code } }
|
||||
}
|
||||
|
||||
impl Error<'_> {
|
||||
|
|
|
@ -5,16 +5,15 @@
|
|||
|
||||
use core::alloc::{Allocator, Layout};
|
||||
|
||||
use crate::{
|
||||
display::{COLOR_DEFAULT, NoneTextDisplay},
|
||||
output::*,
|
||||
};
|
||||
use crate::display::{COLOR_DEFAULT, NoneTextDisplay};
|
||||
use crate::output::*;
|
||||
|
||||
use aphrodite_proc_macros::*;
|
||||
|
||||
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)]
|
||||
fn indep_boot_entry(
|
||||
display: Option<&dyn crate::display::TextDisplay>,
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
//! Memory allocation.
|
||||
|
||||
use core::{
|
||||
alloc::{Allocator, GlobalAlloc},
|
||||
fmt::Debug,
|
||||
mem::MaybeUninit,
|
||||
num::NonZero,
|
||||
ops::Range,
|
||||
ptr::{NonNull, null_mut},
|
||||
};
|
||||
use core::alloc::{Allocator, GlobalAlloc};
|
||||
use core::fmt::Debug;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::num::NonZero;
|
||||
use core::ops::Range;
|
||||
use core::ptr::{NonNull, null_mut};
|
||||
|
||||
use crate::boot::{MemoryMap, MemoryType};
|
||||
|
||||
|
@ -27,7 +25,8 @@ struct Allocation {
|
|||
|
||||
#[derive(Clone, Copy)]
|
||||
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)]
|
||||
pub used: bool,
|
||||
/// 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.
|
||||
/// Internally, uses [MaybeUninit::assume_init_ref].
|
||||
/// The unsafe counterpart of [MemMapAlloc()]. Doesn't check if the allocator is
|
||||
/// initalized. Internally, uses [MaybeUninit::assume_init_ref].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this instead of [MemMapAlloc] or when the allocator is uninitalized causes
|
||||
/// undefined behavior; check [MaybeUninit::assume_init_ref] for safety guarantees.
|
||||
/// Calling this instead of [MemMapAlloc] or when the allocator is uninitalized
|
||||
/// causes undefined behavior; check [MaybeUninit::assume_init_ref] for safety
|
||||
/// guarantees.
|
||||
pub unsafe fn get_allocator_unchecked() -> &'static MemoryMapAlloc<'static> {
|
||||
#[allow(static_mut_refs)]
|
||||
unsafe {
|
||||
|
@ -110,7 +110,8 @@ fn memory_map_alloc_init(memmap: crate::boot::MemoryMap) -> Result<(), crate::Er
|
|||
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> {
|
||||
/// The memory map to use to allocate memory.
|
||||
pub memory_map: &'a mut crate::boot::MemoryMap,
|
||||
|
@ -120,7 +121,8 @@ pub struct MemoryMapAlloc<'a> {
|
|||
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;
|
||||
|
||||
/// 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.
|
||||
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;
|
||||
|
||||
impl<'a> Debug for MemoryMapAlloc<'a> {
|
||||
|
@ -150,12 +153,14 @@ impl<'a> Debug for 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
|
||||
/// for at least 32 allocations.
|
||||
/// Note that this function will return an error only if there isn't enough
|
||||
/// allocatable space for at least 32 allocations.
|
||||
pub fn new(
|
||||
memory_map: &'a mut crate::boot::MemoryMap,
|
||||
) -> Result<MemoryMapAlloc<'a>, crate::Error<'a>> {
|
||||
|
@ -223,9 +228,7 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
}
|
||||
|
||||
/// Returns the number of allocations.
|
||||
pub fn number_of_allocations(&self) -> u64 {
|
||||
unsafe { *self.allocationheader }.num_allocations
|
||||
}
|
||||
pub fn number_of_allocations(&self) -> u64 { unsafe { *self.allocationheader }.num_allocations }
|
||||
|
||||
/// Creates a [AllocationIter] to iterate over the current allocations.
|
||||
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 {
|
||||
if cfg!(CONFIG_MEMORY_UNION_ALL = "true") {
|
||||
return false;
|
||||
}
|
||||
if addr >= (self.allocationheader as u64)
|
||||
&& addr < (self.allocationheader as u64 + unsafe { *self.allocationheader }.len)
|
||||
if addr >= (self.allocationheader as u64) &&
|
||||
addr < (self.allocationheader as u64 + unsafe { *self.allocationheader }.len)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -255,7 +259,8 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
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 {
|
||||
if cfg!(CONFIG_MEMORY_UNION_ALL = "true") {
|
||||
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> {
|
||||
for mapping in self.memory_map.clone() {
|
||||
if mapping.len < size {
|
||||
|
@ -452,9 +458,7 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
|
||||
/// Merge contiguous free memory blocks to reduce fragmentation.
|
||||
/// This should be called periodically to keep memory efficient.
|
||||
pub fn merge_contiguous_allocations(&self) {
|
||||
self.merge_free_blocks();
|
||||
}
|
||||
pub fn merge_contiguous_allocations(&self) { self.merge_free_blocks(); }
|
||||
}
|
||||
|
||||
unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
||||
|
@ -485,7 +489,7 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
|||
))
|
||||
};
|
||||
return Err(core::alloc::AllocError);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// 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].
|
||||
/// 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(());
|
||||
|
|
|
@ -52,14 +52,15 @@ pub struct MemorySection {
|
|||
/// The base address.
|
||||
pub address: u64,
|
||||
/// 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,
|
||||
}
|
||||
|
||||
/// Implemented by arch::*::memory::MemorySections. Note to implementers:
|
||||
/// Copy should NOT be implemented. That would lead to issues where a
|
||||
/// struct implementing this trait could be used after [write](MemorySections::write)
|
||||
/// is called, which is not supposed to happen.
|
||||
/// struct implementing this trait could be used after
|
||||
/// [write](MemorySections::write) is called, which is not supposed to happen.
|
||||
pub unsafe trait MemorySections {
|
||||
/// 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]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(clippy::missing_docs_in_private_items)]
|
||||
|
@ -51,11 +52,7 @@ pub use util::*;
|
|||
pub use traits::*;
|
||||
|
||||
/// Returns the version of aphrodite.
|
||||
pub const fn version() -> &'static str {
|
||||
env!("VERSION")
|
||||
}
|
||||
pub const fn version() -> &'static str { env!("VERSION") }
|
||||
|
||||
/// Returns the version of the config for aphrodite.
|
||||
pub const fn cfg_version() -> &'static str {
|
||||
env!("CFG_VERSION")
|
||||
}
|
||||
pub const fn cfg_version() -> &'static str { 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;
|
||||
|
||||
/// 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)]
|
||||
#[derive(Clone)]
|
||||
pub struct Tag {
|
||||
|
@ -12,7 +15,8 @@ pub struct Tag {
|
|||
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)]
|
||||
#[derive(Clone)]
|
||||
pub struct RootTag {
|
||||
|
@ -30,8 +34,8 @@ pub struct Module {
|
|||
pub mod_start: *const u8,
|
||||
/// A pointer to the end of the module
|
||||
pub mod_end: *const u8,
|
||||
/// A string that should be in the format `module_name (command line arguments)`.
|
||||
/// See <https://aphrodite-os.github.io/book/bootloader-modules.html>.
|
||||
/// A string that should be in the format `module_name (command line
|
||||
/// arguments)`. See <https://aphrodite-os.github.io/book/bootloader-modules.html>.
|
||||
pub mod_str: &'static core::ffi::CStr,
|
||||
}
|
||||
|
||||
|
@ -43,8 +47,8 @@ pub struct MemorySection {
|
|||
pub base_addr: u64,
|
||||
/// The length of the section.
|
||||
pub length: u64,
|
||||
/// The type of the section. Name is changed from the one provided in the Multiboot2 docs
|
||||
/// as "type" is a keyword in rust.
|
||||
/// The type of the section. Name is changed from the one provided in the
|
||||
/// Multiboot2 docs as "type" is a keyword in rust.
|
||||
pub mem_type: u32,
|
||||
/// Reserved space. Should be ignored.
|
||||
reserved: u32,
|
||||
|
@ -78,7 +82,8 @@ pub struct RawMemoryMap {
|
|||
pub entry_size: u32,
|
||||
/// 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
|
||||
/// 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],
|
||||
}
|
||||
|
||||
|
@ -87,7 +92,8 @@ pub struct RawMemoryMap {
|
|||
pub struct MemoryMap {
|
||||
/// The version of the memory map. Should be disregarded as it's 0.
|
||||
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,
|
||||
/// All sections.
|
||||
pub sections: &'static [crate::boot::MemoryMapping],
|
||||
|
@ -186,37 +192,42 @@ pub struct Multiboot2BootInfo {
|
|||
/// See above
|
||||
pub mem_upper: Option<u32>,
|
||||
|
||||
// Multiboot2 bootloaders may provide us with the BIOS device and partition, but we're not interested.
|
||||
// To ensure future developers don't get any ideas, I'm leaving it out here.
|
||||
// Multiboot2 bootloaders may provide us with the BIOS device and partition, but we're not
|
||||
// interested. To ensure future developers don't get any ideas, I'm leaving it out here.
|
||||
// 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
|
||||
/// the bootloader.
|
||||
/// We're provided with a C-style UTF-8(null-terminated UTF-8) string. This
|
||||
/// 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>,
|
||||
|
||||
// Due to the way modules work, it's not easily possible to make a struct that contains all the modules.
|
||||
// Therefore, they are loaded on the fly.
|
||||
// Due to the way modules work, it's not easily possible to make a struct that contains all the
|
||||
// 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
|
||||
// unnecessary, so I don't care. Sorry if you are affected by this.
|
||||
// Multiboot2 bootloaders may provide us with ELF symbols, but I'm feeling lazy and right now
|
||||
// it's mostly unnecessary, so I don't care. Sorry if you are affected by this.
|
||||
/// The memory map provided by the bootloader.
|
||||
pub memory_map: Option<MemoryMap>,
|
||||
|
||||
/// The name of the bootloader(for example, "GRUB 2.12"). C-style UTF-8(null-terminated UTF-8) string.
|
||||
/// This should contain the original pointer provided by the bootloader.
|
||||
/// The name of the bootloader(for example, "GRUB 2.12"). C-style
|
||||
/// 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>,
|
||||
|
||||
// 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.
|
||||
pub framebuffer_info: Option<FramebufferInfo>,
|
||||
/// Color info, stored separately from [FramebufferInfo] because rust
|
||||
pub color_info: Option<ColorInfo>,
|
||||
// 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 the SMBIOS table in.
|
||||
// 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
|
||||
// the SMBIOS table in.
|
||||
|
||||
// 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 quote::{ToTokens, quote};
|
||||
use syn::{
|
||||
ItemFn, Signature, Token,
|
||||
parse::{Parse, ParseStream},
|
||||
};
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::{ItemFn, Signature, Token};
|
||||
|
||||
struct KernelItemNameInput {
|
||||
item: syn::Ident,
|
||||
|
|
Loading…
Add table
Reference in a new issue