Worked on build script a bunch, added format script and formatted everything

This commit is contained in:
Arthur Beck 2025-02-16 20:32:36 -06:00
parent 7ae1677a87
commit 884e9aa3cf
Signed by: ArthurB
GPG key ID: ACE3D14F5CEF14BF
33 changed files with 393 additions and 272 deletions

View file

@ -21,7 +21,3 @@ path = "src/arch_boot_entry/x86.rs"
[lib] [lib]
name = "aphrodite" name = "aphrodite"
path = "src/kernel/mod.rs" path = "src/kernel/mod.rs"
[[test]]
name = "test_aphrodite"
path = "src/include/test.rs"

View file

@ -1,29 +1,33 @@
#!/bin/bash #!/bin/bash
( (
set -o errexit -o pipefail -o noclobber flags=$-
set -o pipefail -o noclobber
HAVE_GETOPT=true HAVE_GETOPT="${HAVE_GETOPT:-true}"
getopt --test > /dev/null && true getopt --test > /dev/null && true
if [[ $? -ne 4 ]]; then if [[ $? -ne 4 && $HAVE_GETOPT ]]; then
if [[ -n "EXIT_WITHOUT_GETOPT" ]]; then if [[ -n "EXIT_WITHOUT_GETOPT" ]]; then
echo '`getopt --test` failed. Exiting.' echo '[ERROR] `getopt --test` failed. Exiting.'
exit 1 exit 1
else else
echo '`getopt --test` failed. Continuing and ignoring command line flags. (note that $1 will still be used for the target)' echo '[WARN] `getopt --test` failed. Continuing and ignoring command line flags. (note that $1 will still be used for the target)'
echo '(to exit instead of ignoring, set the environment variable `EXIT_WITHOUT_GETOPT` to a non-null value)' echo '[WARN] (to exit instead of ignoring, set the environment variable `EXIT_WITHOUT_GETOPT` to a non-null value)'
HAVE_GETOPT=false HAVE_GETOPT=false
fi fi
fi fi
set -o errexit # put down here as getopt returns error code four if it's working, and it probably would work otherwise, but I'm not taking chances
check=false check=false
format=false
if [[ "$HAVE_GETOPT" = "true" ]]; then if [[ "$HAVE_GETOPT" = "true" ]]; then
LONGOPTS=check LONGOPTS=check,format
OPTIONS=c OPTIONS=cf
PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") || ( PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") || (
echo '`getopt` failed to parse command line arguments. Check the arguments passed.' echo '[ERROR] Failed to parse command line arguments. If your getopt is broken, set HAVE_GETOPT=true.'
exit 1 exit 1
) )
eval set -- "$PARSED" eval set -- "$PARSED"
@ -34,6 +38,10 @@
check=true check=true
shift shift
;; ;;
-f|--format)
format=true
shift
;;
--) --)
shift shift
break break
@ -44,6 +52,12 @@
;; ;;
esac esac
done done
if [[ $check == "true" && $format == "true" ]]; then
echo "[WARN] Both --check and --format were passed."
echo "[WARN] Interpretting as only --format, as format will also check that Aphrokern can compile."
check=false
fi
fi fi
export KERNEL_DIR=$(readlink -e .) export KERNEL_DIR=$(readlink -e .)
@ -79,11 +93,11 @@
function compile_one { function compile_one {
target=$1 target=$1
real_target=${!target} real_target=${!target}
real_target=$(basename $real_target)
echo "Compiling target $target(with rust target of $real_target)"
if [[ $check = "true" ]]; then if [[ $check = "true" ]]; then
echo "[INFO] Checking target $target(with rust target of $real_target)"
cargo check --target "$real_target" --release -Zbuild-std=core,alloc --bin entrypoint_$target cargo check --target "$real_target" --release -Zbuild-std=core,alloc --bin entrypoint_$target
else else
echo "[INFO] Compiling target $target(with rust target of $real_target)"
cargo build --target "$real_target" --release -Zbuild-std=core,alloc --bin entrypoint_$target cargo build --target "$real_target" --release -Zbuild-std=core,alloc --bin entrypoint_$target
cp "target/$(echo $real_target | sed 's/\.json//')/release/entrypoint_$target" kernel-$target cp "target/$(echo $real_target | sed 's/\.json//')/release/entrypoint_$target" kernel-$target
@ -103,6 +117,12 @@
fi fi
} }
if [[ $format = "true" ]]; then
echo "[INFO] Formatting"
cargo fmt --all
exit 0
fi
if [[ $# -ge 1 ]]; then if [[ $# -ge 1 ]]; then
echo "[INFO] Compiling only target $1" echo "[INFO] Compiling only target $1"
compile_one $1 compile_one $1
@ -114,4 +134,5 @@
done done
reset_version_vars reset_version_vars
set +$flags
) )

View file

@ -2,21 +2,41 @@ fn main() {
let env = std::env::vars(); let env = std::env::vars();
// Begin checks // Begin checks
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_DISABLE_MULTIBOOT2_SUPPORT, values("true", "false", none()))"#); println!(
r#"cargo:rustc-check-cfg=cfg(CONFIG_DISABLE_MULTIBOOT2_SUPPORT, values("true", "false", none()))"#
);
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_HALT_ON_PANIC, values("true", "false", none()))"#); println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_HALT_ON_PANIC, values("true", "false", none()))"#);
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_SPIN_ON_PANIC, values("true", "false", none()))"#); println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_SPIN_ON_PANIC, values("true", "false", none()))"#);
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH, values("true", "false", none()))"#); println!(
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH, values("true", "false", none()))"#); r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH, values("true", "false", none()))"#
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_WARN_ON_INVALID_LENGTH, values("true", "false", none()))"#); );
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH, values("true", "false", none()))"#); println!(
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH, values("true", "false", none()))"#
);
println!(
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_WARN_ON_INVALID_LENGTH, values("true", "false", none()))"#
);
println!(
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH, values("true", "false", none()))"#
);
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_DEBUG, values("true", "false", none()))"#); println!(
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_INFO, values("true", "false", none()))"#); r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_DEBUG, values("true", "false", none()))"#
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_WARN, values("true", "false", none()))"#); );
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_ERROR, values("true", "false", none()))"#); println!(
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_FATAL, values("true", "false", none()))"#); r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_INFO, values("true", "false", none()))"#
);
println!(
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_WARN, values("true", "false", none()))"#
);
println!(
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_ERROR, values("true", "false", none()))"#
);
println!(
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_FATAL, values("true", "false", none()))"#
);
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_BUILD_GRUB, values("true", "false", none()))"#); println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_BUILD_GRUB, values("true", "false", none()))"#);
// End checks // End checks
@ -26,7 +46,7 @@ fn main() {
for (var, val) in env { for (var, val) in env {
if !var.starts_with("CONFIG_") { if !var.starts_with("CONFIG_") {
continue continue;
} }
println!("cargo:rerun-if-env-changed={}", var); println!("cargo:rerun-if-env-changed={}", var);
println!("cargo:rustc-cfg={}=\"{}\"", var, val); println!("cargo:rustc-cfg={}=\"{}\"", var, val);

View file

@ -1,3 +0,0 @@
#!/bin/bash
RUSTFLAGS='-Clink-arg=--script=link.x' cargo expand --target i686-unknown-none.json --release -Zbuild-std --bin entrypoint_x86

7
kernel/format Executable file
View file

@ -0,0 +1,7 @@
#!/bin/bash
(
set -o errexit -o pipefail -o noclobber
./build --format $!
)

View file

@ -1,3 +1,5 @@
#!/bin/bash
function get_version() { function get_version() {
local TEMP_SUFFIX local TEMP_SUFFIX
if git add . && git diff --quiet && git diff --cached --quiet if git add . && git diff --quiet && git diff --cached --quiet

View file

@ -9,15 +9,17 @@
#![feature(cfg_match)] #![feature(cfg_match)]
#![feature(formatting_options)] #![feature(formatting_options)]
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
use core::fmt::Debug; use core::fmt::Debug;
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
use aphrodite::boot::{BootInfo, MemoryMapping}; use aphrodite::arch::egatext;
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::boot::{BootInfo, MemoryMapping};
use aphrodite::output::*;
use aphrodite::display::COLOR_DEFAULT; use aphrodite::display::COLOR_DEFAULT;
use aphrodite::multiboot2::{
FramebufferInfo, MemoryMap, MemorySection, RawMemoryMap, RootTag, Tag,
};
use aphrodite::output::*;
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))] #[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
#[unsafe(link_section = ".bootheader")] #[unsafe(link_section = ".bootheader")]
@ -27,7 +29,6 @@ static MULTIBOOT2_HEADER: [u8; 24] = [
0x00, 0x00, 0x00, 0x00, // Architecture 0x00, 0x00, 0x00, 0x00, // Architecture
0x18, 0x00, 0x00, 0x00, // Size 0x18, 0x00, 0x00, 0x00, // Size
0x12, 0xaf, 0xad, 0x17, // Checksum 0x12, 0xaf, 0xad, 0x17, // Checksum
0x00, 0x00, // End tag 0x00, 0x00, // End tag
0x00, 0x00, // Flags 0x00, 0x00, // Flags
0x08, 0x00, 0x00, 0x00, // Size 0x08, 0x00, 0x00, 0x00, // Size
@ -45,7 +46,8 @@ static mut MM: MemoryMap = MemoryMap {
sections: &[], sections: &[],
}; };
static mut FBI: aphrodite::arch::egatext::FramebufferInfo = aphrodite::arch::egatext::FramebufferInfo { static mut FBI: aphrodite::arch::egatext::FramebufferInfo =
aphrodite::arch::egatext::FramebufferInfo {
address: 0, address: 0,
pitch: 0, pitch: 0,
width: 0, width: 0,
@ -61,7 +63,8 @@ static mut MAGIC: u32 = 0xFFFFFFFF;
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
#[aphrodite_proc_macros::kernel_item(ArchBootEntry)] #[aphrodite_proc_macros::kernel_item(ArchBootEntry)]
extern "C" fn _start() -> ! { extern "C" fn _start() -> ! {
unsafe { // Copy values provided by the bootloader out 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. // 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) // (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. // we force using ebx and eax as the output of an empty assembly block to let it know.
@ -81,7 +84,8 @@ extern "C" fn _start() -> ! {
unsafe { unsafe {
match MAGIC { match MAGIC {
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))] #[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
0x36D76289 => { // Multiboot2 0x36D76289 => {
// Multiboot2
RT = O as *const RootTag; // This is unsafe rust! We can do whatever we want! *manical laughter* RT = O as *const RootTag; // This is unsafe rust! We can do whatever we want! *manical laughter*
sdebugs("Total boot info length is "); sdebugs("Total boot info length is ");
@ -92,7 +96,8 @@ extern "C" fn _start() -> ! {
sdebugbnp(&aphrodite::usize_as_u8_slice(O as usize)); sdebugbnp(&aphrodite::usize_as_u8_slice(O as usize));
sdebugunp(b'\n'); sdebugunp(b'\n');
if (*RT).total_len<16 { // Size of root tag+size of terminating tag. Something's up. if (*RT).total_len < 16 {
// Size of root tag+size of terminating tag. Something's up.
panic!("total length < 16") panic!("total length < 16")
} }
@ -116,24 +121,32 @@ extern "C" fn _start() -> ! {
sdebugbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_len)); sdebugbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_len));
match current_tag.tag_type { match current_tag.tag_type {
0 => { // Ending tag 0 => {
if current_tag.tag_len != 8 { // Unexpected size, something is probably up // Ending tag
if current_tag.tag_len != 8 {
// Unexpected size, something is probably up
panic!("size of ending tag != 8"); panic!("size of ending tag != 8");
} }
break break;
}, }
4 => { // Basic memory information 4 => {
if current_tag.tag_len != 16 { // Unexpected size, something is probably up // Basic memory information
if current_tag.tag_len != 16 {
// Unexpected size, something is probably up
panic!("size of basic memory information tag != 16"); panic!("size of basic memory information tag != 16");
} }
}, }
5 => { // BIOS boot device, ignore 5 => {
if current_tag.tag_len != 20 { // Unexpected size, something is probably up // BIOS boot device, ignore
if current_tag.tag_len != 20 {
// Unexpected size, something is probably up
panic!("size of bios boot device tag != 20"); panic!("size of bios boot device tag != 20");
} }
}, }
1 => { // Command line 1 => {
if current_tag.tag_len < 8 { // Unexpected size, something is probably up // Command line
if current_tag.tag_len < 8 {
// Unexpected size, something is probably up
panic!("size of command line tag < 8"); panic!("size of command line tag < 8");
} }
let cstring = CStr::from_ptr((ptr + 8) as *const i8); let cstring = CStr::from_ptr((ptr + 8) as *const i8);
@ -141,13 +154,16 @@ 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 => { // Memory map tag 6 => {
if current_tag.tag_len < 16 { // Unexpected size, something is probably up // Memory map tag
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: *mut RawMemoryMap = core::ptr::from_raw_parts_mut( let rawmemorymap: *mut RawMemoryMap = core::ptr::from_raw_parts_mut(
ptr as *mut 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
@ -169,12 +185,14 @@ extern "C" fn _start() -> ! {
size_pages: 1, size_pages: 1,
page_size: MM.mem_size(), page_size: MM.mem_size(),
sections: MM.sections, sections: MM.sections,
idx: 0 idx: 0,
}; };
BI.memory_map = Some(mm2); BI.memory_map = Some(mm2);
}, }
2 => { // Bootloader name 2 => {
if current_tag.tag_len < 8 { // Unexpected size, something is probably up // Bootloader name
if current_tag.tag_len < 8 {
// Unexpected size, something is probably up
panic!("size of command line tag < 8"); panic!("size of command line tag < 8");
} }
let cstring = CStr::from_ptr((ptr + 8) as *const i8); let cstring = CStr::from_ptr((ptr + 8) as *const i8);
@ -182,21 +200,26 @@ 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 => { // Framebuffer info 8 => {
if current_tag.tag_len < 32 { // Unexpected size, something is probably up // Framebuffer info
if current_tag.tag_len < 32 {
// Unexpected size, something is probably up
panic!("size of framebuffer info tag < 32"); panic!("size of framebuffer info tag < 32");
} }
let framebufferinfo: *const FramebufferInfo = (ptr as usize + size_of::<Tag>()) as *const FramebufferInfo; let framebufferinfo: *const FramebufferInfo =
(ptr as usize + size_of::<Tag>()) as *const FramebufferInfo;
match (*framebufferinfo).fb_type { match (*framebufferinfo).fb_type {
0 => { // Indexed 0 => {
// Indexed
panic!("Indexed color is unimplemented"); panic!("Indexed color is unimplemented");
}, }
1 => { // RGB 1 => {
// 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")
} }
@ -212,8 +235,9 @@ 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));
} }
@ -242,8 +266,9 @@ 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");
} }
} }
@ -261,7 +286,9 @@ extern "C" fn _start() -> ! {
sdebugs("Framebuffer pitch: "); sdebugs("Framebuffer pitch: ");
sdebugbnpln(&aphrodite::u32_as_u8_slice(framebuffer_info.pitch)); sdebugbnpln(&aphrodite::u32_as_u8_slice(framebuffer_info.pitch));
sdebugs("Framebuffer address: "); sdebugs("Framebuffer address: ");
sdebugbnpln(&aphrodite::usize_as_u8_slice(framebuffer_info.address as usize)); sdebugbnpln(&aphrodite::usize_as_u8_slice(
framebuffer_info.address as usize,
));
sdebugs("Framebuffer bpp: "); sdebugs("Framebuffer bpp: ");
sdebugbnpln(&aphrodite::u8_as_u8_slice(framebuffer_info.bpp)); sdebugbnpln(&aphrodite::u8_as_u8_slice(framebuffer_info.bpp));
@ -293,8 +320,9 @@ fn halt_on_panic(info: &PanicInfo) -> ! {
sfatalsnp(":"); sfatalsnp(":");
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line())); sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
sfatalsnp(":"); sfatalsnp(":");
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().column())); sfatalbnpln(&aphrodite::u32_as_u8_slice(
sfatalsnp(": "); info.location().unwrap().column(),
));
} else { } else {
sfatals("Panic: "); sfatals("Panic: ");
} }
@ -308,7 +336,7 @@ fn halt_on_panic(info: &PanicInfo) -> ! {
#[unsafe(link_section = ".panic")] #[unsafe(link_section = ".panic")]
#[panic_handler] #[panic_handler]
#[cfg(all(CONFIG_SPIN_ON_PANIC = "true", CONFIG_PREUSER_HALT_ON_PANIC = "false"))] #[cfg(all(CONFIG_SPIN_ON_PANIC = "true", CONFIG_HALT_ON_PANIC = "false"))]
fn spin_on_panic(info: &PanicInfo) -> ! { fn spin_on_panic(info: &PanicInfo) -> ! {
if info.location().is_some() { if info.location().is_some() {
sfatals("Panic at "); sfatals("Panic at ");
@ -316,7 +344,9 @@ fn spin_on_panic(info: &PanicInfo) -> ! {
sfatalsnp(":"); sfatalsnp(":");
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line())); sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
sfatalsnp(":"); sfatalsnp(":");
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().column())); sfatalbnp(&aphrodite::u32_as_u8_slice(
info.location().unwrap().column(),
));
sfatalsnp(": "); sfatalsnp(": ");
} else { } else {
sfatals("Panic: "); sfatals("Panic: ");

View file

@ -0,0 +1 @@

View file

@ -7,6 +7,7 @@
//! actual architecture, of course): //! actual architecture, of course):
//! #![cfg(any(target_arch = "arch"))] //! #![cfg(any(target_arch = "arch"))]
/// 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
} }
@ -28,15 +29,11 @@ pub mod interrupts {
/// Enables interrupts. /// Enables interrupts.
#[aphrodite_proc_macros::kernel_item(InterruptsEnable)] #[aphrodite_proc_macros::kernel_item(InterruptsEnable)]
fn enable_interrupts() { fn enable_interrupts() {}
}
/// Disables interrupts. /// Disables interrupts.
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)] #[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
fn disable_interrupts() { fn disable_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].
@ -47,15 +44,11 @@ pub mod interrupts {
/// 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)]
fn restore_irq(irq: u64) { fn restore_irq(_irq: u64) {}
irq;
}
/// Activates an IDT. /// Activates an IDT.
#[aphrodite_proc_macros::kernel_item(ActivateIDT)] #[aphrodite_proc_macros::kernel_item(ActivateIDT)]
fn activate_idt(idt: Idt) { fn activate_idt(_idt: Idt) {}
idt;
}
/// An IDT. /// An IDT.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -95,7 +88,7 @@ pub mod interrupts {
Idt { Idt {
vectors: self.vectors, vectors: self.vectors,
funcs: self.funcs, funcs: self.funcs,
len: self.idx len: self.idx,
} }
} }
} }
@ -106,9 +99,3 @@ pub mod output {
//! LOT of output functions must be implemented. Using macros to //! LOT of output functions must be implemented. Using macros to
//! implement these is HIGHLY recommended. //! implement these is HIGHLY recommended.
} }
/// Returns whether paging is available for this architecture.
#[aphrodite_proc_macros::kernel_item(PagingAvailabe)]
pub fn paging_available() -> bool {
true
}

View file

@ -2,8 +2,8 @@
//! //!
//! 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.
mod x86;
pub mod example_impl; pub mod example_impl;
mod x86;
pub use x86::*; pub use x86::*;

View file

@ -34,7 +34,12 @@ impl core::fmt::Write for FramebufferInfo {
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>> {
let mut clr = color.0; let mut clr = color.0;
if color.1 { if color.1 {
match clr { match clr {
@ -69,7 +74,6 @@ impl crate::display::TextDisplay for FramebufferInfo {
} }
impl FramebufferInfo { impl FramebufferInfo {
/// Disables the cursor. /// Disables the cursor.
pub fn disable_cursor(self) { pub fn disable_cursor(self) {
super::ports::outb(0x3D4, 0x0A); super::ports::outb(0x3D4, 0x0A);

View file

@ -5,8 +5,11 @@ 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(entries: Vec<GDTEntry>) -> Result<*const [u8], crate::Error<'static>> { pub unsafe fn write_gdt_entries(
let mut mem = unsafe { alloc::alloc::alloc(Layout::from_size_align(8*entries.len(), 1).unwrap()) }; entries: Vec<GDTEntry>,
) -> Result<*const [u8], crate::Error<'static>> {
let mut mem =
unsafe { alloc::alloc::alloc(Layout::from_size_align(8 * entries.len(), 1).unwrap()) };
for ele in &entries { for ele in &entries {
let ele: &GDTEntry = ele; let ele: &GDTEntry = ele;
unsafe { ele.write_to_addr(mem as *mut ())? } unsafe { ele.write_to_addr(mem as *mut ())? }
@ -35,7 +38,10 @@ const GDT_WRITE_ADDR_INVALID_LIMIT: i16 = -1;
impl GDTEntry { impl GDTEntry {
const unsafe fn write_to_addr(self, ptr: *mut ()) -> Result<(), crate::Error<'static>> { const unsafe fn write_to_addr(self, ptr: *mut ()) -> Result<(), crate::Error<'static>> {
if self.limit > 0xFFFFF { if self.limit > 0xFFFFF {
return Err(crate::Error::new("Invalid GDT entry limit(more than 0xFFFFF)", GDT_WRITE_ADDR_INVALID_LIMIT)); return Err(crate::Error::new(
"Invalid GDT entry limit(more than 0xFFFFF)",
GDT_WRITE_ADDR_INVALID_LIMIT,
));
} }
let mut serialized = (0u64).to_ne_bytes(); let mut serialized = (0u64).to_ne_bytes();

View file

@ -2,7 +2,11 @@
#![cfg(any(target_arch = "x86"))] #![cfg(any(target_arch = "x86"))]
#![allow(static_mut_refs)] #![allow(static_mut_refs)]
use core::{alloc::{Allocator, Layout}, arch::asm, mem::MaybeUninit}; use core::{
alloc::{Allocator, Layout},
arch::asm,
mem::MaybeUninit,
};
/// The syscall vector. /// The syscall vector.
pub const USER_SYSCALL_VECTOR: u16 = 0xA0; pub const USER_SYSCALL_VECTOR: u16 = 0xA0;
@ -23,9 +27,7 @@ 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 { unsafe { asm!("cli") }
asm!("cli")
}
} }
/// PoppedInterrupts implements drop and restores the interrupts upon being dropped. /// PoppedInterrupts implements drop and restores the interrupts upon being dropped.
@ -62,9 +64,7 @@ pub fn restore_irq(flags: PoppedInterrupts) {
asm!( asm!(
"push {0:e}", in(reg) flags "push {0:e}", in(reg) flags
); );
asm!( asm!("popf");
"popf"
);
} }
} }
@ -73,7 +73,7 @@ pub fn restore_irq(flags: PoppedInterrupts) {
#[repr(C)] #[repr(C)]
struct IDTR { struct IDTR {
base: *const u8, base: *const u8,
size: usize size: usize,
} }
unsafe impl Send for IDTR {} unsafe impl Send for IDTR {}
@ -83,28 +83,26 @@ unsafe impl Sync for IDTR {}
fn load_idt(base: *const u8, size: usize) { fn load_idt(base: *const u8, size: usize) {
static mut IDTR: MaybeUninit<IDTR> = MaybeUninit::uninit(); static mut IDTR: MaybeUninit<IDTR> = MaybeUninit::uninit();
unsafe { unsafe {
IDTR.write(IDTR { IDTR.write(IDTR { base, size });
base,
size
});
}
unsafe {
asm!("lidt {}", in(reg) IDTR.as_ptr() as usize)
} }
unsafe { asm!("lidt {}", in(reg) IDTR.as_ptr() as usize) }
} }
/// Activate an IDT. /// Activate an IDT.
#[aphrodite_proc_macros::kernel_item(ActivateIDT)] #[aphrodite_proc_macros::kernel_item(ActivateIDT)]
fn activate_idt(idt: Idt, alloc: crate::mem::MemoryMapAlloc) { fn activate_idt(idt: Idt, alloc: crate::mem::MemoryMapAlloc) {
let mem = alloc.allocate(unsafe { Layout::from_size_align_unchecked(8*idt.len, 1) }).unwrap().as_mut_ptr(); let _mem = alloc
.allocate(unsafe { Layout::from_size_align_unchecked(8 * idt.len, 1) })
.unwrap()
.as_mut_ptr();
for i in 0..idt.len { for i in 0..idt.len {
let vector = idt.vectors[i]; let _vector = idt.vectors[i];
let func = unsafe { idt.funcs[i].assume_init() } as usize as u64; let _func = unsafe { idt.funcs[i].assume_init() } as usize as u64;
let user_callable = idt.user_callable[i]; let _user_callable = idt.user_callable[i];
} }
} }
/// An Interrupt Descriptor Table.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Idt { pub struct Idt {
vectors: [u16; 256], vectors: [u16; 256],
@ -113,6 +111,7 @@ pub struct Idt {
len: usize, len: usize,
} }
/// A builder of an [Idt].
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct IdtBuilder { pub struct IdtBuilder {
vectors: [u16; 256], vectors: [u16; 256],
@ -122,6 +121,7 @@ pub struct IdtBuilder {
} }
impl IdtBuilder { impl IdtBuilder {
/// Create a new IdtBuilder.
pub fn new() -> Self { pub fn new() -> Self {
IdtBuilder { IdtBuilder {
vectors: [0; 256], vectors: [0; 256],
@ -130,6 +130,7 @@ impl IdtBuilder {
idx: 0, idx: 0,
} }
} }
/// Add a function to this IdtBuilder.
pub fn add_fn(&mut self, vector: u16, func: fn(), user_callable: bool) -> &mut Self { pub fn add_fn(&mut self, vector: u16, func: fn(), user_callable: bool) -> &mut Self {
self.vectors[self.idx] = vector; self.vectors[self.idx] = vector;
self.funcs[self.idx].write(func); self.funcs[self.idx].write(func);
@ -137,12 +138,13 @@ impl IdtBuilder {
self.idx += 1; self.idx += 1;
self self
} }
/// Finish creating this IdtBuilder and return an [Idt].
pub fn finish(&self) -> Idt { pub fn finish(&self) -> Idt {
Idt { Idt {
vectors: self.vectors, vectors: self.vectors,
funcs: self.funcs, funcs: self.funcs,
user_callable: self.user_callable, user_callable: self.user_callable,
len: self.idx len: self.idx,
} }
} }
} }

View file

@ -6,8 +6,9 @@ use alloc::{vec, vec::Vec};
use crate::memsections::*; use crate::memsections::*;
use super::gdt::{write_gdt_entries, GDTEntry}; use super::gdt::{GDTEntry, write_gdt_entries};
/// A list of memory sections. Create one with [MemorySectionBuilder].
pub struct MemorySections { pub struct MemorySections {
sections: Vec<MemorySection>, sections: Vec<MemorySection>,
} }
@ -100,7 +101,7 @@ unsafe impl crate::memsections::MemorySections for MemorySections {
let gdtr = GDTR { let gdtr = GDTR {
address: ptr as *const u8 as usize as u32, address: ptr as *const u8 as usize as u32,
size: (ptr.len()-1) as u16 size: (ptr.len() - 1) as u16,
}; };
let addr = &gdtr as *const GDTR as *const () as usize as u32; let addr = &gdtr as *const GDTR as *const () as usize as u32;
@ -156,16 +157,19 @@ pub struct MemorySectionBuilder {
} }
impl MemorySectionBuilder { impl 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.
pub fn add_section(&mut self, section: MemorySection) -> &mut Self { pub fn add_section(&mut self, section: MemorySection) -> &mut Self {
self.sections.push(section); self.sections.push(section);
self self
} }
/// Finishes this MemorySectionBuilder and returns a MemorySections.
pub fn finish(self) -> MemorySections { pub fn finish(self) -> MemorySections {
MemorySections { MemorySections {
sections: self.sections, sections: self.sections,

View file

@ -3,13 +3,13 @@
use core::arch::asm; use core::arch::asm;
pub mod interrupts;
pub mod ports;
pub mod output;
pub mod egatext; pub mod egatext;
pub mod paging;
mod gdt; mod gdt;
pub mod interrupts;
pub mod memory; pub mod memory;
pub mod output;
pub mod paging;
pub mod ports;
mod constants; mod constants;
@ -17,15 +17,11 @@ pub(self) use constants::*;
use interrupts::{pop_irq, restore_irq}; use interrupts::{pop_irq, restore_irq};
use ports::{inb, outb}; use ports::{inb, outb};
/// 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
} }
#[aphrodite_proc_macros::kernel_item(PagingAvailabe)]
pub fn paging_available() -> bool {
true
}
/// Returns information from the CPUID command in the form /// Returns information from the CPUID command in the form
/// (ebx, edx, ecx). /// (ebx, edx, ecx).
pub fn cpuid(id: u32) -> (u32, u32, u32) { pub fn cpuid(id: u32) -> (u32, u32, u32) {
@ -124,7 +120,7 @@ pub fn enable_a20_keyboard() {
pub fn enable_a20_fasta20() { pub fn enable_a20_fasta20() {
let mut a = inb(0x92); let mut a = inb(0x92);
if a & 0b10 > 0 { if a & 0b10 > 0 {
return return;
} }
a |= 0b10; a |= 0b10;
a &= 0xFE; a &= 0xFE;

View file

@ -94,7 +94,7 @@ macro_rules! message_funcs {
ports::outb(super::DEBUG_PORT, s); ports::outb(super::DEBUG_PORT, s);
} }
} }
} };
} }
message_funcs!(debug, "[DEBUG] ", CONFIG_PREUSER_OUTPUT_DEBUG); message_funcs!(debug, "[DEBUG] ", CONFIG_PREUSER_OUTPUT_DEBUG);
@ -103,4 +103,3 @@ message_funcs!(warning, "[WARN] ", CONFIG_PREUSER_OUTPUT_WARN);
message_funcs!(error, "[ERROR] ", CONFIG_PREUSER_OUTPUT_ERROR); message_funcs!(error, "[ERROR] ", CONFIG_PREUSER_OUTPUT_ERROR);
message_funcs!(fatal, "[FATAL] ", CONFIG_PREUSER_OUTPUT_FATAL); message_funcs!(fatal, "[FATAL] ", CONFIG_PREUSER_OUTPUT_FATAL);
message_funcs!(output, "", NONE); message_funcs!(output, "", NONE);

View file

@ -4,8 +4,11 @@ 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.
pub enum PageDirectoryEntry { pub enum PageDirectoryEntry {
/// A four megabyte page.
FourMb(u32), FourMb(u32),
/// A smaller page.
Other(u32), Other(u32),
} }
@ -114,11 +117,9 @@ impl PageDirectoryEntry {
static mut PAGE_DIRECTORY: PageDirectoryEntry = static mut PAGE_DIRECTORY: PageDirectoryEntry =
PageDirectoryEntry::create_other(0, false, 0, false, false, false, false, false, false, false); PageDirectoryEntry::create_other(0, false, 0, false, false, false, false, false, false, false);
/// Initalize paging.
#[kernel_item(PagingInit)] #[kernel_item(PagingInit)]
pub fn initalize_paging() { pub fn initalize_paging() {}
}
/// Disables paging by clearing bit 31 in the cr0 register. /// Disables paging by clearing bit 31 in the cr0 register.
#[kernel_item(PagingDeinit)] #[kernel_item(PagingDeinit)]

View file

@ -41,8 +41,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"),

View file

@ -19,14 +19,14 @@ pub struct Argument {
/// The name of an argument. /// The name of an argument.
pub name: &'static str, pub name: &'static str,
/// The value of an argument. /// The value of an argument.
pub value: ArgumentValue pub value: ArgumentValue,
} }
/// A single flag in a [Cmdline]. /// A single flag in a [Cmdline].
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Flag { pub struct Flag {
/// The name of a flag. /// The name of a flag.
pub name: &'static str pub name: &'static str,
} }
/// A kernel command line. /// A kernel command line.
@ -83,7 +83,10 @@ impl Validator for CmdlineValidator {
} }
} }
if !correct { if !correct {
return Err(crate::Error::new("invalid argument in command line", ERR_INVALID_ARGUMENT)); return Err(crate::Error::new(
"invalid argument in command line",
ERR_INVALID_ARGUMENT,
));
} }
} }
@ -96,7 +99,10 @@ impl Validator for CmdlineValidator {
} }
} }
if !correct { if !correct {
return Err(crate::Error::new("invalid flag in command line", ERR_INVALID_FLAG)); return Err(crate::Error::new(
"invalid flag in command line",
ERR_INVALID_FLAG,
));
} }
} }
Ok(()) Ok(())

View file

@ -18,7 +18,12 @@ 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: core::fmt::Write { 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.
fn get_size(&self) -> (u32, u32); fn get_size(&self) -> (u32, u32);
} }
@ -35,13 +40,18 @@ impl dyn TextDisplay + '_ {
} }
/// Writes a &str to the screen. /// Writes a &str to the screen.
pub fn write_str(&self, pos: (u32, u32), str: &str, color: Color) -> Result<(u32, u32), crate::Error<'static>> { pub fn write_str(
&self,
pos: (u32, u32),
str: &str,
color: Color,
) -> Result<(u32, u32), crate::Error<'static>> {
let (width, _) = self.get_size(); let (width, _) = self.get_size();
let (mut x, mut y) = pos; let (mut x, mut y) = pos;
for char in str.as_bytes() { for char in str.as_bytes() {
self.write_char((x, y), *char, color)?; self.write_char((x, y), *char, color)?;
if *char == 0 { if *char == 0 {
continue continue;
} }
x += 1; x += 1;
while x > width { while x > width {
@ -53,13 +63,18 @@ impl dyn TextDisplay + '_ {
} }
/// Writes a &\[u8] to the screen. /// Writes a &\[u8] to the screen.
pub fn write_bytes(&self, pos: (u32, u32), str: &[u8], color: Color) -> Result<(u32, u32), crate::Error<'static>> { pub fn write_bytes(
&self,
pos: (u32, u32),
str: &[u8],
color: Color,
) -> Result<(u32, u32), crate::Error<'static>> {
let (width, _) = self.get_size(); let (width, _) = self.get_size();
let (mut x, mut y) = pos; let (mut x, mut y) = pos;
for char in str { for char in str {
self.write_char((x, y), *char, color)?; self.write_char((x, y), *char, color)?;
if *char == 0 { if *char == 0 {
continue continue;
} }
x += 1; x += 1;
while x > width { while x > width {

View file

@ -6,7 +6,7 @@ use crate::display::TextDisplay;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Error<'a> { pub struct Error<'a> {
message: &'a str, message: &'a str,
code: i16 code: i16,
} }
impl<'a> Error<'a> { impl<'a> Error<'a> {
@ -17,7 +17,7 @@ impl<'a> Error<'a> {
} }
impl Error<'_> { impl Error<'_> {
/// Display the contents of the error on a [TextDisplay]. /// Display the contents of the error on a [TextDisplay] with no prefix.
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).unwrap(); crate::output::terrorbnp(&crate::i16_as_u8_slice(self.code), display).unwrap();
crate::output::terrorsnp(": ", display).unwrap(); crate::output::terrorsnp(": ", display).unwrap();

View file

@ -5,7 +5,10 @@
use core::alloc::{Allocator, Layout}; use core::alloc::{Allocator, Layout};
use crate::{display::{NoneTextDisplay, COLOR_DEFAULT}, output::*}; use crate::{
display::{COLOR_DEFAULT, NoneTextDisplay},
output::*,
};
use aphrodite_proc_macros::*; use aphrodite_proc_macros::*;
@ -17,7 +20,10 @@ fn indep_boot_entry(
display: Option<&dyn crate::display::TextDisplay>, display: Option<&dyn crate::display::TextDisplay>,
#[allow(non_snake_case)] BI: &crate::boot::BootInfo, #[allow(non_snake_case)] BI: &crate::boot::BootInfo,
) -> ! { ) -> ! {
assert_ne!(crate::arch::get_arch(), crate::arch::Architecture::ExampleDummy); assert_ne!(
crate::arch::get_arch(),
crate::arch::Architecture::ExampleDummy
);
crate::arch::output::sdebugsln("IndepBootEntry called"); crate::arch::output::sdebugsln("IndepBootEntry called");
let display = display.unwrap_or(&NoneTextDisplay {}); let display = display.unwrap_or(&NoneTextDisplay {});
@ -64,6 +70,8 @@ fn indep_boot_entry(
terrors("Failed to deallocate: ", display).unwrap(); terrors("Failed to deallocate: ", display).unwrap();
err.display_np(display); err.display_np(display);
panic!("Deallocation failure"); panic!("Deallocation failure");
} else {
tdebugsln("Successfully deallocated!", display).unwrap();
} }
} }
tdebugsln("", display).unwrap(); tdebugsln("", display).unwrap();

View file

@ -48,8 +48,6 @@ 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> {
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; self.idx += 1;
if self.idx > self.num_allocations { if self.idx > self.num_allocations {
return None; return None;
@ -139,7 +137,11 @@ 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 uses the memory mapping to ///
/// 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.
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>> {
@ -222,6 +224,9 @@ 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>> {
if !allocation.used {
crate::arch::output::swarningsln("Adding unused allocation");
}
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 }
@ -355,7 +360,7 @@ pub const MAYBE_MEMORY_MAP_ALLOC_UNINITALIZED: i16 = -8;
struct MaybeMemoryMapAlloc<'a> { struct MaybeMemoryMapAlloc<'a> {
alloc: MaybeUninit<MemoryMapAlloc<'a>>, alloc: MaybeUninit<MemoryMapAlloc<'a>>,
initalized: bool initalized: bool,
} }
impl<'a> MaybeMemoryMapAlloc<'a> { impl<'a> MaybeMemoryMapAlloc<'a> {
const fn new(alloc: Option<MemoryMapAlloc<'a>>) -> Self { const fn new(alloc: Option<MemoryMapAlloc<'a>>) -> Self {
@ -363,7 +368,7 @@ impl<'a> MaybeMemoryMapAlloc<'a> {
return MaybeMemoryMapAlloc { return MaybeMemoryMapAlloc {
alloc: MaybeUninit::uninit(), alloc: MaybeUninit::uninit(),
initalized: false, initalized: false,
} };
} }
MaybeMemoryMapAlloc { MaybeMemoryMapAlloc {
alloc: MaybeUninit::new(alloc.unwrap()), alloc: MaybeUninit::new(alloc.unwrap()),
@ -385,7 +390,9 @@ impl<'a> MaybeMemoryMapAlloc<'a> {
if !self.initalized { if !self.initalized {
return; return;
} }
unsafe { self.alloc.assume_init_drop(); } unsafe {
self.alloc.assume_init_drop();
}
self.initalized = false; self.initalized = false;
} }
} }
@ -418,7 +425,10 @@ unsafe impl<'a> GlobalAlloc for MaybeMemoryMapAlloc<'a> {
} }
unsafe impl<'a> Allocator for MaybeMemoryMapAlloc<'a> { unsafe impl<'a> Allocator for MaybeMemoryMapAlloc<'a> {
fn allocate(&self, layout: core::alloc::Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> { fn allocate(
&self,
layout: core::alloc::Layout,
) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
if !self.initalized { if !self.initalized {
unsafe { unsafe {
LAST_MEMMAP_ERR = Err(crate::Error::new( LAST_MEMMAP_ERR = Err(crate::Error::new(
@ -545,6 +555,7 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
} }
return; return;
} }
crate::arch::output::sdebugsln("Searching for allocation");
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice( crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(
unsafe { *self.allocationheader }.num_allocations, unsafe { *self.allocationheader }.num_allocations,
)); ));
@ -552,6 +563,17 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
crate::arch::output::sdebugsln("Allocation"); crate::arch::output::sdebugsln("Allocation");
let alloc = unsafe { *allocation }.clone(); let alloc = unsafe { *allocation }.clone();
if !alloc.used { if !alloc.used {
crate::arch::output::sdebugs("Unused, addr is ");
if alloc.addr == addr {
crate::arch::output::sdebugsnp("correct and ");
} else {
crate::arch::output::sdebugsnp("incorrect and ");
}
if alloc.addr == 0 {
crate::arch::output::sdebugsnpln("null");
} else {
crate::arch::output::sdebugsnpln("non-null");
}
continue; continue;
} }
crate::arch::output::sdebugsln("Used"); crate::arch::output::sdebugsln("Used");
@ -560,6 +582,7 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
return; return;
} }
} }
crate::arch::output::sdebugsln("Memory unallocated");
// Memory not allocated, something is up, this is put after the loop to prevent a costly call to check_addr // Memory not allocated, something is up, this is put after the loop to prevent a costly call to check_addr
unsafe { unsafe {
LAST_MEMMAP_ERR = Err(crate::Error::new( LAST_MEMMAP_ERR = Err(crate::Error::new(

View file

@ -12,7 +12,7 @@ pub enum SectionType {
CodeSection { CodeSection {
/// Whether more powerful owners can jump to this if the owner /// Whether more powerful owners can jump to this if the owner
/// is less powerful. /// is less powerful.
can_powerful_sections_jump: bool can_powerful_sections_jump: bool,
}, },
/// A data section. Generally at least one of these for the kernel. /// A data section. Generally at least one of these for the kernel.
DataSection, DataSection,
@ -21,7 +21,7 @@ pub enum SectionType {
/// if they aren't directly supported by the hardware. /// if they aren't directly supported by the hardware.
TaskSection { TaskSection {
/// Whether the section is busy. /// Whether the section is busy.
busy: bool busy: bool,
}, },
} }

View file

@ -29,12 +29,12 @@ pub mod display;
mod errors; mod errors;
pub mod indep_boot_entry; pub mod indep_boot_entry;
pub mod mem; pub mod mem;
pub mod memsections;
pub mod multiboot2; pub mod multiboot2;
pub mod output; pub mod output;
pub mod psfont; pub mod psfont;
mod traits; mod traits;
mod util; mod util;
pub mod memsections;
#[macro_use] #[macro_use]
pub(crate) mod cfg; pub(crate) mod cfg;
@ -47,3 +47,11 @@ 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::*;
pub const fn version() -> &'static str {
env!("VERSION")
}
pub const fn cfg_version() -> &'static str {
env!("CFG_VERSION")
}

View file

@ -9,7 +9,7 @@ pub struct Tag {
/// The type of the tag. /// The type of the tag.
pub tag_type: u32, pub tag_type: u32,
/// The length of the tag. /// The length of the 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.
@ -32,7 +32,7 @@ pub struct 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 arguments)`.
/// See <https://aphrodite-os.github.io/book/bootloader-modules.html>. /// See <https://aphrodite-os.github.io/book/bootloader-modules.html>.
pub mod_str: &'static core::ffi::CStr pub mod_str: &'static core::ffi::CStr,
} }
/// One memory section provided by a Multiboot2 bootloader. /// One memory section provided by a Multiboot2 bootloader.
@ -58,10 +58,10 @@ impl Into<crate::boot::MemoryMapping> for MemorySection {
2 => crate::boot::MemoryType::HardwareReserved, 2 => crate::boot::MemoryType::HardwareReserved,
3 => crate::boot::MemoryType::HardwareSpecific(3, false), 3 => crate::boot::MemoryType::HardwareSpecific(3, false),
5 => crate::boot::MemoryType::Faulty, 5 => crate::boot::MemoryType::Faulty,
_ => crate::boot::MemoryType::Reserved _ => crate::boot::MemoryType::Reserved,
}, },
start: self.base_addr, start: self.base_addr,
len: self.length len: self.length,
} }
} }
} }
@ -79,7 +79,7 @@ pub struct RawMemoryMap {
/// 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],
} }
/// A full memory map provided by a Multiboot2 bootloader. /// A full memory map provided by a Multiboot2 bootloader.
@ -119,7 +119,7 @@ pub struct PaletteColorDescriptor {
/// The green value /// The green value
pub green: u8, pub green: u8,
/// The blue value /// The blue value
pub blue: u8 pub blue: u8,
} }
/// Information about color, for use in [FramebufferInfo]. /// Information about color, for use in [FramebufferInfo].
@ -131,7 +131,7 @@ pub enum ColorInfo {
/// The number of colors in the palette. /// The number of colors in the palette.
num_colors: u32, num_colors: u32,
/// The first color in the palette. /// The first color in the palette.
palette: *const PaletteColorDescriptor palette: *const PaletteColorDescriptor,
}, },
/// RGB information for use on the framebuffer. /// RGB information for use on the framebuffer.
RGBColor { RGBColor {
@ -151,7 +151,7 @@ pub enum ColorInfo {
blue_mask_size: u8, blue_mask_size: u8,
}, },
/// Text information, no metadata /// Text information, no metadata
EGAText EGAText,
} }
/// Information about the framebuffer. /// Information about the framebuffer.
@ -172,7 +172,6 @@ pub struct FramebufferInfo {
pub fb_type: u8, pub fb_type: u8,
/// Reserved space. Ignore. /// Reserved space. Ignore.
reserved: u8, reserved: u8,
// Color info after this; we need separate structs for each colorinfo as // Color info after this; we need separate structs for each colorinfo as
// we have to understand the format the bootloader gives us. // we have to understand the format the bootloader gives us.
} }
@ -190,7 +189,6 @@ pub struct Multiboot2BootInfo {
// 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 interested.
// To ensure future developers don't get any ideas, I'm leaving it out here. // 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 should contain the original pointer provided by
/// the bootloader. /// 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.
@ -201,7 +199,6 @@ pub struct Multiboot2BootInfo {
// 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 it's mostly
// unnecessary, so I don't care. Sorry if you are affected by this. // 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>,
@ -212,12 +209,10 @@ pub struct Multiboot2BootInfo {
// 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 for it ourselves.
// This is because right now I cannot figure out what format it provides the SMBIOS table in. // This is because right now I cannot figure out what format it provides the SMBIOS table in.

View file

@ -1,7 +1,7 @@
//! Architecture-independent output functions. //! Architecture-independent output functions.
use paste::paste;
use crate::display::COLOR_DEFAULT; use crate::display::COLOR_DEFAULT;
use paste::paste;
/// The position to output stuff to. /// The position to output stuff to.
static mut OUTPUT_TERM_POSITION: (u32, u32) = (0, 0); static mut OUTPUT_TERM_POSITION: (u32, u32) = (0, 0);

View file

@ -82,17 +82,13 @@ pub fn parse_raw_pc_screen_font(data: Vec<u8>) -> Result<RawPCScreenFont, crate:
} }
/// Parses a PC Screen Font into a [PCScreenFont]. /// Parses a PC Screen Font into a [PCScreenFont].
pub fn parse_pc_screen_font( pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate::Error<'static>> {
data: RawPCScreenFont,
) -> Result<PCScreenFont, crate::Error<'static>> {
unsafe { unsafe {
if data.flags == 0 { if data.flags == 0 {
let mut unitable: Vec<Vec<u8>> = Vec::with_capacity(data.num_glyphs as usize * core::mem::size_of::<Vec<u8>>()); let mut unitable: Vec<Vec<u8>> =
Vec::with_capacity(data.num_glyphs as usize * core::mem::size_of::<Vec<u8>>());
let unistr = (data let unistr = (data.glyphs.as_slice() as *const [u8])
.glyphs
.as_slice()
as *const [u8])
.byte_add(data.bytes_per_glyph as usize * data.num_glyphs as usize); .byte_add(data.bytes_per_glyph as usize * data.num_glyphs as usize);
let mut i = 0usize; let mut i = 0usize;
@ -136,9 +132,7 @@ pub fn parse_pc_screen_font(
} }
/// Parses a Vec<u8> into a [PCScreenFont]. /// Parses a Vec<u8> into a [PCScreenFont].
pub fn parse_psfu( pub fn parse_psfu(data: Vec<u8>) -> Result<PCScreenFont, crate::Error<'static>> {
data: Vec<u8>,
) -> Result<PCScreenFont, crate::Error<'static>> {
let data = parse_raw_pc_screen_font(data)?; let data = parse_raw_pc_screen_font(data)?;
parse_pc_screen_font(data) parse_pc_screen_font(data)
} }