Compare commits
4 Commits
develop
...
explore/pa
Author | SHA1 | Date |
---|---|---|
|
c618cc18d4 | |
|
0466589ddf | |
|
5c7de9ceec | |
|
059566e698 |
|
@ -2,6 +2,12 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.1"
|
||||
|
@ -35,6 +41,78 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "endian-type-rs"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6419a5c75e40011b9fe0174db3fe24006ab122fbe1b7e9cc5974b338a755c76"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||
|
||||
[[package]]
|
||||
name = "fdt-rs"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99a40cabc11c8258822a593f5c51f2d9f4923e715ca9e2a0630cf77ae15f390b"
|
||||
dependencies = [
|
||||
"endian-type-rs",
|
||||
"fallible-iterator",
|
||||
"memoffset",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"rustc_version",
|
||||
"static_assertions",
|
||||
"unsafe_unwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.27"
|
||||
|
@ -65,6 +143,43 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "shrinkwraprs"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e63e6744142336dfb606fe2b068afa2e1cca1ee6a5d8377277a92945d81fa331"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snafu"
|
||||
version = "0.7.0-beta.0"
|
||||
|
@ -86,6 +201,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.73"
|
||||
|
@ -109,6 +230,12 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe_unwrap"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1230ec65f13e0f9b28d789da20d2d419511893ea9dac2c1f4ef67b8b14e5da80"
|
||||
|
||||
[[package]]
|
||||
name = "usize_conversions"
|
||||
version = "0.2.0"
|
||||
|
@ -129,8 +256,10 @@ dependencies = [
|
|||
"bitflags",
|
||||
"cfg-if",
|
||||
"cortex-a",
|
||||
"fdt-rs",
|
||||
"qemu-exit",
|
||||
"r0",
|
||||
"shrinkwraprs",
|
||||
"snafu",
|
||||
"tock-registers",
|
||||
"usize_conversions",
|
||||
|
|
|
@ -34,3 +34,10 @@ bit_field = "0.10.1"
|
|||
bitflags = "1.2"
|
||||
cfg-if = "1.0"
|
||||
snafu = { version = "0.7.0-beta.0", default-features = false }
|
||||
shrinkwraprs = { version = "0.3", default-features = false }
|
||||
#dtb = "0.2" # Dec 2019 by Simon Prikhodko
|
||||
# Alternatives to dtb to look at:
|
||||
#device_tree = "1.1.0" # Jun 2016 by Marc Brinkmann
|
||||
# fdt-rs latest 0.4.3 Jul 2021 by Sean Wilson -- interface is more basic than in dtb
|
||||
fdt-rs = { version = "0.4", default-features = false }
|
||||
# @todo Added from_raw_pointer() finally
|
||||
|
|
|
@ -8,6 +8,14 @@
|
|||
//! Low-level boot of the Raspberry's processor
|
||||
//! <http://infocenter.arm.com/help/topic/com.arm.doc.dai0527a/DAI0527A_baremetal_boot_code_for_ARMv8_A_processors.pdf>
|
||||
|
||||
//! Raspi kernel boot helper: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub8.S
|
||||
//! In particular, see dtb_ptr32
|
||||
|
||||
//! To get memory size from DTB:
|
||||
//! 1. Find nodes with unit-names `/memory`
|
||||
//! 2. From those read reg entries, using `/#address-cells` and `/#size-cells` as units
|
||||
//! 3. Union of all these reg entries will be the available memory. Enter it as mem-regions.
|
||||
|
||||
use {
|
||||
crate::endless_sleep,
|
||||
cortex_a::{asm, registers::*},
|
||||
|
@ -24,11 +32,11 @@ macro_rules! entry {
|
|||
/// # Safety
|
||||
/// Only type-checks!
|
||||
#[export_name = "main"]
|
||||
pub unsafe fn __main() -> ! {
|
||||
pub unsafe fn __main(dtb: u32) -> ! {
|
||||
// type check the given path
|
||||
let f: fn() -> ! = $path;
|
||||
let f: fn(u32) -> ! = $path;
|
||||
|
||||
f()
|
||||
f(dtb)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -41,7 +49,7 @@ macro_rules! entry {
|
|||
///
|
||||
/// Totally unsafe! We're in the hardware land.
|
||||
#[link_section = ".text.boot"]
|
||||
unsafe fn reset() -> ! {
|
||||
unsafe fn reset(dtb: u32) -> ! {
|
||||
extern "C" {
|
||||
// Boundaries of the .bss section, provided by the linker script
|
||||
static mut __BSS_START: u64;
|
||||
|
@ -52,10 +60,10 @@ unsafe fn reset() -> ! {
|
|||
r0::zero_bss(&mut __BSS_START, &mut __BSS_END);
|
||||
|
||||
extern "Rust" {
|
||||
fn main() -> !;
|
||||
fn main(dtb: u32) -> !;
|
||||
}
|
||||
|
||||
main()
|
||||
main(dtb)
|
||||
}
|
||||
|
||||
// [ARMv6 unaligned data access restrictions](https://developer.arm.com/documentation/ddi0333/h/unaligned-and-mixed-endian-data-access-support/unaligned-access-support/armv6-unaligned-data-access-restrictions?lang=en)
|
||||
|
@ -108,11 +116,16 @@ fn shared_setup_and_enter_pre() {
|
|||
|
||||
#[link_section = ".text.boot"]
|
||||
#[inline]
|
||||
fn shared_setup_and_enter_post() -> ! {
|
||||
fn shared_setup_and_enter_post(dtb: u32) -> ! {
|
||||
// Set up SP_EL1 (stack pointer), which will be used by EL1 once
|
||||
// we "return" to it.
|
||||
SP_EL1.set(STACK_START);
|
||||
|
||||
unsafe {
|
||||
asm!("mov {dtb:w}, w0", dtb = in(reg) dtb);
|
||||
// @todo How to enforce dtb being in w0 at this point? -- must be an arg to eret()
|
||||
}
|
||||
|
||||
// Use `eret` to "return" to EL1. This will result in execution of
|
||||
// `reset()` in EL1.
|
||||
asm::eret()
|
||||
|
@ -123,7 +136,7 @@ fn shared_setup_and_enter_post() -> ! {
|
|||
/// Prepare and execute transition from EL2 to EL1.
|
||||
#[link_section = ".text.boot"]
|
||||
#[inline]
|
||||
fn setup_and_enter_el1_from_el2() -> ! {
|
||||
fn setup_and_enter_el1_from_el2(dtb: u32) -> ! {
|
||||
// Set Saved Program Status Register (EL2)
|
||||
// Set up a simulated exception return.
|
||||
//
|
||||
|
@ -140,7 +153,7 @@ fn setup_and_enter_el1_from_el2() -> ! {
|
|||
// Make the Exception Link Register (EL2) point to reset().
|
||||
ELR_EL2.set(reset as *const () as u64);
|
||||
|
||||
shared_setup_and_enter_post()
|
||||
shared_setup_and_enter_post(dtb)
|
||||
}
|
||||
|
||||
/// QEMU boot-up sequence.
|
||||
|
@ -156,7 +169,7 @@ fn setup_and_enter_el1_from_el2() -> ! {
|
|||
#[cfg(qemu)]
|
||||
#[link_section = ".text.boot"]
|
||||
#[inline]
|
||||
fn setup_and_enter_el1_from_el3() -> ! {
|
||||
fn setup_and_enter_el1_from_el3(dtb: u32) -> ! {
|
||||
// Set Secure Configuration Register (EL3)
|
||||
SCR_EL3.write(SCR_EL3::RW::NextELIsAarch64 + SCR_EL3::NS::NonSecure);
|
||||
|
||||
|
@ -176,7 +189,7 @@ fn setup_and_enter_el1_from_el3() -> ! {
|
|||
// Make the Exception Link Register (EL3) point to reset().
|
||||
ELR_EL3.set(reset as *const () as u64);
|
||||
|
||||
shared_setup_and_enter_post()
|
||||
shared_setup_and_enter_post(dtb)
|
||||
}
|
||||
|
||||
/// Entrypoint of the processor.
|
||||
|
@ -192,7 +205,7 @@ fn setup_and_enter_el1_from_el3() -> ! {
|
|||
///
|
||||
#[no_mangle]
|
||||
#[link_section = ".text.boot.entry"]
|
||||
pub unsafe extern "C" fn _boot_cores() -> ! {
|
||||
pub unsafe extern "C" fn _boot_cores(dtb: u32) -> ! {
|
||||
const CORE_0: u64 = 0;
|
||||
const CORE_MASK: u64 = 0x3;
|
||||
// Can't match values with dots in match, so use intermediate consts.
|
||||
|
@ -207,11 +220,14 @@ pub unsafe extern "C" fn _boot_cores() -> ! {
|
|||
shared_setup_and_enter_pre();
|
||||
|
||||
if CORE_0 == MPIDR_EL1.get() & CORE_MASK {
|
||||
// @todo On entry, w0 should contain the dtb address.
|
||||
// For non-primary cores it however contains 0.
|
||||
|
||||
match CurrentEL.get() {
|
||||
#[cfg(qemu)]
|
||||
EL3 => setup_and_enter_el1_from_el3(),
|
||||
EL2 => setup_and_enter_el1_from_el2(),
|
||||
EL1 => reset(),
|
||||
EL3 => setup_and_enter_el1_from_el3(dtb),
|
||||
EL2 => setup_and_enter_el1_from_el2(dtb),
|
||||
EL1 => reset(dtb),
|
||||
_ => endless_sleep(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
use shrinkwraprs::Shrinkwrap;
|
||||
|
||||
#[derive(Shrinkwrap)]
|
||||
pub struct DeadTree<'a>(dtb::Reader<'a>);
|
||||
|
||||
impl<'a> DeadTree<'a> {
|
||||
pub fn new(reader: dtb::Reader<'a>) -> Self {
|
||||
Self(reader)
|
||||
}
|
||||
|
||||
pub fn try_struct_u32_value<'s, P: Into<&'s str>>(&self, path: P) -> Result<u32, dtb::Error> {
|
||||
let mut buf = [0u8; 4];
|
||||
Ok(self
|
||||
.0
|
||||
.struct_items()
|
||||
.path_struct_items(path.into())
|
||||
.next()
|
||||
.ok_or(dtb::Error::BadPropertyName)?
|
||||
.0
|
||||
.value_u32_list(&mut buf)?[0])
|
||||
}
|
||||
|
||||
pub fn try_struct_str_value<'s, P: Into<&'s str>>(&self, path: P) -> Result<&str, dtb::Error> {
|
||||
self.0
|
||||
.struct_items()
|
||||
.path_struct_items(path.into())
|
||||
.next()
|
||||
.ok_or(dtb::Error::BadPropertyName)?
|
||||
.0
|
||||
.value_str()
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ use architecture_not_supported_sorry;
|
|||
#[macro_use]
|
||||
pub mod arch;
|
||||
pub use arch::*;
|
||||
mod device_tree;
|
||||
mod devices;
|
||||
mod macros;
|
||||
mod mm;
|
||||
|
@ -51,6 +52,7 @@ use {
|
|||
vc::VC,
|
||||
},
|
||||
cfg_if::cfg_if,
|
||||
fdt_rs::base::DevTree,
|
||||
};
|
||||
|
||||
entry!(kmain);
|
||||
|
@ -151,7 +153,7 @@ fn init_uart_serial() {
|
|||
/// Kernel entry point.
|
||||
/// `arch` crate is responsible for calling it.
|
||||
#[inline]
|
||||
pub fn kmain() -> ! {
|
||||
pub fn kmain(dtb: u32) -> ! {
|
||||
#[cfg(feature = "jtag")]
|
||||
jtag::wait_debugger();
|
||||
|
||||
|
@ -164,6 +166,38 @@ pub fn kmain() -> ! {
|
|||
#[cfg(test)]
|
||||
test_main();
|
||||
|
||||
println!("DTB loaded at {:x}", dtb);
|
||||
|
||||
// Safety: we got the address from the bootloader, if it lied - well, we're screwed!
|
||||
let device_tree =
|
||||
unsafe { DevTree::from_raw_pointer(dtb as *const _).expect("DeviceTree failed to read") };
|
||||
|
||||
// List unusable memory, and remove it from the memory regions for the allocator.
|
||||
for entry in device_tree.compatible_nodes("memory") {
|
||||
println!("reserved: {:?} bytes at {:?}", entry.size, entry.address);
|
||||
}
|
||||
// Also, remove the DTB memory region.
|
||||
|
||||
// To init memory allocation we need to parse memory regions from dtb and add the regions to
|
||||
// available memory regions list. Then initial BootRegionAllocator will get memory from these
|
||||
// regions and record their usage into some OTHER structures, removing these allocations from
|
||||
// the free regions list.
|
||||
// memory allocation is described by reg attribute of /memory block.
|
||||
// /#address-cells and /#size-cells specify the sizes of address and size attributes in reg.
|
||||
|
||||
let address_cells = device_tree.try_struct_u32_value("/#address-cells");
|
||||
let size_cells = device_tree.try_struct_u32_value("/#size-cells");
|
||||
let board = device_tree.try_struct_str_value("/model");
|
||||
|
||||
if board.is_ok() {
|
||||
println!("Running on {}", board.unwrap());
|
||||
}
|
||||
|
||||
println!(
|
||||
"Memory DTB info: address-cells {:?}, size-cells {:?}",
|
||||
address_cells, size_cells
|
||||
);
|
||||
|
||||
command_prompt();
|
||||
|
||||
reboot()
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue