rustfmt config
All checks were successful
/ test (push) Successful in 13s

This commit is contained in:
Arthur Beck 2025-02-22 20:06:17 -06:00
parent c8c5b5ad86
commit 3b7fa25cd2
Signed by: ArthurB
GPG key ID: ACE3D14F5CEF14BF
22 changed files with 199 additions and 193 deletions

View file

@ -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
View 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

View file

@ -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");

View file

@ -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)]

View file

@ -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.

View file

@ -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 {

View file

@ -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 {

View file

@ -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.

View file

@ -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 {

View file

@ -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.

View file

@ -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),

View file

@ -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);
}

View file

@ -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").

View file

@ -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],
} }

View file

@ -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(())
}
} }

View file

@ -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<'_> {

View file

@ -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>,

View file

@ -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(());

View file

@ -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.
/// ///

View file

@ -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")
}

View file

@ -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.
} }

View file

@ -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,