diff --git a/kernel/.cargo/config.toml b/kernel/.cargo/config.toml index 7c4343d..0b867da 100644 --- a/kernel/.cargo/config.toml +++ b/kernel/.cargo/config.toml @@ -8,7 +8,7 @@ rustflags = [ "-C", "link-arg=-Tsrc/arch/riscv64/link.ld", "-C", "link-arg=--omagic", ] -runner = "qemu-system-riscv64 -nographic -semihosting -cpu rv64 -machine virt -bios none -smp 4 -m 1G -drive file=test.raw,format=raw -kernel" +runner = "qemu-system-riscv64 -nographic -semihosting -cpu rv64 -machine virt -bios none -smp 4 -m 1G -device virtio-blk-pci,drive=test -drive file=test.raw,format=raw,id=test -kernel" [unstable] build-std = ["core", "compiler_builtins", "alloc"] diff --git a/kernel/src/dev/fdt.rs b/kernel/src/dev/fdt.rs index 7222241..cadc5e4 100644 --- a/kernel/src/dev/fdt.rs +++ b/kernel/src/dev/fdt.rs @@ -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, } +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 { + 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 { + 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 { + 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::()).next() { - let d: [u8; size_of::()] = 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, -} - -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 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 { - 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 { - 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 - } -} diff --git a/kernel/src/dev/mem.rs b/kernel/src/dev/mem.rs new file mode 100644 index 0000000..d069d99 --- /dev/null +++ b/kernel/src/dev/mem.rs @@ -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::()).next() { + let d: [u8; size_of::()] = 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, +} + +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 for Range<*mut u8> { + fn from(val: FDTMemRange) -> Self { + Range { + start: val.start(), + end: val.end(), + } + } +} diff --git a/kernel/src/dev/mod.rs b/kernel/src/dev/mod.rs index 4c4ceb3..6668bff 100644 --- a/kernel/src/dev/mod.rs +++ b/kernel/src/dev/mod.rs @@ -1,2 +1,3 @@ -pub mod uart; pub mod fdt; +pub mod mem; +pub mod uart; diff --git a/kernel/stuff b/kernel/stuff new file mode 100644 index 0000000..915b634 --- /dev/null +++ b/kernel/stuff @@ -0,0 +1,879 @@ +we out here vibin +memory range: 0x81626000..0xc0000000 +Node { + name: "", + props: [ + Prop { + name: "#address-cells", + data_len: 4, + }, + Prop { + name: "#size-cells", + data_len: 4, + }, + Prop { + name: "compatible", + data_len: 16, + }, + Prop { + name: "model", + data_len: 20, + }, + ], + children: [ + Node { + name: "poweroff", + props: [ + Prop { + name: "value", + data_len: 4, + }, + Prop { + name: "offset", + data_len: 4, + }, + Prop { + name: "regmap", + data_len: 4, + }, + Prop { + name: "compatible", + data_len: 16, + }, + ], + children: [], + }, + Node { + name: "reboot", + props: [ + Prop { + name: "value", + data_len: 4, + }, + Prop { + name: "offset", + data_len: 4, + }, + Prop { + name: "regmap", + data_len: 4, + }, + Prop { + name: "compatible", + data_len: 16, + }, + ], + children: [], + }, + Node { + name: "platform-bus@4000000", + props: [ + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "ranges", + data_len: 16, + }, + Prop { + name: "#address-cells", + data_len: 4, + }, + Prop { + name: "#size-cells", + data_len: 4, + }, + Prop { + name: "compatible", + data_len: 28, + }, + ], + children: [], + }, + Node { + name: "memory@80000000", + props: [ + Prop { + name: "device_type", + data_len: 8, + }, + Prop { + name: "reg", + data_len: 16, + }, + ], + children: [], + }, + Node { + name: "cpus", + props: [ + Prop { + name: "#address-cells", + data_len: 4, + }, + Prop { + name: "#size-cells", + data_len: 4, + }, + Prop { + name: "timebase-frequency", + data_len: 4, + }, + ], + children: [ + Node { + name: "cpu@0", + props: [ + Prop { + name: "phandle", + data_len: 4, + }, + Prop { + name: "device_type", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 4, + }, + Prop { + name: "status", + data_len: 8, + }, + Prop { + name: "compatible", + data_len: 8, + }, + Prop { + name: "riscv,cboz-block-size", + data_len: 4, + }, + Prop { + name: "riscv,cbom-block-size", + data_len: 4, + }, + Prop { + name: "riscv,isa", + data_len: 124, + }, + Prop { + name: "mmu-type", + data_len: 12, + }, + ], + children: [ + Node { + name: "interrupt-controller", + props: [ + Prop { + name: "#interrupt-cells", + data_len: 4, + }, + Prop { + name: "interrupt-controller", + data_len: 0, + }, + Prop { + name: "compatible", + data_len: 16, + }, + Prop { + name: "phandle", + data_len: 4, + }, + ], + children: [], + }, + ], + }, + Node { + name: "cpu@1", + props: [ + Prop { + name: "phandle", + data_len: 4, + }, + Prop { + name: "device_type", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 4, + }, + Prop { + name: "status", + data_len: 8, + }, + Prop { + name: "compatible", + data_len: 8, + }, + Prop { + name: "riscv,cboz-block-size", + data_len: 4, + }, + Prop { + name: "riscv,cbom-block-size", + data_len: 4, + }, + Prop { + name: "riscv,isa", + data_len: 124, + }, + Prop { + name: "mmu-type", + data_len: 12, + }, + ], + children: [ + Node { + name: "interrupt-controller", + props: [ + Prop { + name: "#interrupt-cells", + data_len: 4, + }, + Prop { + name: "interrupt-controller", + data_len: 0, + }, + Prop { + name: "compatible", + data_len: 16, + }, + Prop { + name: "phandle", + data_len: 4, + }, + ], + children: [], + }, + ], + }, + Node { + name: "cpu@2", + props: [ + Prop { + name: "phandle", + data_len: 4, + }, + Prop { + name: "device_type", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 4, + }, + Prop { + name: "status", + data_len: 8, + }, + Prop { + name: "compatible", + data_len: 8, + }, + Prop { + name: "riscv,cboz-block-size", + data_len: 4, + }, + Prop { + name: "riscv,cbom-block-size", + data_len: 4, + }, + Prop { + name: "riscv,isa", + data_len: 124, + }, + Prop { + name: "mmu-type", + data_len: 12, + }, + ], + children: [ + Node { + name: "interrupt-controller", + props: [ + Prop { + name: "#interrupt-cells", + data_len: 4, + }, + Prop { + name: "interrupt-controller", + data_len: 0, + }, + Prop { + name: "compatible", + data_len: 16, + }, + Prop { + name: "phandle", + data_len: 4, + }, + ], + children: [], + }, + ], + }, + Node { + name: "cpu@3", + props: [ + Prop { + name: "phandle", + data_len: 4, + }, + Prop { + name: "device_type", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 4, + }, + Prop { + name: "status", + data_len: 8, + }, + Prop { + name: "compatible", + data_len: 8, + }, + Prop { + name: "riscv,cboz-block-size", + data_len: 4, + }, + Prop { + name: "riscv,cbom-block-size", + data_len: 4, + }, + Prop { + name: "riscv,isa", + data_len: 124, + }, + Prop { + name: "mmu-type", + data_len: 12, + }, + ], + children: [ + Node { + name: "interrupt-controller", + props: [ + Prop { + name: "#interrupt-cells", + data_len: 4, + }, + Prop { + name: "interrupt-controller", + data_len: 0, + }, + Prop { + name: "compatible", + data_len: 16, + }, + Prop { + name: "phandle", + data_len: 4, + }, + ], + children: [], + }, + ], + }, + Node { + name: "cpu-map", + props: [], + children: [ + Node { + name: "cluster0", + props: [], + children: [ + Node { + name: "core0", + props: [ + Prop { + name: "cpu", + data_len: 4, + }, + ], + children: [], + }, + Node { + name: "core1", + props: [ + Prop { + name: "cpu", + data_len: 4, + }, + ], + children: [], + }, + Node { + name: "core2", + props: [ + Prop { + name: "cpu", + data_len: 4, + }, + ], + children: [], + }, + Node { + name: "core3", + props: [ + Prop { + name: "cpu", + data_len: 4, + }, + ], + children: [], + }, + ], + }, + ], + }, + ], + }, + Node { + name: "pmu", + props: [ + Prop { + name: "riscv,event-to-mhpmcounters", + data_len: 60, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "fw-cfg@10100000", + props: [ + Prop { + name: "dma-coherent", + data_len: 0, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 20, + }, + ], + children: [], + }, + Node { + name: "flash@20000000", + props: [ + Prop { + name: "bank-width", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 32, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "chosen", + props: [ + Prop { + name: "stdout-path", + data_len: 24, + }, + Prop { + name: "rng-seed", + data_len: 32, + }, + ], + children: [], + }, + Node { + name: "soc", + props: [ + Prop { + name: "#address-cells", + data_len: 4, + }, + Prop { + name: "#size-cells", + data_len: 4, + }, + Prop { + name: "compatible", + data_len: 12, + }, + Prop { + name: "ranges", + data_len: 0, + }, + ], + children: [ + Node { + name: "rtc@101000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 20, + }, + ], + children: [], + }, + Node { + name: "serial@10000000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "clock-frequency", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "test@100000", + props: [ + Prop { + name: "phandle", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 36, + }, + ], + children: [], + }, + Node { + name: "pci@30000000", + props: [ + Prop { + name: "interrupt-map-mask", + data_len: 16, + }, + Prop { + name: "interrupt-map", + data_len: 384, + }, + Prop { + name: "ranges", + data_len: 84, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "dma-coherent", + data_len: 0, + }, + Prop { + name: "bus-range", + data_len: 8, + }, + Prop { + name: "linux,pci-domain", + data_len: 4, + }, + Prop { + name: "device_type", + data_len: 4, + }, + Prop { + name: "compatible", + data_len: 24, + }, + Prop { + name: "#size-cells", + data_len: 4, + }, + Prop { + name: "#interrupt-cells", + data_len: 4, + }, + Prop { + name: "#address-cells", + data_len: 4, + }, + ], + children: [], + }, + Node { + name: "virtio_mmio@10008000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "virtio_mmio@10007000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "virtio_mmio@10006000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "virtio_mmio@10005000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "virtio_mmio@10004000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "virtio_mmio@10003000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "virtio_mmio@10002000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "virtio_mmio@10001000", + props: [ + Prop { + name: "interrupts", + data_len: 4, + }, + Prop { + name: "interrupt-parent", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 12, + }, + ], + children: [], + }, + Node { + name: "plic@c000000", + props: [ + Prop { + name: "phandle", + data_len: 4, + }, + Prop { + name: "riscv,ndev", + data_len: 4, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "interrupts-extended", + data_len: 64, + }, + Prop { + name: "interrupt-controller", + data_len: 0, + }, + Prop { + name: "compatible", + data_len: 32, + }, + Prop { + name: "#address-cells", + data_len: 4, + }, + Prop { + name: "#interrupt-cells", + data_len: 4, + }, + ], + children: [], + }, + Node { + name: "clint@2000000", + props: [ + Prop { + name: "interrupts-extended", + data_len: 64, + }, + Prop { + name: "reg", + data_len: 16, + }, + Prop { + name: "compatible", + data_len: 28, + }, + ], + children: [], + }, + ], + }, + ], +} diff --git a/kernel/test.raw b/kernel/test.raw index 4fce05a..36406a1 100644 Binary files a/kernel/test.raw and b/kernel/test.raw differ