diff --git a/kernel/src/drivers/block/mod.rs b/kernel/src/drivers/block/mod.rs
index 04d3c79d75ddb09ce4a30e99c87e126199f66b5e..30667673a3123cbf7ea7f044279dca7b63365bf1 100644
--- a/kernel/src/drivers/block/mod.rs
+++ b/kernel/src/drivers/block/mod.rs
@@ -1,12 +1,13 @@
 //! 块设备驱动层
 
 mod virtio_blk;
+mod virtio_impl;
 
 pub use virtio_blk::VirtIOBlock;
 
+use crate::board::BlockDeviceImpl;
 use alloc::sync::Arc;
 use fat32::BlockDevice;
-use crate::board::BlockDeviceImpl;
 
 lazy_static! {
     pub static ref BLOCK_DEVICE: Arc<dyn BlockDevice> = Arc::new(BlockDeviceImpl::new());
diff --git a/kernel/src/drivers/block/virtio_blk.rs b/kernel/src/drivers/block/virtio_blk.rs
index 1bfa7f15e75428f90536faa69e670709ddc5f964..a3091a81cc4f1ec48cb5a920e58d1493e9197382 100644
--- a/kernel/src/drivers/block/virtio_blk.rs
+++ b/kernel/src/drivers/block/virtio_blk.rs
@@ -8,23 +8,46 @@ use crate::{
         VirtAddr,
     },
 };
+use alloc::sync::Arc;
 use alloc::vec::Vec;
+use core::ptr::NonNull;
 use spin::Mutex;
-use virtio_drivers::{VirtIOBlk, VirtIOHeader};
+use virtio_drivers::{
+    device::blk::VirtIOBlk,
+    transport::{
+        self,
+        mmio::{MmioTransport, VirtIOHeader},
+        DeviceType, Transport,
+    },
+};
+
+use super::virtio_impl::HalImpl;
 
 #[allow(unused)]
 const VIRTIO0: usize = 0x10001000;
 
-lazy_static! {
-    static ref QUEUE_FRAMES: Mutex<Vec<FrameTracker>> = Mutex::new(Vec::new());
-}
-
 /// VirtIO 总线架构下的块设备
-/// 
+///
 /// 将 `virtio-drivers` crate 提供的 VirtIO 块设备抽象 `VirtIOBlk` 包装为我们自己的 `VirtIOBlock`
-/// 
-/// 实质上只是加上了一层互斥锁,生成一个新的类型来实现 fat32 需要的 `BlockDevice` Trait
-pub struct VirtIOBlock(Mutex<VirtIOBlk<'static>>);
+pub struct VirtIOBlock(Mutex<VirtIOBlk<HalImpl, MmioTransport>>);
+
+unsafe impl Send for VirtIOBlock {}
+unsafe impl Sync for VirtIOBlock {}
+
+impl VirtIOBlock {
+    pub fn new() -> Self {
+        let header = NonNull::new(VIRTIO0 as *mut VirtIOHeader).unwrap();
+        let mut blk = match unsafe { MmioTransport::new(header) } {
+            Err(e) => {
+                panic!("Error creating VirtIO MMIO transport: {}", e)
+            }
+            Ok(transport) => VirtIOBlk::<HalImpl, MmioTransport>::new(transport)
+                .expect("failed to create blk driver"),
+        };
+
+        Self(Mutex::new(blk))
+    }
+}
 
 impl BlockDevice for VirtIOBlock {
     fn read_block(&self, block_id: usize, buf: &mut [u8]) {
@@ -45,51 +68,51 @@ impl BlockDevice for VirtIOBlock {
     }
 }
 
-impl VirtIOBlock {
-    #[allow(unused)]
-    pub fn new() -> Self {
-        unsafe {
-            Self(Mutex::new(
-                // VirtIOHeader 实际上就代表以 MMIO 方式访问 VirtIO 设备所需的一组设备寄存器
-                VirtIOBlk::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap(),
-            ))
-        }
-    }
-}
-
-#[no_mangle]
-pub extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr {
-    let mut ppn_base = PhysPageNum(0);
-    for i in 0..pages {
-        let frame = alloc_frame().unwrap();
-        if i == 0 {
-            ppn_base = frame.ppn;
-        }
-        assert_eq!(frame.ppn.0, ppn_base.0 + i);
-        QUEUE_FRAMES.lock().push(frame);
-    }
-    ppn_base.into()
-}
-
-#[no_mangle]
-pub extern "C" fn virtio_dma_dealloc(pa: PhysAddr, pages: usize) -> i32 {
-    let mut ppn_base: PhysPageNum = pa.into();
-    for _ in 0..pages {
-        dealloc_frame(ppn_base);
-        ppn_base.step();
-    }
-
-    0
-}
-
-#[no_mangle]
-pub extern "C" fn virtio_phys_to_virt(paddr: PhysAddr) -> VirtAddr {
-    VirtAddr(paddr.0)
-}
-
-#[no_mangle]
-pub extern "C" fn virtio_virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
-    PageTable::from_token(kernel_token!())
-        .translate_va(vaddr)
-        .unwrap()
-}
+// use virtio_drivers::{VirtIOBlk, VirtIOHeader};
+// lazy_static! {
+//     static ref QUEUE_FRAMES: Mutex<Vec<FrameTracker>> = Mutex::new(Vec::new());
+// }
+// pub struct  VirtIOBlock(Mutex<VirtIOBlk<'static>>);
+// impl VirtIOBlock {
+//     #[allow(unused)]
+//     pub fn new() -> Self {
+//         unsafe {
+//             Self(Mutex::new(
+//                 // VirtIOHeader 实际上就代表以 MMIO 方式访问 VirtIO 设备所需的一组设备寄存器
+//                 VirtIOBlk::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap(),
+//             ))
+//         }
+//     }
+// }
+// #[no_mangle]
+// pub extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr {
+//     let mut ppn_base = PhysPageNum(0);
+//     for i in 0..pages {
+//         let frame = alloc_frame().unwrap();
+//         if i == 0 {
+//             ppn_base = frame.ppn;
+//         }
+//         assert_eq!(frame.ppn.0, ppn_base.0 + i);
+//         QUEUE_FRAMES.lock().push(frame);
+//     }
+//     ppn_base.into()
+// }
+// #[no_mangle]
+// pub extern "C" fn virtio_dma_dealloc(pa: PhysAddr, pages: usize) -> i32 {
+//     let mut ppn_base: PhysPageNum = pa.into();
+//     for _ in 0..pages {
+//         dealloc_frame(ppn_base);
+//         ppn_base.step();
+//     }
+//     0
+// }
+// #[no_mangle]
+// pub extern "C" fn virtio_phys_to_virt(paddr: PhysAddr) -> VirtAddr {
+//     VirtAddr(paddr.0)
+// }
+// #[no_mangle]
+// pub extern "C" fn virtio_virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
+//     PageTable::from_token(kernel_token!())
+//         .translate_va(vaddr)
+//         .unwrap()
+// }
diff --git a/kernel/src/drivers/block/virtio_impl.rs b/kernel/src/drivers/block/virtio_impl.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ac1ea3512c33c441dd97035c1bfb4279722e814d
--- /dev/null
+++ b/kernel/src/drivers/block/virtio_impl.rs
@@ -0,0 +1,80 @@
+use core::{
+    ptr::NonNull,
+    sync::atomic::{AtomicUsize, Ordering},
+};
+use lazy_static::lazy_static;
+use virtio_drivers::{BufferDirection, Hal, PhysAddr, PAGE_SIZE};
+
+use crate::{
+    kernel_token,
+    mm::{
+        alloc_frame, dealloc_frame, FrameTracker, PageTable, PhysAddr as KPhysAddr, PhysPageNum,
+        StepByOne, VirtAddr,
+    },
+};
+use alloc::vec::Vec;
+use spin::Mutex;
+
+lazy_static! {
+    static ref DMA_PADDR: Mutex<Vec<FrameTracker>> = Mutex::new(Vec::new());
+}
+
+pub struct HalImpl;
+
+unsafe impl Hal for HalImpl {
+    #[no_mangle]
+    fn dma_alloc(pages: usize, _direction: BufferDirection) -> (PhysAddr, NonNull<u8>) {
+        let mut ppn_base = PhysPageNum(0);
+        for i in 0..pages {
+            let frame = alloc_frame().unwrap();
+            if i == 0 {
+                ppn_base = frame.ppn;
+            }
+            assert_eq!(frame.ppn.0, ppn_base.0 + i);
+            DMA_PADDR.lock().push(frame);
+        }
+        let kpaddr: KPhysAddr = ppn_base.into();
+        let paddr: PhysAddr = kpaddr.0;
+
+        crate::info!("alloc DMA: paddr={:#x}, pages={}", paddr, pages);
+        let vaddr = NonNull::new(paddr as _).unwrap();
+        (paddr, vaddr)
+    }
+
+    #[no_mangle]
+    unsafe fn dma_dealloc(paddr: PhysAddr, _vaddr: NonNull<u8>, pages: usize) -> i32 {
+        let pa: KPhysAddr = paddr.into();
+        let mut ppn_base: PhysPageNum = pa.into();
+        for _ in 0..pages {
+            dealloc_frame(ppn_base);
+            ppn_base.step();
+        }
+        crate::info!("dealloc DMA: paddr={:#x}, pages={}", paddr, pages);
+        0
+    }
+
+    #[no_mangle]
+    unsafe fn mmio_phys_to_virt(paddr: PhysAddr, _size: usize) -> NonNull<u8> {
+        NonNull::new(paddr as _).unwrap()
+    }
+
+    #[no_mangle]
+    unsafe fn share(buffer: NonNull<[u8]>, _direction: BufferDirection) -> PhysAddr {
+        let vaddr = buffer.as_ptr() as *mut u8 as usize;
+        // Nothing to do, as the host already has access to all memory.
+        virt_to_phys(vaddr)
+    }
+
+    #[no_mangle]
+    unsafe fn unshare(_paddr: PhysAddr, _buffer: NonNull<[u8]>, _direction: BufferDirection) {
+        // Nothing to do, as the host already has access to all memory and we didn't copy the buffer
+        // anywhere else.
+    }
+}
+
+fn virt_to_phys(vaddr: usize) -> PhysAddr {
+    PageTable::from_token(kernel_token!())
+        .translate_va(vaddr.into())
+        .unwrap()
+        .0
+}
diff --git a/kernel/src/fs/inode.rs b/kernel/src/fs/inode.rs
index a0607055ba3358bfb9635b8bf120e30fc492b8e8..d0ec12aa56722c81ffc61cf454d3751a086bcba6 100644
--- a/kernel/src/fs/inode.rs
+++ b/kernel/src/fs/inode.rs
@@ -263,24 +263,41 @@ pub fn open(
 }
 
 // display debug todo
+// work_path 绝对路径
 pub fn chdir(work_path: &str, path: &str) -> Option<String> {
+    let mut current_work_path_vec: Vec<&str> = work_path.split('/').collect();
+    if work_path.chars().nth(0).unwrap() == '/' {
+        current_work_path_vec.remove(0); // 移除一个多余的 ""
+    }
+    let path_vec: Vec<&str> = path.split('/').collect();
+
     let current_inode = {
         if path.chars().nth(0).unwrap() == '/' {
             // 传入路径是绝对路径
             ROOT_INODE.clone()
         } else {
             // 传入路径是相对路径
-            let current_work_pathv: Vec<&str> = work_path.split('/').collect();
-            ROOT_INODE.find_vfile_bypath(current_work_pathv).unwrap()
+            ROOT_INODE
+                .find_vfile_bypath(current_work_path_vec.clone())
+                .unwrap()
         }
     };
-    let pathv: Vec<&str> = path.split('/').collect();
-    if let Some(_) = current_inode.find_vfile_bypath(pathv) {
-        let new_current_path = String::from_str("/").unwrap() + &String::from_str(path).unwrap();
-        if current_inode.name() == "/" {
-            Some(new_current_path)
+    if let Some(_) = current_inode.find_vfile_bypath(path_vec.clone()) {
+        if path.chars().nth(0).unwrap() == '/' {
+            Some(path.to_string())
         } else {
-            Some(String::from_str(current_inode.name()).unwrap() + &new_current_path)
+            // 将 work_path 和 path 拼接, work_path 为绝对路径, path 为相对路径
+            for i in 0..path_vec.len() {
+                if path_vec[i] == "." || path_vec[i] == "" {
+                    continue;
+                } else if path_vec[i] == ".." {
+                    current_work_path_vec.pop();
+                } else {
+                    current_work_path_vec.push(path_vec[i]);
+                }
+            }
+
+            Some(current_work_path_vec.join("/"))
         }
     } else {
         None