continuing to chug along, working on arch-independence
This commit is contained in:
parent
6a2a677cde
commit
dd168ab5fd
14 changed files with 313 additions and 32 deletions
|
@ -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"
|
||||||
|
|
|
@ -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()))"#);
|
||||||
|
|
|
@ -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.
|
@ -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.
115
kernel/src/include/_entry.rs
Normal file
115
kernel/src/include/_entry.rs
Normal 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 {}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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::*;
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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 != "" {
|
||||||
|
|
Loading…
Add table
Reference in a new issue