parent
9fc13c8ebb
commit
a13f39149b
@ -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"
|
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "atags"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["koumingyang <1761674434@qq.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
@ -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<Core> {
|
||||||
|
match self {
|
||||||
|
Atag::Core(x) => Some(x),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `Some` if this is a `Mem` ATAG. Otherwise returns `None`.
|
||||||
|
pub fn mem(self) -> Option<Mem> {
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<Atag> {
|
||||||
|
let cur = self.ptr;
|
||||||
|
match cur.next() {
|
||||||
|
Some(next) => {
|
||||||
|
let result = Some(Atag::from(cur));
|
||||||
|
self.ptr = next;
|
||||||
|
result
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
#![no_std]
|
||||||
|
|
||||||
|
mod raw;
|
||||||
|
mod atag;
|
||||||
|
|
||||||
|
pub mod atags;
|
@ -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
|
||||||
|
}
|
@ -1,8 +1,34 @@
|
|||||||
//! Memory initialization for aarch64.
|
//! Memory initialization for aarch64.
|
||||||
|
|
||||||
use ucore_memory::PAGE_SIZE;
|
use ucore_memory::PAGE_SIZE;
|
||||||
|
use super::atags::atags::Atags;
|
||||||
|
use super::super::HEAP_ALLOCATOR;
|
||||||
|
|
||||||
/// Memory initialization.
|
/// Memory initialization.
|
||||||
pub fn init() {
|
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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in new issue