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