|
@@ -0,0 +1,73 @@
|
|
|
+#![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!()
|
|
|
+}
|