Large backlog of changes; been working on this commit for a few weeks
This commit is contained in:
parent
da73321233
commit
a2311366f2
35 changed files with 463 additions and 146 deletions
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
|
@ -2,6 +2,8 @@
|
||||||
"rust-analyzer.cargo.allTargets": false,
|
"rust-analyzer.cargo.allTargets": false,
|
||||||
"rust-analyzer.check.allTargets": false,
|
"rust-analyzer.check.allTargets": false,
|
||||||
"rust-analyzer.linkedProjects": [
|
"rust-analyzer.linkedProjects": [
|
||||||
"kernel/Cargo.toml"
|
"kernel/Cargo.toml",
|
||||||
]
|
"kernel/aphrodite_proc_macros/Cargo.toml",
|
||||||
|
"kernel/aphrodite_common/Cargo.toml"
|
||||||
|
],
|
||||||
}
|
}
|
|
@ -4,4 +4,5 @@ cpu: reset_on_triple_fault=0, model=tigerlake
|
||||||
magic_break: enabled=1
|
magic_break: enabled=1
|
||||||
|
|
||||||
ata0-master: type=cdrom, path=../kernel/aphrodite.iso, status=inserted
|
ata0-master: type=cdrom, path=../kernel/aphrodite.iso, status=inserted
|
||||||
boot: cdrom
|
boot: cdrom
|
||||||
|
memory: guest=512, host=512
|
26
emulation/bx_enh_dbg.ini
Normal file
26
emulation/bx_enh_dbg.ini
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# bx_enh_dbg_ini
|
||||||
|
SeeReg[0] = TRUE
|
||||||
|
SeeReg[1] = TRUE
|
||||||
|
SeeReg[2] = TRUE
|
||||||
|
SeeReg[3] = TRUE
|
||||||
|
SeeReg[4] = FALSE
|
||||||
|
SeeReg[5] = FALSE
|
||||||
|
SeeReg[6] = FALSE
|
||||||
|
SeeReg[7] = FALSE
|
||||||
|
SingleCPU = FALSE
|
||||||
|
ShowIOWindows = TRUE
|
||||||
|
ShowButtons = TRUE
|
||||||
|
SeeRegColors = TRUE
|
||||||
|
ignoreNxtT = TRUE
|
||||||
|
ignSSDisasm = TRUE
|
||||||
|
UprCase = 0
|
||||||
|
DumpInAsciiMode = 3
|
||||||
|
isLittleEndian = TRUE
|
||||||
|
DefaultAsmLines = 512
|
||||||
|
DumpWSIndex = 0
|
||||||
|
DockOrder = 0x123
|
||||||
|
ListWidthPix[0] = 179
|
||||||
|
ListWidthPix[1] = 245
|
||||||
|
ListWidthPix[2] = 281
|
||||||
|
MainWindow = 0, 0, 709, 500
|
||||||
|
FontName = Normal
|
|
@ -5,6 +5,7 @@ edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
|
aphrodite_proc_macros = { path = "./aphrodite_proc_macros"}
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
|
@ -15,15 +16,11 @@ panic = "abort"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "entrypoint_x86"
|
name = "entrypoint_x86"
|
||||||
path = "src/internal/arch/x86_asmp/entry.rs"
|
path = "src/arch_boot_entry/x86.rs"
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "main"
|
|
||||||
path = "src/internal/main.rs"
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "aphrodite"
|
name = "aphrodite"
|
||||||
path = "src/include/mod.rs"
|
path = "src/kernel/mod.rs"
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "test_aphrodite"
|
name = "test_aphrodite"
|
||||||
|
|
12
kernel/aphrodite_common/Cargo.toml
Normal file
12
kernel/aphrodite_common/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "aphrodite_common"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "../src/common/mod.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
strum = "0.27.0"
|
||||||
|
strum_macros = "0.27.0"
|
||||||
|
syn = "2.0.98"
|
14
kernel/aphrodite_proc_macros/Cargo.toml
Normal file
14
kernel/aphrodite_proc_macros/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "aphrodite_proc_macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
path = "../src/proc_macros/mod.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
quote = "1.0.38"
|
||||||
|
syn = { version = "2.0.98", features = ["full"] }
|
||||||
|
aphrodite_common = { path = "../aphrodite_common" }
|
||||||
|
proc-macro2 = "1.0.93"
|
37
kernel/build
37
kernel/build
|
@ -3,9 +3,8 @@
|
||||||
(
|
(
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [[ -n "$KERNEL_DIR" ]]; then
|
|
||||||
export KERNEL_DIR=$(readlink -e .)
|
export KERNEL_DIR=$(readlink -e .)
|
||||||
fi
|
|
||||||
|
|
||||||
DIR="${BASH_SOURCE%/*}"
|
DIR="${BASH_SOURCE%/*}"
|
||||||
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
|
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
|
||||||
|
@ -40,24 +39,22 @@
|
||||||
for target in $TARGETS; do
|
for target in $TARGETS; do
|
||||||
real_target=${!target}
|
real_target=${!target}
|
||||||
cargo build --target "$real_target" --release -Zbuild-std --bin entrypoint_$target
|
cargo build --target "$real_target" --release -Zbuild-std --bin entrypoint_$target
|
||||||
|
cp target/i686-unknown-none/release/entrypoint_$target kernel.flat
|
||||||
|
|
||||||
|
if [[ "$CONFIG_BUILD_GRUB" = "true" ]]; then
|
||||||
|
rm -rf grub aphrodite-grub.iso
|
||||||
|
if [[ "$target" = "x86" ]]; then
|
||||||
|
cp -r ./grub_template ./grub
|
||||||
|
|
||||||
|
cp kernel.flat ./grub/boot/aphrodite.kernel
|
||||||
|
|
||||||
|
sed -i "s@%{VERSION}@$VERSION@g" ./grub/boot/grub/grub.cfg
|
||||||
|
|
||||||
|
grub-mkrescue -o aphrodite-grub.iso grub
|
||||||
|
cp aphrodite-grub.iso aphrodite.iso
|
||||||
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
# build the kernel's entrypoint
|
|
||||||
|
|
||||||
cp target/i686-unknown-none/release/entrypoint kernel.flat
|
|
||||||
# copy it out
|
|
||||||
|
|
||||||
rm -rf grub aphrodite.iso aphrodite-grub.iso
|
|
||||||
|
|
||||||
if [[ $CONFIG_BUILD_GRUB = "true" ]]; then
|
|
||||||
cp -r ./grub_template ./grub
|
|
||||||
|
|
||||||
cp kernel.flat ./grub/boot/aphrodite.kernel
|
|
||||||
|
|
||||||
sed -i "s@%{VERSION}@$VERSION@g" ./grub/boot/grub/grub.cfg
|
|
||||||
|
|
||||||
grub-mkrescue -o aphrodite-grub.iso grub
|
|
||||||
cp aphrodite-grub.iso aphrodite.iso
|
|
||||||
fi
|
|
||||||
|
|
||||||
reset_version_vars
|
reset_version_vars
|
||||||
)
|
)
|
|
@ -7,9 +7,12 @@
|
||||||
#![allow(static_mut_refs)]
|
#![allow(static_mut_refs)]
|
||||||
#![feature(ptr_metadata)]
|
#![feature(ptr_metadata)]
|
||||||
#![feature(cfg_match)]
|
#![feature(cfg_match)]
|
||||||
|
#![feature(formatting_options)]
|
||||||
|
|
||||||
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
|
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
|
||||||
use aphrodite::boot::BootInfo;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
|
use aphrodite::boot::{BootInfo, MemoryMapping};
|
||||||
use aphrodite::multiboot2::{FramebufferInfo, MemoryMap, MemorySection, RawMemoryMap, RootTag, Tag};
|
use aphrodite::multiboot2::{FramebufferInfo, MemoryMap, MemorySection, RawMemoryMap, RootTag, Tag};
|
||||||
use aphrodite::arch::output::*;
|
use aphrodite::arch::output::*;
|
||||||
use aphrodite::arch::egatext as egatext;
|
use aphrodite::arch::egatext as egatext;
|
||||||
|
@ -40,7 +43,6 @@ static mut MM: MemoryMap = MemoryMap {
|
||||||
entry_size: 0,
|
entry_size: 0,
|
||||||
version: 0,
|
version: 0,
|
||||||
sections: &[],
|
sections: &[],
|
||||||
idx: 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static mut FBI: aphrodite::arch::egatext::FramebufferInfo = aphrodite::arch::egatext::FramebufferInfo {
|
static mut FBI: aphrodite::arch::egatext::FramebufferInfo = aphrodite::arch::egatext::FramebufferInfo {
|
||||||
|
@ -142,17 +144,23 @@ extern "C" fn _start() -> ! {
|
||||||
if current_tag.tag_len < 16 { // Unexpected size, something is probably up
|
if current_tag.tag_len < 16 { // Unexpected size, something is probably up
|
||||||
panic!("size of memory map tag < 16");
|
panic!("size of memory map tag < 16");
|
||||||
}
|
}
|
||||||
let rawmemorymap: *const RawMemoryMap = core::ptr::from_raw_parts(
|
let rawmemorymap: *mut RawMemoryMap = core::ptr::from_raw_parts_mut(
|
||||||
ptr as *const u8, (current_tag.tag_len / *((ptr + 8usize) as *const u32)) as usize
|
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
|
// 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
|
// 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.
|
||||||
|
|
||||||
|
for ele in &mut *memorysections {
|
||||||
|
(*ele) = core::mem::transmute(Into::<MemoryMapping>::into(*ele))
|
||||||
|
}
|
||||||
|
|
||||||
MM = MemoryMap {
|
MM = MemoryMap {
|
||||||
version: (*rawmemorymap).entry_version,
|
version: (*rawmemorymap).entry_version,
|
||||||
entry_size: (*rawmemorymap).entry_size,
|
entry_size: (*rawmemorymap).entry_size,
|
||||||
sections: &*core::ptr::from_raw_parts((&(*rawmemorymap).sections[0]) as &MemorySection, (*rawmemorymap).sections.len()),
|
sections: core::mem::transmute(memorysections),
|
||||||
idx: 0
|
|
||||||
};
|
};
|
||||||
let mm2 = aphrodite::boot::MemoryMap {
|
let mm2 = aphrodite::boot::MemoryMap {
|
||||||
len: MM.sections.len() as u64,
|
len: MM.sections.len() as u64,
|
||||||
|
@ -264,17 +272,19 @@ extern "C" fn _start() -> ! {
|
||||||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||||
|
|
||||||
aphrodite::_entry::_entry(Some(ega), &BI);
|
aphrodite::indep_boot_entry::indep_boot_entry(Some(ega), &BI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aphrodite::_entry::_entry(None, &BI);
|
aphrodite::indep_boot_entry::indep_boot_entry(None, &BI);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(link_section = ".panic")]
|
#[unsafe(link_section = ".panic")]
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
#[cfg(not(CONFIG_HALT_ON_PANIC = "false"))]
|
#[cfg(not(CONFIG_HALT_ON_PANIC = "false"))]
|
||||||
fn halt_on_panic(info: &PanicInfo) -> ! {
|
fn halt_on_panic(info: &PanicInfo) -> ! {
|
||||||
|
use core::fmt::FormattingOptions;
|
||||||
|
|
||||||
if info.location().is_some() {
|
if info.location().is_some() {
|
||||||
sfatals("Panic at ");
|
sfatals("Panic at ");
|
||||||
sfatalsnp(info.location().unwrap().file());
|
sfatalsnp(info.location().unwrap().file());
|
||||||
|
@ -286,10 +296,8 @@ fn halt_on_panic(info: &PanicInfo) -> ! {
|
||||||
} else {
|
} else {
|
||||||
sfatals("Panic: ");
|
sfatals("Panic: ");
|
||||||
}
|
}
|
||||||
let message = info.message().as_str().unwrap_or("");
|
let mut formatter = FormattingOptions::new().create_formatter(unsafe { &mut FBI });
|
||||||
if message != "" {
|
let _ = info.message().fmt(&mut formatter);
|
||||||
sfatalsnpln(message);
|
|
||||||
}
|
|
||||||
aphrodite::arch::interrupts::disable_interrupts();
|
aphrodite::arch::interrupts::disable_interrupts();
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("hlt", options(noreturn));
|
asm!("hlt", options(noreturn));
|
||||||
|
@ -314,6 +322,8 @@ fn spin_on_panic(info: &PanicInfo) -> ! {
|
||||||
let message = info.message().as_str().unwrap_or("");
|
let message = info.message().as_str().unwrap_or("");
|
||||||
if message != "" {
|
if message != "" {
|
||||||
sfatalsnpln(message);
|
sfatalsnpln(message);
|
||||||
|
} else {
|
||||||
|
sfatalsnp("\n");
|
||||||
}
|
}
|
||||||
aphrodite::arch::interrupts::disable_interrupts();
|
aphrodite::arch::interrupts::disable_interrupts();
|
||||||
loop {}
|
loop {}
|
37
kernel/src/common/mod.rs
Normal file
37
kernel/src/common/mod.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use syn::{parse::Parse, Ident};
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
use strum_macros::EnumIter;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, EnumIter)]
|
||||||
|
pub enum KernelItem {
|
||||||
|
IndepBootEntry,
|
||||||
|
ArchBootEntry,
|
||||||
|
SyscallSetup,
|
||||||
|
MemMapGen,
|
||||||
|
MemMapAlloc,
|
||||||
|
PreuserModLoad,
|
||||||
|
InitEnv,
|
||||||
|
KernelFSMount,
|
||||||
|
StorageFSMount,
|
||||||
|
PreuserMod,
|
||||||
|
RamLoader,
|
||||||
|
UserInit,
|
||||||
|
UserModLoad,
|
||||||
|
ProcessFSMount
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for KernelItem {
|
||||||
|
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||||
|
let ident: Ident = input.parse()?;
|
||||||
|
|
||||||
|
for variant in Self::iter() {
|
||||||
|
let name = format!("{:?}", variant);
|
||||||
|
|
||||||
|
if ident.to_string().as_str() == name {
|
||||||
|
return Ok(variant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(syn::Error::new(ident.span(), "Expected one of aphrodite_common::KernelItem's variants"))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
//! The main code for the kernel.
|
|
||||||
#![warn(missing_docs)]
|
|
||||||
#![allow(unexpected_cfgs)]
|
|
||||||
#![allow(static_mut_refs)]
|
|
||||||
|
|
||||||
use core::alloc::{Allocator, Layout};
|
|
||||||
|
|
||||||
use crate::output::*;
|
|
||||||
|
|
||||||
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.
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn _entry(display: Option<&dyn crate::display::TextDisplay>, BI: &crate::boot::BootInfo) -> ! {
|
|
||||||
let mut mem_map = BI.memory_map.unwrap();
|
|
||||||
let allocator = crate::mem::MemoryMapAlloc::new(&mut mem_map).unwrap();
|
|
||||||
tdebugsln("Testing allocator...", display.unwrap());
|
|
||||||
|
|
||||||
for size in MEM_TEST_SIZES {
|
|
||||||
tdebugs("Allocating ", display.unwrap());
|
|
||||||
tdebugbnp(&crate::usize_as_u8_slice(size), display.unwrap());
|
|
||||||
tdebugsnpln(" bytes of memory...", display.unwrap());
|
|
||||||
if let Err(_) = allocator.allocate(Layout::from_size_align(size, 1).unwrap()) {
|
|
||||||
terrors("Failed to allocate: ",display.unwrap());
|
|
||||||
unsafe { crate::mem::LAST_MEMMAP_ERR.unwrap_err().display_np(display.unwrap()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loop {}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! 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.
|
||||||
|
|
||||||
mod x86_asmp;
|
mod x86;
|
||||||
|
|
||||||
pub use x86_asmp::*;
|
pub use x86::*;
|
|
@ -25,6 +25,13 @@ pub const ERR_INVALID_X: i16 = -1;
|
||||||
/// Returned when the provided position is invalid in the Y direction.
|
/// Returned when the provided position is invalid in the Y direction.
|
||||||
pub const ERR_INVALID_Y: i16 = -2;
|
pub const ERR_INVALID_Y: i16 = -2;
|
||||||
|
|
||||||
|
impl core::fmt::Write for FramebufferInfo {
|
||||||
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
|
crate::output::toutputsnp(s, self).unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl crate::display::TextDisplay for FramebufferInfo {
|
impl crate::display::TextDisplay for FramebufferInfo {
|
||||||
/// Writes a character to the screen.
|
/// Writes a character to the screen.
|
||||||
fn write_char(&self, mut pos: (u32, u32), char: u8, color: Color) -> Result<(), crate::Error<'static>> {
|
fn write_char(&self, mut pos: (u32, u32), char: u8, color: Color) -> Result<(), crate::Error<'static>> {
|
|
@ -9,7 +9,7 @@
|
||||||
pub enum MemoryType {
|
pub enum MemoryType {
|
||||||
/// Free RAM with no use.
|
/// Free RAM with no use.
|
||||||
Free,
|
Free,
|
||||||
/// RAM used by the kernel
|
/// RAM where the kernel is loaded.
|
||||||
Kernel,
|
Kernel,
|
||||||
/// Reserved by something.
|
/// Reserved by something.
|
||||||
Reserved,
|
Reserved,
|
||||||
|
@ -26,6 +26,31 @@ pub enum MemoryType {
|
||||||
Permanent,
|
Permanent,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MemoryType {
|
||||||
|
/// 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"),
|
||||||
|
MemoryType::Faulty => crate::arch::output::sdebugsnp("Faulty RAM"),
|
||||||
|
MemoryType::HardwareReserved => crate::arch::output::sdebugsnp("Hardware Reserved"),
|
||||||
|
MemoryType::HardwareSpecific(val, allocatable) => {
|
||||||
|
crate::arch::output::sdebugsnp("Hardware specific ");
|
||||||
|
crate::arch::output::sdebugbnp(&crate::u32_as_u8_slice(*val));
|
||||||
|
if *allocatable {
|
||||||
|
crate::arch::output::sdebugsnp(" allocatable");
|
||||||
|
} 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"),
|
||||||
|
MemoryType::Unknown => crate::arch::output::sdebugsnp("Unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A single memory mapping for [MemoryMap].
|
/// A single memory mapping for [MemoryMap].
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct MemoryMapping {
|
pub struct MemoryMapping {
|
||||||
|
@ -37,10 +62,26 @@ pub struct MemoryMapping {
|
||||||
pub len: u64,
|
pub len: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MemoryMapping {
|
||||||
|
/// Converts this MemoryMapping to [core::fmt::Arguments].
|
||||||
|
pub fn output(&self) {
|
||||||
|
crate::arch::output::sdebugs("Memory type: ");
|
||||||
|
self.mem_type.output();
|
||||||
|
crate::arch::output::sdebugsnp("; Start: ");
|
||||||
|
crate::arch::output::sdebugbnp(&crate::u64_as_u8_slice(self.start));
|
||||||
|
crate::arch::output::sdebugsnp("; Length: ");
|
||||||
|
crate::arch::output::sdebugbnp(&crate::u64_as_u8_slice(self.len));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A memory map outputted by the bootloader or by the kernel.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct MemoryMap {
|
pub struct MemoryMap {
|
||||||
|
/// The number of [MemoryMapping]s in this MemoryMap.
|
||||||
pub len: u64,
|
pub len: u64,
|
||||||
|
/// The size of memory in pages.
|
||||||
pub size_pages: u64,
|
pub size_pages: u64,
|
||||||
|
/// The size of one page.
|
||||||
pub page_size: u64,
|
pub page_size: u64,
|
||||||
|
|
||||||
/// All sections.
|
/// All sections.
|
||||||
|
@ -51,12 +92,11 @@ pub struct MemoryMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryMap {
|
impl MemoryMap {
|
||||||
pub fn len(&self) -> u64 {
|
/// Resets the index of the iterator (sets self.idx to 0).
|
||||||
self.sections.len() as u64
|
|
||||||
}
|
|
||||||
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.
|
||||||
pub fn mem_size(&mut self) -> u64 {
|
pub fn mem_size(&mut self) -> u64 {
|
||||||
let curr_idx = self.idx;
|
let curr_idx = self.idx;
|
||||||
self.reset_iter();
|
self.reset_iter();
|
||||||
|
@ -87,10 +127,11 @@ impl core::iter::Iterator for MemoryMap {
|
||||||
type Item = MemoryMapping;
|
type Item = MemoryMapping;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
if self.sections.len()<=self.idx-1 {
|
if self.sections.len() <= self.idx - 1 {
|
||||||
|
self.reset_iter();
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(self.sections[self.idx-1].into())
|
Some(self.sections[self.idx - 1].into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Config-related stuff.
|
//! Config-related stuff.
|
||||||
//!
|
|
||||||
|
/// C
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cfg_int {
|
macro_rules! cfg_int {
|
||||||
($cfg:literal, $type:ident) => {
|
($cfg:literal, $type:ident) => {
|
|
@ -14,7 +14,7 @@ pub const COLOR_BLACK: Color = (0, true);
|
||||||
pub const COLOR_DEFAULT: Color = (1, true);
|
pub const COLOR_DEFAULT: Color = (1, true);
|
||||||
|
|
||||||
/// Some form of display that can be written to with text.
|
/// Some form of display that can be written to with text.
|
||||||
pub trait TextDisplay {
|
pub trait TextDisplay: core::fmt::Write {
|
||||||
/// Writes a single character to the specified position.
|
/// Writes a single character to the specified position.
|
||||||
fn write_char(&self, pos: (u32, u32), char: u8, color: Color) -> Result<(), crate::Error<'static>>;
|
fn write_char(&self, pos: (u32, u32), char: u8, color: Color) -> Result<(), crate::Error<'static>>;
|
||||||
/// Gets the size of the screen.
|
/// Gets the size of the screen.
|
|
@ -17,10 +17,11 @@ impl<'a> Error<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error<'_> {
|
impl Error<'_> {
|
||||||
|
/// Display the contents of the error on a [TextDisplay].
|
||||||
pub fn display_np(&self, display: &dyn TextDisplay) {
|
pub fn display_np(&self, display: &dyn TextDisplay) {
|
||||||
crate::output::terrorbnp(&crate::i16_as_u8_slice(self.code), display);
|
crate::output::terrorbnp(&crate::i16_as_u8_slice(self.code), display).unwrap();
|
||||||
crate::output::terrorsnp(": ", display);
|
crate::output::terrorsnp(": ", display).unwrap();
|
||||||
crate::output::terrorsnpln(self.message, display);
|
crate::output::terrorsnpln(self.message, display).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
62
kernel/src/kernel/indep_boot_entry.rs
Normal file
62
kernel/src/kernel/indep_boot_entry.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
//! The main code for the kernel.
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
#![allow(unexpected_cfgs)]
|
||||||
|
#![allow(static_mut_refs)]
|
||||||
|
|
||||||
|
use core::alloc::{Allocator, Layout};
|
||||||
|
|
||||||
|
use crate::{display::COLOR_DEFAULT, 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.
|
||||||
|
#[kernel_item(IndepBootEntry)]
|
||||||
|
pub fn indep_boot_entry(display: Option<&dyn crate::display::TextDisplay>, BI: &crate::boot::BootInfo) -> ! {
|
||||||
|
crate::arch::output::sdebugsln("Entrypoint called");
|
||||||
|
|
||||||
|
let display = display.unwrap();
|
||||||
|
|
||||||
|
display.clear_screen(COLOR_DEFAULT);
|
||||||
|
sreset();
|
||||||
|
|
||||||
|
let mut mem_map = BI.memory_map.unwrap();
|
||||||
|
let allocator_res = crate::mem::MemoryMapAlloc::new(&mut mem_map);
|
||||||
|
if allocator_res.is_err() {
|
||||||
|
panic!("{}", allocator_res.unwrap_err());
|
||||||
|
}
|
||||||
|
let allocator = allocator_res.unwrap();
|
||||||
|
|
||||||
|
tdebugsln("Testing allocator...", display).unwrap();
|
||||||
|
|
||||||
|
for size in MEM_TEST_SIZES {
|
||||||
|
tdebugs("Number of allocations: ", display).unwrap();
|
||||||
|
tdebugbnpln(&crate::u64_as_u8_slice(allocator.number_of_allocations()), display).unwrap();
|
||||||
|
|
||||||
|
tdebugs("Allocating ", display).unwrap();
|
||||||
|
tdebugbnp(&crate::usize_as_u8_slice(size), display).unwrap();
|
||||||
|
tdebugsnpln(" byte(s) of memory...", display).unwrap();
|
||||||
|
|
||||||
|
let allocation = allocator.allocate(Layout::from_size_align(size, 1).unwrap());
|
||||||
|
if let Err(_) = allocation {
|
||||||
|
terrors("Failed to allocate: ",display).unwrap();
|
||||||
|
unsafe { crate::mem::LAST_MEMMAP_ERR.unwrap_err().display_np(display) }
|
||||||
|
panic!("Allocation failure");
|
||||||
|
} else if let Ok(ptr) = allocation {
|
||||||
|
tdebugs("Successfully allocated! Address is ", display).unwrap();
|
||||||
|
tdebugbnp(&crate::usize_as_u8_slice(ptr.addr().get()), display).unwrap();
|
||||||
|
tdebugsnpln(".", display).unwrap();
|
||||||
|
tdebugsln("", display).unwrap();
|
||||||
|
tdebugsln("Deallocating memory...", display).unwrap();
|
||||||
|
unsafe { allocator.deallocate(ptr.as_non_null_ptr(), Layout::from_size_align(size, 1).unwrap()) }
|
||||||
|
if let Err(err) = unsafe { crate::mem::LAST_MEMMAP_ERR } {
|
||||||
|
terrors("Failed to deallocate: ", display).unwrap();
|
||||||
|
err.display_np(display);
|
||||||
|
panic!("Deallocation failure");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tdebugsln("", display).unwrap();
|
||||||
|
}
|
||||||
|
loop {}
|
||||||
|
}
|
|
@ -1,26 +1,34 @@
|
||||||
//! Memory allocation.
|
//! Memory allocation.
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
alloc::{Allocator, GlobalAlloc},
|
alloc::{Allocator, GlobalAlloc}, fmt::Debug, num::NonZero, ops::Range, ptr::{null_mut, NonNull}
|
||||||
num::NonZero,
|
|
||||||
ops::Range,
|
|
||||||
ptr::{NonNull, null_mut},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::boot::MemoryType;
|
use crate::boot::MemoryType;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
struct Allocation {
|
struct Allocation {
|
||||||
|
/// Whether this allocation is used. This is used so that the
|
||||||
|
/// entire allocation table doesn't need to be shifted back
|
||||||
|
/// on every allocation.
|
||||||
pub used: bool,
|
pub used: bool,
|
||||||
|
/// The starting address of the allocation.
|
||||||
pub addr: u64,
|
pub addr: u64,
|
||||||
|
/// The length of the allocation.
|
||||||
pub len: u64,
|
pub len: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
struct AllocationHeader {
|
struct AllocationHeader {
|
||||||
|
/// Whether this allocation table is used. Kept for parity with [Allocation]s.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub used: bool,
|
pub used: bool,
|
||||||
|
/// The starting address of the allocation table.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub addr: u64,
|
pub addr: u64,
|
||||||
|
/// The length in bytes of the allocation table.
|
||||||
pub len: u64,
|
pub len: u64,
|
||||||
|
/// The number of allocations in the allocation table.
|
||||||
pub num_allocations: u64,
|
pub num_allocations: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +41,16 @@ struct AllocationIter {
|
||||||
impl Iterator for AllocationIter {
|
impl Iterator for AllocationIter {
|
||||||
type Item = *mut Allocation;
|
type Item = *mut Allocation;
|
||||||
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
||||||
if self.idx >= self.num_allocations {
|
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(self.num_allocations));
|
||||||
|
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(self.idx));
|
||||||
|
self.idx += 1;
|
||||||
|
if self.idx > self.num_allocations {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
crate::arch::output::sdebugsln("Providing allocation from iterator");
|
||||||
|
|
||||||
Some(&unsafe {
|
Some(&unsafe {
|
||||||
*((self.ptr as usize + (size_of::<Allocation>() * self.idx as usize))
|
*((self.ptr as usize + (size_of::<Allocation>() * (self.idx as usize-1)))
|
||||||
as *const Allocation)
|
as *const Allocation)
|
||||||
} as *const Allocation as *mut Allocation)
|
} as *const Allocation as *mut Allocation)
|
||||||
}
|
}
|
||||||
|
@ -68,6 +81,15 @@ 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.
|
||||||
const EXTEND_ALLOCATION_OTHER_ALLOCATION: i16 = -6;
|
const EXTEND_ALLOCATION_OTHER_ALLOCATION: i16 = -6;
|
||||||
|
|
||||||
|
impl<'a> Debug for MemoryMapAlloc<'a> {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.write_str("MemoryMapAlloc with ")?;
|
||||||
|
f.write_str(core::str::from_utf8(&crate::u64_as_u8_slice(unsafe { *self.allocationheader }.num_allocations)).unwrap())?;
|
||||||
|
f.write_str(" allocations")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 uses the memory mapping to
|
/// This method uses the memory mapping to
|
||||||
|
@ -82,6 +104,8 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
};
|
};
|
||||||
out.memory_map.reset_iter();
|
out.memory_map.reset_iter();
|
||||||
for mapping in &mut *out.memory_map {
|
for mapping in &mut *out.memory_map {
|
||||||
|
mapping.output();
|
||||||
|
crate::arch::output::sdebugsnpln("");
|
||||||
if mapping.len < (size_of::<Allocation>() * 32) as u64 {
|
if mapping.len < (size_of::<Allocation>() * 32) as u64 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -125,12 +149,17 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
used: true,
|
used: true,
|
||||||
addr: out.allocations as usize as u64,
|
addr: out.allocations as usize as u64,
|
||||||
len: (size_of::<Allocation>() * 32) as u64,
|
len: (size_of::<Allocation>() * 32) as u64,
|
||||||
num_allocations: 0
|
num_allocations: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the number of allocations.
|
||||||
|
pub fn number_of_allocations(&self) -> u64 {
|
||||||
|
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 {
|
||||||
AllocationIter {
|
AllocationIter {
|
||||||
|
@ -142,17 +171,12 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
|
|
||||||
/// Add an allocation to [MemoryMapAlloc::allocations]. It will overwrite allocations with `used` set to false.
|
/// Add an allocation to [MemoryMapAlloc::allocations]. It will overwrite allocations with `used` set to false.
|
||||||
fn add_allocation(&self, allocation: Allocation) -> Result<(), crate::Error<'static>> {
|
fn add_allocation(&self, allocation: Allocation) -> Result<(), crate::Error<'static>> {
|
||||||
let mut created_allocation = false;
|
|
||||||
for alloc in self.allocations_iter() {
|
for alloc in self.allocations_iter() {
|
||||||
if !unsafe { *alloc }.used {
|
if !unsafe { *alloc }.used {
|
||||||
unsafe { (*alloc) = allocation }
|
unsafe { (*alloc) = allocation }
|
||||||
created_allocation = true;
|
return Ok(());
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if created_allocation {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { *self.allocationheader }.num_allocations += 1;
|
unsafe { *self.allocationheader }.num_allocations += 1;
|
||||||
|
|
||||||
|
@ -168,7 +192,7 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = self.extend_allocation(0, size_of::<Allocation>() as u64);
|
let res = self.extend_allocation_header(size_of::<Allocation>() as u64);
|
||||||
if let Err(err) = res {
|
if let Err(err) = res {
|
||||||
unsafe { *self.allocationheader }.num_allocations -= 1;
|
unsafe { *self.allocationheader }.num_allocations -= 1;
|
||||||
return Err(err);
|
return Err(err);
|
||||||
|
@ -186,7 +210,6 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
|
|
||||||
/// Extend an allocation. This has numerous checks, so please use this
|
/// Extend an allocation. This has numerous checks, so please use this
|
||||||
/// instead of manually changing [Allocation::len]!
|
/// instead of manually changing [Allocation::len]!
|
||||||
#[inline(always)]
|
|
||||||
fn extend_allocation(&self, idx: u64, by: u64) -> Result<(), crate::Error<'static>> {
|
fn extend_allocation(&self, idx: u64, by: u64) -> Result<(), crate::Error<'static>> {
|
||||||
if idx > unsafe { *self.allocationheader }.num_allocations {
|
if idx > unsafe { *self.allocationheader }.num_allocations {
|
||||||
return Err(crate::Error::new(
|
return Err(crate::Error::new(
|
||||||
|
@ -220,11 +243,35 @@ impl<'a> MemoryMapAlloc<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extend the allocation header. This has numerous checks, so please use this
|
||||||
|
/// instead of manually changing [AllocationHeader::len]!
|
||||||
|
fn extend_allocation_header(&self, by: u64) -> Result<(), crate::Error<'static>> {
|
||||||
|
let alloc = self.allocationheader;
|
||||||
|
|
||||||
|
if self.check_range(
|
||||||
|
(unsafe { *alloc }.addr + unsafe { *alloc }.len)
|
||||||
|
..(unsafe { *alloc }.addr + unsafe { *alloc }.len + by),
|
||||||
|
) {
|
||||||
|
return Err(crate::Error::new(
|
||||||
|
"the allocation header, if extended, would extend into another allocation",
|
||||||
|
EXTEND_ALLOCATION_OTHER_ALLOCATION,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(*alloc).len += by;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// 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 addr >= (self.allocationheader as u64) && addr < (self.allocationheader as u64+unsafe { *self.allocationheader }.len) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
for ele in self.allocations_iter() {
|
for ele in self.allocations_iter() {
|
||||||
let alloc = unsafe { *ele };
|
let alloc = unsafe { *ele };
|
||||||
if addr > alloc.addr && addr < alloc.addr + alloc.len {
|
if addr >= alloc.addr && addr < alloc.addr + alloc.len {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +302,7 @@ unsafe impl<'a> GlobalAlloc for MemoryMapAlloc<'a> {
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
return null_mut();
|
return null_mut();
|
||||||
}
|
}
|
||||||
result.unwrap().as_mut_ptr() as *mut u8
|
result.unwrap().as_mut_ptr()
|
||||||
}
|
}
|
||||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -299,11 +346,24 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
||||||
}
|
}
|
||||||
if allocatable {
|
if allocatable {
|
||||||
addr = mapping.start+mapping.len-layout.size() as u64;
|
addr = mapping.start+mapping.len-layout.size() as u64;
|
||||||
while self.check_range(addr..addr+layout.size() as u64) && (addr as usize % layout.align() != 0) {
|
while self.check_range(addr..addr+layout.size() as u64) && (addr as usize % layout.align() != 0) && addr >= mapping.start {
|
||||||
addr -= layout.size() as u64/crate::cfg_int!("CONFIG_ALLOC_PRECISION", u64);
|
addr -= layout.size() as u64/crate::cfg_int!("CONFIG_ALLOC_PRECISION", u64);
|
||||||
}
|
}
|
||||||
|
if (!self.check_range(addr..addr+layout.size() as u64)) && (addr as usize % layout.align() == 0) && addr >= mapping.start {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if addr == 0 {
|
||||||
|
unsafe {
|
||||||
|
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
||||||
|
"Free memory of the correct size and alignment couldn't be found",
|
||||||
|
FREE_MEMORY_UNAVAILABLE,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
return Err(core::alloc::AllocError {});
|
||||||
|
}
|
||||||
if let Err(err) = self.add_allocation(Allocation { used: true, addr, len: layout.size() as u64 }) {
|
if let Err(err) = self.add_allocation(Allocation { used: true, addr, len: layout.size() as u64 }) {
|
||||||
unsafe { LAST_MEMMAP_ERR = Err(err) }
|
unsafe { LAST_MEMMAP_ERR = Err(err) }
|
||||||
return Err(core::alloc::AllocError {});
|
return Err(core::alloc::AllocError {});
|
||||||
|
@ -314,13 +374,10 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
||||||
layout.size(),
|
layout.size(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn deallocate(&self, ptr: core::ptr::NonNull<u8>, _layout: core::alloc::Layout) {
|
unsafe fn deallocate(&self, ptr: core::ptr::NonNull<u8>, _layout: core::alloc::Layout) {
|
||||||
unsafe { LAST_MEMMAP_ERR = Ok(()) }
|
unsafe { LAST_MEMMAP_ERR = Ok(()) }
|
||||||
let addr = ptr.addr().get() as u64;
|
let addr = ptr.addr().get() as u64;
|
||||||
if !self.check_addr(addr) { // Memory not allocated, something is up
|
|
||||||
unsafe { LAST_MEMMAP_ERR = Err(crate::Error::new("memory not allocated", MEMORY_NOT_ALLOCATED)) }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if self.allocations == core::ptr::null_mut() {
|
if self.allocations == core::ptr::null_mut() {
|
||||||
unsafe {
|
unsafe {
|
||||||
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
||||||
|
@ -330,14 +387,21 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(unsafe { *self.allocationheader }.num_allocations));
|
||||||
for allocation in self.allocations_iter() {
|
for allocation in self.allocations_iter() {
|
||||||
if !unsafe { *allocation }.used {
|
crate::arch::output::sdebugsln("Allocation");
|
||||||
|
let alloc = unsafe { *allocation }.clone();
|
||||||
|
if !alloc.used {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if unsafe { *allocation }.addr == addr {
|
crate::arch::output::sdebugsln("Used");
|
||||||
|
if alloc.addr == addr {
|
||||||
unsafe { *allocation }.used = false;
|
unsafe { *allocation }.used = false;
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Memory not allocated, something is up, this is put after the loop to prevent a costly call to check_addr
|
||||||
|
unsafe { LAST_MEMMAP_ERR = Err(crate::Error::new("memory not allocated", MEMORY_NOT_ALLOCATED)) }
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
//! 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)]
|
||||||
|
// tidy-alphabetical-start
|
||||||
#![feature(ptr_metadata)]
|
#![feature(ptr_metadata)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(f128)]
|
#![feature(f128)]
|
||||||
|
@ -8,26 +9,28 @@
|
||||||
#![feature(allocator_api)]
|
#![feature(allocator_api)]
|
||||||
#![feature(slice_ptr_get)]
|
#![feature(slice_ptr_get)]
|
||||||
#![feature(nonnull_provenance)]
|
#![feature(nonnull_provenance)]
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
#![allow(internal_features)]
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
// tidy-alphabetical-end
|
||||||
|
|
||||||
mod constants;
|
pub mod indep_boot_entry;
|
||||||
mod util;
|
|
||||||
pub mod multiboot2;
|
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
mod errors;
|
|
||||||
pub mod _entry;
|
|
||||||
mod traits;
|
|
||||||
pub mod output;
|
|
||||||
pub mod boot;
|
pub mod boot;
|
||||||
pub mod psfont;
|
|
||||||
pub mod display;
|
|
||||||
pub mod cmdline;
|
pub mod cmdline;
|
||||||
|
mod constants;
|
||||||
|
pub mod display;
|
||||||
|
mod errors;
|
||||||
pub mod mem;
|
pub mod mem;
|
||||||
|
pub mod multiboot2;
|
||||||
|
pub mod output;
|
||||||
|
pub mod psfont;
|
||||||
|
mod traits;
|
||||||
|
mod util;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod cfg;
|
mod cfg;
|
||||||
|
|
||||||
pub use cfg::*;
|
|
||||||
|
|
||||||
#[allow(unused_imports)] // if there are no constants, then it gives a warning
|
#[allow(unused_imports)] // if there are no constants, then it gives a warning
|
||||||
pub use constants::*;
|
pub use constants::*;
|
||||||
|
|
||||||
|
@ -35,4 +38,4 @@ pub use errors::*;
|
||||||
pub use util::*;
|
pub use util::*;
|
||||||
|
|
||||||
#[allow(unused_imports)] // if there are no traits, then it gives a warning
|
#[allow(unused_imports)] // if there are no traits, then it gives a warning
|
||||||
pub use traits::*;
|
pub use traits::*;
|
|
@ -91,17 +91,11 @@ pub struct MemoryMap {
|
||||||
pub entry_size: u32,
|
pub entry_size: u32,
|
||||||
/// All sections.
|
/// All sections.
|
||||||
pub sections: &'static [crate::boot::MemoryMapping],
|
pub sections: &'static [crate::boot::MemoryMapping],
|
||||||
/// Iterator's index.
|
|
||||||
pub idx: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryMap {
|
impl MemoryMap {
|
||||||
pub fn reset_iter(&mut self) {
|
/// The size of allocatable memory in bytes.
|
||||||
self.idx = 0;
|
|
||||||
}
|
|
||||||
pub fn mem_size(&mut self) -> u64 {
|
pub fn mem_size(&mut self) -> u64 {
|
||||||
let curr_idx = self.idx;
|
|
||||||
self.reset_iter();
|
|
||||||
let mut out = 0u64;
|
let mut out = 0u64;
|
||||||
for ele in self.sections {
|
for ele in self.sections {
|
||||||
if ele.mem_type == crate::boot::MemoryType::Free {
|
if ele.mem_type == crate::boot::MemoryType::Free {
|
||||||
|
@ -112,7 +106,6 @@ impl MemoryMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.idx = curr_idx;
|
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
use paste::paste;
|
use paste::paste;
|
||||||
use crate::display::COLOR_DEFAULT;
|
use crate::display::COLOR_DEFAULT;
|
||||||
|
|
||||||
|
/// The position to output stuff to.
|
||||||
static mut OUTPUT_TERM_POSITION: (u32, u32) = (0, 0);
|
static mut OUTPUT_TERM_POSITION: (u32, u32) = (0, 0);
|
||||||
|
|
||||||
macro_rules! message_funcs {
|
macro_rules! message_funcs {
|
|
@ -90,56 +90,74 @@ pub const fn u64_as_u8_slice(mut value: u64) -> [u8; 20] {
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an &mut \[u8] to a i16. `value` is clobbered.
|
/// Converts an &mut \[u8] to a i16.
|
||||||
pub fn str_as_i16(mut value: &mut [u8]) -> i16 {
|
pub fn str_as_i16(mut value: &[u8]) -> i16 {
|
||||||
let mut out = 0i16;
|
let mut out = 0i16;
|
||||||
let negative = core::str::from_utf8(value).unwrap().starts_with("-");
|
let negative = core::str::from_utf8(value).unwrap().starts_with("-");
|
||||||
if negative {
|
if negative {
|
||||||
value = &mut value[1..];
|
value = &value[1..];
|
||||||
}
|
}
|
||||||
value.reverse();
|
|
||||||
for byte in value {
|
for byte in value {
|
||||||
let byte = *byte;
|
let byte = *byte;
|
||||||
if byte == b'_' {
|
if byte < b'0' || byte > b'9' {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out *= 10;
|
out *= 10;
|
||||||
out += (byte-b'0') as i16;
|
out += (byte-b'0') as i16;
|
||||||
}
|
}
|
||||||
if negative {
|
|
||||||
out = -out;
|
let mut reversed = 0;
|
||||||
|
|
||||||
|
while out != 0 {
|
||||||
|
reversed = reversed * 10 + out % 10;
|
||||||
|
out /= 10;
|
||||||
}
|
}
|
||||||
out
|
|
||||||
|
reversed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an &mut \[u8] to a u32. `value` is clobbered.
|
/// Converts an &mut \[u8] to a u32.
|
||||||
pub fn str_as_u32(value: &mut [u8]) -> u32 {
|
pub fn str_as_u32(value: &[u8]) -> u32 {
|
||||||
let mut out = 0u32;
|
let mut out = 0u32;
|
||||||
value.reverse();
|
|
||||||
for byte in value {
|
for byte in value {
|
||||||
let byte = *byte;
|
let byte = *byte;
|
||||||
if byte == b'_' {
|
if byte < b'0' || byte > b'9' {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out *= 10;
|
out *= 10;
|
||||||
out += (byte-b'0') as u32;
|
out += (byte-b'0') as u32;
|
||||||
}
|
}
|
||||||
out
|
|
||||||
|
let mut reversed = 0;
|
||||||
|
|
||||||
|
while out != 0 {
|
||||||
|
reversed = reversed * 10 + out % 10;
|
||||||
|
out /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
reversed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an &mut \[u8] to a u128. `value` is clobbered.
|
/// Converts an &mut \[u8] to a u128.
|
||||||
pub fn str_as_u128(value: &mut [u8]) -> u128 {
|
pub fn str_as_u128(value: &[u8]) -> u128 {
|
||||||
let mut out = 0u128;
|
let mut out = 0u128;
|
||||||
value.reverse();
|
|
||||||
for byte in value {
|
for byte in value {
|
||||||
let byte = *byte;
|
let byte = *byte;
|
||||||
if byte == b'_' {
|
if byte < b'0' || byte > b'9' {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out *= 10;
|
out *= 10;
|
||||||
out += (byte-b'0') as u128;
|
out += (byte-b'0') as u128;
|
||||||
}
|
}
|
||||||
out
|
|
||||||
|
let mut reversed = 0;
|
||||||
|
|
||||||
|
while out != 0 {
|
||||||
|
reversed = reversed * 10 + out % 10;
|
||||||
|
out /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
reversed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an &mut \[u8] to a u64.
|
/// Converts an &mut \[u8] to a u64.
|
59
kernel/src/proc_macros/mod.rs
Normal file
59
kernel/src/proc_macros/mod.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::{quote_spanned, ToTokens};
|
||||||
|
use syn::{parse::{Parse, ParseStream}, spanned::Spanned, ItemFn, Signature, Token};
|
||||||
|
|
||||||
|
struct KernelItemNameInput {
|
||||||
|
item: aphrodite_common::KernelItem
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for KernelItemNameInput {
|
||||||
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
|
let item: aphrodite_common::KernelItem = input.parse()?;
|
||||||
|
Ok(KernelItemNameInput { item })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_tokens(signature: Signature, tokens: &mut TokenStream) {
|
||||||
|
signature.constness.to_tokens(&mut (*tokens).clone().into());
|
||||||
|
signature.asyncness.to_tokens(&mut (*tokens).clone().into());
|
||||||
|
signature.unsafety.to_tokens(&mut (*tokens).clone().into());
|
||||||
|
signature.abi.to_tokens(&mut (*tokens).clone().into());
|
||||||
|
signature.fn_token.to_tokens(&mut (*tokens).clone().into());
|
||||||
|
signature.generics.to_tokens(&mut (*tokens).clone().into());
|
||||||
|
signature.paren_token.surround(&mut (*tokens).clone().into(), |tokens| {
|
||||||
|
signature.inputs.to_tokens(tokens);
|
||||||
|
if let Some(variadic) = &signature.variadic {
|
||||||
|
if !signature.inputs.empty_or_trailing() {
|
||||||
|
<Token![,]>::default().to_tokens(tokens);
|
||||||
|
}
|
||||||
|
variadic.to_tokens(tokens);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
signature.output.to_tokens(&mut (*tokens).clone().into());
|
||||||
|
signature.generics.where_clause.to_tokens(&mut (*tokens).clone().into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_token_stream(signature: Signature) -> TokenStream {
|
||||||
|
let mut tokens = proc_macro::TokenStream::new();
|
||||||
|
to_tokens(signature, &mut tokens);
|
||||||
|
tokens.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement a kernel item.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn kernel_item(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let item_name_input: KernelItemNameInput = syn::parse_macro_input!(attr);
|
||||||
|
let item_name = format!("{:?}", item_name_input.item);
|
||||||
|
|
||||||
|
let input_fn: ItemFn = syn::parse_macro_input!(item as ItemFn);
|
||||||
|
let fn_name = input_fn.clone().sig.ident;
|
||||||
|
let fn_sig = to_token_stream(input_fn.clone().sig);
|
||||||
|
|
||||||
|
quote_spanned!(input_fn.span()=>{
|
||||||
|
// The #item_name kernel item.
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
pub const #item_name: #fn_sig = #fn_name;
|
||||||
|
|
||||||
|
#input_fn
|
||||||
|
}).into()
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue