arch-independent stuff working, x86 renamed to x86_asmp because missile

This commit is contained in:
Arthur Beck 2025-01-25 19:32:03 -06:00
parent 86a85b8b0d
commit e39bd7bf6e
16 changed files with 158 additions and 154 deletions

View file

@ -15,7 +15,7 @@ panic = "abort"
[[bin]] [[bin]]
name = "entrypoint" name = "entrypoint"
path = "src/internal/arch/x86/entry.rs" path = "src/internal/arch/x86_asmp/entry.rs"
[[bin]] [[bin]]
name = "main" name = "main"

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-6a2a677-out-of-tree' { menuentry "Aphrodite" --class aphrodite --class kernel --class os $menuentry_id_option 'aphrodite-basic-devel-86a85b8-out-of-tree' {
echo 'Loading Aphrodite aphrodite-devel-6a2a677-out-of-tree ...' echo 'Loading Aphrodite aphrodite-devel-86a85b8-out-of-tree ...'
multiboot2 /boot/aphrodite.kernel multiboot2 /boot/aphrodite.kernel
boot boot
} }

Binary file not shown.

View file

@ -1,5 +1,5 @@
//! Arch-specific code. //! Arch-specific code.
mod x86; mod x86_asmp;
pub use x86::*; pub use x86_asmp::*;

View file

@ -9,6 +9,8 @@
pub enum MemoryType { pub enum MemoryType {
/// Free RAM with no use. /// Free RAM with no use.
Free, Free,
/// RAM used by the kernel
Kernel,
/// Reserved by something. /// Reserved by something.
Reserved, Reserved,
/// Reserved by something on the hardware. /// Reserved by something on the hardware.
@ -19,7 +21,9 @@ pub enum MemoryType {
Unknown, Unknown,
/// Hardware-specific use. The boolean argument states /// Hardware-specific use. The boolean argument states
/// whether memory can be allocated in this region. /// whether memory can be allocated in this region.
HardwareSpecific(u32, bool) HardwareSpecific(u32, bool),
/// Flash/semi-permanent memory. Generally used in embedded systems.
Permanent
} }
/// A single memory mapping for [MemoryMap]. /// A single memory mapping for [MemoryMap].
@ -27,17 +31,20 @@ pub trait MemoryMapping {
/// Returns the type of the memory. /// Returns the type of the memory.
fn get_type(&self) -> MemoryType; fn get_type(&self) -> MemoryType;
/// Returns the beginning of the memory. /// Returns the beginning of the memory.
fn get_start(&self) -> usize; fn get_start(&self) -> u64;
/// Returns the length of the memory. /// Returns the length of the memory.
fn get_length(&self) -> usize; fn get_length(&self) -> u64;
} }
/// Memory mapping. /// Memory mapping.
pub trait MemoryMap<'a>: core::iter::Iterator<Item = &'a dyn MemoryMapping> + core::ops::Index<usize, Output = &'a dyn MemoryMapping> { pub trait _MemoryMap: core::iter::Iterator<Item = &'static dyn MemoryMapping> + core::ops::Index<usize, Output = dyn MemoryMapping> {
/// Returns the number of [MemoryMapping]s in the MemoryMap. This is total, not remainder. /// Returns the number of [MemoryMapping]s in the MemoryMap. This is total, not remainder.
fn len(&self) -> usize; fn len(&self) -> usize;
} }
/// Memory mapping. Used so that we can downcast.
pub trait MemoryMap: _MemoryMap + core::any::Any {}
/// Bootloader-independent information. /// Bootloader-independent information.
#[derive(Clone)] #[derive(Clone)]
pub struct BootInfo<'a> { pub struct BootInfo<'a> {
@ -46,7 +53,7 @@ pub struct BootInfo<'a> {
pub cmdline: Option<&'static str>, pub cmdline: Option<&'static str>,
/// The memory map provided by the bootloader. If None, the kernel will attempt to generate it. /// The memory map provided by the bootloader. If None, the kernel will attempt to generate it.
pub memory_map: Option<&'a dyn MemoryMap<'a>>, pub memory_map: Option<&'a dyn MemoryMap>,
/// The name of the bootloader(for example, "GRUB 2.12"). /// The name of the bootloader(for example, "GRUB 2.12").
pub bootloader_name: Option<&'static str>, pub bootloader_name: Option<&'static str>,

View file

@ -1,38 +1,5 @@
//! Definitions of structs for multiboot2 information. Mostly used during pre-userspace. //! Definitions of structs for multiboot2 information. Mostly used during pre-userspace.
/// Used when a CString is passed. Move into separate file?
#[derive(Clone, Copy)]
pub struct CString {
/// The raw pointer to the string.
pub ptr: *const u8,
/// The length of the string, excluding the null byte(\0) at the end.
pub len: usize,
}
impl core::ops::Index<usize> for CString {
type Output = u8;
fn index(&self, index: usize) -> &Self::Output {
unsafe {
if index>self.len {
panic!("index into CString too large");
}
let mut ptr = self.ptr as usize;
ptr += index * size_of::<u8>();
let ptr = ptr as *const u8;
&*ptr
}
}
}
impl Into<&'static str> for CString {
fn into(self) -> &'static str {
unsafe {
let val: *const str = core::ptr::from_raw_parts(self.ptr, self.len);
return &*val;
}
}
}
/// Used for Multiboot2 tags. This shouldn't be used after a [BootInfo] struct has been initalized, but it still can be used. /// Used for Multiboot2 tags. This shouldn't be used after a [BootInfo] struct has been initalized, but it still can be used.
#[repr(C)] #[repr(C)]
#[derive(Clone)] #[derive(Clone)]
@ -63,7 +30,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://github.com/AverseABFun/aphrodite/wiki/Plan/#Bootloader-modules (remember to update link later!). /// See https://github.com/AverseABFun/aphrodite/wiki/Plan/#Bootloader-modules (remember to update link later!).
pub mod_str: CString pub mod_str: &'static core::ffi::CStr
} }
/// One memory section provided by a Multiboot2 bootloader. /// One memory section provided by a Multiboot2 bootloader.
@ -81,6 +48,24 @@ pub struct MemorySection {
reserved: u32, reserved: u32,
} }
impl crate::boot::MemoryMapping for MemorySection {
fn get_type(&self) -> crate::boot::MemoryType {
match self.mem_type {
1 => crate::boot::MemoryType::Free,
2 => crate::boot::MemoryType::HardwareReserved,
3 => crate::boot::MemoryType::HardwareSpecific(3, false),
5 => crate::boot::MemoryType::Faulty,
_ => crate::boot::MemoryType::Reserved
}
}
fn get_start(&self) -> u64 {
self.base_addr
}
fn get_length(&self) -> u64 {
self.length
}
}
/// The raw memory map provided by a Multiboot2 bootloader. This is interpreted /// The raw memory map provided by a Multiboot2 bootloader. This is interpreted
/// into a [MemoryMap]. /// into a [MemoryMap].
#[repr(C)] #[repr(C)]
@ -106,6 +91,36 @@ pub struct MemoryMap {
pub entry_size: u32, pub entry_size: u32,
/// All sections. /// All sections.
pub sections: &'static [MemorySection], pub sections: &'static [MemorySection],
/// Iterator's index.
pub idx: usize,
}
impl crate::boot::MemoryMap for MemoryMap {}
impl crate::boot::_MemoryMap for MemoryMap {
fn len(&self) -> usize {
self.sections.len()
}
}
impl core::ops::Index<usize> for MemoryMap {
type Output = dyn crate::boot::MemoryMapping;
fn index(&self, index: usize) -> &Self::Output {
&self.sections[index] as &'static dyn crate::boot::MemoryMapping
}
}
impl core::iter::Iterator for MemoryMap {
type Item = &'static dyn crate::boot::MemoryMapping;
fn next(&mut self) -> Option<Self::Item> {
self.idx += 1;
if self.sections.len()<=self.idx-1 {
return None;
}
Some(&self.sections[self.idx-1])
}
} }
/// A color descriptor for [ColorInfo::Palette]. /// A color descriptor for [ColorInfo::Palette].
@ -177,7 +192,7 @@ pub struct FramebufferInfo {
/// Boot info collected from provided [Tag]s. /// Boot info collected from provided [Tag]s.
#[derive(Clone)] #[derive(Clone)]
pub struct BootInfo { pub struct Multiboot2BootInfo {
/// See https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-memory-information. /// See https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-memory-information.
/// Tl;dr: mem_lower indicates the amount of "lower memory" /// Tl;dr: mem_lower indicates the amount of "lower memory"
/// and mem_upper the amount of "upper memory". /// and mem_upper the amount of "upper memory".
@ -192,7 +207,7 @@ pub struct BootInfo {
/// 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://github.com/AverseABFun/aphrodite/wiki/Plan#bootloader (remember to update link later!) for the format. /// See https://github.com/AverseABFun/aphrodite/wiki/Plan#bootloader (remember to update link later!) for the format.
pub cmdline: Option<CString>, pub cmdline: Option<&'static core::ffi::CStr>,
// Due to the way modules work, it's not easily possible to make a struct that contains all the modules. // Due to the way modules work, it's not easily possible to make a struct that contains all the modules.
// Therefore, they are loaded on the fly. // Therefore, they are loaded on the fly.
@ -205,7 +220,7 @@ pub struct BootInfo {
/// The name of the bootloader(for example, "GRUB 2.12"). C-style UTF-8(null-terminated UTF-8) string. /// The name of the bootloader(for example, "GRUB 2.12"). C-style UTF-8(null-terminated UTF-8) string.
/// This should contain the original pointer provided by the bootloader. /// This should contain the original pointer provided by the bootloader.
pub bootloader_name: Option<CString>, pub bootloader_name: Option<&'static core::ffi::CStr>,
// APM table is ignored as APM has been superseded by ACPI. If your system doesn't support ACPI, good luck. // APM table is ignored as APM has been superseded by ACPI. If your system doesn't support ACPI, good luck.

View file

@ -6,8 +6,8 @@ pub type Color = u8;
/// Black-on-black. /// Black-on-black.
pub const COLOR_BLACK: Color = 0; pub const COLOR_BLACK: Color = 0;
/// Should be whatever colors commonly used for status messages. /// Should be whatever color commonly used for status messages.
/// Generally should be white-on-black. /// Generally should be white-on-black. Value is one.
pub const COLOR_DEFAULT: Color = 1; pub const COLOR_DEFAULT: Color = 1;
/// Some form of display that can be written too with text. /// Some form of display that can be written too with text.

View file

@ -8,10 +8,12 @@
#![feature(cfg_match)] #![feature(cfg_match)]
use core::{arch::asm, ffi::CStr, panic::PanicInfo}; use core::{arch::asm, ffi::CStr, panic::PanicInfo};
use aphrodite::multiboot2::{BootInfo, CString, ColorInfo, FramebufferInfo, MemoryMap, MemorySection, PaletteColorDescriptor, RawMemoryMap, RootTag, Tag}; use aphrodite::boot::BootInfo;
use aphrodite::arch::x86::output::*; use aphrodite::multiboot2::{FramebufferInfo, MemoryMap, MemorySection, RawMemoryMap, RootTag, Tag};
use aphrodite::arch::x86::egatext as egatext; use aphrodite::arch::output::*;
use aphrodite::arch::egatext as egatext;
use egatext::*; use egatext::*;
use aphrodite::output::*;
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))] #[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
#[unsafe(link_section = ".multiboot2")] #[unsafe(link_section = ".multiboot2")]
@ -25,26 +27,39 @@ static MULTIBOOT2_HEADER: [u8; 29] = [
// The root tag, provided directly from the multiboot2 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.
static mut BI: BootInfo = BootInfo {
mem_lower: None,
mem_upper: None,
cmdline: None,
memory_map: None,
bootloader_name: None,
framebuffer_info: None,
color_info: None,
};
// The raw pointer to bootloader-specific data. // The raw pointer to bootloader-specific data.
static mut O: *const u8 = core::ptr::null(); static mut O: *const u8 = core::ptr::null();
static mut MM: MemoryMap = MemoryMap {
entry_size: 0,
version: 0,
sections: &[],
idx: 0,
};
static mut FBI: aphrodite::arch::egatext::FramebufferInfo = aphrodite::arch::egatext::FramebufferInfo {
address: 0,
pitch: 0,
width: 0,
height: 0,
bpp: 0,
change_cursor: false,
};
// The magic number in eax. 0x36D76289 for multiboot2. // The magic number in eax. 0x36D76289 for multiboot2.
static mut MAGIC: u32 = 0xFFFFFFFF; static mut MAGIC: u32 = 0xFFFFFFFF;
#[unsafe(link_section = ".start")] #[unsafe(link_section = ".start")]
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
extern "C" fn _start() -> ! { extern "C" fn _start() -> ! {
#[allow(non_snake_case)]
let mut BI: BootInfo<'static> = BootInfo {
cmdline: None,
memory_map: None,
bootloader_name: None,
output: None,
};
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.
@ -103,10 +118,6 @@ 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 basic memory information tag != 16"); panic!("size of basic memory information tag != 16");
} }
BI.mem_lower = Some(*((ptr + 8) as *const u32));
BI.mem_upper = Some(*((ptr + 12) as *const u32));
// The end result of the above is adding an offset to a pointer and retrieving the value at that pointer
}, },
5 => { // BIOS boot device, ignore 5 => { // BIOS boot device, ignore
if current_tag.tag_len != 20 { // Unexpected size, something is probably up if current_tag.tag_len != 20 { // Unexpected size, something is probably up
@ -120,13 +131,7 @@ extern "C" fn _start() -> ! {
let cstring = CStr::from_ptr((ptr + 8) as *const i8); let cstring = CStr::from_ptr((ptr + 8) as *const i8);
// creates a &core::ffi::CStr from the start of the command line... // creates a &core::ffi::CStr from the start of the command line...
let cstring = CString { BI.cmdline = Some(cstring.to_str().unwrap());
ptr: cstring.as_ptr() as *const u8,
len: cstring.to_bytes().len()
};
// ...which can then be converted to a aphrodite::multiboot2::CString...
BI.cmdline = Some(cstring);
// ...before the BootInfo's commandline is set. // ...before the BootInfo's commandline is set.
}, },
6 => { // Memory map tag 6 => { // Memory map tag
@ -139,11 +144,13 @@ extern "C" fn _start() -> ! {
// 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
BI.memory_map = Some(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::ptr::from_raw_parts((&(*rawmemorymap).sections[0]) as &MemorySection, (*rawmemorymap).sections.len()),
}); idx: 0
};
BI.memory_map = Some(&MM);
}, },
2 => { // Bootloader name 2 => { // Bootloader name
if current_tag.tag_len < 8 { // Unexpected size, something is probably up if current_tag.tag_len < 8 { // Unexpected size, something is probably up
@ -152,13 +159,7 @@ extern "C" fn _start() -> ! {
let cstring = CStr::from_ptr((ptr + 8) as *const i8); let cstring = CStr::from_ptr((ptr + 8) as *const i8);
// creates a &core::ffi::CStr from the start of the bootloader name... // creates a &core::ffi::CStr from the start of the bootloader name...
let cstring = CString { BI.bootloader_name = Some(cstring.to_str().unwrap());
ptr: cstring.as_ptr() as *const u8,
len: cstring.to_bytes().len()
};
// ...which can then be converted to a aphrodite::multiboot2::CString...
BI.bootloader_name = Some(cstring);
// ...before the BootInfo's bootloader_name is set. // ...before the BootInfo's bootloader_name is set.
}, },
8 => { // Framebuffer info 8 => { // Framebuffer info
@ -166,33 +167,30 @@ extern "C" fn _start() -> ! {
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;
let colorinfo: ColorInfo;
match (*framebufferinfo).fb_type { match (*framebufferinfo).fb_type {
0 => { // Indexed 0 => { // Indexed
colorinfo = ColorInfo::Palette { panic!("Indexed color is unimplemented");
num_colors: *((ptr + 32) as *const u32),
palette: (ptr + 36) as *const PaletteColorDescriptor
};
}, },
1 => { // RGB 1 => { // RGB
colorinfo = ColorInfo::RGBColor { panic!("RGB color is unimplemented");
red_field_position: *((ptr + 32) as *const u8),
red_mask_size: *((ptr + 33) as *const u8),
green_field_position: *((ptr + 34) as *const u8),
green_mask_size: *((ptr + 35) as *const u8),
blue_field_position: *((ptr + 36) as *const u8),
blue_mask_size: *((ptr + 37) as *const u8)
}
}, },
2 => { // EGA Text 2 => { // EGA Text
colorinfo = ColorInfo::EGAText;
}, },
_ => { _ => {
panic!("unknown color info type") panic!("unknown color info type")
} }
} }
BI.framebuffer_info = Some((*framebufferinfo).clone()); let framebuffer_info = (*framebufferinfo).clone();
BI.color_info = Some(colorinfo);
FBI = egatext::FramebufferInfo {
address: framebuffer_info.address,
pitch: framebuffer_info.pitch,
width: framebuffer_info.width,
height: framebuffer_info.height,
bpp: framebuffer_info.bpp,
change_cursor: false,
};
BI.output = Some(&FBI)
}, },
_ => { // Unknown/unimplemented tag type, ignore _ => { // Unknown/unimplemented tag type, ignore
swarnings("Unknown tag type "); swarnings("Unknown tag type ");
@ -232,9 +230,8 @@ extern "C" fn _start() -> ! {
sdebugsln("Bootloader information has been successfully loaded"); sdebugsln("Bootloader information has been successfully loaded");
soutputu(b'\n'); soutputu(b'\n');
unsafe { unsafe {
if BI.framebuffer_info.clone().is_some() { if BI.output.clone().is_some() {
let framebuffer_info = BI.framebuffer_info.clone().unwrap(); let framebuffer_info = FBI;
let color_info = BI.color_info.clone().unwrap();
sdebugs("Framebuffer width: "); sdebugs("Framebuffer width: ");
sdebugbnpln(&aphrodite::u32_as_u8_slice(framebuffer_info.width)); sdebugbnpln(&aphrodite::u32_as_u8_slice(framebuffer_info.width));
@ -246,68 +243,43 @@ extern "C" fn _start() -> ! {
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));
sdebugs("Framebuffer type: ");
sdebugbnp(&aphrodite::u8_as_u8_slice(framebuffer_info.fb_type));
match framebuffer_info.fb_type { sdebugsln("Beginning output to screen...");
0 => { // Indexed
sdebugsnpln("(Indexed)");
let ColorInfo::Palette{num_colors, palette: _} = color_info else { unreachable!() };
sdebugs("Number of palette colors: ");
sdebugbnpln(&aphrodite::u32_as_u8_slice(num_colors));
sfatalsln("Halting CPU; Indexed color unimplemented"); let ega: &dyn aphrodite::TextDisplay = &framebuffer_info;
asm!("hlt", options(noreturn)); framebuffer_info.disable_cursor();
}, ega.clear_screen(WHITE_ON_BLACK);
1 => { // RGB tdebugsln("Testing EGA Text framebuffer...", ega).unwrap();
sdebugsnpln("(RGB)"); tdebugsln("Testing EGA Text framebuffer...", ega).unwrap();
tdebugsln("Testing EGA Text framebuffer...", ega).unwrap();
sfatalsln("Halting CPU; RGB color unimplemented"); aphrodite::_entry::_entry(Some(ega), &BI);
asm!("hlt", options(noreturn));
},
2 => { // EGA Text
sdebugsnpln("(EGA Text)");
sdebugsln("Beginning output to screen...");
let ega = egatext::FramebufferInfo {
address: framebuffer_info.address,
pitch: framebuffer_info.pitch,
width: framebuffer_info.width,
height: framebuffer_info.height,
bpp: framebuffer_info.bpp,
change_cursor: true,
};
ega.clear_screen(WHITE_ON_BLACK);
ega.enable_cursor(14, 15);
ega.set_cursor_location((0, 0));
tdebugsln("Testing EGA Text framebuffer...", ega).unwrap();
tdebugsln("Testing EGA Text framebuffer...", ega).unwrap();
tdebugsln("Testing EGA Text framebuffer...", ega).unwrap();
aphrodite::_entry::_entry(Some(ega), &BI);
},
_ => {
unreachable!();
}
}
} }
} }
unsafe { aphrodite::_entry::_entry(None, &BI);
aphrodite::_entry::_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) -> ! {
if info.location().is_some() {
sfatals("Panic at ");
sfatalsnp(info.location().unwrap().file());
sfatalsnp(":");
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
sfatalsnp(":");
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().column()));
sfatalsnp(": ");
} else {
sfatals("Panic: ");
}
let message = info.message().as_str().unwrap_or(""); let message = info.message().as_str().unwrap_or("");
if message != "" { if message != "" {
sfatals(message); sfatalsnpln(message);
aphrodite::arch::x86::ports::outb(aphrodite::arch::x86::DEBUG_PORT, b'\n');
} }
aphrodite::arch::x86::interrupts::disable_interrupts(); aphrodite::arch::interrupts::disable_interrupts();
unsafe { unsafe {
asm!("hlt", options(noreturn)); asm!("hlt", options(noreturn));
} }
@ -317,11 +289,21 @@ fn halt_on_panic(info: &PanicInfo) -> ! {
#[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_PREUSER_HALT_ON_PANIC = "false"))]
fn spin_on_panic(info: &PanicInfo) -> ! { fn spin_on_panic(info: &PanicInfo) -> ! {
if info.location().is_some() {
sfatals("Panic at ");
sfatalsnp(info.location().unwrap().file());
sfatalsnp(":");
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
sfatalsnp(":");
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().column()));
sfatalsnp(": ");
} else {
sfatals("Panic: ");
}
let message = info.message().as_str().unwrap_or(""); let message = info.message().as_str().unwrap_or("");
if message != "" { if message != "" {
sfatals(message); sfatalsnpln(message);
aphrodite::arch::x86::ports::outb(aphrodite::arch::x86::DEBUG_PORT, b'\n');
} }
aphrodite::arch::x86::interrupts::disable_interrupts(); aphrodite::arch::interrupts::disable_interrupts();
loop {} loop {}
} }