FINALLY PAGING AND HEAP WORK WITH REALLY BAD CODE
This commit is contained in:
@@ -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 = [
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,3 +27,7 @@ pub(crate) use linker_static;
|
||||
pub fn wfi() {
|
||||
unsafe { asm!("wfi") }
|
||||
}
|
||||
|
||||
pub unsafe fn mret() {
|
||||
asm!("mret");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ SECTIONS
|
||||
. += 0x8000;
|
||||
PROVIDE(_stack_end = .);
|
||||
. = ALIGN(4096); /* 2^12 */
|
||||
PROVIDE(_heap_start = .);
|
||||
. += 0x20000000;
|
||||
PROVIDE(_end = .);
|
||||
}
|
||||
|
||||
|
||||
@@ -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::<Table>();
|
||||
|
||||
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 }
|
||||
}
|
||||
|
||||
@@ -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() -> ! {
|
||||
|
||||
@@ -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::<Token>();
|
||||
impl Token {
|
||||
pub fn from_bytes(data: &[u8]) -> Self {
|
||||
unsafe { transmute(be_32::<TOKEN_SIZE>(data)) }
|
||||
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
|
||||
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<u32>,
|
||||
pub totalsize: Be<u32>,
|
||||
pub off_dt_struct: Be<u32>,
|
||||
pub off_dt_strings: Be<u32>,
|
||||
pub off_mem_rsvmap: Be<u32>,
|
||||
pub version: Be<u32>,
|
||||
pub last_comp_version: Be<u32>,
|
||||
pub boot_cpuid_phys: Be<u32>,
|
||||
pub size_dt_strings: Be<u32>,
|
||||
pub size_dt_struct: Be<u32>,
|
||||
}
|
||||
|
||||
const HEADER_SIZE: usize = size_of::<Header>();
|
||||
impl Header {
|
||||
pub fn from_addr(addr: usize) -> Self {
|
||||
unsafe { transmute(from_be_32::<HEADER_SIZE>(addr)) }
|
||||
}
|
||||
const PROP_SIZE: usize = size_of::<RawProp>();
|
||||
pub struct RawProp {
|
||||
len: Be<u32>,
|
||||
nameoff: Be<u32>,
|
||||
}
|
||||
|
||||
const PROP_SIZE: usize = size_of::<Prop>();
|
||||
#[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::<PROP_SIZE>(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<RawNode> {
|
||||
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<Self::Item> {
|
||||
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::<MemRange>()) {
|
||||
let d: [u8; size_of::<MemRange>()] = 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<const S: usize>(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<usize>,
|
||||
pub len: Be<usize>,
|
||||
}
|
||||
|
||||
pub unsafe fn be_32<const S: usize>(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<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 { 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<Prop> {
|
||||
self.into_iter().find(|p| p.name == name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
46
kernel/src/util/bits.rs
Normal file
46
kernel/src/util/bits.rs
Normal file
@@ -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: BeRep>(T);
|
||||
impl<T: BeRep> Be<T> {
|
||||
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<u32> {
|
||||
if bytes.len() < 4 {
|
||||
return None;
|
||||
}
|
||||
unsafe { Some(transmute([bytes[0], bytes[1], bytes[2], bytes[3]])) }
|
||||
}
|
||||
1
kernel/src/util/mod.rs
Normal file
1
kernel/src/util/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod bits;
|
||||
Reference in New Issue
Block a user