diff --git a/crate/atags/Cargo.lock b/crate/atags/Cargo.lock new file mode 100644 index 0000000..42d11eb --- /dev/null +++ b/crate/atags/Cargo.lock @@ -0,0 +1,14 @@ +[[package]] +name = "atags" +version = "0.1.0" +dependencies = [ + "volatile 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "volatile" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum volatile 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ca391c55768e479d5c2f8beb40c136df09257292a809ea514e82cfdfc15d00" diff --git a/crate/atags/Cargo.toml b/crate/atags/Cargo.toml new file mode 100644 index 0000000..3c095bf --- /dev/null +++ b/crate/atags/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "atags" +version = "0.1.0" +authors = ["koumingyang <1761674434@qq.com>"] + +[dependencies] \ No newline at end of file diff --git a/crate/atags/src/atag.rs b/crate/atags/src/atag.rs new file mode 100644 index 0000000..77f729a --- /dev/null +++ b/crate/atags/src/atag.rs @@ -0,0 +1,67 @@ +use raw; +use core::slice; +use core::str; + +pub use raw::{Core, Mem}; + +/// An ATAG. +#[derive(Debug, Copy, Clone)] +pub enum Atag { + Core(raw::Core), + Mem(raw::Mem), + Cmd(&'static str), + Unknown(u32), + None +} + +impl Atag { + /// Returns `Some` if this is a `Core` ATAG. Otherwise returns `None`. + pub fn core(self) -> Option { + match self { + Atag::Core(x) => Some(x), + _ => None, + } + } + + /// Returns `Some` if this is a `Mem` ATAG. Otherwise returns `None`. + pub fn mem(self) -> Option { + match self { + Atag::Mem(x) => Some(x), + _ => None, + } + } + + /// Returns `Some` with the command line string if this is a `Cmd` ATAG. + /// Otherwise returns `None`. + pub fn cmd(self) -> Option<&'static str> { + match self { + Atag::Cmd(x) => Some(x), + _ => None, + } + } +} + +// Convert between raw::* types and Atag wrapper. +impl<'a> From<&'a raw::Atag> for Atag { + fn from(atag: &raw::Atag) -> Atag { + unsafe { + match (atag.tag, &atag.kind) { + (raw::Atag::CORE, &raw::Kind { core }) => Atag::Core(core), + (raw::Atag::MEM, &raw::Kind { mem }) => Atag::Mem(mem), + (raw::Atag::CMDLINE, &raw::Kind { ref cmd }) => { + let mut cmd_ptr: *const u8 = &cmd.cmd as *const u8; + let mut len: usize = 0; + + while *cmd_ptr.add(len) != 0 { + len += 1; + } + + let cmd_slice = slice::from_raw_parts(cmd_ptr, len); + Atag::Cmd(str::from_utf8_unchecked(cmd_slice)) + }, + (raw::Atag::NONE, _) => Atag::None, + (id, _) => Atag::Unknown(id), + } + } + } +} diff --git a/crate/atags/src/atags.rs b/crate/atags/src/atags.rs new file mode 100644 index 0000000..98b7522 --- /dev/null +++ b/crate/atags/src/atags.rs @@ -0,0 +1,37 @@ +pub use atag::*; +use raw; + +/// The address at which the firmware loads the ATAGS. +const ATAG_BASE: usize = 0x100; + +/// An iterator over the ATAGS on this system. +pub struct Atags { + ptr: &'static raw::Atag, +} + +impl Atags { + /// Returns an instance of `Atags`, an iterator over ATAGS on this system. + pub fn get() -> Atags { + Atags { + ptr: unsafe { &*(ATAG_BASE as *const raw::Atag) } + } + } +} + +impl Iterator for Atags { + type Item = Atag; + + /// Iterate over Atags. Returns a valid Atag until the iterator hits the + /// Atag::None. + fn next(&mut self) -> Option { + let cur = self.ptr; + match cur.next() { + Some(next) => { + let result = Some(Atag::from(cur)); + self.ptr = next; + result + }, + None => None, + } + } +} diff --git a/crate/atags/src/lib.rs b/crate/atags/src/lib.rs new file mode 100644 index 0000000..33c76c2 --- /dev/null +++ b/crate/atags/src/lib.rs @@ -0,0 +1,6 @@ +#![no_std] + +mod raw; +mod atag; + +pub mod atags; diff --git a/crate/atags/src/raw.rs b/crate/atags/src/raw.rs new file mode 100644 index 0000000..abfd166 --- /dev/null +++ b/crate/atags/src/raw.rs @@ -0,0 +1,67 @@ +/// A raw `ATAG` as laid out in memory. +#[repr(C)] +pub struct Atag { + pub dwords: u32, + pub tag: u32, + pub kind: Kind +} + +impl Atag { + pub const NONE: u32 = 0x00000000; + pub const CORE: u32 = 0x54410001; + pub const MEM: u32 = 0x54410002; + pub const VIDEOTEXT: u32 = 0x54410003; + pub const RAMDISK: u32 = 0x54410004; + pub const INITRD2: u32 = 0x54420005; + pub const SERIAL: u32 = 0x54410006; + pub const REVISION: u32 = 0x54410007; + pub const VIDEOLFB: u32 = 0x54410008; + pub const CMDLINE: u32 = 0x54410009; + + /// Returns the ATAG following `self`, if there is one. + pub fn next(&self) -> Option<&Atag> { + if self.tag == Atag::NONE { + None + } else { + let current = self as *const Atag as *const u32; + let next: &Atag = unsafe { + &*(current.add(self.dwords as usize) as *const Atag) + }; + + Some(next) + } + } +} + +/// The possible variant of an ATAG. +#[repr(C)] +pub union Kind { + pub core: Core, + pub mem: Mem, + pub cmd: Cmd +} + +/// A `CORE` ATAG. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Core { + pub flags: u32, + pub page_size: u32, + pub root_dev: u32 +} + +/// A `MEM` ATAG. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Mem { + pub size: u32, + pub start: u32 +} + +/// A `CMDLINE` ATAG. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Cmd { + /// The first byte of the command line string. + pub cmd: u8 +} diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 3d0ffa6..e1b7d05 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -1,3 +1,7 @@ +[[package]] +name = "atags" +version = "0.1.0" + [[package]] name = "bare-metal" version = "0.2.3" @@ -239,6 +243,7 @@ dependencies = [ name = "ucore" version = "0.1.0" dependencies = [ + "atags 0.1.0", "bbl 0.1.0", "bcm2837 0.1.0", "bit-allocator 0.1.0", @@ -246,6 +251,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bootloader 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cortex-a 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked_list_allocator 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 476d0c5..e2bba97 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -44,6 +44,8 @@ riscv = { path = "../crate/riscv" } bbl = { path = "../crate/bbl" } [target.'cfg(target_arch = "aarch64")'.dependencies] +cortex-a = "2.2.1" +atags = { path = "../crate/atags" } bcm2837 = { path = "../crate/bcm2837", features = ["use_generic_timer"] } [package.metadata.bootimage] diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index 05fff9d..085ab36 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -1,8 +1,34 @@ //! Memory initialization for aarch64. use ucore_memory::PAGE_SIZE; +use super::atags::atags::Atags; +use super::super::HEAP_ALLOCATOR; /// Memory initialization. pub fn init() { - // TODO + let (start, end) = memory_map().expect("failed to find memory map"); + unsafe { + HEAP_ALLOCATOR.lock().init(start, end - start); + } +} + +extern "C" { + static _end: u8; +} + +/// Returns the (start address, end address) of the available memory on this +/// system if it can be determined. If it cannot, `None` is returned. +/// +/// This function is expected to return `Some` under all normal cirumstances. +pub fn memory_map() -> Option<(usize, usize)> { + let binary_end = unsafe { (&_end as *const u8) as u32 }; + + let mut atags: Atags = Atags::get(); + while let Some(atag) = atags.next() { + if let Some(mem) = atag.mem() { + return Some((binary_end as usize, (mem.start + mem.size) as usize)); + } + } + + None } diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 01f4d4e..826078d 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -1,5 +1,7 @@ //! Entrance and initialization for aarch64. +extern crate atags; + pub mod io; pub mod paging; pub mod memory; @@ -18,6 +20,18 @@ pub extern "C" fn rust_main() -> ! { // Init board to enable serial port. board::init(); + let (start, end) = memory::memory_map().expect("failed to find memory map"); + println!("The value of start is: {}, end is {}", start, end); + + memory::init(); + println!("memory init over"); + + let mut v = vec![]; + for i in 0..1000 { + v.push(i); + println!("{:?}", v); + } + // First init log mod, so that we can print log info. // FIXME // ::logging::init();