dev: implement #*-cells according to the spec

This commit is contained in:
Mark Poliakov 2023-08-09 10:36:32 +03:00
parent c49c9fdacd
commit 37e6fc098b
4 changed files with 110 additions and 24 deletions

View File

@ -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" }

View File

@ -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,
});
}
}

View File

@ -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;

View File

@ -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")] {