diff --git a/lab4/.gdbinit b/lab4/.gdbinit
index 3cb3026..5934363 100644
--- a/lab4/.gdbinit
+++ b/lab4/.gdbinit
@@ -13,4 +13,4 @@ define add-symbol-file-auto
 end
 
 add-symbol-file-auto ./build/kernel.img
-add-symbol-file-auto ./user/build/ramdisk/ipc_reg.bin
+add-symbol-file-auto ./user/build/ramdisk/ipc_mem.bin
diff --git a/lab4/CMakeLists.txt b/lab4/CMakeLists.txt
index 6406c44..483fd25 100644
--- a/lab4/CMakeLists.txt
+++ b/lab4/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.14)
 
 set(CMAKE_VERBOSE_MAKEFILE on)
 
-set(CMAKE_BUILD_TYPE "Release")  # "Release" or "Debug"
+set(CMAKE_BUILD_TYPE "Debug")  # "Release" or "Debug"
 set(CHCORE_PLAT "raspi3")
 set(CHCORE_ARCH "aarch64")
 
diff --git a/lab5/.gdbinit b/lab5/.gdbinit
index 43110e8..cb97c65 100644
--- a/lab5/.gdbinit
+++ b/lab5/.gdbinit
@@ -13,4 +13,4 @@ define add-symbol-file-auto
 end
 
 add-symbol-file-auto ./build/kernel.img
-add-symbol-file-auto ./user/build/ramdisk/fs_test.bin
+add-symbol-file-auto ./user/build/ramdisk/tmpfs_test.bin
diff --git a/lab5/kernel/common/printk.c b/lab5/kernel/common/printk.c
index 4c2ca6e..e32c839 100644
--- a/lab5/kernel/common/printk.c
+++ b/lab5/kernel/common/printk.c
@@ -220,6 +220,13 @@ static int simple_vsprintf(char **out, const char *format, va_list ap)
 						     flags, 'a');
 				break;
 
+            case ('b'):
+                u.u = va_arg(ap, unsigned int);
+                pc +=
+                        printk_write_num(out, u.u, 2, 0, width,
+                                         flags, 'a');
+                break;
+
 			case ('x'):
 				u.u = va_arg(ap, unsigned int);
 				pc +=
diff --git a/lab5/kernel/exception/pgfault.c b/lab5/kernel/exception/pgfault.c
index 32a1dba..1127509 100644
--- a/lab5/kernel/exception/pgfault.c
+++ b/lab5/kernel/exception/pgfault.c
@@ -39,6 +39,7 @@ void do_page_fault(u64 esr, u64 fault_ins_addr)
 	int fsc;		// fault status code
 
 	fault_addr = get_fault_addr();
+	kdebug("Page fault addr = %x, cpu = %d\n", fault_addr, smp_get_cpu_id());
 	fsc = GET_ESR_EL1_FSC(esr);
 	switch (fsc) {
 	case DFSC_TRANS_FAULT_L0:
diff --git a/lab5/user/lab5/apps/init.c b/lab5/user/lab5/apps/init.c
index 44d6a5d..b6398af 100644
--- a/lab5/user/lab5/apps/init.c
+++ b/lab5/user/lab5/apps/init.c
@@ -52,9 +52,15 @@ char *readline(const char *prompt)
 		c = getch();
 		if (c < 0)
 			return NULL;
-		// TODO: your code here
-
+        buf[complement_time++] = c;
+        printf("%c", c);
+        if (c == '\r') {
+            usys_putc('\n');
+            break;
+        }
 	}
+
+    buf[complement_time - 1] = '\0';
 	return buf;
 }
 
@@ -77,21 +83,55 @@ int do_top()
 	return 0;
 }
 
-void fs_scan(char *path)
+int fs_scan(char *path)
 {
 	// TODO: your code here
+    int count = 4096/2;
+    char str[256];
+    struct fs_request fr;
+    int ret;
+
+    fr.req = FS_REQ_SCAN;
+    fr.buff = (char *) TMPFS_SCAN_BUF_VADDR;
+    strcpy(fr.path + 1, path);
+    fr.path[0] = '/';
+    fr.offset = 0;
+    fr.count = count;
+
+    printf("Send ls: %s\n", path);
+    ipc_msg_t *ipc_msg = ipc_create_msg(tmpfs_ipc_struct, sizeof(fr), 1);
+    ipc_set_msg_data(ipc_msg, (void *)&fr, 0, sizeof(fr));
+    ipc_set_msg_cap(ipc_msg, 0, tmpfs_scan_pmo_cap);
+    ret = ipc_call(tmpfs_ipc_struct, ipc_msg);
+    printf("Return ls: %d\n", ret);
+    ipc_destroy_msg(ipc_msg);
+    return ret;
 }
 
 int do_ls(char *cmdline)
 {
 	char pathbuf[BUFLEN];
+	int ret;
 
 	pathbuf[0] = '\0';
 	cmdline += 2;
 	while (*cmdline == ' ')
 		cmdline++;
 	strcat(pathbuf, cmdline);
-	fs_scan(pathbuf);
+    ret = fs_scan(pathbuf);
+    if (ret >= 0) {
+        char *print_ptr;
+        struct dirent *dirat;
+        print_ptr = (char *) TMPFS_SCAN_BUF_VADDR;
+
+        for (int i = 0; i < ret; i++) {
+            dirat = (struct dirent *) print_ptr;
+            printf(" %s\n", dirat->d_name);
+            print_ptr += dirat->d_reclen;
+        }
+    } else {
+        printf("ls returns code %d\n", ret);
+    }
 	return 0;
 }
 
diff --git a/lab5/user/lab5/apps/init_main.c b/lab5/user/lab5/apps/init_main.c
index 5a3aca0..290107f 100644
--- a/lab5/user/lab5/apps/init_main.c
+++ b/lab5/user/lab5/apps/init_main.c
@@ -8,7 +8,8 @@
 char getch()
 {
 	char c;
-	// TODO: your code here
+
+	c = usys_getc();
 
 	return c;
 }
diff --git a/lab5/user/lab5/tmpfs/tmpfs_main.c b/lab5/user/lab5/tmpfs/tmpfs_main.c
index 08abfdf..995cb13 100644
--- a/lab5/user/lab5/tmpfs/tmpfs_main.c
+++ b/lab5/user/lab5/tmpfs/tmpfs_main.c
@@ -14,7 +14,13 @@ static void fs_dispatch(ipc_msg_t * ipc_msg)
 		    ipc_get_msg_data(ipc_msg);
 		switch (fr->req) {
 		case FS_REQ_SCAN:{
+                int cap = ipc_get_msg_cap(ipc_msg, 0);
+                ret = usys_map_pmo(SELF_CAP, cap, (u64) fr->buff, VM_READ | VM_WRITE);
+                if (ret != 0) {
+                    break;
+                }
 				ret = fs_server_scan(fr->path, fr->offset, fr->buff, fr->count);
+                usys_unmap_pmo(SELF_CAP, cap, (u64) fr->buff);
 				break;
 			}
 		case FS_REQ_MKDIR:
@@ -40,12 +46,20 @@ static void fs_dispatch(ipc_msg_t * ipc_msg)
 			usys_exit(-1);
 			break;
 		case FS_REQ_WRITE:{
-				// TODO: you code here
+                int cap = ipc_get_msg_cap(ipc_msg, 0);
+                ret = usys_map_pmo(SELF_CAP, cap, (u64) fr->buff, VM_READ | VM_WRITE);
+                if (ret != 0) {
+                    break;
+                }
                 ret = fs_server_write(fr->path, fr->offset, fr->buff, fr->count);
 				break;
 			}
 		case FS_REQ_READ:{
-				// TODO: you code here
+                int cap = ipc_get_msg_cap(ipc_msg, 0);
+                ret = usys_map_pmo(SELF_CAP, cap, (u64) fr->buff, VM_READ | VM_WRITE);
+                if (ret != 0) {
+                    break;
+                }
                 ret = fs_server_read(fr->path, fr->offset, fr->buff, fr->count);
 				break;
 			}
diff --git a/lab5/user/lib/malloc.c b/lab5/user/lib/malloc.c
index 180cd2a..5e8f7aa 100644
--- a/lab5/user/lib/malloc.c
+++ b/lab5/user/lib/malloc.c
@@ -4,7 +4,8 @@
 #include "syscall.h"
 
 #define PMO_SIZE        0x1000
-#define MAP_VA          0x1000000
+// FIXME 0x1000000 就会出诡异 bug
+#define MAP_VA          0x1500000
 
 /* virtual memory rights */
 #define VM_READ  (1 << 0)