#![no_std] #![no_main] #[macro_use] extern crate log; #[macro_use] extern crate opensbi_rt; use device_tree::util::SliceRead; use device_tree::{DeviceTree, Node}; use log::LevelFilter; use virtio_drivers::{DeviceType, VirtIOBlk, VirtIOHeader}; mod virtio_impl; #[no_mangle] extern "C" fn main(_hartid: usize, device_tree_paddr: usize) { log::set_max_level(LevelFilter::Info); init_dt(device_tree_paddr); } fn init_dt(dtb: usize) { info!("device tree @ {:#x}", dtb); struct DtbHeader { be_magic: u32, be_size: u32, } let header = unsafe { &*(dtb as *const DtbHeader) }; let magic = u32::from_be(header.be_magic); const DEVICE_TREE_MAGIC: u32 = 0xd00dfeed; assert_eq!(magic, DEVICE_TREE_MAGIC); let size = u32::from_be(header.be_size); let dtb_data = unsafe { core::slice::from_raw_parts(dtb as *const u8, size as usize) }; let dt = DeviceTree::load(dtb_data).expect("failed to parse device tree"); walk_dt_node(&dt.root); } fn walk_dt_node(dt: &Node) { if let Ok(compatible) = dt.prop_str("compatible") { if compatible == "virtio,mmio" { virtio_probe(dt); } } for child in dt.children.iter() { walk_dt_node(child); } } fn virtio_probe(node: &Node) { if let Some(reg) = node.prop_raw("reg") { let paddr = reg.as_slice().read_be_u64(0).unwrap(); let size = reg.as_slice().read_be_u64(8).unwrap(); let vaddr = paddr; info!("walk dt addr={:#x}, size={:#x}", paddr, size); let header = unsafe { &mut *(vaddr as *mut VirtIOHeader) }; info!( "Detected virtio device with vendor id {:#X}", header.vendor_id() ); info!("Device tree node {:?}", node); match header.device_type() { DeviceType::Block => virtio_blk(header), t => warn!("Unrecognized virtio device: {:?}", t), } } } fn virtio_blk(header: &'static mut VirtIOHeader) { let mut blk = VirtIOBlk::new(header).expect("failed to create blk driver"); let mut buf = [0u8; 512]; blk.read_block(0, &mut buf); unimplemented!() }