diff --git a/Cargo.lock b/Cargo.lock index d843811efe22190e71bd657fdf6c4db700d12a7c..8876d327e78a5fa8402ac2a7748a99822195cf91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,11 @@ name = "bitflags" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byteorder" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cc" version = "1.0.17" @@ -35,6 +40,7 @@ name = "pamb_os" version = "0.1.0" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "linked_list_allocator 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -105,6 +111,7 @@ dependencies = [ [metadata] "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" "checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d" "checksum goblin 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81af14056c25d33759862c5ae2035452acb1255bfb1b16db57819f183921e259" "checksum linked_list_allocator 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1ee3eeeadfa301cf51b59684c034ad47a9796d03a8b70650d46b6b400a4a3258" diff --git a/Cargo.toml b/Cargo.toml index 934bfe55b702f4fea92f916aaf2aceeaf0ced574..2c081d74a67062a55db73f22f62e459299ed6cbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ linked_list_allocator = "0.6.1" slab_allocator = { path = "slab_allocator" , optional = true} raw-cpuid = "3.0" redox_syscall = { path = "syscall"} +byteorder = { version = "1", default-features = false } [profile.dev] panic = "abort" diff --git a/LICENSE b/LICENSE index b19d52dca835c8e06c9abba410946b6586fb3ee0..a9ea7f89bce708f7a837df059bbc28fa75dfe6da 100644 --- a/LICENSE +++ b/LICENSE @@ -20,6 +20,10 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +This project is based on the Redox kernel. +Link: https://gitlab.redox-os.org/redox-os/kernel +The license for the Redox kernel is as follows: + MIT License Copyright (c) 2017 Jeremy Soller diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs index e5da1dd68a3efcc26d097b8a8622bc993469ba76..dc4ea40cd698394c73eeac3d667721be3f400af1 100755 --- a/src/arch/x86_64/start.rs +++ b/src/arch/x86_64/start.rs @@ -18,6 +18,7 @@ use idt; use interrupt; use memory; use paging; +use paging::ActivePageTable; /// Test of zero values in BSS. static BSS_TEST_ZERO: usize = 0; @@ -48,7 +49,7 @@ pub struct KernelArgs { /// The entry to Rust, all things must be initialized #[no_mangle] -pub unsafe extern fn kstart(args_ptr: *const KernelArgs) { +pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ActivePageTable { let env = { let args = &*args_ptr; @@ -131,9 +132,11 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) { BSP_READY.store(true, Ordering::SeqCst); - slice::from_raw_parts(env_base as *const u8, env_size) + slice::from_raw_parts(env_base as *const u8, env_size); + active_table }; - + env + // ::kmain(CPU_COUNT.load(Ordering::SeqCst), env); } diff --git a/src/lib.rs b/src/lib.rs index 4ecdc491f591ce005d06bf3890e9623faa973a35..4b692085da5ac37cbf8709a07da88c5fcb480983 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,15 +8,16 @@ #![feature(naked_functions)] #![feature(thread_local)] #![feature(alloc)] -//#![feature(allocator_internals)] -//#![default_lib_allocator] #![feature(allocator_api, heap_api)] #![feature(global_allocator)] #![feature(core_intrinsics)] +#![feature(type_ascription)] + extern crate rlibc; extern crate spin; extern crate syscall; extern crate linked_list_allocator; +extern crate byteorder; #[cfg(feature = "slab")] extern crate slab_allocator; @@ -42,6 +43,7 @@ pub mod allocator; pub mod memory; pub mod time; pub mod elf; +pub mod partition; //pub mod paging; pub mod consts; pub mod panic; @@ -68,128 +70,13 @@ static ALLOCATOR: allocator::Allocator = allocator::Allocator; use core::slice; use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; -/// Test of zero values in BSS. -static BSS_TEST_ZERO: usize = 0; -/// Test of non-zero values in data. -static DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF; -/// Test of zero values in thread BSS -#[thread_local] -static mut TBSS_TEST_ZERO: usize = 0; -/// Test of non-zero values in thread data. -#[thread_local] -static mut TDATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF; - -pub static KERNEL_BASE: AtomicUsize = ATOMIC_USIZE_INIT; -pub static KERNEL_SIZE: AtomicUsize = ATOMIC_USIZE_INIT; -pub static CPU_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; -pub static AP_READY: AtomicBool = ATOMIC_BOOL_INIT; -pub static BSP_READY: AtomicBool = ATOMIC_BOOL_INIT; - -/* -#[repr(packed)] -pub struct KernelArgs { - kernel_base: u64, - kernel_size: u64, - stack_base: u64, - stack_size: u64, - env_base: u64, - env_size: u64, -} -*/ - +//pub const BLOCK_SIZE: u64 = 4096; + #[no_mangle] pub unsafe extern fn rust_main(args_ptr: *const arch::x86_64::start::KernelArgs) -> ! { - arch::x86_64::start::kstart(args_ptr); -// vga_buffer::clear_screen(); - /* let env = { - let args = &*args_ptr; - - let kernel_base = args.kernel_base as usize; - let kernel_size = args.kernel_size as usize; - let stack_base = args.stack_base as usize; - let stack_size = args.stack_size as usize; - let env_base = args.env_base as usize; - let env_size = args.env_size as usize; - - // BSS should already be zero - { - assert_eq!(BSS_TEST_ZERO, 0); - assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF); - } - - KERNEL_BASE.store(kernel_base, Ordering::SeqCst); - KERNEL_SIZE.store(kernel_size, Ordering::SeqCst); - - println!("Kernel: {:X}:{:X}", kernel_base, kernel_base + kernel_size); - println!("Stack: {:X}:{:X}", stack_base, stack_base + stack_size); - println!("Env: {:X}:{:X}", env_base, env_base + env_size); - // Set up GDT before paging - gdt::init(); - - };*/ - /* // Set up IDT before paging - idt::init(); - - // Initialize memory management - memory::init(0, kernel_base + ((kernel_size + 4095)/4096) * 4096); - - // Initialize paging - let (mut active_table, tcb_offset) = paging::init(0, kernel_base, kernel_base + kernel_size, stack_base, stack_base + stack_size); - - // Set up GDT after paging with TLS - gdt::init_paging(tcb_offset, stack_base + stack_size); - - // Set up IDT - idt::init_paging(); - - // Test tdata and tbss - { - assert_eq!(TBSS_TEST_ZERO, 0); - TBSS_TEST_ZERO += 1; - assert_eq!(TBSS_TEST_ZERO, 1); - assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF); - TDATA_TEST_NONZERO -= 1; - assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFE); - } - - // Reset AP variables - CPU_COUNT.store(1, Ordering::SeqCst); - AP_READY.store(false, Ordering::SeqCst); - BSP_READY.store(false, Ordering::SeqCst); - - // Setup kernel heap - allocator::init(&mut active_table); - - // Use graphical debug - #[cfg(feature="graphical_debug")] - graphical_debug::init(&mut active_table); - - // Initialize devices - device::init(&mut active_table); - - // Read ACPI tables, starts APs - #[cfg(feature = "acpi")] - acpi::init(&mut active_table); - - // Initialize all of the non-core devices not otherwise needed to complete initialization - device::init_noncore(); - - // Initialize memory functions after core has loaded - memory::init_noncore(); - - // Stop graphical debug - #[cfg(feature="graphical_debug")] - graphical_debug::fini(&mut active_table); - - BSP_READY.store(true, Ordering::SeqCst); - - slice::from_raw_parts(env_base as *const u8, env_size) - }; - - - serial::init(); -*/ + let mut active_table = arch::x86_64::start::kstart(args_ptr); + let mut mbr = partition::read_bootsector(&mut active_table); println!("Hello World!"); println!("Loader Stub Initialized"); diff --git a/src/partition/mbr.rs b/src/partition/mbr.rs new file mode 100755 index 0000000000000000000000000000000000000000..a9bbf4fea98cb32fe87ddbbb314846a02e08b564 --- /dev/null +++ b/src/partition/mbr.rs @@ -0,0 +1,93 @@ +use byteorder::{LittleEndian, ByteOrder}; +use core::{slice, mem}; +use core::ops::{Deref, DerefMut}; + +use paging::PAGE_SIZE; + +#[repr(packed)] +#[derive(Copy, Clone)] +pub struct MbrTableEntry +{ + data: [u8; 16] +} + +#[repr(packed)] +#[derive(Copy, Clone)] +pub struct Mbr +{ + /// The bootstrap code, last 10 bytes can be used as the uuid + pub code: [u8; 446], + /// The partition partition table + pub partition_table: [MbrTableEntry; 4], + /// Signature bytes + pub signature: [u8; 2], + /// Padding + pub padding: [u8; PAGE_SIZE - 512] +} + +impl Mbr +{ + pub fn default() -> Mbr { + Mbr { + code: [0; 446], + partition_table: [MbrTableEntry::new(); 4], + signature: [0; 2], + padding: [0; PAGE_SIZE - 512] + } + } + + pub fn is_valid(&self) -> bool { + self.signature[0] == 0x55 && self.signature[1] == 0xaa + } + +} + +impl MbrTableEntry +{ + pub fn new() -> MbrTableEntry { + MbrTableEntry { + data: [0; 16] + } + } + + pub fn is_bootable(&self) -> bool + { + self.data[0] == 0x80 + } + + pub fn system_id(&self) -> u8 + { + self.data[4] + } + + pub fn starting_lba(&self) -> u32 + { + let mut buf = &self.data[8..12]; + LittleEndian::read_u32(&buf) + } + + pub fn partition_length(&self) -> u32 + { + let mut buf = &self.data[12..16]; + LittleEndian::read_u32(&buf) + } + +} + +impl Deref for MbrTableEntry { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const MbrTableEntry as *const u8, mem::size_of::<MbrTableEntry>()) as &[u8] + } + } +} + +impl DerefMut for MbrTableEntry { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut MbrTableEntry as *mut u8, mem::size_of::<MbrTableEntry>()) as &mut [u8] + } + } +} + diff --git a/src/partition/mod.rs b/src/partition/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..f80ef6398929184e70a57ea5ec65227761047c2e --- /dev/null +++ b/src/partition/mod.rs @@ -0,0 +1,54 @@ +use memory::Frame; +use paging::{ActivePageTable, Page, PhysicalAddress, VirtualAddress}; +use paging::entry::EntryFlags; +use paging::mapper::MapperFlushAll; + +use self::mbr::Mbr; +use paging::PAGE_SIZE; +pub mod mbr; + + +pub fn read_bootsector(active_table: &mut ActivePageTable) -> Mbr { + let mut mbr = Mbr::default(); + let bootsector_addr = 0x7c00; + let follow_up = 0x7c00 + PAGE_SIZE; + + let ret; + { + let page = Page::containing_address(VirtualAddress::new(bootsector_addr)); + let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get())); + let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::NO_EXECUTE); + result.flush(active_table); + } + + { + let page = Page::containing_address(VirtualAddress::new(follow_up)); + let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get())); + let result = active_table.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::NO_EXECUTE); + result.flush(active_table); + } + + + + { + let bootsector = unsafe { &mut *(bootsector_addr as *mut Mbr) }; + ret = bootsector.clone(); + println!("Checking if Bootsector is valid: {}", bootsector.is_valid()); + } + + { + let page = Page::containing_address(VirtualAddress::new(bootsector_addr)); + let (result, _frame) = active_table.unmap_return(page, false); + result.flush(active_table); + } + + { + let page = Page::containing_address(VirtualAddress::new(follow_up)); + let (result, _frame) = active_table.unmap_return(page, false); + result.flush(active_table); + } + + + ret +} + diff --git a/src/vga_buffer.rs b/src/vga_buffer.rs deleted file mode 100644 index 952d5457bd7eaaf5de74072ea595717a1506075c..0000000000000000000000000000000000000000 --- a/src/vga_buffer.rs +++ /dev/null @@ -1,157 +0,0 @@ -#[allow(dead_code)] -#[repr(u8)] -#[derive(Clone, Copy)] -pub enum Color { - Black = 0, - Blue = 1, - Green = 2, - Cyan = 3, - Red = 4, - Magenta = 5, - Brown = 6, - LightGray = 7, - DarkGray = 8, - LightBlue = 9, - LightGreen = 10, - LightCyan = 11, - LightRed = 12, - Pink = 13, - Yellow = 14, - White = 15, -} -#[derive(Clone, Copy)] -struct ColorCode(u8); - -impl ColorCode { - const fn new(foreground: Color, background: Color) -> ColorCode { - ColorCode((background as u8) << 4 | (foreground as u8)) - } -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct ScreenChar { - ascii_character: u8, - color_code: ColorCode, -} - -const BUFFER_HEIGHT: usize = 25; -const BUFFER_WIDTH: usize = 80; - -struct Buffer { - chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT], -} - - -use core::ptr::Unique; - -pub struct Writer { - column_position: usize, - color_code: ColorCode, - buffer: *mut Buffer, -} - -impl Writer { - pub fn write_byte(&mut self, byte: u8) { - match byte { - b'\n' => self.new_line(), - byte => { - if self.column_position >= BUFFER_WIDTH { - self.new_line(); - } - - let row = BUFFER_HEIGHT - 1; - let col = self.column_position; - - self.buffer().chars[row][col] = ScreenChar { - ascii_character: byte, - color_code: self.color_code, - }; - self.column_position += 1; - } - } - } - - fn buffer(&mut self) -> &mut Buffer { - use core::intrinsics::transmute; - unsafe { transmute::<*mut Buffer, &mut Buffer>(self.buffer) } - } - - fn new_line(&mut self) { - for row in 0..(BUFFER_HEIGHT - 1) { - let buffer = self.buffer(); - buffer.chars[row] = buffer.chars[row + 1] - } - - self.clear_row(BUFFER_HEIGHT - 1); - self.column_position = 0; - } - - fn clear_row(&mut self, row: usize) { - let blank = ScreenChar { - ascii_character: b' ', - color_code: self.color_code, - }; - self.buffer().chars[row] = [blank; BUFFER_WIDTH]; - } - - - - pub fn write_str(&mut self, s: &str) { - for byte in s.bytes() { - self.write_byte(byte) - } - } -} - -pub fn print_something() { - let mut writer = Writer { - column_position: 0, - color_code: ColorCode::new(Color::LightGreen, Color::Black), - buffer: unsafe { 0xb8000 as *mut _ } - }; - - writer.write_byte(b'H'); -} - -impl ::core::fmt::Write for Writer { - fn write_str(&mut self, s: &str) -> ::core::fmt::Result { - for byte in s.bytes() { - self.write_byte(byte) - } - Ok(()) - } -} - -use spin::Mutex; - -pub static WRITER: Mutex<Writer> = Mutex::new(Writer { - column_position: 0, - color_code: ColorCode::new(Color::LightGreen, Color::Black), - buffer: unsafe { 0xb8000 as *mut _} -}); - -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -macro_rules! print { - ($($arg:tt)*) => ({ - use core::fmt::Write; - let mut writer = $crate::vga_buffer::WRITER.lock(); - writer.write_fmt(format_args!($($arg)*)).unwrap(); - }); -} - -pub fn clear_screen() { - for _ in 0..BUFFER_HEIGHT { - println!(""); - } -} - - - - - -