diff --git a/kernel/.cargo/config.toml b/kernel/.cargo/config.toml index 40ecdc5..3b3ddd3 100644 --- a/kernel/.cargo/config.toml +++ b/kernel/.cargo/config.toml @@ -1,6 +1,7 @@ [build] # rustflags = ["-g"] -target = ["riscv64gc-unknown-none-elf", "x86_64-unknown-none"] +# target = ["riscv64gc-unknown-none-elf", "x86_64-unknown-none"] +target = ["riscv64gc-unknown-none-elf"] [target.riscv64gc-unknown-none-elf] rustflags = [ diff --git a/kernel/src/allocator.rs b/kernel/src/allocator.rs index beeba40..770d3ce 100644 --- a/kernel/src/allocator.rs +++ b/kernel/src/allocator.rs @@ -3,11 +3,8 @@ use linked_list_allocator::LockedHeap; #[global_allocator] static ALLOCATOR: LockedHeap = LockedHeap::empty(); -pub const HEAP_START: *mut u8 = 0x9000_0000 as *mut u8; -pub const HEAP_SIZE: usize = 100 * 1024; - pub fn init_heap() { unsafe { - ALLOCATOR.lock().init(HEAP_START, HEAP_SIZE); + ALLOCATOR.lock().init(crate::arch::paging::first_free(), crate::arch::paging::free_len()); } } diff --git a/kernel/src/arch/riscv64/asm.rs b/kernel/src/arch/riscv64/asm.rs index aa598f2..86a95f4 100644 --- a/kernel/src/arch/riscv64/asm.rs +++ b/kernel/src/arch/riscv64/asm.rs @@ -27,3 +27,7 @@ pub(crate) use linker_static; pub fn wfi() { unsafe { asm!("wfi") } } + +pub unsafe fn mret() { + asm!("mret"); +} diff --git a/kernel/src/arch/riscv64/csr.rs b/kernel/src/arch/riscv64/csr.rs index f167815..1270ac3 100644 --- a/kernel/src/arch/riscv64/csr.rs +++ b/kernel/src/arch/riscv64/csr.rs @@ -1,12 +1,10 @@ macro_rules! csrr { ($name:expr) => {{ let mut out: u64; - unsafe { - core::arch::asm!( - concat!("csrr {out}, ", $name), - out = out(reg) out, - ); - } + core::arch::asm!( + concat!("csrr {out}, ", $name), + out = out(reg) out, + ); out }}; } @@ -35,15 +33,9 @@ macro_rules! csrw { }; } -macro_rules! bits { - ($name:ident[$high:expr,$low:expr]) => {{ - ($name & ((2u64.pow($high - $low + 1) - 1) << $low)) >> $low - }}; -} - pub mod hartid { pub fn read() -> u64 { - csrr!("mhartid") + unsafe { csrr!("mhartid") } } } @@ -56,20 +48,60 @@ pub mod mtvec { } pub(crate) use init; pub fn read() -> u64 { - csrr!("mtvec") + unsafe { csrr!("mtvec") } } } pub mod mcause { - pub fn read() -> u64 { - csrr!("mcause") + use core::mem::transmute; + + #[derive(Debug)] + pub enum MCause { + // interrupt = 1 + SupervisorSoftwareInterrupt = (1 << 63) | 1, + VirtualSupervisorSoftwareInterrupt = (1 << 63) | 2, + MachineSoftwareInterrupt = (1 << 63) | 3, + + SupervisorTimerInterrupt = (1 << 63) | 5, + VirtualSupervisorTimerInterrupt = (1 << 63) | 6, + MachineTimerInterrupt = (1 << 63) | 7, + + SupervisorExternalInterrupt = (1 << 63) | 9, + VirtualSupervisorExternalInterrupt = (1 << 63) | 10, + MachineExternalInterrupt = (1 << 63) | 11, + + SupervisorGuestExternalInterrupt = (1 << 63) | 12, + + // interrupt = 0 + InstructionAddrMisaligned = 0, + InstructionAccessFault = 1, + IllegalInstruction = 2, + Breakpoint = 3, + LoadAddressMisaligned = 4, + LoadAccessFault = 5, + StoreAMOAddressMisaligned = 6, + StoreAMOAccessFault = 7, + EnvCallUorVU = 8, + EnvCallHS = 9, + EnvCallVS = 10, + EnvCallM = 11, + InstructionPageFault = 12, + LoadPageFault = 13, + StoreAMOPageFault = 15, + InstructionGuestPageFault = 20, + LoadGuestPageFault = 21, + VirtualInstruction = 22, + StoreAMOGuestPageFault = 23, + } + pub fn read() -> MCause { + unsafe { transmute(csrr!("mcause")) } } } pub mod satp { use core::mem::transmute; - use crate::arch::paging::Table; + use crate::{arch::paging::Table, util::bits::get_bits}; #[derive(Debug)] #[repr(u64)] @@ -98,10 +130,10 @@ pub mod satp { pub ppn: *mut Table, } pub fn read() -> Satp { - let satp = csrr!("satp"); - let mode = unsafe { transmute(bits!(satp[63,60])) }; - let asid = bits!(satp[59, 44]); - let ppn = unsafe { transmute(bits!(satp[43, 0]) << 12) }; + let satp = unsafe { csrr!("satp") }; + let mode = unsafe { transmute(get_bits!(satp[63,60])) }; + let asid = get_bits!(satp[59, 44]); + let ppn = unsafe { transmute(get_bits!(satp[43, 0]) << 12) }; Satp { mode, asid, ppn } } pub fn write(satp: Satp) { @@ -109,3 +141,12 @@ pub mod satp { csrw!("satp", val); } } + +pub mod mstatus { + pub fn read() -> u64 { + unsafe { csrr!("mstatus") } + } + pub fn write(val: u64) { + csrw!("mstatus", val); + } +} diff --git a/kernel/src/arch/riscv64/init.rs b/kernel/src/arch/riscv64/init.rs index c642415..183b6dc 100644 --- a/kernel/src/arch/riscv64/init.rs +++ b/kernel/src/arch/riscv64/init.rs @@ -1,7 +1,13 @@ +use core::ptr::null_mut; + use crate::{ - arch::{asm, csr, interrupts, paging, wait}, main, println + arch::{asm, csr, interrupts, paging, wait}, + fdt::FDT, + main, }; +static mut DT_ADDR: *mut FDT = null_mut(); + #[no_mangle] #[link_section = ".text.init"] #[naked] @@ -18,25 +24,47 @@ unsafe extern "C" fn _start() -> ! { "slli t0, t0, 12", "sub sp, sp, t0", // continue to rest of program - "tail {entry}", + // "tail {entry}", + // ok so this should be done in rust + "li t0, 0b11 << 11", + "csrw mstatus, t0", + "la t0, {init}", + "csrw mepc, t0", + "la ra, 2f", + "mret", - entry = sym entry, + "2:", + "li t0, (1 << 8) | (1 << 5)", + "csrw sstatus, t0", + "li t0, (7 << 0) | (1 << 3)", + "csrw pmpcfg0, t0", + "li t0, 0xffffffffffff", + "csrw pmpaddr0, t0", + "li t2, (1 << 1) | (1 << 5) | (1 << 9)", + "csrw mideleg, t2", + "csrw sie, t2", + "la t0, {start}", + "csrw sepc, t0", + "sfence.vma", + "sret", + + start = sym start, + init = sym init, options(noreturn) ); } -pub fn entry() -> ! { - let dt_addr = asm::reg!("a1") as usize; +pub fn init() { + let dt_addr = asm::reg!("a1") as *mut u8; let hart = csr::hartid::read(); - println!("yo from hart {hart}"); if hart != 0 { wait(); } interrupts::init(); - paging::init(dt_addr); - println!( - "machine trap vector base address: 0x{:x}", - csr::mtvec::read() - ); - main(dt_addr) + let fdt = FDT::from_addr(dt_addr); + paging::init(fdt); +} + +pub fn start() { + main(unsafe { DT_ADDR }); } diff --git a/kernel/src/arch/riscv64/interrupts.rs b/kernel/src/arch/riscv64/interrupts.rs index 8c9f485..9daf548 100644 --- a/kernel/src/arch/riscv64/interrupts.rs +++ b/kernel/src/arch/riscv64/interrupts.rs @@ -7,6 +7,6 @@ pub fn init() { #[repr(align(4))] pub fn stuff() -> ! { let mcause = csr::mcause::read(); - crate::println!("interrupt triggered: {mcause}"); + crate::println!("interrupt triggered: {mcause:?}"); super::qemu::exit(); } diff --git a/kernel/src/arch/riscv64/link.ld b/kernel/src/arch/riscv64/link.ld index 2e9affa..8ad2109 100644 --- a/kernel/src/arch/riscv64/link.ld +++ b/kernel/src/arch/riscv64/link.ld @@ -22,7 +22,6 @@ SECTIONS . += 0x8000; PROVIDE(_stack_end = .); . = ALIGN(4096); /* 2^12 */ - PROVIDE(_heap_start = .); - . += 0x20000000; + PROVIDE(_end = .); } diff --git a/kernel/src/arch/riscv64/paging.rs b/kernel/src/arch/riscv64/paging.rs index 917c863..304db3d 100644 --- a/kernel/src/arch/riscv64/paging.rs +++ b/kernel/src/arch/riscv64/paging.rs @@ -1,33 +1,138 @@ +use super::asm::linker_static; use crate::{ arch::csr::{self, satp}, - fdt::print_mem_layout, + fdt::FDT, println, + util::bits::get_bits, }; +use core::{ptr::null_mut, slice}; -use super::asm::linker_static; +linker_static!(END: usize, ".dword _end"); +const PAGE_SIZE: usize = 4096; +const TABLE_LEN: usize = 2usize.pow(9); +const TABLE_SIZE: usize = core::mem::size_of::(); -linker_static!(HEAP_START: usize, ".dword _heap_start"); -static HEAP_SIZE: usize = 128 * 1024 * 1024; +static mut FIRST_FREE: *mut u8 = null_mut(); +static mut MEM_END: *mut u8 = null_mut(); -pub struct Entry(u64); +#[repr(C)] +pub struct Entry(usize); -pub struct Table { - pub entries: [Entry; 2usize.pow(9)], +impl Entry { + pub fn set_table(&mut self, addr: *const Table) { + self.0 = addr as usize >> 2; + self.set_valid(true); + } + pub fn set_valid(&mut self, valid: bool) { + if valid { + self.0 |= 1; + } else { + self.0 &= !1; + } + } + pub fn set_addr(&mut self, addr: usize) { + self.clear(); + self.0 |= addr as usize >> 2; + self.0 |= 0b1110; + self.set_valid(true); + } + pub fn get_table(&self) -> *const Table { + ((self.0 & !0b1111111111) << 2) as *const Table + } + pub fn get_addr(&self) -> usize { + let val = self.0; + get_bits!(val[53,10]) << 12 + } + pub fn clear(&mut self) { + self.0 = 0; + } } -pub fn init(fdt: usize) { +#[repr(C, align(4096))] +pub struct Table { + pub entries: [Entry; TABLE_LEN], +} + +pub fn init(fdt: FDT) { unsafe { - println!("heap start: 0x{:x}", HEAP_START); - print_mem_layout(fdt); - let table_start = HEAP_START as *mut Table; + println!("program end: 0x{:x}", END); + let range = fdt.mem_range(); + let start = range.start.get(); + let len = range.len.get(); + let end = start + len; + MEM_END = end as *mut u8; + println!("memory range: 0x{:x} -> 0x{:x}", start, end); + let total_pages = end / 4096; + let lvl1_count = (total_pages.saturating_sub(1)) / TABLE_LEN + 1; + let lvl2_count = (lvl1_count.saturating_sub(1)) / TABLE_LEN + 1; + let lvl2 = &mut *(END as *mut Table); + let lvl1_arr = slice::from_raw_parts_mut((lvl2 as *mut Table).add(TABLE_SIZE), lvl2_count); + let lvl0_arr = slice::from_raw_parts_mut( + lvl1_arr.as_ptr().add(lvl1_arr.len()) as *mut Table, + lvl1_count, + ); + let mut lvl1itr = lvl1_arr.iter(); + for entry in &mut lvl2.entries { + if let Some(table) = lvl1itr.next() { + entry.set_table(table as *const Table); + } else { + entry.clear(); + } + } + let mut lvl0itr = lvl0_arr.iter(); + for lvl1 in lvl1_arr { + for entry in &mut lvl1.entries { + if let Some(table) = lvl0itr.next() { + entry.set_table(table as *const Table); + } else { + entry.clear(); + } + } + } + let mut i = 0; + for lvl0 in &mut *lvl0_arr { + for entry in &mut lvl0.entries { + if i < total_pages { + entry.set_addr(i * PAGE_SIZE); + } else { + entry.clear() + } + i += 1; + } + } + csr::satp::write(satp::Satp { mode: satp::Mode::Sv39, asid: 0, - ppn: table_start, + ppn: lvl2, }); let satp = csr::satp::read(); println!("satp: {satp:?}"); - let x = *(0x9000_0000 as *mut u8); - println!("we got {x}"); + let end = lvl0_arr.as_ptr().add(lvl0_arr.len()) as *mut u8; + FIRST_FREE = end; } } + +pub fn virt_to_physical(table: &Table, addr: usize) -> usize { + let ppn2 = get_bits!(addr[38,30]); + let ppn1 = get_bits!(addr[29,21]); + let ppn0 = get_bits!(addr[20,12]); + let offset = get_bits!(addr[11,0]); + // let satp = csr::satp::read(); + unsafe { + let lvl2 = table as *const Table; + let lvl1 = (*lvl2).entries[ppn2].get_table(); + let lvl0 = (*lvl1).entries[ppn1].get_table(); + let base = (*lvl0).entries[ppn0].get_addr(); + let addr = base + offset; + addr + } +} + +pub fn first_free() -> *mut u8 { + unsafe { FIRST_FREE } +} + +pub fn free_len() -> usize { + unsafe { MEM_END.offset_from(FIRST_FREE) as usize } +} diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 646ec9f..4554445 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1,5 +1,3 @@ -use crate::main; - pub mod framebuffer; pub mod gdt; pub mod interrupts; @@ -13,7 +11,9 @@ fn _start(boot_info: &'static mut bootloader_api::BootInfo) -> ! { if let Some(framebuffer) = boot_info.framebuffer.as_mut() { framebuffer::draw_test(framebuffer); } - main(0); + // not working on this anymore for now + // main(null_mut()); + loop {} } pub fn hlt_loop() -> ! { diff --git a/kernel/src/fdt.rs b/kernel/src/fdt.rs index a81cbbd..a8a82c3 100644 --- a/kernel/src/fdt.rs +++ b/kernel/src/fdt.rs @@ -1,6 +1,11 @@ // NOTE: basically none of this is safe rn, ideally it's eventually made safe / able to recover +// also, I do a ton of slice.try_into and then transmuting which I'm pretty sure is bad and +// I really should be transmuting into references but I cannot be bothered rn -use crate::{print, println}; +use crate::{ + println, + util::bits::{u32_from_bytes, Be}, +}; use core::{ mem::{size_of, transmute}, slice, @@ -11,257 +16,222 @@ const MAGIC: u32 = 0xd00dfeed; #[repr(u32)] #[derive(Clone, Copy, Debug)] enum Token { - BeginNode = 0x00000001, - EndNode = 0x00000002, - Prop = 0x00000003, - Nop = 0x00000004, - End = 0x00000009, + BeginNode, + EndNode, + Prop, + Nop, + End, } const TOKEN_SIZE: usize = size_of::(); impl Token { - pub fn from_bytes(data: &[u8]) -> Self { - unsafe { transmute(be_32::(data)) } + pub fn from_bytes(bytes: &[u8]) -> Option { + let val = u32_from_bytes(bytes)?.to_be(); + Some(match val { + 0x00000001 => Token::BeginNode, + 0x00000002 => Token::EndNode, + 0x00000003 => Token::Prop, + 0x00000004 => Token::Nop, + 0x00000009 => Token::End, + _ => { + println!("Failed to parse token!"); + return None; + } + }) } } -#[derive(Clone, Copy)] #[repr(C)] pub struct Header { - pub magic: u32, - pub totalsize: u32, - pub off_dt_struct: u32, - pub off_dt_strings: u32, - pub off_mem_rsvmap: u32, - pub version: u32, - pub last_comp_version: u32, - pub boot_cpuid_phys: u32, - pub size_dt_strings: u32, - pub size_dt_struct: u32, + pub magic: Be, + pub totalsize: Be, + pub off_dt_struct: Be, + pub off_dt_strings: Be, + pub off_mem_rsvmap: Be, + pub version: Be, + pub last_comp_version: Be, + pub boot_cpuid_phys: Be, + pub size_dt_strings: Be, + pub size_dt_struct: Be, } -const HEADER_SIZE: usize = size_of::
(); -impl Header { - pub fn from_addr(addr: usize) -> Self { - unsafe { transmute(from_be_32::(addr)) } - } +const PROP_SIZE: usize = size_of::(); +pub struct RawProp { + len: Be, + nameoff: Be, } -const PROP_SIZE: usize = size_of::(); -#[derive(Debug)] pub struct Prop { - len: u32, - nameoff: u32, + pub name: &'static str, + pub data: &'static [u8], } impl Prop { - pub fn from_bytes(data: &[u8]) -> Self { - unsafe { transmute(be_32::(data)) } + pub fn full_len(&self) -> usize { + return PROP_SIZE + self.data.len(); } } pub struct FDT { - pub header: Header, -} - -impl FDT { - pub fn new(addr: usize) -> Self { - let header = Header::from_addr(addr); - Self { header } - } -} - -pub struct RawFDT { - pub header: Header, + pub header: &'static 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(); +impl IntoIterator for &FDT { + type Item = Node; + type IntoIter = NodeIter; + fn into_iter(self) -> Self::IntoIter { + Self::IntoIter { + pos: self.nodes, + strings: self.strings, } } } -pub struct RawNode { +pub struct NodeIter { + pub pos: &'static [u8], 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 { +impl Iterator for NodeIter { + type Item = Node; + fn next(&mut self) -> Option { + let token: Token = Token::from_bytes(self.pos)?; + self.pos = &self.pos[4..]; + if let Token::End = token { + return None; + } + let name_start = self.pos; + 'outer: loop { + let bytes = &self.pos[..4]; + self.pos = &self.pos[4..]; + for byte in bytes { if *byte == 0 { + break 'outer; + } + } + } + let name = unsafe { transmute(&name_start[..name_start.len() - self.pos.len()]) }; + let node_start = self.pos; + let node_data = if let Some(prop) = (PropIter { + strings: self.strings, + pos: self.pos, + }) + .last() + { + let node_len = + (prop.data.as_ptr() as usize + prop.data.len()) - self.pos.as_ptr() as usize; + self.pos = &self.pos[node_len..]; + &node_start[..node_len] + } else { + &[] + }; + let node = Node { + name, + props: node_data, + strings: self.strings, + }; + loop { + if let Some(token) = Token::from_bytes(self.pos) { + if let Token::EndNode = token { + self.pos = &self.pos[4..]; + } else { 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 { + } 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; + } + } + Some(node) + } +} + +impl FDT { + pub fn from_addr(addr: *mut u8) -> Self { + unsafe { + let header: &Header = transmute(addr); + if header.magic.get() != MAGIC { + panic!("fdt magic wrong"); + } + let data = slice::from_raw_parts(addr as *mut u8, 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) -> MemRange { + if let Some(node) = self.into_iter().find(|n| n.name.starts_with("memory@")) { + let prop = node.find_prop("reg"); + if let Some(prop) = prop { + for d in prop.data.chunks(size_of::()) { + let d: [u8; size_of::()] = d.try_into().unwrap(); + // just return first one for now + return unsafe { transmute(d) }; } - 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()); } } + panic!("failed to get memory range"); } } -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) { - slice.reverse(); - } - data +#[repr(C)] +pub struct MemRange { + pub start: Be, + pub len: Be, } -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 +pub struct Node { + pub name: &'static str, + pub strings: &'static [u8], + pub props: &'static [u8], +} + +impl IntoIterator for &Node { + type Item = Prop; + type IntoIter = PropIter; + fn into_iter(self) -> Self::IntoIter { + Self::IntoIter { + pos: self.props, + strings: self.strings, + } + } +} + +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 { transmute(self.pos.as_ptr()) }; + 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 = unsafe { transmute(&name_start[..i]) }; + return Some(Prop { name, data }); + } + } + println!("failed to read prop name, not sure what to do"); + None + } +} + +impl Node { + pub fn find_prop(&self, name: &str) -> Option { + self.into_iter().find(|p| p.name == name) + } } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index a70c95f..43918c7 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -4,6 +4,8 @@ #![feature(naked_functions)] #![feature(fn_align)] +use fdt::FDT; + extern crate alloc; pub mod allocator; @@ -11,14 +13,17 @@ pub mod arch; pub mod fdt; pub mod log; pub mod qemu; +pub mod util; -pub fn main(dt_addr: usize) -> ! { +pub fn main(dt_addr: *mut FDT) -> ! { println!("we out here vibin"); allocator::init_heap(); - let fdt = fdt::FDT::new(dt_addr); + let mut test = alloc::vec![1, 2, 3]; + test.push(3); + println!("{:?}", test); // for _ in 0..40000000 {} - let x = unsafe { *(0xdeadbeef as *mut u8) }; - println!("we got {x}"); + // let x = unsafe { *(0x10000000000 as *mut u8) }; + // println!("we got {x}"); qemu::exit(); } diff --git a/kernel/src/util/bits.rs b/kernel/src/util/bits.rs new file mode 100644 index 0000000..237aba2 --- /dev/null +++ b/kernel/src/util/bits.rs @@ -0,0 +1,46 @@ +use core::mem::transmute; + +macro_rules! get_bits { + ($name:ident[$high:expr,$low:expr]) => {{ + ($name & ((($name - $name + 2).pow($high - $low + 1) - 1) << $low)) >> $low + }}; +} +pub(crate) use get_bits; + +pub trait BeRep { + fn _from_be(&self) -> Self; +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct Be(T); +impl Be { + pub fn get(&self) -> T { + self.0._from_be() + } +} + +impl BeRep for u32 { + fn _from_be(&self) -> Self { + self.to_be() + } +} + +impl BeRep for u64 { + fn _from_be(&self) -> Self { + self.to_be() + } +} + +impl BeRep for usize { + fn _from_be(&self) -> Self { + self.to_be() + } +} + +pub fn u32_from_bytes(bytes: &[u8]) -> Option { + if bytes.len() < 4 { + return None; + } + unsafe { Some(transmute([bytes[0], bytes[1], bytes[2], bytes[3]])) } +} diff --git a/kernel/src/util/mod.rs b/kernel/src/util/mod.rs new file mode 100644 index 0000000..e79b623 --- /dev/null +++ b/kernel/src/util/mod.rs @@ -0,0 +1 @@ +pub mod bits; diff --git a/runner/src/main.rs b/runner/src/main.rs index 77f3f89..a431ebf 100644 --- a/runner/src/main.rs +++ b/runner/src/main.rs @@ -28,7 +28,7 @@ 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"]); + 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"); diff --git a/runner/src/target.rs b/runner/src/target.rs index 2acf535..88d8dad 100644 --- a/runner/src/target.rs +++ b/runner/src/target.rs @@ -40,6 +40,7 @@ impl Target { let mut cmd = Command::new("qemu-system-riscv64"); cmd.arg("-nographic"); cmd.arg("-semihosting"); + cmd.args(["-cpu", "rv64"]); cmd.args(["-machine", "virt"]); cmd.args(["-bios", "none"]); cmd.args(["-smp", "4"]);