Upgrade fdt library to the very latest

The new helpers remove a lot of boilerplace. Unfortunately some rough edges still remain (in particular issue gh#12 which renders interrupts() helper useless)
This commit is contained in:
Andrey Turkin
2024-07-16 05:23:00 +03:00
parent 32e114885b
commit d08861e586
11 changed files with 149 additions and 370 deletions
Generated
+2 -5
View File
@@ -76,11 +76,8 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fdt"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/rosehuds/fdt.git#7358607679114ccab5f97e14894ed3b59c5d42d6"
dependencies = [
"byteorder",
]
version = "0.2.0-alpha1"
source = "git+https://github.com/repnop/fdt.git?rev=2fb1409edd1877c714a0aa36b6a7c5351004be54#2fb1409edd1877c714a0aa36b6a7c5351004be54"
[[package]]
name = "goblin"
+1 -1
View File
@@ -37,7 +37,7 @@ default-features = false
[target.'cfg(target_arch = "aarch64")'.dependencies]
byteorder = { version = "1", default-features = false }
fdt = { git = "https://gitlab.redox-os.org/rosehuds/fdt.git", default-features = false }
fdt = { git = "https://github.com/repnop/fdt.git", rev = "2fb1409edd1877c714a0aa36b6a7c5351004be54" }
[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies]
raw-cpuid = "10.2.0"
+8 -14
View File
@@ -3,11 +3,11 @@ use log::info;
use crate::{
arch::device::irqchip::IRQ_CHIP, context, context::timeout,
device::cpu::registers::control_regs, dtb::DTB_BINARY, init::device_tree::find_compatible_node,
interrupt::irq::trigger, time,
device::cpu::registers::control_regs, dtb::DTB_BINARY, interrupt::irq::trigger, time,
};
use alloc::vec::Vec;
use byteorder::{ByteOrder, BE};
use fdt::Fdt;
use super::irqchip::{register_irq, InterruptHandler};
@@ -26,23 +26,17 @@ pub unsafe fn init() {
};
timer.init();
let data = DTB_BINARY.get().unwrap();
let fdt = fdt::DeviceTree::new(data).unwrap();
if let Some(node) = find_compatible_node(&fdt, "arm,armv7-timer") {
let interrupts = node
.properties()
.find(|p| p.name.contains("interrupts"))
.unwrap();
let fdt = Fdt::new(data).unwrap();
if let Some(node) = fdt.find_compatible(&["arm,armv7-timer"]) {
let interrupts = node.property("interrupts").unwrap();
let mut intr_data = Vec::new();
for chunk in interrupts.data.chunks(4) {
for chunk in interrupts.value.chunks(4) {
let val = BE::read_u32(chunk);
intr_data.push(val);
}
let mut ic_idx = IRQ_CHIP.irq_chip_list.root_idx;
if let Some(interrupt_parent) = node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
{
let phandle = BE::read_u32(interrupt_parent.data);
if let Some(interrupt_parent) = node.property("interrupt-parent") {
let phandle = interrupt_parent.as_usize().unwrap() as u32;
let mut i = 0;
while i < IRQ_CHIP.irq_chip_list.chips.len() {
let item = &IRQ_CHIP.irq_chip_list.chips[i];
+14 -18
View File
@@ -1,10 +1,7 @@
use core::ptr::{read_volatile, write_volatile};
use fdt::{node::FdtNode, Fdt};
use byteorder::{ByteOrder, BE};
use fdt::{DeviceTree, Node};
use crate::init::device_tree::find_compatible_node;
use log::{debug, info};
use log::info;
use syscall::{
error::{Error, EINVAL},
Result,
@@ -46,30 +43,29 @@ impl GenericInterruptController {
irq_range: (0, 0),
}
}
pub fn parse(fdt: &DeviceTree) -> Result<(usize, usize, usize, usize)> {
if let Some(node) = find_compatible_node(fdt, "arm,cortex-a15-gic") {
pub fn parse(fdt: &Fdt) -> Result<(usize, usize, usize, usize)> {
if let Some(node) = fdt.find_compatible(&["arm,cortex-a15-gic"]) {
return GenericInterruptController::parse_inner(&node);
} else {
return Err(Error::new(EINVAL));
}
}
fn parse_inner(node: &Node) -> Result<(usize, usize, usize, usize)> {
fn parse_inner(node: &FdtNode) -> Result<(usize, usize, usize, usize)> {
//assert address_cells == 0x2, size_cells == 0x2
let reg = node.properties().find(|p| p.name.contains("reg")).unwrap();
let reg = node.reg().unwrap();
let mut regs = (0, 0, 0, 0);
let mut idx = 0;
for chunk in reg.data.chunks(8) {
let val = BE::read_u64(chunk) as usize;
debug!("idx{} = {:08x}", idx, val);
for chunk in reg {
if chunk.size.is_none() {
break;
}
match idx {
0 => regs.0 = val,
1 => regs.1 = val,
2 => regs.2 = val,
3 => regs.3 = val,
0 => (regs.0, regs.1) = (chunk.starting_address as usize, chunk.size.unwrap()),
2 => (regs.2, regs.3) = (chunk.starting_address as usize, chunk.size.unwrap()),
_ => break,
}
idx += 1;
idx += 2;
}
if idx == 4 {
@@ -83,7 +79,7 @@ impl GenericInterruptController {
impl InterruptController for GenericInterruptController {
fn irq_init(
&mut self,
fdt: &DeviceTree,
fdt: &Fdt,
irq_desc: &mut [IrqDesc; 1024],
ic_idx: usize,
irq_idx: &mut usize,
+15 -24
View File
@@ -1,11 +1,9 @@
use alloc::vec::Vec;
use core::arch::asm;
use byteorder::{ByteOrder, BE};
use fdt::DeviceTree;
use fdt::{node::NodeProperty, Fdt};
use super::gic::GicDistIf;
use crate::init::device_tree::find_compatible_node;
use log::info;
use syscall::{
error::{Error, EINVAL},
Result,
@@ -36,8 +34,8 @@ impl GicV3 {
}
}
pub fn parse(&mut self, fdt: &DeviceTree) -> Result<()> {
let Some(node) = find_compatible_node(fdt, "arm,gic-v3") else {
pub fn parse(&mut self, fdt: &Fdt) -> Result<()> {
let Some(node) = fdt.find_compatible(&["arm,gic-v3"]) else {
return Err(Error::new(EINVAL));
};
@@ -47,30 +45,23 @@ impl GicV3 {
self.gicrs.clear();
// Get number of GICRs
let gicrs = match node
.properties()
.find(|p| p.name.contains("#redistributor-regions"))
{
Some(prop) => BE::read_u32(prop.data),
None => 1,
};
let gicrs = node
.property("#redistributor-regions")
.and_then(NodeProperty::as_usize)
.unwrap_or(1);
// Read registers
let reg = node.properties().find(|p| p.name.contains("reg")).unwrap();
let mut chunks = reg.data.chunks_exact(16).map(|chunk| {
(
BE::read_u64(&chunk[0..8]) as usize,
BE::read_u64(&chunk[8..16]) as usize,
)
});
if let Some((gicd_addr, _gicd_size)) = chunks.next() {
let mut chunks = node.reg().unwrap();
if let Some(gicd) = chunks.next() {
unsafe {
self.gic_dist_if.init(crate::PHYS_OFFSET + gicd_addr);
self.gic_dist_if
.init(crate::PHYS_OFFSET + gicd.starting_address as usize);
}
}
for _ in 0..gicrs {
if let Some(gicr) = chunks.next() {
self.gicrs.push(gicr);
self.gicrs
.push((gicr.starting_address as usize, gicr.size.unwrap()));
}
}
@@ -85,7 +76,7 @@ impl GicV3 {
impl InterruptController for GicV3 {
fn irq_init(
&mut self,
fdt: &DeviceTree,
fdt: &Fdt,
irq_desc: &mut [IrqDesc; 1024],
ic_idx: usize,
irq_idx: &mut usize,
+12 -21
View File
@@ -3,9 +3,8 @@ use core::ptr::{read_volatile, write_volatile};
use crate::arch::device::irqchip::IRQ_CHIP;
use byteorder::{ByteOrder, BE};
use fdt::{DeviceTree, Node};
use fdt::{node::FdtNode, Fdt};
use crate::init::device_tree::find_compatible_node;
use log::{debug, error, info};
use syscall::{
@@ -67,33 +66,25 @@ impl Bcm2835ArmInterruptController {
irq_range: (0, 0),
}
}
pub fn parse(fdt: &DeviceTree) -> Result<(usize, usize, Option<usize>)> {
//TODO: try to parse dtb using stable library
if let Some(node) = find_compatible_node(fdt, "brcm,bcm2836-armctrl-ic") {
pub fn parse(fdt: &Fdt) -> Result<(usize, usize, Option<usize>)> {
if let Some(node) = fdt.find_compatible(&["brcm,bcm2836-armctrl-ic"]) {
return unsafe { Bcm2835ArmInterruptController::parse_inner(&node) };
} else {
return Err(Error::new(EINVAL));
}
}
unsafe fn parse_inner(node: &Node) -> Result<(usize, usize, Option<usize>)> {
unsafe fn parse_inner(node: &FdtNode) -> Result<(usize, usize, Option<usize>)> {
//assert address_cells == 0x1, size_cells == 0x1
let reg = node.properties().find(|p| p.name.contains("reg")).unwrap();
let (base, size) = reg.data.split_at(4);
let base = BE::read_u32(base);
let size = BE::read_u32(size);
let mem = node.reg().unwrap().nth(0).unwrap();
let base = mem.starting_address as u32;
let size = mem.size.unwrap() as u32;
let mut ret_virq = None;
if let Some(interrupt_parent) = node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
{
let phandle = BE::read_u32(interrupt_parent.data);
let interrupts = node
.properties()
.find(|p| p.name.contains("interrupts"))
.unwrap();
if let Some(interrupt_parent) = node.property("interrupt-parent") {
let phandle = interrupt_parent.as_usize().unwrap() as u32;
let interrupts = node.property("interrupts").unwrap();
let mut intr_data = Vec::new();
for chunk in interrupts.data.chunks(4) {
for chunk in interrupts.value.chunks(4) {
let val = BE::read_u32(chunk);
intr_data.push(val);
}
@@ -141,7 +132,7 @@ impl Bcm2835ArmInterruptController {
impl InterruptController for Bcm2835ArmInterruptController {
fn irq_init(
&mut self,
fdt: &DeviceTree,
fdt: &Fdt,
irq_desc: &mut [IrqDesc; 1024],
ic_idx: usize,
irq_idx: &mut usize,
+7 -15
View File
@@ -2,13 +2,9 @@ use core::{
arch::asm,
ptr::{read_volatile, write_volatile},
};
use fdt::{node::FdtNode, Fdt};
use byteorder::{ByteOrder, BE};
use fdt::{DeviceTree, Node};
use crate::init::device_tree::find_compatible_node;
use log::{debug, info};
use syscall::{
error::{Error, EINVAL},
Result,
@@ -71,22 +67,18 @@ impl Bcm2836ArmInterruptController {
active_cpu: 0,
}
}
pub fn parse(fdt: &DeviceTree) -> Result<(usize, usize)> {
//TODO: try to parse dtb using stable library
if let Some(node) = find_compatible_node(fdt, "brcm,bcm2836-l1-intc") {
pub fn parse(fdt: &Fdt) -> Result<(usize, usize)> {
if let Some(node) = fdt.find_compatible(&["brcm,bcm2836-l1-intc"]) {
return Bcm2836ArmInterruptController::parse_inner(&node);
} else {
return Err(Error::new(EINVAL));
}
}
fn parse_inner(node: &Node) -> Result<(usize, usize)> {
fn parse_inner(node: &FdtNode) -> Result<(usize, usize)> {
//assert address_cells == 0x1, size_cells == 0x1
let reg = node.properties().find(|p| p.name.contains("reg")).unwrap();
let (base, size) = reg.data.split_at(4);
let base = BE::read_u32(base);
let size = BE::read_u32(size);
let reg = node.reg().unwrap().nth(0).unwrap();
Ok((base as usize, size as usize))
Ok((reg.starting_address as usize, reg.size.unwrap()))
}
unsafe fn init(&mut self) {
@@ -114,7 +106,7 @@ impl Bcm2836ArmInterruptController {
impl InterruptController for Bcm2836ArmInterruptController {
fn irq_init(
&mut self,
fdt: &DeviceTree,
fdt: &Fdt,
irq_desc: &mut [IrqDesc; 1024],
ic_idx: usize,
irq_idx: &mut usize,
+23 -44
View File
@@ -1,6 +1,6 @@
use alloc::{boxed::Box, vec::Vec};
use byteorder::{ByteOrder, BE};
use fdt::DeviceTree;
use fdt::Fdt;
use syscall::Result;
use crate::init::device_tree::travel_interrupt_ctrl;
@@ -14,7 +14,7 @@ mod irq_bcm2836;
pub trait InterruptController {
fn irq_init(
&mut self,
fdt: &DeviceTree,
fdt: &Fdt,
irq_desc: &mut [IrqDesc; 1024],
ic_idx: usize,
irq_idx: &mut usize,
@@ -62,62 +62,41 @@ pub struct IrqDesc {
}
impl IrqChipList {
fn init_inner1(&mut self, fdt: &fdt::DeviceTree) {
let root_node = fdt.nodes().nth(0).unwrap();
fn init_inner1(&mut self, fdt: &Fdt) {
let root_node = fdt.root();
let mut idx = 0;
let intr = root_node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
.unwrap();
let intr = root_node.property("interrupt-parent").unwrap();
let root_intr_parent = BE::read_u32(&intr.data);
let root_intr_parent = intr.as_usize().unwrap() as u32;
debug!("root parent = 0x{:08x}", root_intr_parent);
self.root_phandle = root_intr_parent;
for node in fdt.nodes() {
if node
.properties()
.find(|p| p.name.contains("interrupt-controller"))
.is_some()
{
let compatible = node
.properties()
.find(|p| p.name.contains("compatible"))
.unwrap();
let phandle = node
.properties()
.find(|p| p.name.contains("phandle"))
.unwrap();
let intr_cells = node
.properties()
.find(|p| p.name.contains("#interrupt-cells"))
.unwrap();
let _intr = node
.properties()
.find(|p| p.name.contains("interrupt-parent"));
let _intr_data = node.properties().find(|p| p.name.contains("interrupts"));
for node in fdt.all_nodes() {
if node.property("interrupt-controller").is_some() {
let compatible = node.property("compatible").unwrap().as_str().unwrap();
let phandle = node.property("phandle").unwrap().as_usize().unwrap() as u32;
let intr_cells = node.interrupt_cells().unwrap();
let _intr = node.property("interrupt-parent");
let _intr_data = node.property("interrupts");
let s = core::str::from_utf8(compatible.data).unwrap();
debug!(
"{}, compatible = {}, #interrupt-cells = 0x{:08x}, phandle = 0x{:08x}",
node.name,
s,
BE::read_u32(intr_cells.data),
BE::read_u32(phandle.data)
node.name, compatible, intr_cells, phandle
);
let mut item = IrqChipItem {
phandle: BE::read_u32(phandle.data),
phandle,
parent_phandle: None,
parent: None,
childs: Vec::new(),
interrupts: Vec::new(),
ic: IrqChipCore::new_ic(&s).unwrap(),
ic: IrqChipCore::new_ic(compatible).unwrap(),
};
if let Some(intr) = _intr {
if let Some(intr_data) = _intr_data {
debug!("interrupt-parent = 0x{:08x}", BE::read_u32(intr.data));
item.parent_phandle = Some(BE::read_u32(intr.data));
let intr = intr.as_usize().unwrap() as u32;
debug!("interrupt-parent = 0x{:08x}", intr);
item.parent_phandle = Some(intr);
debug!("interrupts begin:");
for chunk in intr_data.data.chunks(4) {
for chunk in intr_data.value.chunks(4) {
debug!("0x{:08x}, ", BE::read_u32(chunk));
item.interrupts.push(BE::read_u32(chunk));
}
@@ -157,7 +136,7 @@ impl IrqChipList {
}
}
fn init_inner3(&mut self, fdt: &fdt::DeviceTree, irq_desc: &mut [IrqDesc; 1024]) {
fn init_inner3(&mut self, fdt: &fdt::Fdt, irq_desc: &mut [IrqDesc; 1024]) {
//run init
let mut queue = Vec::new();
let mut irq_idx: usize = 0;
@@ -219,7 +198,7 @@ impl IrqChipCore {
.irq_to_virq(hwirq)
}
pub fn init(&mut self, fdt: &DeviceTree) {
pub fn init(&mut self, fdt: &Fdt) {
for i in 0..1024 {
self.irq_desc[i].basic.idx = i;
}
@@ -264,7 +243,7 @@ pub static mut IRQ_CHIP: IrqChipCore = IrqChipCore {
irq_desc: [INIT_IRQ_DESC; 1024],
};
pub fn init(fdt: &DeviceTree) {
pub fn init(fdt: &Fdt) {
travel_interrupt_ctrl(fdt);
unsafe {
IRQ_CHIP.init(fdt);
+1 -1
View File
@@ -10,7 +10,7 @@ pub mod uart_pl011;
pub unsafe fn init() {
info!("IRQCHIP INIT");
let data = DTB_BINARY.get().unwrap();
let fdt = fdt::DeviceTree::new(data).unwrap();
let fdt = fdt::Fdt::new(data).unwrap();
irqchip::init(&fdt);
info!("GIT INIT");
generic_timer::init();
+8 -13
View File
@@ -4,9 +4,10 @@ use spin::Mutex;
use crate::{device::uart_pl011::SerialPort, init::device_tree, interrupt::irq::trigger};
use super::irqchip::{register_irq, InterruptHandler, IRQ_CHIP};
use crate::{dtb::DTB_BINARY, init::device_tree::find_compatible_node};
use crate::dtb::DTB_BINARY;
use alloc::vec::Vec;
use byteorder::{ByteOrder, BE};
use fdt::Fdt;
use log::info;
pub static COM1: Mutex<Option<SerialPort>> = Mutex::new(None);
@@ -43,23 +44,17 @@ pub unsafe fn init_early(dtb_base: usize, dtb_size: usize) {
pub unsafe fn init() {
let data = DTB_BINARY.get().unwrap();
let fdt = fdt::DeviceTree::new(data).unwrap();
if let Some(node) = find_compatible_node(&fdt, "arm,pl011") {
let interrupts = node
.properties()
.find(|p| p.name.contains("interrupts"))
.unwrap();
let fdt = Fdt::new(data).unwrap();
if let Some(node) = fdt.find_compatible(&["arm,pl011"]) {
let interrupts = node.property("interrupts").unwrap();
let mut intr_data = Vec::new();
for chunk in interrupts.data.chunks(4) {
for chunk in interrupts.value.chunks(4) {
let val = BE::read_u32(chunk);
intr_data.push(val);
}
let mut ic_idx = IRQ_CHIP.irq_chip_list.root_idx;
if let Some(interrupt_parent) = node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
{
let phandle = BE::read_u32(interrupt_parent.data);
if let Some(interrupt_parent) = node.property("interrupt-parent") {
let phandle = interrupt_parent.as_usize().unwrap() as u32;
let mut i = 0;
while i < IRQ_CHIP.irq_chip_list.chips.len() {
let item = &IRQ_CHIP.irq_chip_list.chips[i];
+58 -214
View File
@@ -1,9 +1,6 @@
extern crate byteorder;
extern crate fdt;
use self::byteorder::{ByteOrder, BE};
use byteorder::{ByteOrder, BE};
use core::slice;
use fdt::Node;
use fdt::{node::NodeProperty, Fdt};
use log::debug;
#[derive(Copy, Clone, Debug, Default)]
@@ -22,68 +19,32 @@ pub static mut MEMORY_MAP: [MemoryArea; 512] = [MemoryArea {
acpi: 0,
}; 512];
pub fn root_cell_sz(dt: &fdt::DeviceTree) -> Option<(u32, u32)> {
let root_node = dt.nodes().nth(0).unwrap();
let address_cells = root_node
.properties()
.find(|p| p.name.contains("#address-cells"))
pub fn travel_interrupt_ctrl(fdt: &Fdt) {
let root_intr_parent = fdt
.root()
.property("interrupt-parent")
.and_then(NodeProperty::as_usize)
.unwrap();
let size_cells = root_node
.properties()
.find(|p| p.name.contains("#size-cells"))
.unwrap();
Some((
BE::read_u32(&address_cells.data),
BE::read_u32(&size_cells.data),
))
}
pub fn travel_interrupt_ctrl(fdt: &fdt::DeviceTree) {
let root_node = fdt.nodes().nth(0).unwrap();
let intr = root_node
.properties()
.find(|p| p.name.contains("interrupt-parent"))
.unwrap();
let root_intr_parent = BE::read_u32(&intr.data);
debug!("root parent = 0x{:08x}", root_intr_parent);
for node in fdt.nodes() {
if node
.properties()
.find(|p| p.name.contains("interrupt-controller"))
.is_some()
{
let compatible = node
.properties()
.find(|p| p.name.contains("compatible"))
.unwrap();
let phandle = node
.properties()
.find(|p| p.name.contains("phandle"))
.unwrap();
let intr_cells = node
.properties()
.find(|p| p.name.contains("#interrupt-cells"))
.unwrap();
for node in fdt.all_nodes() {
if node.property("interrupt-controller").is_some() {
let compatible = node.property("compatible").unwrap().as_str().unwrap();
let phandle = node.property("phandle").unwrap().as_usize().unwrap();
let intr_cells = node.interrupt_cells().unwrap();
let _intr = node
.properties()
.find(|p| p.name.contains("interrupt-parent"));
let _intr_data = node.properties().find(|p| p.name.contains("interrupts"));
.property("interrupt-parent")
.and_then(NodeProperty::as_usize);
let _intr_data = node.property("interrupts");
let s = core::str::from_utf8(compatible.data).unwrap();
debug!(
"{}, compatible = {}, #interrupt-cells = 0x{:08x}, phandle = 0x{:08x}",
node.name,
s,
BE::read_u32(intr_cells.data),
BE::read_u32(phandle.data)
node.name, compatible, intr_cells, phandle
);
if let Some(intr) = _intr {
if let Some(intr_data) = _intr_data {
debug!("interrupt-parent = 0x{:08x}", BE::read_u32(intr.data));
debug!("interrupt-parent = 0x{:08x}", intr);
debug!("interrupts begin:");
for chunk in intr_data.data.chunks(4) {
for chunk in intr_data.value.chunks(4) {
debug!("0x{:08x}, ", BE::read_u32(chunk));
}
debug!("interrupts end");
@@ -94,56 +55,23 @@ pub fn travel_interrupt_ctrl(fdt: &fdt::DeviceTree) {
}
#[allow(unused)]
fn memory_ranges(
dt: &fdt::DeviceTree,
address_cells: usize,
size_cells: usize,
ranges: &mut [(usize, usize); 10],
) -> usize {
let (memory_node, _memory_cells) = dt.find_node("/memory").unwrap();
let reg = memory_node
.properties()
.find(|p| p.name.contains("reg"))
.unwrap();
let chunk_sz = (address_cells + size_cells) * 4;
let chunk_count = reg.data.len() / chunk_sz;
fn memory_ranges(dt: &Fdt, ranges: &mut [(usize, usize); 10]) -> usize {
let mut index = 0;
for chunk in reg.data.chunks(chunk_sz as usize) {
if index == chunk_count {
return index;
for chunk in dt.memory().regions() {
if index >= ranges.len() || chunk.size.is_none() {
break;
}
let (base, size) = chunk.split_at((address_cells * 4) as usize);
let mut b = 0;
for base_chunk in base.rchunks(4) {
b += BE::read_u32(base_chunk);
}
let mut s = 0;
for sz_chunk in size.rchunks(4) {
s += BE::read_u32(sz_chunk);
}
ranges[index] = (b as usize, s as usize);
ranges[index] = (chunk.starting_address as usize, chunk.size.unwrap());
index += 1;
}
index
}
fn dev_memory_ranges(
dt: &fdt::DeviceTree,
address_cells: usize,
size_cells: usize,
ranges: &mut [(usize, usize); 10],
) -> usize {
fn dev_memory_ranges(dt: &Fdt, ranges: &mut [(usize, usize); 10]) -> usize {
// work around for qemu-arm64
// dev mem: 128MB - 1GB, see https://github.com/qemu/qemu/blob/master/hw/arm/virt.c for details
let root_node = dt.nodes().nth(0).unwrap();
let is_qemu_virt = {
if let Some(model) = root_node.properties().find(|p| p.name.contains("model")) {
let model_str = core::str::from_utf8(model.data).unwrap();
model_str.contains("linux,dummy-virt")
} else {
true
}
};
let root_node = dt.root();
let is_qemu_virt = root_node.model().contains("linux,dummy-virt");
if is_qemu_virt {
ranges[0] = (0x08000000, 0x08000000);
@@ -151,54 +79,23 @@ fn dev_memory_ranges(
return 2;
}
let (memory_node, _memory_cells) = dt.find_node("/soc").unwrap();
let reg = memory_node
.properties()
.find(|p| p.name.contains("ranges"))
.unwrap();
let chunk_sz = (address_cells * 2 + size_cells) * 4;
let chunk_count = reg.data.len() / chunk_sz;
let soc_node = dt.find_node("/soc").unwrap();
let reg = soc_node.ranges().unwrap();
let mut index = 0;
for chunk in reg.data.chunks(chunk_sz as usize) {
if index == chunk_count {
return index;
for chunk in reg {
if index >= ranges.len() {
break;
}
let child_bus_addr = {
if address_cells == 1 {
BE::read_u32(&chunk[0..4]) as u64
} else if address_cells == 2 {
BE::read_u64(&chunk[0..8])
} else {
return 0;
}
};
let parent_bus_addr = {
if address_cells == 1 {
BE::read_u32(&chunk[4..8]) as u64
} else if address_cells == 2 {
BE::read_u64(&chunk[8..16])
} else {
return 0;
}
};
let addr_size = {
// FIXME offsets incorrect if address_cells != size_cells
if address_cells == 1 {
BE::read_u32(&chunk[8..12]) as u64
} else if address_cells == 2 {
BE::read_u64(&chunk[16..24])
} else {
return 0;
}
};
debug!(
"dev mem 0x{:08x} 0x{:08x} 0x{:08x}",
child_bus_addr, parent_bus_addr, addr_size
"dev mem 0x{:08x} 0x{:08x} 0x{:08x} 0x{:08x}",
chunk.child_bus_address_hi,
chunk.child_bus_address,
chunk.parent_bus_address,
chunk.size
);
ranges[index] = (parent_bus_addr as usize, addr_size as usize);
ranges[index] = (chunk.parent_bus_address, chunk.size);
index += 1;
}
index
@@ -206,82 +103,35 @@ fn dev_memory_ranges(
pub fn diag_uart_range(dtb_base: usize, dtb_size: usize) -> Option<(usize, usize, bool, bool)> {
let data = unsafe { slice::from_raw_parts(dtb_base as *const u8, dtb_size) };
let dt = fdt::DeviceTree::new(data).unwrap();
let dt = Fdt::new(data).unwrap();
let (chosen_node, _chosen_cells) = dt.find_node("/chosen").unwrap();
let stdout_path = chosen_node
.properties()
.find(|p| p.name.contains("stdout-path"))
.unwrap();
let uart_node_name = core::str::from_utf8(stdout_path.data)
.unwrap()
.split('/')
.nth(1)?
.trim_end();
let len = uart_node_name.len();
let uart_node_name = &uart_node_name[0..len - 1];
let uart_node = dt
.nodes()
.find(|n| n.name.contains(uart_node_name))
.unwrap();
let skip_init = uart_node
.properties()
.find(|p| p.name.contains("skip-init"))
.is_some();
let cts_event_walkaround = uart_node
.properties()
.find(|p| p.name.contains("cts-event-walkaround"))
.is_some();
let reg = uart_node
.properties()
.find(|p| p.name.contains("reg"))
.unwrap();
let stdout_path = dt.chosen().stdout().unwrap();
let uart_node = stdout_path.node();
let skip_init = uart_node.property("skip-init").is_some();
let cts_event_walkaround = uart_node.property("cts-event-walkaround").is_some();
let (address_cells, size_cells) = root_cell_sz(&dt).unwrap();
let _chunk_sz = (address_cells + size_cells) * 4;
let (base, size) = reg.data.split_at((address_cells * 4) as usize);
let mut b = 0;
// FIXME likely needs shifting before addition
for base_chunk in base.rchunks(4) {
b += BE::read_u32(base_chunk);
}
let mut s = 0;
for sz_chunk in size.rchunks(4) {
s += BE::read_u32(sz_chunk);
}
Some((b as usize, s as usize, skip_init, cts_event_walkaround))
}
let mut reg = uart_node.reg().unwrap();
let memory = reg.nth(0).unwrap();
pub fn find_compatible_node<'a>(
dt: &'a fdt::DeviceTree<'a>,
compat_string: &str,
) -> Option<Node<'a, 'a>> {
for node in dt.nodes() {
if let Some(compatible) = node.properties().find(|p| p.name.contains("compatible")) {
let s = core::str::from_utf8(compatible.data).unwrap();
if s.contains(compat_string) {
return Some(node);
}
}
}
None
Some((
memory.starting_address as usize,
memory.size.unwrap(),
skip_init,
cts_event_walkaround,
))
}
#[allow(unused)]
pub fn fill_env_data(dtb_base: usize, dtb_size: usize, env_base: usize) -> usize {
let data = unsafe { slice::from_raw_parts(dtb_base as *const u8, dtb_size) };
let dt = fdt::DeviceTree::new(data).unwrap();
let dt = Fdt::new(data).unwrap();
let (chosen_node, _chosen_cells) = dt.find_node("/chosen").unwrap();
if let Some(bootargs) = chosen_node
.properties()
.find(|p| p.name.contains("bootargs"))
{
let bootargs_len = bootargs.data.len();
if let Some(bootargs) = dt.chosen().bootargs() {
let bootargs_len = bootargs.len();
let env_base_slice =
unsafe { slice::from_raw_parts_mut(env_base as *mut u8, bootargs_len) };
env_base_slice[..bootargs_len].clone_from_slice(bootargs.data);
env_base_slice[..bootargs_len].clone_from_slice(bootargs.as_bytes());
bootargs_len
} else {
@@ -291,19 +141,13 @@ pub fn fill_env_data(dtb_base: usize, dtb_size: usize, env_base: usize) -> usize
pub fn fill_memory_map(dtb_base: usize, dtb_size: usize) {
let data = unsafe { slice::from_raw_parts(dtb_base as *const u8, dtb_size) };
let dt = fdt::DeviceTree::new(data).unwrap();
let dt = Fdt::new(data).unwrap();
let (address_cells, size_cells) = root_cell_sz(&dt).unwrap();
let mut ranges: [(usize, usize); 10] = [(0, 0); 10];
//in uefi boot mode, ignore memory node, just read the device memory range
//let nranges = memory_ranges(&dt, address_cells as usize, size_cells as usize, &mut ranges);
let nranges = dev_memory_ranges(
&dt,
address_cells as usize,
size_cells as usize,
&mut ranges,
);
//let nranges = memory_ranges(&dt, &mut ranges);
let nranges = dev_memory_ranges(&dt, &mut ranges);
for index in 0..nranges {
let (base, size) = ranges[index];