continuing to chug along, working on arch-independence

This commit is contained in:
Arthur Beck 2025-01-25 18:22:32 -06:00
parent 6a2a677cde
commit dd168ab5fd
14 changed files with 313 additions and 32 deletions

View file

@ -17,6 +17,10 @@ panic = "abort"
name = "entrypoint" name = "entrypoint"
path = "src/internal/arch/x86/entry.rs" path = "src/internal/arch/x86/entry.rs"
[[bin]]
name = "main"
path = "src/internal/main.rs"
[lib] [lib]
name = "aphrodite" name = "aphrodite"
path = "src/include/mod.rs" path = "src/include/mod.rs"

View file

@ -4,8 +4,8 @@ fn main() {
// 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_PREUSER_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_PREUSER_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!(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_PANIC_ON_INVALID_LENGTH, values("true", "false", none()))"#); println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH, values("true", "false", none()))"#);

View file

@ -1,5 +1,5 @@
# config.aphro for aphrodite devel-2df6e24-out-of-tree # config.aphro for aphrodite devel-6a2a677-out-of-tree
CFG_VERSION=devel-2df6e24-out-of-tree CFG_VERSION=devel-6a2a677-out-of-tree
CONT_WITH_DIFFERENT_VERSION=false CONT_WITH_DIFFERENT_VERSION=false
# Begin metadata # Begin metadata
@ -14,8 +14,8 @@ VERSION=generate
CONFIG_DISABLE_MULTIBOOT2_SUPPORT=false CONFIG_DISABLE_MULTIBOOT2_SUPPORT=false
# Panic behavior. When debugging, generally halt on panic is more useful. # Panic behavior. When debugging, generally halt on panic is more useful.
CONFIG_PREUSER_HALT_ON_PANIC=true CONFIG_HALT_ON_PANIC=true
CONFIG_PREUSER_SPIN_ON_PANIC=false CONFIG_SPIN_ON_PANIC=false
CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH=true CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH=true
CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH=false CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH=false

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

Binary file not shown.

View file

@ -0,0 +1,115 @@
//! The main code for the kernel.
#![warn(missing_docs)]
#![allow(unexpected_cfgs)]
#![allow(static_mut_refs)]
use crate::arch::x86::output::*;
use crate::arch::x86::egatext as egatext;
use crate::multiboot2::BootInfo;
use egatext::*;
/// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files eventually call this.
#[allow(non_snake_case)]
pub fn _entry(ega: Option<crate::arch::x86::egatext::FramebufferInfo>, BI: &BootInfo) -> ! {
if ega.is_some() {
let ega = ega.unwrap();
ega.clear_screen(WHITE_ON_BLACK);
sreset();
let extended_functions = crate::arch::x86::cpuid_extended_functions();
if extended_functions {
binfosln("This CPU supports extended functions", ega).unwrap();
let longmode_support = crate::arch::x86::cpuid(0x80000001).1 & (1<<29) > 1;
if longmode_support {
binfosln("This CPU supports long mode", ega).unwrap();
} else {
binfosln("This CPU does NOT support long mode!", ega).unwrap();
bdebugs("Long mode CPUID: ", ega).unwrap();
bdebugbnpln(&crate::u32_as_u8_slice(crate::arch::x86::cpuid(0x80000001).1), ega).unwrap();
}
} else {
binfosln("This CPU does NOT support extended functions or long mode!", ega).unwrap();
}
if BI.bootloader_name.is_some() {
binfos("Kernel booted by ", ega).unwrap();
binfosnpln(BI.bootloader_name.unwrap().into(), ega).unwrap();
}
if BI.cmdline.is_some() {
binfos("Command line passed: \"", ega).unwrap();
binfosnp(BI.cmdline.unwrap().into(), ega).unwrap();
binfosnpln("\"", ega).unwrap();
}
if BI.mem_lower.is_some() {
binfos("Amount of lower memory: ", ega).unwrap();
binfobnpln(&crate::u32_as_u8_slice(BI.mem_lower.unwrap()), ega).unwrap();
}
if BI.mem_upper.is_some() {
binfos("Amount of upper memory: ", ega).unwrap();
binfobnpln(&crate::u32_as_u8_slice(BI.mem_upper.unwrap()), ega).unwrap();
}
if BI.memory_map.is_some() {
binfos("Recieved memory map from bootloader with ", ega).unwrap();
binfobnp(&crate::usize_as_u8_slice(BI.memory_map.unwrap().sections.len()), ega).unwrap();
binfosnpln(" sections", ega).unwrap();
let mut i = 0;
for ele in BI.memory_map.unwrap().sections {
binfos("Section #", ega).unwrap();
binfobnp(&crate::usize_as_u8_slice(i), ega).unwrap();
binfosnp(": ", ega).unwrap();
match ele.mem_type {
1 => {
binfosnp("Available RAM", ega).unwrap();
},
2 => {
binfosnp("Reserved by hardware", ega).unwrap();
}
3 => {
binfosnp("ACPI information", ega).unwrap();
},
4 => {
binfosnp("Reserved memory", ega).unwrap();
},
5 => {
binfosnp("Defective", ega).unwrap();
},
_ => {
binfosnp("Reserved/unknown (type=", ega).unwrap();
binfobnp(&crate::u32_as_u8_slice(ele.mem_type), ega).unwrap();
binfosnp(")", ega).unwrap();
}
}
binfosnp(", starting at ", ega).unwrap();
binfobnp(&crate::u64_as_u8_slice(ele.base_addr), ega).unwrap();
binfosnp(" and running for ", ega).unwrap();
binfobnp(&crate::u64_as_u8_slice(ele.length), ega).unwrap();
binfosnpln(" bytes", ega).unwrap();
i += 1;
}
}
} else {
if BI.bootloader_name.is_some() {
sinfos("Kernel booted by ");
sinfosnpln(BI.bootloader_name.unwrap().into());
}
if BI.cmdline.is_some() {
sinfos("Command line passed: \"");
sinfosnp(BI.cmdline.unwrap().into());
sinfosnpln("\"");
}
if BI.memory_map.is_some() {
sinfosln("Recieved memory map from bootloader");
}
if BI.mem_lower.is_some() {
sinfos("Amount of lower memory: ");
sinfobnpln(&crate::u32_as_u8_slice(BI.mem_lower.unwrap()));
}
if BI.mem_upper.is_some() {
sinfos("Amount of upper memory: ");
sinfobnpln(&crate::u32_as_u8_slice(BI.mem_upper.unwrap()));
}
}
loop {}
}

View file

@ -14,6 +14,8 @@ pub struct FramebufferInfo {
pub height: u32, pub height: u32,
/// Bits per pixel. /// Bits per pixel.
pub bpp: u8, pub bpp: u8,
/// Whether to change the cursor position after outputting text.
pub change_cursor: bool,
} }
/// Returned when the provided position is invalid in the X direction. /// Returned when the provided position is invalid in the X direction.
@ -29,7 +31,7 @@ pub const BLACK_ON_BLACK: u8 = 0b00000000;
impl FramebufferInfo { impl FramebufferInfo {
/// Writes a character to the screen. /// Writes a character to the screen.
pub fn write_char(self, pos: (u32, u32), char: u8, color: u8) -> Result<(), crate::Error<'static>> { pub fn write_char(self, mut pos: (u32, u32), char: u8, color: u8) -> Result<(), crate::Error<'static>> {
if pos.0>self.width { if pos.0>self.width {
return Err(crate::Error::new("Invalid X position", ERR_INVALID_X)); return Err(crate::Error::new("Invalid X position", ERR_INVALID_X));
} }
@ -43,6 +45,10 @@ impl FramebufferInfo {
let base_ptr = addr as *mut u16; let base_ptr = addr as *mut u16;
(*base_ptr) = ((color as u16)<<8) | (char as u16); (*base_ptr) = ((color as u16)<<8) | (char as u16);
} }
pos.1 += 1;
if self.change_cursor {
self.set_cursor_location(pos);
}
Ok(()) Ok(())
} }
@ -56,30 +62,52 @@ impl FramebufferInfo {
} }
/// Writes a &str to the screen. /// Writes a &str to the screen.
pub fn write_str(self, pos: (u32, u32), str: &str, color: u8) -> Result<(u32, u32), crate::Error<'static>> { pub fn write_str(mut self, pos: (u32, u32), str: &str, color: u8) -> Result<(u32, u32), crate::Error<'static>> {
let (mut x, mut y) = pos; let (mut x, mut y) = pos;
let change_cursor = self.change_cursor;
if change_cursor {
self.change_cursor = false;
}
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 {
continue
}
x += 1; x += 1;
while x>self.width { while x>self.width {
x -= self.width; x -= self.width;
y += 1; y += 1;
} }
} }
if change_cursor {
self.change_cursor = true;
self.set_cursor_location((x, y));
}
Ok((x, y)) Ok((x, y))
} }
/// Writes a &\[u8] to the screen. /// Writes a &\[u8] to the screen.
pub fn write_bytes(self, pos: (u32, u32), str: &[u8], color: u8) -> Result<(u32, u32), crate::Error<'static>> { pub fn write_bytes(mut self, pos: (u32, u32), str: &[u8], color: u8) -> Result<(u32, u32), crate::Error<'static>> {
let (mut x, mut y) = pos; let (mut x, mut y) = pos;
let change_cursor = self.change_cursor;
if change_cursor {
self.change_cursor = false;
}
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 {
continue
}
x += 1; x += 1;
while x>self.width { while x>self.width {
x -= self.width; x -= self.width;
y += 1; y += 1;
} }
} }
if change_cursor {
self.change_cursor = true;
self.set_cursor_location((x, y));
}
Ok((x, y)) Ok((x, y))
} }
@ -107,4 +135,17 @@ impl FramebufferInfo {
super::ports::outb(0x3D4, 0x0E); super::ports::outb(0x3D4, 0x0E);
super::ports::outb(0x3D5, ((addr >> 8) & 0xFF) as u8); super::ports::outb(0x3D5, ((addr >> 8) & 0xFF) as u8);
} }
/// Gets the cursor's location.
pub fn get_cursor_location(self) -> (u32, u32) {
let mut addr: u32 = 0;
super::ports::outb(0x3D4, 0x0F);
addr |= super::ports::inb(0x3D5) as u32;
super::ports::outb(0x3D4, 0x0E);
addr |= (super::ports::inb(0x3D5) as u32) << 8;
return (addr % self.width, addr / self.width);
}
} }

View file

@ -17,11 +17,22 @@ pub use constants::*;
pub fn cpuid(id: u32) -> (u32, u32, u32) { pub fn cpuid(id: u32) -> (u32, u32, u32) {
let mut out = (0u32, 0u32, 0u32); let mut out = (0u32, 0u32, 0u32);
unsafe { unsafe {
// ebx is moved into eax as apparently ebx is used internally by LLVM
asm!( asm!(
"cpuid", "cpuid", in("eax") id, out("ebx") out.0, out("edx") out.1, out("ecx") out.2
"mov eax, ebx", in("eax") id, lateout("eax") out.0, out("edx") out.1, out("ecx") out.2
) )
} }
out out
}
/// Returns whether extended functions are available
/// (more specifically, 0x80000001 or higher)
pub fn cpuid_extended_functions() -> bool {
let out: u32;
unsafe {
asm!(
"mov eax, 0x80000000",
"cpuid", out("eax") out
)
}
out >= 0x80000001
} }

View file

@ -233,6 +233,79 @@ macro_rules! message_funcs {
} }
Ok(()) Ok(())
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// Outputs a $func_name message &str to the terminal.
pub fn [< b $func_name s >](s: &str, info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name s >](s);
[< t $func_name s >](s, info)?;
Ok(())
}
/// Outputs a $func_name message &str and a newline to the terminal.
pub fn [< b $func_name sln >](s: &str, info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name sln >](s);
[< t $func_name sln >](s, info)?;
Ok(())
}
/// Outputs a $func_name message &\[u8] to the terminal.
pub fn [< b $func_name b >](s: &[u8], info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name b >](s);
[< t $func_name b >](s, info)?;
Ok(())
}
/// Outputs a $func_name message &\[u8] and a newline to the terminal.
pub fn [< b $func_name bln >](s: &[u8], info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name bln >](s);
[< t $func_name bln >](s, info)?;
Ok(())
}
/// Outputs a(n) $func_name message u8 to the terminal.
pub fn [< b $func_name u >](s: u8, info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name u >](s);
[< t $func_name u >](s, info)?;
Ok(())
}
///////////////////////////////////////////////////////////////
/// Outputs a $func_name message &str to the terminal without a prefix.
pub fn [< b $func_name snp >](s: &str, info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name snp >](s);
[< t $func_name snp >](s, info)?;
Ok(())
}
/// Outputs a $func_name message &str and a newline to the terminal without a prefix.
pub fn [< b $func_name snpln >](s: &str, info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name snpln >](s);
[< t $func_name snpln >](s, info)?;
Ok(())
}
/// Outputs a $func_name message &\[u8] to the terminal without a prefix.
pub fn [< b $func_name bnp >](s: &[u8], info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name bnp >](s);
[< t $func_name bnp >](s, info)?;
Ok(())
}
/// Outputs a $func_name message &\[u8] and a newline to the terminal without a prefix.
pub fn [< b $func_name bnpln >](s: &[u8], info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name bnpln >](s);
[< t $func_name bnpln >](s, info)?;
Ok(())
}
/// Outputs a(n) $func_name message u8 to the terminal without a prefix.
pub fn [< b $func_name unp >](s: u8, info: FramebufferInfo) -> Result<(), crate::Error<'static>> {
[< s $func_name unp >](s);
[< t $func_name unp >](s, info)?;
Ok(())
}
} }
} }
} }
@ -244,3 +317,10 @@ 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);
/// Resets the position of output to the screen.
pub fn sreset() {
unsafe {
OUTPUT_TERM_POSITION = (0, 0);
}
}

View file

@ -2,12 +2,14 @@
#![no_std] #![no_std]
#![warn(missing_docs)] #![warn(missing_docs)]
#![feature(ptr_metadata)] #![feature(ptr_metadata)]
#![feature(const_trait_impl)]
mod constants; mod constants;
mod util; mod util;
pub mod multiboot2; pub mod multiboot2;
pub mod arch; pub mod arch;
mod errors; mod errors;
pub mod _entry;
#[allow(unused_imports)] // if there are no constants, then it gives a warning #[allow(unused_imports)] // if there are no constants, then it gives a warning
pub use constants::*; pub use constants::*;

View file

@ -1,7 +1,7 @@
//! 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? /// Used when a CString is passed. Move into separate file?
#[derive(Clone)] #[derive(Clone, Copy)]
pub struct CString { pub struct CString {
/// The raw pointer to the string. /// The raw pointer to the string.
pub ptr: *const u8, pub ptr: *const u8,
@ -24,6 +24,15 @@ impl core::ops::Index<usize> for CString {
} }
} }
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)]
@ -89,16 +98,14 @@ pub struct RawMemoryMap {
} }
/// A full memory map provided by a Multiboot2 bootloader. /// A full memory map provided by a Multiboot2 bootloader.
#[derive(Clone)] #[derive(Clone, Copy)]
pub struct MemoryMap { pub struct MemoryMap {
/// 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 version: u32, // currently is 0, future Multiboot2 versions may increment pub version: u32, // currently is 0, future Multiboot2 versions may increment
/// Size of one entry(one [MemorySection] for Aphrodite) /// Size of one entry(one [MemorySection] for Aphrodite)
pub entry_size: u32, pub entry_size: u32,
/// A pointer to the first section. /// All sections.
pub sections: *const MemorySection, pub sections: &'static [MemorySection],
/// The number of sections.
pub sections_len: usize
} }
/// A color descriptor for [ColorInfo::Palette]. /// A color descriptor for [ColorInfo::Palette].
@ -190,13 +197,13 @@ pub struct BootInfo {
// 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.
// Multiboot2 bootloaders may provide us with ELF symbols, but I'm feeling lazy and right now the kernel is a // Multiboot2 bootloaders may provide us with ELF symbols, but I'm feeling lazy and right now it's mostly
// flat binary, 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>,
/// The name of the bootloader(for example, "GRUB"). 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<CString>,

View file

@ -72,3 +72,20 @@ pub fn usize_as_u8_slice(mut value: usize) -> [u8; 20] {
} }
buf buf
} }
/// Converts an u64 to an [u8; 10].
pub fn u64_as_u8_slice(mut value: u64) -> [u8; 20] {
let mut buf = [0u8; 20];
let mut i = 19;
if value == 0 {
buf[0] = b'0';
}
while value > 0 {
let digit = value%10;
let char = b'0' + digit as u8;
buf[i] = char;
value = value / 10;
i -= 1;
}
buf
}

View file

@ -8,7 +8,7 @@
#![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, PaletteColorDescriptor, RawMemoryMap, RootTag, Tag}; use aphrodite::multiboot2::{BootInfo, CString, ColorInfo, FramebufferInfo, MemoryMap, MemorySection, PaletteColorDescriptor, RawMemoryMap, RootTag, Tag};
use aphrodite::arch::x86::output::*; use aphrodite::arch::x86::output::*;
use aphrodite::arch::x86::egatext as egatext; use aphrodite::arch::x86::egatext as egatext;
use egatext::*; use egatext::*;
@ -142,8 +142,7 @@ extern "C" fn _start() -> ! {
BI.memory_map = Some(MemoryMap { BI.memory_map = Some(MemoryMap {
version: (*rawmemorymap).entry_version, version: (*rawmemorymap).entry_version,
entry_size: (*rawmemorymap).entry_size, entry_size: (*rawmemorymap).entry_size,
sections: &(*rawmemorymap).sections[0], sections: &*core::ptr::from_raw_parts((&(*rawmemorymap).sections[0]) as &MemorySection, (*rawmemorymap).sections.len()),
sections_len: (*rawmemorymap).sections.len()
}); });
}, },
2 => { // Bootloader name 2 => { // Bootloader name
@ -268,21 +267,24 @@ extern "C" fn _start() -> ! {
}, },
2 => { // EGA Text 2 => { // EGA Text
sdebugsnpln("(EGA Text)"); sdebugsnpln("(EGA Text)");
sdebugsln("Attempting to output to screen(will then loop for 100000000 cycles)..."); sdebugsln("Beginning output to screen...");
let ega = egatext::FramebufferInfo { let ega = egatext::FramebufferInfo {
address: framebuffer_info.address, address: framebuffer_info.address,
pitch: framebuffer_info.pitch, pitch: framebuffer_info.pitch,
width: framebuffer_info.width, width: framebuffer_info.width,
height: framebuffer_info.height, height: framebuffer_info.height,
bpp: framebuffer_info.bpp bpp: framebuffer_info.bpp,
change_cursor: true,
}; };
ega.clear_screen(BLACK_ON_BLACK); ega.clear_screen(WHITE_ON_BLACK);
ega.enable_cursor(14, 15); ega.enable_cursor(14, 15);
ega.set_cursor_location((0, 0)); 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(); 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!(); unreachable!();
@ -291,12 +293,14 @@ extern "C" fn _start() -> ! {
} }
} }
panic!("kernel unexpectedly exited"); unsafe {
aphrodite::_entry::_entry(None, &BI);
}
} }
#[unsafe(link_section = ".panic")] #[unsafe(link_section = ".panic")]
#[panic_handler] #[panic_handler]
#[cfg(not(CONFIG_PREUSER_HALT_ON_PANIC = "false"))] #[cfg(not(CONFIG_HALT_ON_PANIC = "false"))]
fn halt_on_panic(info: &PanicInfo) -> ! { 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 != "" {
@ -311,7 +315,7 @@ fn halt_on_panic(info: &PanicInfo) -> ! {
#[unsafe(link_section = ".panic")] #[unsafe(link_section = ".panic")]
#[panic_handler] #[panic_handler]
#[cfg(all(CONFIG_PREUSER_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) -> ! {
let message = info.message().as_str().unwrap_or(""); let message = info.message().as_str().unwrap_or("");
if message != "" { if message != "" {