commit before bed, i'm making good progress

This commit is contained in:
Arthur Beck 2025-01-24 21:48:50 -06:00
parent 83f6c5cea4
commit b3558c2508
11 changed files with 207 additions and 45 deletions

7
.gitignore vendored
View file

@ -24,3 +24,10 @@ Cargo.lock
kernel/grub/ kernel/grub/
aphrodite-grub.iso aphrodite-grub.iso
aphrodite.iso aphrodite.iso
# Generated files
kernel.flat
config.aphro.tmp
# Per-developer files
config.aphro

View file

@ -7,6 +7,10 @@ if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
get_version get_version
cp config.aphro config.aphro.tmp
export $(grep -Ev '^#' config.aphro.tmp | xargs)
cd ../kernel cd ../kernel
cargo build --target i686-unknown-none.json --release -Zbuild-std --bin entrypoint cargo build --target i686-unknown-none.json --release -Zbuild-std --bin entrypoint
@ -15,13 +19,17 @@ cargo build --target i686-unknown-none.json --release -Zbuild-std --bin entrypoi
cp target/i686-unknown-none/release/entrypoint kernel.flat cp target/i686-unknown-none/release/entrypoint kernel.flat
# copy it out # copy it out
rm -rf grub rm -rf grub aphrodite.iso aphrodite-grub.iso
cp -r ./grub_template ./grub if [[ $CONFIG_BUILD_GRUB = "true" ]]; then
cp -r ./grub_template ./grub
cp kernel.flat ./grub/boot/aphrodite.kernel cp kernel.flat ./grub/boot/aphrodite.kernel
sed -i "s@%{VERSION}@$VERSION@g" ./grub/boot/grub/grub.cfg sed -i "s@%{VERSION}@$VERSION@g" ./grub/boot/grub/grub.cfg
grub-mkrescue -o aphrodite-grub.iso grub grub-mkrescue -o aphrodite-grub.iso grub
cp aphrodite-grub.iso aphrodite.iso cp aphrodite-grub.iso aphrodite.iso
fi
reset_version_vars

26
kernel/build.rs Normal file
View file

@ -0,0 +1,26 @@
fn main() {
let env = std::env::vars();
// 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_PREUSER_HALT_ON_PANIC, values("true", "false", none()))"#);
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_SPIN_ON_PANIC, values("true", "false", none()))"#);
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_DEBUG, values("true", "false", none()))"#);
println!(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()))"#);
// End checks
// Configuration name used when a config is required but should always evaluate to true
println!(r#"cargo:rustc-check-cfg=cfg(NONE, values("false", none()))"#);
for (var, val) in env {
if !var.starts_with("CONFIG_") {
continue
}
println!("cargo:rerun-if-env-changed={}", var);
println!("cargo:rustc-cfg={}=\"{}\"", var, val);
}
}

View file

@ -0,0 +1,23 @@
# config.aphro for aphrodite devel-83f6c5c-out-of-tree
# Begin metadata
# Set VERSION=generate to attempt to autogenerate a version based on git information
VERSION=generate
# SUFFIX is unset
# End metadata
# Begin configs
CONFIG_DISABLE_MULTIBOOT2_SUPPORT=false
CONFIG_PREUSER_HALT_ON_PANIC=false
CONFIG_PREUSER_SPIN_ON_PANIC=true
CONFIG_PREUSER_OUTPUT_DEBUG=true
CONFIG_PREUSER_OUTPUT_INFO=true
CONFIG_PREUSER_OUTPUT_WARN=true
CONFIG_PREUSER_OUTPUT_ERROR=true
CONFIG_PREUSER_OUTPUT_FATAL=true
CONFIG_BUILD_GRUB=true
# End configs

View file

@ -1,10 +1,10 @@
function get_version() { function get_version() {
local TEMP_SUFFIX local TEMP_SUFFIX
if [[ $VERSION = "generate" ]]; then
unset VERSION
fi
if git diff-index HEAD -- 2>&1 > /dev/null if git diff-index HEAD -- 2>&1 > /dev/null
then then
echo -n
# N/A
else
TEMP_SUFFIX="-out-of-tree" TEMP_SUFFIX="-out-of-tree"
fi fi
SUFFIX="$SUFFIX$TEMP_SUFFIX" SUFFIX="$SUFFIX$TEMP_SUFFIX"

Binary file not shown.

View file

@ -1,8 +1,8 @@
set timeout=15 set timeout=15
set default=0 set default=0
menuentry "Aphrodite" --class aphrodite --class kernel --class os $menuentry_id_option 'aphrodite-basic-devel-0b87ccb' { menuentry "Aphrodite" --class aphrodite --class kernel --class os $menuentry_id_option 'aphrodite-basic-generate' {
echo 'Loading Aphrodite aphrodite-devel-0b87ccb ...' echo 'Loading Aphrodite aphrodite-generate ...'
multiboot2 /boot/aphrodite.kernel multiboot2 /boot/aphrodite.kernel
boot boot
} }

Binary file not shown.

View file

@ -15,6 +15,13 @@ pub fn interrupts_enabled() -> bool {
(flags & (1 << 9)) == 0 (flags & (1 << 9)) == 0
} }
/// Disables interrupts.
pub fn disable_interrupts() {
unsafe {
asm!("cli")
}
}
/// Disables interrupts and returns the value of them. /// Disables interrupts and returns the value of them.
pub fn pop_irq() -> u32 { pub fn pop_irq() -> u32 {
let flags: u32; let flags: u32;

View file

@ -6,31 +6,102 @@ use super::ports;
use paste::paste; use paste::paste;
macro_rules! message_funcs { macro_rules! message_funcs {
($func_name:ident, $prefix:literal) => { ($func_name:ident, $prefix:literal, $level:ident) => {
paste! { paste! {
/// Outputs a $func_name message &str to the debug serial port. /// Outputs a $func_name message &str to the debug serial port.
pub fn [< s $func_name s >](s: &str) { pub fn [< s $func_name s >](s: &str) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, $prefix.as_bytes()); ports::outbs(super::DEBUG_PORT, $prefix.as_bytes());
ports::outbs(super::DEBUG_PORT, s.as_bytes()); ports::outbs(super::DEBUG_PORT, s.as_bytes());
} }
/// Outputs a $func_name message &str and a newline to the debug serial port.
pub fn [< s $func_name sln >](s: &str) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, $prefix.as_bytes());
ports::outbs(super::DEBUG_PORT, s.as_bytes());
ports::outb(super::DEBUG_PORT, b'\n');
}
/// Outputs a $func_name message &\[u8] to the debug serial port. /// Outputs a $func_name message &\[u8] to the debug serial port.
pub fn [< s $func_name b >](s: &[u8]) { pub fn [< s $func_name b >](s: &[u8]) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, $prefix.as_bytes()); ports::outbs(super::DEBUG_PORT, $prefix.as_bytes());
ports::outbs(super::DEBUG_PORT, s); ports::outbs(super::DEBUG_PORT, s);
} }
/// Outputs a $func_name message &\[u8] and a newline to the debug serial port.
pub fn [< s $func_name bln >](s: &[u8]) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, $prefix.as_bytes());
ports::outbs(super::DEBUG_PORT, s);
ports::outb(super::DEBUG_PORT, b'\n');
}
/// Outputs a(n) $func_name message u8 to the debug serial port. /// Outputs a(n) $func_name message u8 to the debug serial port.
pub fn [< s $func_name u >](s: u8) { pub fn [< s $func_name u >](s: u8) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, $prefix.as_bytes()); ports::outbs(super::DEBUG_PORT, $prefix.as_bytes());
ports::outb(super::DEBUG_PORT, s); ports::outb(super::DEBUG_PORT, s);
} }
///////////////////////////////////////////////////////////////
/// Outputs a $func_name message &str to the debug serial port without a prefix.
pub fn [< s $func_name snp >](s: &str) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, s.as_bytes());
}
/// Outputs a $func_name message &str and a newline to the debug serial port without a prefix.
pub fn [< s $func_name snpln >](s: &str) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, s.as_bytes());
ports::outb(super::DEBUG_PORT, b'\n');
}
/// Outputs a $func_name message &\[u8] to the debug serial port without a prefix.
pub fn [< s $func_name bnp >](s: &[u8]) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, s);
}
/// Outputs a $func_name message &\[u8] and a newline to the debug serial port without a prefix.
pub fn [< s $func_name bnpln >](s: &[u8]) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, s);
ports::outb(super::DEBUG_PORT, b'\n');
}
/// Outputs a(n) $func_name message u8 to the debug serial port without a prefix.
pub fn [< s $func_name unp >](s: u8) {
if cfg!($level = "false") {
return
}
ports::outb(super::DEBUG_PORT, s);
}
} }
} }
} }
message_funcs!(debug, "[DEBUG] "); message_funcs!(debug, "[DEBUG] ", CONFIG_PREUSER_OUTPUT_DEBUG);
message_funcs!(info, "[INFO] "); message_funcs!(info, "[INFO] ", CONFIG_PREUSER_OUTPUT_INFO);
message_funcs!(warning, "[WARN] "); message_funcs!(warning, "[WARN] ", CONFIG_PREUSER_OUTPUT_WARN);
message_funcs!(error, "[ERROR] "); message_funcs!(error, "[ERROR] ", CONFIG_PREUSER_OUTPUT_ERROR);
message_funcs!(fatal, "[FATAL] "); message_funcs!(fatal, "[FATAL] ", CONFIG_PREUSER_OUTPUT_FATAL);
message_funcs!(output, ""); message_funcs!(output, "", NONE);

View file

@ -2,12 +2,14 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![warn(missing_docs)] #![warn(missing_docs)]
#![allow(unexpected_cfgs)]
#![feature(ptr_metadata)] #![feature(ptr_metadata)]
use core::{arch::asm, ffi::CStr, panic::PanicInfo}; use core::{arch::asm, ffi::CStr, panic::PanicInfo};
use aphrodite::multiboot2::{BootInfo, CString, ColorInfo, FramebufferInfo, MemoryMap, PaletteColorDescriptor, RawMemoryMap, RootTag, Tag}; use aphrodite::multiboot2::{BootInfo, CString, ColorInfo, FramebufferInfo, MemoryMap, PaletteColorDescriptor, RawMemoryMap, RootTag, Tag};
use aphrodite::arch::x86::output::*; use aphrodite::arch::x86::output::*;
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
#[unsafe(link_section = ".multiboot2")] #[unsafe(link_section = ".multiboot2")]
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
static MULTIBOOT2_HEADER: [u8; 29] = [ static MULTIBOOT2_HEADER: [u8; 29] = [
@ -17,7 +19,7 @@ static MULTIBOOT2_HEADER: [u8; 29] = [
0xe9, 0x55, 0x00, 0x00, 0x00 0xe9, 0x55, 0x00, 0x00, 0x00
]; ];
// The root tag, provided directly from the multiboot bootloader. // The root tag, provided directly from the multiboot2 bootloader.
static mut RT: *const RootTag = core::ptr::null(); static mut RT: *const RootTag = core::ptr::null();
// The boot info struct, created from all of the tags. // The boot info struct, created from all of the tags.
static mut BI: BootInfo = BootInfo { static mut BI: BootInfo = BootInfo {
@ -40,30 +42,36 @@ static mut MAGIC: u32 = 0xFFFFFFFF;
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
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.
// we force using ebx and eax as the output of an empty assembly block to let it know.
asm!( asm!(
"mov ebx, ebx", out("ebx") O, // Bootloader-specific data(ebx) "", out("ebx") O, // Bootloader-specific data(ebx)
out("eax") MAGIC, // Magic number(eax) out("eax") MAGIC, // Magic number(eax)
options(nomem, nostack, preserves_flags, pure) options(nomem, nostack, preserves_flags, pure)
); );
} }
unsafe { unsafe {
match MAGIC { match MAGIC {
#[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: "); sdebugs("Total boot info length is ");
soutputb(&aphrodite::u32_as_u8_slice((*RT).total_len)); sdebugbnp(&aphrodite::u32_as_u8_slice((*RT).total_len));
soutputu(b'\n'); sdebugunp(b'\n');
sdebugs("Root tag address is: "); sdebugs("Root tag address is ");
soutputb(&aphrodite::usize_as_u8_slice(O as usize)); sdebugbnp(&aphrodite::usize_as_u8_slice(O as usize));
soutputu(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")
} }
soutputu(b'\n'); let end_addr = O as usize+(*RT).total_len as usize;
sdebugunp(b'\n');
let mut ptr = O as usize; let mut ptr = O as usize;
ptr += size_of::<RootTag>(); ptr += size_of::<RootTag>();
@ -71,19 +79,14 @@ extern "C" fn _start() -> ! {
let mut current_tag = core::ptr::read_volatile(ptr as *const Tag); let mut current_tag = core::ptr::read_volatile(ptr as *const Tag);
loop { loop {
sdebugs("Tag address is: "); sdebugs("Tag address is ");
soutputb(&aphrodite::usize_as_u8_slice(ptr)); sdebugbnpln(&aphrodite::usize_as_u8_slice(ptr));
soutputu(b'\n');
sdebugs("Tag type is: "); sdebugs("Tag type is ");
soutputb(&aphrodite::u32_as_u8_slice(current_tag.tag_type)); sdebugbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
soutputu(b'\n');
sdebugs("Tag length is: "); sdebugs("Tag length is ");
soutputb(&aphrodite::u32_as_u8_slice(current_tag.tag_len)); sdebugbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_len));
soutputu(b'\n');
soutputu(b'\n');
match current_tag.tag_type { match current_tag.tag_type {
0 => { // Ending tag 0 => { // Ending tag
@ -188,14 +191,16 @@ extern "C" fn _start() -> ! {
BI.framebuffer_info = Some((*framebufferinfo).clone()); BI.framebuffer_info = Some((*framebufferinfo).clone());
BI.color_info = Some(colorinfo); BI.color_info = Some(colorinfo);
}, },
4294967295 => { // oh no, THIS bug happened
panic!("your code is fucked up")
},
_ => { // Unknown/unimplemented tag type, ignore _ => { // Unknown/unimplemented tag type, ignore
// TODO: Add info message sinfos("Unknown tag type ");
sinfobnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
} }
} }
sinfounp(b'\n');
ptr = ptr + current_tag.tag_len as usize; ptr = ptr + current_tag.tag_len as usize;
if ptr>end_addr {
panic!("current tag length would put pointer out-of-bounds")
}
current_tag = core::ptr::read_volatile(ptr as *const Tag); current_tag = core::ptr::read_volatile(ptr as *const Tag);
} }
}, },
@ -210,13 +215,28 @@ extern "C" fn _start() -> ! {
#[unsafe(link_section = ".panic")] #[unsafe(link_section = ".panic")]
#[panic_handler] #[panic_handler]
fn handle_panic(info: &PanicInfo) -> ! { #[cfg(not(CONFIG_PREUSER_HALT_ON_PANIC = "false"))]
fn halt_on_panic(info: &PanicInfo) -> ! {
let message = info.message().as_str().unwrap_or(""); let message = info.message().as_str().unwrap_or("");
if message != "" { if message != "" {
sfatals(message); sfatals(message);
aphrodite::arch::x86::ports::outb(aphrodite::arch::x86::DEBUG_PORT, b'\n'); aphrodite::arch::x86::ports::outb(aphrodite::arch::x86::DEBUG_PORT, b'\n');
} }
aphrodite::arch::x86::interrupts::disable_interrupts();
unsafe { unsafe {
asm!("hlt", options(noreturn)); asm!("hlt", options(noreturn));
} }
} }
#[unsafe(link_section = ".panic")]
#[panic_handler]
#[cfg(all(CONFIG_PREUSER_SPIN_ON_PANIC = "true", CONFIG_PREUSER_HALT_ON_PANIC = "false"))]
fn spin_on_panic(info: &PanicInfo) -> ! {
let message = info.message().as_str().unwrap_or("");
if message != "" {
sfatals(message);
aphrodite::arch::x86::ports::outb(aphrodite::arch::x86::DEBUG_PORT, b'\n');
}
aphrodite::arch::x86::interrupts::disable_interrupts();
loop {}
}