From ae53913fc230dd7f0ef2eed3757112781036388a Mon Sep 17 00:00:00 2001 From: Bryan McShea Date: Fri, 26 Jan 2024 23:05:09 -0500 Subject: [PATCH] LOST SANITY BUT I SHOULD BE GOOD NOW --- kernel/src/arch/riscv64/link.ld | 1 + kernel/src/arch/riscv64/paging.rs | 4 +- kernel/src/fdt.rs | 270 ++++++++++++++++++++++-------- runner/src/main.rs | 4 +- 4 files changed, 203 insertions(+), 76 deletions(-) diff --git a/kernel/src/arch/riscv64/link.ld b/kernel/src/arch/riscv64/link.ld index cc0b195..2e9affa 100644 --- a/kernel/src/arch/riscv64/link.ld +++ b/kernel/src/arch/riscv64/link.ld @@ -23,5 +23,6 @@ SECTIONS PROVIDE(_stack_end = .); . = ALIGN(4096); /* 2^12 */ PROVIDE(_heap_start = .); + . += 0x20000000; } diff --git a/kernel/src/arch/riscv64/paging.rs b/kernel/src/arch/riscv64/paging.rs index 8d3cd1e..57adc16 100644 --- a/kernel/src/arch/riscv64/paging.rs +++ b/kernel/src/arch/riscv64/paging.rs @@ -2,7 +2,7 @@ // following for now bc don't wanna learn x86_64 :) use crate::{ - arch::csr::{self, satp}, fdt::print_fdt, println + arch::{csr::{self, satp}, wait}, fdt::print_mem_layout, println }; use super::asm::linker_static; @@ -19,7 +19,7 @@ pub struct Table { pub fn init(fdt: usize) { unsafe { println!("heap start: 0x{:x}", HEAP_START); - print_fdt(fdt); + print_mem_layout(fdt); let table_start = HEAP_START as *mut Table; csr::satp::write(satp::Satp { mode: satp::Mode::Sv39, diff --git a/kernel/src/fdt.rs b/kernel/src/fdt.rs index c6b0197..a81cbbd 100644 --- a/kernel/src/fdt.rs +++ b/kernel/src/fdt.rs @@ -1,12 +1,10 @@ // NOTE: basically none of this is safe rn, ideally it's eventually made safe / able to recover use crate::{print, println}; -use alloc::vec; -use core::mem::{size_of, transmute}; - -pub struct FDT { - pub header: Header, -} +use core::{ + mem::{size_of, transmute}, + slice, +}; const MAGIC: u32 = 0xd00dfeed; @@ -21,8 +19,8 @@ enum Token { } const TOKEN_SIZE: usize = size_of::(); impl Token { - pub fn from_addr(addr: usize) -> Self { - unsafe { transmute(from_be_32::(addr)) } + pub fn from_bytes(data: &[u8]) -> Self { + unsafe { transmute(be_32::(data)) } } } @@ -56,29 +54,201 @@ pub struct Prop { } impl Prop { - pub fn from_addr(addr: usize) -> Self { - unsafe { transmute(from_be_32::(addr)) } + pub fn from_bytes(data: &[u8]) -> Self { + unsafe { transmute(be_32::(data)) } } } +pub struct FDT { + pub header: Header, +} + impl FDT { pub fn new(addr: usize) -> Self { let header = Header::from_addr(addr); - if header.magic != MAGIC { - panic!("FDT magic incorrect"); - } - if header.version != 17 { - panic!("FDT version not implemented {}", header.version); - } - let dt_structs = addr + header.off_dt_struct as usize; - let first_node: Token = Token::from_addr(dt_structs); - println!("{first_node:?}"); - let a = vec![1, 2]; - println!("arst{a:?}"); Self { header } } } +pub struct RawFDT { + pub header: Header, + pub nodes: &'static [u8], + pub strings: &'static [u8], +} + +impl RawFDT { + pub fn new(addr: usize) -> Self { + let header = Header::from_addr(addr); + let data = unsafe { slice::from_raw_parts(addr as *mut u8, header.totalsize as usize) }; + Self { + header, + nodes: &data[header.off_dt_struct as usize..], + strings: &data[header.off_dt_strings as usize..], + } + } + pub fn print_all(&self) { + let mut pos = self.nodes; + loop { + let token: Token = Token::from_bytes(pos); + pos = &pos[4..]; + if let Token::End = token { + break; + } + if let Token::EndNode = token { + continue; + } + print!("name: "); + 'outer: loop { + let bytes = &pos[..4]; + pos = &pos[4..]; + for byte in bytes { + if *byte == 0 { + break 'outer; + } + let c = *byte as char; + print!("{}", c); + } + } + println!(); + let node = RawNode { + data: pos, + strings: self.strings, + }; + pos = node.print_props(); + } + } + + pub fn find_node(&self, str: &str) -> Option { + let mut pos = self.nodes; + loop { + let token: Token = Token::from_bytes(pos); + pos = &pos[4..]; + if let Token::End = token { + break None; + } + if let Token::EndNode = token { + continue; + } + let mut i = 0; + let check = str.as_bytes(); + let mut failed = false; + 'outer: loop { + let bytes = &pos[..4]; + pos = &pos[4..]; + for byte in bytes { + if *byte == 0 { + break 'outer; + } + if i < check.len() && check[i] != *byte { + failed = true; + } + i += 1; + } + } + let node = RawNode { + data: pos, + strings: self.strings, + }; + if !failed && i >= check.len() { + return Some(node); + } + pos = node.pass_props(); + } + } +} + +pub struct RawNode { + pub strings: &'static [u8], + pub data: &'static [u8], +} + +impl RawNode { + pub fn get_prop(&self, str: &str) -> Option<&'static [u8]> { + let mut pos = self.data; + loop { + let token: Token = Token::from_bytes(pos); + let Token::Prop = token else { + break None; + }; + pos = &pos[4..]; + let prop: Prop = Prop::from_bytes(pos); + let name_bytes = &self.strings[prop.nameoff as usize..]; + let mut i = 0; + let mut failed = false; + let check = str.as_bytes(); + for byte in name_bytes { + if *byte == 0 { + break; + } + if i < check.len() && check[i] != *byte { + failed = true; + } + i += 1; + } + pos = &pos[PROP_SIZE..]; + if !failed && i >= check.len() { + return Some(&pos[..prop.len as usize]); + } + let len = (prop.len as usize + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1); + pos = &pos[len..]; + } + } + pub fn print_props(&self) -> &'static [u8] { + let mut pos = self.data; + loop { + let token: Token = Token::from_bytes(pos); + let Token::Prop = token else { + break; + }; + pos = &pos[4..]; + let prop: Prop = Prop::from_bytes(pos); + let name_bytes = &self.strings[prop.nameoff as usize..]; + print!(" "); + for byte in name_bytes { + if *byte == 0 { + break; + } + let c = *byte as char; + print!("{}", c); + } + println!(": {prop:?}"); + let aligned_len = (prop.len as usize + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1); + pos = &pos[PROP_SIZE + aligned_len..]; + } + pos + } + pub fn pass_props(&self) -> &'static [u8] { + let mut pos = self.data; + loop { + let token: Token = Token::from_bytes(pos); + let Token::Prop = token else { + break; + }; + pos = &pos[4..]; + let prop: Prop = Prop::from_bytes(pos); + let aligned_len = (prop.len as usize + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1); + pos = &pos[PROP_SIZE + aligned_len..]; + } + pos + } +} + +pub fn print_mem_layout(addr: usize) { + let fdt = RawFDT::new(addr); + fdt.print_all(); + if let Some(node) = fdt.find_node("memory") { + println!("mem:"); + let data = node.get_prop("reg"); + if let Some(data) = data { + for d in data.chunks(8) { + let mut arr: [u8; 8] = d.try_into().unwrap(); + let num: u64 = unsafe { transmute(arr) }; + println!("0x{:x}", num.to_be()); + } + } + } +} + pub unsafe fn from_be_32(addr: usize) -> [u8; S] { let mut data = *(addr as *mut [u8; S]); for slice in data.chunks_mut(4) { @@ -87,57 +257,11 @@ pub unsafe fn from_be_32(addr: usize) -> [u8; S] { data } -pub fn print_fdt(addr: usize) { - let header = Header::from_addr(addr); - let str_addr = header.off_dt_strings as usize + addr; - let mut addr = header.off_dt_struct as usize + addr; - loop { - let token: Token = Token::from_addr(addr); - addr += TOKEN_SIZE; - if let Token::End = token { - break; - } - if let Token::EndNode = token { - continue; - } - print!("name: "); - 'outer: loop { - let bytes = unsafe { *(addr as *mut [u8; TOKEN_SIZE]) }; - addr += TOKEN_SIZE; - for byte in bytes { - if byte == 0 { - break 'outer; - } - let c = byte as char; - print!("{}", c); - } - } - println!(); - print_props(str_addr, &mut addr) - } -} - -pub fn print_props(str_addr: usize, addr: &mut usize) { - loop { - let token: Token = Token::from_addr(*addr); - let Token::Prop = token else { - break; - }; - *addr += TOKEN_SIZE; - let prop: Prop = Prop::from_addr(*addr); - let mut name_addr = str_addr + prop.nameoff as usize; - print!(" "); - loop { - let byte = unsafe { *(name_addr as *mut u8) }; - name_addr += 1; - if byte == 0 { - break; - } - let c = byte as char; - print!("{}", c); - } - println!(": {prop:?}"); - let aligned_len = (prop.len as usize + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1); - *addr += PROP_SIZE + aligned_len; +pub unsafe fn be_32(data: &[u8]) -> [u8; S] { + let data: &[u8; S] = data[..S].try_into().unwrap(); + let mut data = (*data).clone(); + for slice in data.chunks_mut(4) { + slice.reverse(); } + data } diff --git a/runner/src/main.rs b/runner/src/main.rs index a0fdc0f..77f3f89 100644 --- a/runner/src/main.rs +++ b/runner/src/main.rs @@ -26,10 +26,12 @@ fn main() { fn run_qemu(target: &Target, gdb: Option>) { let mut qemu = target.qemu(); + qemu.args(["-d", "guest_errors"]); + qemu.args(["-m", "4G"]); + // qemu.args(["-monitor", "telnet:127.0.0.1:1235,server,nowait"]); if let Some(port) = gdb { let port = port.unwrap_or(1234); qemu.arg("-S"); - qemu.args(["-m", "4G"]); qemu.args(["-gdb", &format!("tcp::{}", port)]); let mut gdb = target.gdb(); gdb.arg("-q");