actually good fdt formatting
This commit is contained in:
@@ -4,12 +4,7 @@ use crate::{
|
||||
println,
|
||||
util::bits::{u32_from_bytes, Be},
|
||||
};
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
mem::{size_of, transmute},
|
||||
ops::Range,
|
||||
slice,
|
||||
};
|
||||
use core::{fmt::Debug, mem::size_of, slice};
|
||||
|
||||
const MAGIC: u32 = 0xd00dfeed;
|
||||
|
||||
@@ -35,7 +30,6 @@ impl Token {
|
||||
0x00000004 => Token::Nop,
|
||||
0x00000009 => Token::End,
|
||||
_ => {
|
||||
println!("Failed to parse token!");
|
||||
return None;
|
||||
}
|
||||
})
|
||||
@@ -62,6 +56,74 @@ pub struct RawProp {
|
||||
nameoff: Be<u32>,
|
||||
}
|
||||
|
||||
pub struct FDT {
|
||||
pub header: &'static Header,
|
||||
pub nodes: &'static [u8],
|
||||
pub strings: &'static [u8],
|
||||
}
|
||||
|
||||
impl FDT {
|
||||
pub fn nodes(&self) -> NodeIter {
|
||||
NodeIter {
|
||||
pos: self.nodes,
|
||||
strings: self.strings,
|
||||
}
|
||||
}
|
||||
pub unsafe fn from_addr(addr: *mut u8) -> Self {
|
||||
let header: &Header = &*(addr as *const Header);
|
||||
if header.magic.get() != MAGIC {
|
||||
panic!("fdt magic wrong");
|
||||
}
|
||||
let data = slice::from_raw_parts(addr, header.totalsize.get() as usize);
|
||||
Self {
|
||||
header,
|
||||
nodes: &data[header.off_dt_struct.get() as usize..],
|
||||
strings: &data[header.off_dt_strings.get() as usize..],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Node {
|
||||
pub name: &'static str,
|
||||
pub strings: &'static [u8],
|
||||
pub props: &'static [u8],
|
||||
pub children: &'static [u8],
|
||||
}
|
||||
|
||||
impl Debug for Node {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let mut fmt = f.debug_struct(self.name);
|
||||
for prop in self.props() {
|
||||
fmt.field(prop.name, &prop.data.len());
|
||||
}
|
||||
for child in self.children() {
|
||||
fmt.field(" - child", &child);
|
||||
}
|
||||
fmt.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn children(&self) -> NodeIter {
|
||||
NodeIter {
|
||||
pos: self.children,
|
||||
strings: self.strings,
|
||||
}
|
||||
}
|
||||
pub fn child(&self, name: &str) -> Option<Node> {
|
||||
self.children().find(|c| c.name == name)
|
||||
}
|
||||
pub fn props(&self) -> PropIter {
|
||||
PropIter {
|
||||
pos: self.props,
|
||||
strings: self.strings,
|
||||
}
|
||||
}
|
||||
pub fn prop(&self, name: &str) -> Option<Prop> {
|
||||
self.props().find(|p| p.name == name)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Prop {
|
||||
pub name: &'static str,
|
||||
pub data: &'static [u8],
|
||||
@@ -82,10 +144,35 @@ impl Prop {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FDT {
|
||||
pub header: &'static Header,
|
||||
pub nodes: &'static [u8],
|
||||
pub struct PropIter {
|
||||
pub strings: &'static [u8],
|
||||
pub pos: &'static [u8],
|
||||
}
|
||||
|
||||
impl Iterator for PropIter {
|
||||
type Item = Prop;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let token: Token = Token::from_bytes(self.pos)?;
|
||||
let Token::Prop = token else {
|
||||
return None;
|
||||
};
|
||||
self.pos = &self.pos[4..];
|
||||
let prop: &RawProp = unsafe { &*(self.pos.as_ptr() as *const RawProp) };
|
||||
self.pos = &self.pos[PROP_SIZE..];
|
||||
let plen = prop.len.get() as usize;
|
||||
let len = (plen + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1);
|
||||
let data = &self.pos[..len];
|
||||
self.pos = &self.pos[len..];
|
||||
let name_start = &self.strings[prop.nameoff.get() as usize..];
|
||||
for (i, c) in name_start.iter().enumerate() {
|
||||
if *c == 0 {
|
||||
let name: &str = core::str::from_utf8(&name_start[..i]).expect("uhhhhh");
|
||||
return Some(Prop { name, data });
|
||||
}
|
||||
}
|
||||
println!("failed to read prop name, not sure what to do");
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NodeIter {
|
||||
@@ -165,137 +252,3 @@ impl Iterator for NodeIter {
|
||||
}
|
||||
}
|
||||
|
||||
impl FDT {
|
||||
pub fn nodes(&self) -> NodeIter {
|
||||
NodeIter {
|
||||
pos: self.nodes,
|
||||
strings: self.strings,
|
||||
}
|
||||
}
|
||||
pub unsafe fn from_addr(addr: *mut u8) -> Self {
|
||||
let header: &Header = &*(addr as *const Header);
|
||||
if header.magic.get() != MAGIC {
|
||||
panic!("fdt magic wrong");
|
||||
}
|
||||
let data = slice::from_raw_parts(addr, header.totalsize.get() as usize);
|
||||
Self {
|
||||
header,
|
||||
nodes: &data[header.off_dt_struct.get() as usize..],
|
||||
strings: &data[header.off_dt_strings.get() as usize..],
|
||||
}
|
||||
}
|
||||
pub fn mem_range(&self) -> FDTMemRange {
|
||||
let root = self.nodes().next().unwrap();
|
||||
if let Some(node) = root.children().find(|n| n.name.starts_with("memory@")) {
|
||||
let prop = node.find_prop("reg");
|
||||
if let Some(prop) = prop {
|
||||
if let Some(d) = prop.data.chunks(size_of::<FDTMemRange>()).next() {
|
||||
let d: [u8; size_of::<FDTMemRange>()] = d.try_into().unwrap();
|
||||
return unsafe { transmute::<[u8; 16], FDTMemRange>(d) };
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("failed to get memory range");
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FDTMemRange {
|
||||
pub start: Be<*mut u8>,
|
||||
pub len: Be<usize>,
|
||||
}
|
||||
|
||||
impl FDTMemRange {
|
||||
pub fn start(&self) -> *mut u8 {
|
||||
self.start.get()
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.len.get()
|
||||
}
|
||||
pub fn end(&self) -> *mut u8 {
|
||||
unsafe { self.start().add(self.len.get()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FDTMemRange {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "{:?}..{:?}", self.start(), self.end())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FDTMemRange> for Range<*mut u8> {
|
||||
fn from(val: FDTMemRange) -> Self {
|
||||
Range {
|
||||
start: val.start(),
|
||||
end: val.end(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Node {
|
||||
pub name: &'static str,
|
||||
pub strings: &'static [u8],
|
||||
pub props: &'static [u8],
|
||||
pub children: &'static [u8],
|
||||
}
|
||||
|
||||
impl Debug for Node {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let props: alloc::vec::Vec<_> = self.props().collect();
|
||||
let children: alloc::vec::Vec<_> = self.children().collect();
|
||||
f.debug_struct("Node")
|
||||
.field("name", &self.name)
|
||||
.field("props", &props)
|
||||
.field("children", &children)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn children(&self) -> NodeIter {
|
||||
NodeIter {
|
||||
pos: self.children,
|
||||
strings: self.strings,
|
||||
}
|
||||
}
|
||||
pub fn props(&self) -> PropIter {
|
||||
PropIter {
|
||||
pos: self.props,
|
||||
strings: self.strings,
|
||||
}
|
||||
}
|
||||
pub fn find_prop(&self, name: &str) -> Option<Prop> {
|
||||
self.props().find(|p| p.name == name)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PropIter {
|
||||
pub strings: &'static [u8],
|
||||
pub pos: &'static [u8],
|
||||
}
|
||||
|
||||
impl Iterator for PropIter {
|
||||
type Item = Prop;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let token: Token = Token::from_bytes(self.pos)?;
|
||||
let Token::Prop = token else {
|
||||
return None;
|
||||
};
|
||||
self.pos = &self.pos[4..];
|
||||
let prop: &RawProp = unsafe { &*(self.pos.as_ptr() as *const RawProp) };
|
||||
self.pos = &self.pos[PROP_SIZE..];
|
||||
let plen = prop.len.get() as usize;
|
||||
let len = (plen + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1);
|
||||
let data = &self.pos[..len];
|
||||
self.pos = &self.pos[len..];
|
||||
let name_start = &self.strings[prop.nameoff.get() as usize..];
|
||||
for (i, c) in name_start.iter().enumerate() {
|
||||
if *c == 0 {
|
||||
let name: &str = core::str::from_utf8(&name_start[..i]).expect("uhhhhh");
|
||||
return Some(Prop { name, data });
|
||||
}
|
||||
}
|
||||
println!("failed to read prop name, not sure what to do");
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
57
kernel/src/dev/mem.rs
Normal file
57
kernel/src/dev/mem.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
mem::{size_of, transmute},
|
||||
ops::Range,
|
||||
};
|
||||
|
||||
use crate::util::bits::Be;
|
||||
|
||||
use super::fdt::FDT;
|
||||
|
||||
impl FDT {
|
||||
pub fn mem_range(&self) -> FDTMemRange {
|
||||
let root = self.nodes().next().unwrap();
|
||||
if let Some(node) = root.children().find(|n| n.name.starts_with("memory@")) {
|
||||
if let Some(prop) = node.prop("reg") {
|
||||
if let Some(d) = prop.data.chunks(size_of::<FDTMemRange>()).next() {
|
||||
let d: [u8; size_of::<FDTMemRange>()] = d.try_into().unwrap();
|
||||
return unsafe { transmute::<[u8; 16], FDTMemRange>(d) };
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("failed to get memory range");
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FDTMemRange {
|
||||
pub start: Be<*mut u8>,
|
||||
pub len: Be<usize>,
|
||||
}
|
||||
|
||||
impl FDTMemRange {
|
||||
pub fn start(&self) -> *mut u8 {
|
||||
self.start.get()
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.len.get()
|
||||
}
|
||||
pub fn end(&self) -> *mut u8 {
|
||||
unsafe { self.start().add(self.len.get()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FDTMemRange {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "{:?}..{:?}", self.start(), self.end())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FDTMemRange> for Range<*mut u8> {
|
||||
fn from(val: FDTMemRange) -> Self {
|
||||
Range {
|
||||
start: val.start(),
|
||||
end: val.end(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod uart;
|
||||
pub mod fdt;
|
||||
pub mod mem;
|
||||
pub mod uart;
|
||||
|
||||
Reference in New Issue
Block a user