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:
Generated
+2
-5
@@ -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
@@ -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"
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user