diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index c7c29c4..d1e3fa9 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -15,7 +15,7 @@ panic = "abort" [[bin]] name = "entrypoint" -path = "src/internal/arch/x86/entry.rs" +path = "src/internal/arch/x86_asmp/entry.rs" [[bin]] name = "main" diff --git a/kernel/grub/boot/aphrodite.kernel b/kernel/grub/boot/aphrodite.kernel index 88044a2..66281f3 100755 Binary files a/kernel/grub/boot/aphrodite.kernel and b/kernel/grub/boot/aphrodite.kernel differ diff --git a/kernel/grub/boot/grub/grub.cfg b/kernel/grub/boot/grub/grub.cfg index b4d0af5..8be03ea 100644 --- a/kernel/grub/boot/grub/grub.cfg +++ b/kernel/grub/boot/grub/grub.cfg @@ -1,8 +1,8 @@ set timeout=15 set default=0 -menuentry "Aphrodite" --class aphrodite --class kernel --class os $menuentry_id_option 'aphrodite-basic-devel-6a2a677-out-of-tree' { - echo 'Loading Aphrodite aphrodite-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-86a85b8-out-of-tree ...' multiboot2 /boot/aphrodite.kernel boot } \ No newline at end of file diff --git a/kernel/kernel.flat b/kernel/kernel.flat index 88044a2..66281f3 100755 Binary files a/kernel/kernel.flat and b/kernel/kernel.flat differ diff --git a/kernel/src/include/arch/mod.rs b/kernel/src/include/arch/mod.rs index 7bfed5f..840a29c 100644 --- a/kernel/src/include/arch/mod.rs +++ b/kernel/src/include/arch/mod.rs @@ -1,5 +1,5 @@ //! Arch-specific code. -mod x86; +mod x86_asmp; -pub use x86::*; \ No newline at end of file +pub use x86_asmp::*; \ No newline at end of file diff --git a/kernel/src/include/arch/x86/constants.rs b/kernel/src/include/arch/x86_asmp/constants.rs similarity index 100% rename from kernel/src/include/arch/x86/constants.rs rename to kernel/src/include/arch/x86_asmp/constants.rs diff --git a/kernel/src/include/arch/x86/egatext.rs b/kernel/src/include/arch/x86_asmp/egatext.rs similarity index 100% rename from kernel/src/include/arch/x86/egatext.rs rename to kernel/src/include/arch/x86_asmp/egatext.rs diff --git a/kernel/src/include/arch/x86/interrupts.rs b/kernel/src/include/arch/x86_asmp/interrupts.rs similarity index 100% rename from kernel/src/include/arch/x86/interrupts.rs rename to kernel/src/include/arch/x86_asmp/interrupts.rs diff --git a/kernel/src/include/arch/x86/mod.rs b/kernel/src/include/arch/x86_asmp/mod.rs similarity index 100% rename from kernel/src/include/arch/x86/mod.rs rename to kernel/src/include/arch/x86_asmp/mod.rs diff --git a/kernel/src/include/arch/x86/output.rs b/kernel/src/include/arch/x86_asmp/output.rs similarity index 100% rename from kernel/src/include/arch/x86/output.rs rename to kernel/src/include/arch/x86_asmp/output.rs diff --git a/kernel/src/include/arch/x86/paging.rs b/kernel/src/include/arch/x86_asmp/paging.rs similarity index 100% rename from kernel/src/include/arch/x86/paging.rs rename to kernel/src/include/arch/x86_asmp/paging.rs diff --git a/kernel/src/include/arch/x86/ports.rs b/kernel/src/include/arch/x86_asmp/ports.rs similarity index 100% rename from kernel/src/include/arch/x86/ports.rs rename to kernel/src/include/arch/x86_asmp/ports.rs diff --git a/kernel/src/include/boot.rs b/kernel/src/include/boot.rs index b2b32fc..78ada3c 100644 --- a/kernel/src/include/boot.rs +++ b/kernel/src/include/boot.rs @@ -9,6 +9,8 @@ pub enum MemoryType { /// Free RAM with no use. Free, + /// RAM used by the kernel + Kernel, /// Reserved by something. Reserved, /// Reserved by something on the hardware. @@ -19,7 +21,9 @@ pub enum MemoryType { Unknown, /// Hardware-specific use. The boolean argument states /// 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]. @@ -27,17 +31,20 @@ pub trait MemoryMapping { /// Returns the type of the memory. fn get_type(&self) -> MemoryType; /// Returns the beginning of the memory. - fn get_start(&self) -> usize; + fn get_start(&self) -> u64; /// Returns the length of the memory. - fn get_length(&self) -> usize; + fn get_length(&self) -> u64; } /// Memory mapping. -pub trait MemoryMap<'a>: core::iter::Iterator + core::ops::Index { +pub trait _MemoryMap: core::iter::Iterator + core::ops::Index { /// Returns the number of [MemoryMapping]s in the MemoryMap. This is total, not remainder. fn len(&self) -> usize; } +/// Memory mapping. Used so that we can downcast. +pub trait MemoryMap: _MemoryMap + core::any::Any {} + /// Bootloader-independent information. #[derive(Clone)] pub struct BootInfo<'a> { @@ -46,7 +53,7 @@ pub struct BootInfo<'a> { pub cmdline: Option<&'static str>, /// 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"). pub bootloader_name: Option<&'static str>, diff --git a/kernel/src/include/multiboot2.rs b/kernel/src/include/multiboot2.rs index 550aa9c..3589ee9 100644 --- a/kernel/src/include/multiboot2.rs +++ b/kernel/src/include/multiboot2.rs @@ -1,38 +1,5 @@ //! 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 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::(); - 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. #[repr(C)] #[derive(Clone)] @@ -63,7 +30,7 @@ pub struct Module { pub mod_end: *const u8, /// 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!). - pub mod_str: CString + pub mod_str: &'static core::ffi::CStr } /// One memory section provided by a Multiboot2 bootloader. @@ -81,6 +48,24 @@ pub struct MemorySection { 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 /// into a [MemoryMap]. #[repr(C)] @@ -106,6 +91,36 @@ pub struct MemoryMap { pub entry_size: u32, /// All sections. 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 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.idx += 1; + if self.sections.len()<=self.idx-1 { + return None; + } + Some(&self.sections[self.idx-1]) + } } /// A color descriptor for [ColorInfo::Palette]. @@ -177,7 +192,7 @@ pub struct FramebufferInfo { /// Boot info collected from provided [Tag]s. #[derive(Clone)] -pub struct BootInfo { +pub struct Multiboot2BootInfo { /// See https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-memory-information. /// Tl;dr: mem_lower indicates the amount of "lower 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 /// the bootloader. /// See https://github.com/AverseABFun/aphrodite/wiki/Plan#bootloader (remember to update link later!) for the format. - pub cmdline: Option, + 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. // 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. /// This should contain the original pointer provided by the bootloader. - pub bootloader_name: Option, + 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. @@ -222,4 +237,4 @@ pub struct BootInfo { // EFI memory map and image handle pointers are not included for portability. // "Image load base physical address" is not included as at the moment the kernel is not relocatable. -} \ No newline at end of file +} diff --git a/kernel/src/include/traits.rs b/kernel/src/include/traits.rs index 17a589d..e9ce602 100644 --- a/kernel/src/include/traits.rs +++ b/kernel/src/include/traits.rs @@ -6,8 +6,8 @@ pub type Color = u8; /// Black-on-black. pub const COLOR_BLACK: Color = 0; -/// Should be whatever colors commonly used for status messages. -/// Generally should be white-on-black. +/// Should be whatever color commonly used for status messages. +/// Generally should be white-on-black. Value is one. pub const COLOR_DEFAULT: Color = 1; /// Some form of display that can be written too with text. diff --git a/kernel/src/internal/arch/x86/entry.rs b/kernel/src/internal/arch/x86_asmp/entry.rs similarity index 65% rename from kernel/src/internal/arch/x86/entry.rs rename to kernel/src/internal/arch/x86_asmp/entry.rs index 94a8002..ef2e815 100644 --- a/kernel/src/internal/arch/x86/entry.rs +++ b/kernel/src/internal/arch/x86_asmp/entry.rs @@ -8,10 +8,12 @@ #![feature(cfg_match)] use core::{arch::asm, ffi::CStr, panic::PanicInfo}; -use aphrodite::multiboot2::{BootInfo, CString, ColorInfo, FramebufferInfo, MemoryMap, MemorySection, PaletteColorDescriptor, RawMemoryMap, RootTag, Tag}; -use aphrodite::arch::x86::output::*; -use aphrodite::arch::x86::egatext as egatext; +use aphrodite::boot::BootInfo; +use aphrodite::multiboot2::{FramebufferInfo, MemoryMap, MemorySection, RawMemoryMap, RootTag, Tag}; +use aphrodite::arch::output::*; +use aphrodite::arch::egatext as egatext; use egatext::*; +use aphrodite::output::*; #[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))] #[unsafe(link_section = ".multiboot2")] @@ -25,26 +27,39 @@ static MULTIBOOT2_HEADER: [u8; 29] = [ // 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 { - 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. 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. static mut MAGIC: u32 = 0xFFFFFFFF; #[unsafe(link_section = ".start")] #[unsafe(no_mangle)] 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 // 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 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 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); // creates a &core::ffi::CStr from the start of the command line... - let cstring = CString { - 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); + BI.cmdline = Some(cstring.to_str().unwrap()); // ...before the BootInfo's commandline is set. }, 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 // and has all of the [aphrodite::multiboot2::MemorySection]s for the memory map - BI.memory_map = Some(MemoryMap { + MM = MemoryMap { version: (*rawmemorymap).entry_version, entry_size: (*rawmemorymap).entry_size, sections: &*core::ptr::from_raw_parts((&(*rawmemorymap).sections[0]) as &MemorySection, (*rawmemorymap).sections.len()), - }); + idx: 0 + }; + BI.memory_map = Some(&MM); }, 2 => { // Bootloader name 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); // creates a &core::ffi::CStr from the start of the bootloader name... - let cstring = CString { - 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); + BI.bootloader_name = Some(cstring.to_str().unwrap()); // ...before the BootInfo's bootloader_name is set. }, 8 => { // Framebuffer info @@ -166,33 +167,30 @@ extern "C" fn _start() -> ! { panic!("size of framebuffer info tag < 32"); } let framebufferinfo: *const FramebufferInfo = (ptr as usize + size_of::()) as *const FramebufferInfo; - let colorinfo: ColorInfo; match (*framebufferinfo).fb_type { 0 => { // Indexed - colorinfo = ColorInfo::Palette { - num_colors: *((ptr + 32) as *const u32), - palette: (ptr + 36) as *const PaletteColorDescriptor - }; + panic!("Indexed color is unimplemented"); }, 1 => { // RGB - colorinfo = ColorInfo::RGBColor { - 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) - } + panic!("RGB color is unimplemented"); }, - 2 => { // EGA Text - colorinfo = ColorInfo::EGAText; + 2 => { // EGA Text }, _ => { panic!("unknown color info type") } } - BI.framebuffer_info = Some((*framebufferinfo).clone()); - BI.color_info = Some(colorinfo); + let framebuffer_info = (*framebufferinfo).clone(); + + 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 swarnings("Unknown tag type "); @@ -232,9 +230,8 @@ extern "C" fn _start() -> ! { sdebugsln("Bootloader information has been successfully loaded"); soutputu(b'\n'); unsafe { - if BI.framebuffer_info.clone().is_some() { - let framebuffer_info = BI.framebuffer_info.clone().unwrap(); - let color_info = BI.color_info.clone().unwrap(); + if BI.output.clone().is_some() { + let framebuffer_info = FBI; sdebugs("Framebuffer 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)); sdebugs("Framebuffer bpp: "); sdebugbnpln(&aphrodite::u8_as_u8_slice(framebuffer_info.bpp)); - sdebugs("Framebuffer type: "); - sdebugbnp(&aphrodite::u8_as_u8_slice(framebuffer_info.fb_type)); + + sdebugsln("Beginning output to screen..."); - match framebuffer_info.fb_type { - 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"); - asm!("hlt", options(noreturn)); - }, - 1 => { // RGB - sdebugsnpln("(RGB)"); + let ega: &dyn aphrodite::TextDisplay = &framebuffer_info; + framebuffer_info.disable_cursor(); + ega.clear_screen(WHITE_ON_BLACK); + tdebugsln("Testing EGA Text framebuffer...", ega).unwrap(); + tdebugsln("Testing EGA Text framebuffer...", ega).unwrap(); + tdebugsln("Testing EGA Text framebuffer...", ega).unwrap(); - sfatalsln("Halting CPU; RGB color unimplemented"); - 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!(); - } - } + aphrodite::_entry::_entry(Some(ega), &BI); } } - unsafe { - aphrodite::_entry::_entry(None, &BI); - } + aphrodite::_entry::_entry(None, &BI); } #[unsafe(link_section = ".panic")] #[panic_handler] #[cfg(not(CONFIG_HALT_ON_PANIC = "false"))] 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(""); if message != "" { - sfatals(message); - aphrodite::arch::x86::ports::outb(aphrodite::arch::x86::DEBUG_PORT, b'\n'); + sfatalsnpln(message); } - aphrodite::arch::x86::interrupts::disable_interrupts(); + aphrodite::arch::interrupts::disable_interrupts(); unsafe { asm!("hlt", options(noreturn)); } @@ -317,11 +289,21 @@ fn halt_on_panic(info: &PanicInfo) -> ! { #[panic_handler] #[cfg(all(CONFIG_SPIN_ON_PANIC = "true", CONFIG_PREUSER_HALT_ON_PANIC = "false"))] 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(""); if message != "" { - sfatals(message); - aphrodite::arch::x86::ports::outb(aphrodite::arch::x86::DEBUG_PORT, b'\n'); + sfatalsnpln(message); } - aphrodite::arch::x86::interrupts::disable_interrupts(); + aphrodite::arch::interrupts::disable_interrupts(); loop {} } \ No newline at end of file