dev: implement #*-cells according to the spec
This commit is contained in:
parent
c49c9fdacd
commit
37e6fc098b
@ -25,6 +25,8 @@ aarch64-cpu = "9.3.1"
|
||||
bitmap-font = { version = "0.3.0", optional = true }
|
||||
embedded-graphics = { version = "0.8.0", optional = true }
|
||||
|
||||
fdt-rs = { version = "0.4.3", default-features = false }
|
||||
|
||||
[dependencies.elf]
|
||||
version = "0.7.2"
|
||||
git = "https://git.alnyan.me/yggdrasil/yggdrasil-elf.git"
|
||||
@ -32,7 +34,6 @@ default-features = false
|
||||
features = ["no_std_stream"]
|
||||
|
||||
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
||||
fdt-rs = { version = "0.4.3", default-features = false }
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
yboot-proto = { git = "https://git.alnyan.me/yggdrasil/yboot-proto.git" }
|
||||
|
@ -25,10 +25,33 @@ pub type TNode<'a> = DevTreeIndexNode<'a, 'a, 'a>;
|
||||
/// Device tree property
|
||||
pub type TProp<'a> = DevTreeIndexProp<'a, 'a, 'a>;
|
||||
|
||||
/// Helper trait to provide extra functionality for [DevTreeIndexProp]
|
||||
pub trait DevTreeIndexPropExt {
|
||||
/// Reads a cell value from single-type cell array at given cell index
|
||||
fn cell1_array_item(&self, index: usize, cells: usize) -> Option<u64>;
|
||||
/// Reads a cell pair from cell pair array at given pair index
|
||||
fn cell2_array_item(&self, index: usize, cells0: usize, cells1: usize) -> Option<(u64, u64)>;
|
||||
|
||||
/// Reads a cell value from the property at given offset
|
||||
fn read_cell(&self, u32_offset: usize, cell_size: usize) -> Option<u64>;
|
||||
}
|
||||
|
||||
/// Helper trait to provide extra functionality for [DevTreeIndexNode]
|
||||
pub trait DevTreeIndexNodeExt {
|
||||
/// Returns the root node's `#address-cells` property, or the default value defined by the
|
||||
/// specification if it's absent
|
||||
fn address_cells(&self) -> usize;
|
||||
/// Returns the root node's `#size-cells` property, or the default value defined by the
|
||||
/// specification if it's absent
|
||||
fn size_cells(&self) -> usize;
|
||||
}
|
||||
|
||||
/// Iterator for physical memory regions present in the device tree
|
||||
#[derive(Clone)]
|
||||
pub struct FdtMemoryRegionIter<'a> {
|
||||
inner: DevTreeIndexNodeSiblingIter<'a, 'a, 'a>,
|
||||
address_cells: usize,
|
||||
size_cells: usize,
|
||||
}
|
||||
|
||||
/// Device tree wrapper struct
|
||||
@ -63,13 +86,73 @@ impl<'a> DeviceTree<'a> {
|
||||
pub fn size(&self) -> usize {
|
||||
self.tree.totalsize()
|
||||
}
|
||||
|
||||
/// Returns the root node's `#address-cells` property, or the default value defined by the
|
||||
/// specification if it's absent
|
||||
pub fn address_cells(&self) -> usize {
|
||||
self.index.root().address_cells()
|
||||
}
|
||||
|
||||
/// Returns the root node's `#size-cells` property, or the default value defined by the
|
||||
/// specification if it's absent
|
||||
pub fn size_cells(&self) -> usize {
|
||||
self.index.root().size_cells()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'i, 'dt> DevTreeIndexNodeExt for DevTreeIndexNode<'a, 'i, 'dt> {
|
||||
fn address_cells(&self) -> usize {
|
||||
self.props()
|
||||
.find(|p| p.name().unwrap_or("") == "#address-cells")
|
||||
.map(|p| p.u32(0).unwrap() as usize)
|
||||
.unwrap_or(2)
|
||||
}
|
||||
|
||||
fn size_cells(&self) -> usize {
|
||||
self.props()
|
||||
.find(|p| p.name().unwrap_or("") == "#size-cells")
|
||||
.map(|p| p.u32(0).unwrap() as usize)
|
||||
.unwrap_or(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'i, 'dt> DevTreeIndexPropExt for DevTreeIndexProp<'a, 'i, 'dt> {
|
||||
fn read_cell(&self, u32_offset: usize, cell_size: usize) -> Option<u64> {
|
||||
match cell_size {
|
||||
1 => self.u32(u32_offset).map(|x| x as u64).ok(),
|
||||
2 => {
|
||||
let high = self.u32(u32_offset).ok()? as u64;
|
||||
let low = self.u32(u32_offset + 1).ok()? as u64;
|
||||
|
||||
Some((high << 32) | low)
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn cell1_array_item(&self, index: usize, cells: usize) -> Option<u64> {
|
||||
self.read_cell(index * cells, cells)
|
||||
}
|
||||
|
||||
fn cell2_array_item(&self, index: usize, cells0: usize, cells1: usize) -> Option<(u64, u64)> {
|
||||
let u32_index = index * (cells0 + cells1);
|
||||
let cell0 = self.read_cell(u32_index, cells0)?;
|
||||
let cell1 = self.read_cell(u32_index + cells0, cells1)?;
|
||||
Some((cell0, cell1))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FdtMemoryRegionIter<'a> {
|
||||
/// Constructs a memory region iterator for given device tree
|
||||
pub fn new(dt: &'a DeviceTree) -> Self {
|
||||
let inner = dt.index.root().children();
|
||||
Self { inner }
|
||||
let address_cells = dt.address_cells();
|
||||
let size_cells = dt.size_cells();
|
||||
Self {
|
||||
inner,
|
||||
address_cells,
|
||||
size_cells,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,15 +173,13 @@ impl Iterator for FdtMemoryRegionIter<'_> {
|
||||
.find(|p| p.name().unwrap_or("") == "reg")
|
||||
.unwrap();
|
||||
|
||||
#[cfg(not(feature = "aarch64_orange_pi3"))]
|
||||
let (base, size) = reg
|
||||
.cell2_array_item(0, self.address_cells, self.size_cells)
|
||||
.unwrap();
|
||||
|
||||
break Some(PhysicalMemoryRegion {
|
||||
base: reg.u64(0).unwrap() as usize,
|
||||
size: reg.u64(1).unwrap() as usize,
|
||||
});
|
||||
#[cfg(feature = "aarch64_orange_pi3")]
|
||||
break Some(PhysicalMemoryRegion {
|
||||
base: reg.u32(0).unwrap() as usize,
|
||||
size: reg.u32(1).unwrap() as usize,
|
||||
base: base as usize,
|
||||
size: size as usize,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ use core::sync::atomic::Ordering;
|
||||
use aarch64_cpu::registers::{DAIF, ID_AA64MMFR0_EL1, SCTLR_EL1, TCR_EL1, TTBR0_EL1, TTBR1_EL1};
|
||||
use abi::error::Error;
|
||||
use cfg_if::cfg_if;
|
||||
use fdt_rs::prelude::PropReader;
|
||||
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
||||
|
||||
use crate::{
|
||||
@ -26,14 +25,14 @@ use crate::{
|
||||
};
|
||||
|
||||
use self::{
|
||||
devtree::DeviceTree,
|
||||
devtree::{DevTreeIndexPropExt, DeviceTree},
|
||||
table::{init_fixed_tables, KERNEL_TABLES},
|
||||
};
|
||||
|
||||
pub mod plat_qemu;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "aarch64_qemu")] {
|
||||
pub mod plat_qemu;
|
||||
|
||||
pub use plat_qemu::{PlatformImpl, PLATFORM};
|
||||
} else if #[cfg(feature = "aarch64_orange_pi3")] {
|
||||
pub mod plat_orange_pi3;
|
||||
@ -163,7 +162,7 @@ impl AArch64 {
|
||||
"dtb",
|
||||
PhysicalMemoryRegion {
|
||||
base: dtb_phys,
|
||||
size: dt.size(),
|
||||
size: (dt.size() + 0xFFF) & !0xFFF,
|
||||
},
|
||||
);
|
||||
|
||||
@ -175,6 +174,7 @@ impl AArch64 {
|
||||
|
||||
fn setup_initrd() {
|
||||
let dt = ARCHITECTURE.device_tree();
|
||||
|
||||
let Some(chosen) = dt.node_by_path("/chosen") else {
|
||||
return;
|
||||
};
|
||||
@ -186,15 +186,19 @@ fn setup_initrd() {
|
||||
return;
|
||||
};
|
||||
|
||||
#[cfg(feature = "aarch64_orange_pi3")]
|
||||
let initrd_start = initrd_start.u32(0).unwrap() as usize;
|
||||
#[cfg(feature = "aarch64_orange_pi3")]
|
||||
let initrd_end = initrd_end.u32(0).unwrap() as usize;
|
||||
let address_cells = dt.address_cells();
|
||||
|
||||
#[cfg(not(feature = "aarch64_orange_pi3"))]
|
||||
let initrd_start = initrd_start.u64(0).unwrap() as usize;
|
||||
#[cfg(not(feature = "aarch64_orange_pi3"))]
|
||||
let initrd_end = initrd_end.u64(0).unwrap() as usize;
|
||||
let Some(initrd_start) = initrd_start.cell1_array_item(0, address_cells) else {
|
||||
infoln!("No initrd specified");
|
||||
return;
|
||||
};
|
||||
let Some(initrd_end) = initrd_end.cell1_array_item(0, address_cells) else {
|
||||
infoln!("No initrd specified");
|
||||
return;
|
||||
};
|
||||
|
||||
let initrd_start = initrd_start as usize;
|
||||
let initrd_end = initrd_end as usize;
|
||||
|
||||
let start_aligned = initrd_start & !0xFFF;
|
||||
let end_aligned = initrd_end & !0xFFF;
|
||||
|
@ -20,9 +20,9 @@ macro_rules! absolute_address {
|
||||
}};
|
||||
}
|
||||
|
||||
pub mod aarch64;
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "aarch64")] {
|
||||
pub mod aarch64;
|
||||
|
||||
pub use aarch64::{AArch64 as ArchitectureImpl, ARCHITECTURE, PlatformImpl, PLATFORM};
|
||||
} else if #[cfg(target_arch = "x86_64")] {
|
||||
|
Loading…
x
Reference in New Issue
Block a user