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/
aphrodite-grub.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
cp config.aphro config.aphro.tmp
export $(grep -Ev '^#' config.aphro.tmp | xargs)
cd ../kernel
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
# 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
cp aphrodite-grub.iso aphrodite.iso
grub-mkrescue -o aphrodite-grub.iso grub
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() {
local TEMP_SUFFIX
if [[ $VERSION = "generate" ]]; then
unset VERSION
fi
if git diff-index HEAD -- 2>&1 > /dev/null
then
echo -n
# N/A
else
TEMP_SUFFIX="-out-of-tree"
fi
SUFFIX="$SUFFIX$TEMP_SUFFIX"

Binary file not shown.

View file

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

Binary file not shown.

View file

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

View file

@ -6,31 +6,102 @@ use super::ports;
use paste::paste;
macro_rules! message_funcs {
($func_name:ident, $prefix:literal) => {
($func_name:ident, $prefix:literal, $level:ident) => {
paste! {
/// Outputs a $func_name message &str to the debug serial port.
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, 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.
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, 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.
pub fn [< s $func_name u >](s: u8) {
if cfg!($level = "false") {
return
}
ports::outbs(super::DEBUG_PORT, $prefix.as_bytes());
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!(info, "[INFO] ");
message_funcs!(warning, "[WARN] ");
message_funcs!(error, "[ERROR] ");
message_funcs!(fatal, "[FATAL] ");
message_funcs!(output, "");
message_funcs!(debug, "[DEBUG] ", CONFIG_PREUSER_OUTPUT_DEBUG);
message_funcs!(info, "[INFO] ", CONFIG_PREUSER_OUTPUT_INFO);
message_funcs!(warning, "[WARN] ", CONFIG_PREUSER_OUTPUT_WARN);
message_funcs!(error, "[ERROR] ", CONFIG_PREUSER_OUTPUT_ERROR);
message_funcs!(fatal, "[FATAL] ", CONFIG_PREUSER_OUTPUT_FATAL);
message_funcs!(output, "", NONE);

View file

@ -2,12 +2,14 @@
#![no_std]
#![no_main]
#![warn(missing_docs)]
#![allow(unexpected_cfgs)]
#![feature(ptr_metadata)]
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
use aphrodite::multiboot2::{BootInfo, CString, ColorInfo, FramebufferInfo, MemoryMap, PaletteColorDescriptor, RawMemoryMap, RootTag, Tag};
use aphrodite::arch::x86::output::*;
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
#[unsafe(link_section = ".multiboot2")]
#[unsafe(no_mangle)]
static MULTIBOOT2_HEADER: [u8; 29] = [
@ -17,7 +19,7 @@ static MULTIBOOT2_HEADER: [u8; 29] = [
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();
// The boot info struct, created from all of the tags.
static mut BI: BootInfo = BootInfo {
@ -40,30 +42,36 @@ static mut MAGIC: u32 = 0xFFFFFFFF;
#[unsafe(no_mangle)]
extern "C" fn _start() -> ! {
unsafe { // Copy values provided by the bootloader out
// Aphrodite bootloaders pass values in eax and ebx, however rust doesn't know that it can't overwrite those.
// we force using ebx and eax as the output of an empty assembly block to let it know.
asm!(
"mov ebx, ebx", out("ebx") O, // Bootloader-specific data(ebx)
out("eax") MAGIC, // Magic number(eax)
"", out("ebx") O, // Bootloader-specific data(ebx)
out("eax") MAGIC, // Magic number(eax)
options(nomem, nostack, preserves_flags, pure)
);
}
unsafe {
match MAGIC {
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
0x36D76289 => { // Multiboot2
RT = O as *const RootTag; // This is unsafe rust! We can do whatever we want! *manical laughter*
sdebugs("Total boot info length: ");
soutputb(&aphrodite::u32_as_u8_slice((*RT).total_len));
soutputu(b'\n');
sdebugs("Total boot info length is ");
sdebugbnp(&aphrodite::u32_as_u8_slice((*RT).total_len));
sdebugunp(b'\n');
sdebugs("Root tag address is: ");
soutputb(&aphrodite::usize_as_u8_slice(O as usize));
soutputu(b'\n');
sdebugs("Root tag address is ");
sdebugbnp(&aphrodite::usize_as_u8_slice(O as usize));
sdebugunp(b'\n');
if (*RT).total_len<16 { // Size of root tag+size of terminating tag. Something's up.
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;
ptr += size_of::<RootTag>();
@ -71,19 +79,14 @@ extern "C" fn _start() -> ! {
let mut current_tag = core::ptr::read_volatile(ptr as *const Tag);
loop {
sdebugs("Tag address is: ");
soutputb(&aphrodite::usize_as_u8_slice(ptr));
soutputu(b'\n');
sdebugs("Tag address is ");
sdebugbnpln(&aphrodite::usize_as_u8_slice(ptr));
sdebugs("Tag type is: ");
soutputb(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
soutputu(b'\n');
sdebugs("Tag type is ");
sdebugbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
sdebugs("Tag length is: ");
soutputb(&aphrodite::u32_as_u8_slice(current_tag.tag_len));
soutputu(b'\n');
soutputu(b'\n');
sdebugs("Tag length is ");
sdebugbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_len));
match current_tag.tag_type {
0 => { // Ending tag
@ -188,14 +191,16 @@ extern "C" fn _start() -> ! {
BI.framebuffer_info = Some((*framebufferinfo).clone());
BI.color_info = Some(colorinfo);
},
4294967295 => { // oh no, THIS bug happened
panic!("your code is fucked up")
},
_ => { // 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;
if ptr>end_addr {
panic!("current tag length would put pointer out-of-bounds")
}
current_tag = core::ptr::read_volatile(ptr as *const Tag);
}
},
@ -210,13 +215,28 @@ extern "C" fn _start() -> ! {
#[unsafe(link_section = ".panic")]
#[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("");
if message != "" {
sfatals(message);
aphrodite::arch::x86::ports::outb(aphrodite::arch::x86::DEBUG_PORT, b'\n');
}
aphrodite::arch::x86::interrupts::disable_interrupts();
unsafe {
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 {}
}