diff --git a/README.md b/README.md
index 1020d9a..73b7f75 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ The Linux kernel version can be found with:
1. [Introduction](introduction.md)
1. [Build](build.md)
1. [kmod](kmod.md)
+1. [Bibliography](bibliography.md)
1. Examples
1. [Host](host/)
1. Buildroot
diff --git a/bibliography.md b/bibliography.md
new file mode 100644
index 0000000..73a480c
--- /dev/null
+++ b/bibliography.md
@@ -0,0 +1,4 @@
+# Bibliography
+
+- the best, but always outdated, book. Updated source:
+-
diff --git a/busybox_config_fragment b/busybox_config_fragment
new file mode 100644
index 0000000..04798ce
--- /dev/null
+++ b/busybox_config_fragment
@@ -0,0 +1 @@
+CONFIG_STAT=y
diff --git a/kernel_module/fops.c b/kernel_module/fops.c
index 1f7588a..704f23e 100644
--- a/kernel_module/fops.c
+++ b/kernel_module/fops.c
@@ -5,6 +5,9 @@ Usage:
/fops.sh
+No, there ain't no official docs:
+http://stackoverflow.com/questions/15213932/what-are-the-struct-file-operations-arguments
+
fops define what the kernel will do on filesystem system calls on all of
/dev, /proc, /sys, and consistute the main method of userland communication
in drivers (syscalls being the other one).
@@ -13,9 +16,12 @@ Here we use debugfs.
*/
#include
+#include /* EFAULT */
#include
-#include
+#include /* min */
#include
+#include /* printk */
+#include /* copy_from_user, copy_to_user */
MODULE_LICENSE("GPL");
@@ -27,13 +33,26 @@ int fop_open(struct inode *inode, struct file *file)
return 0;
}
+/**/
ssize_t fop_read(struct file *file, char __user *buf, size_t len, loff_t *off)
{
+ ssize_t ret;
+ char s[] = "abcd";
printk(KERN_INFO "read\n");
printk(KERN_INFO "len = %zu\n", len);
- /* TODO. */
- /*copy_to_user(arg, &msg, size);*/
- return 0;
+ printk(KERN_INFO "off = %lld\n", (long long)*off);
+ if (sizeof(s) <= *off) {
+ ret = 0;
+ } else {
+ ret = min(len, sizeof(s) - (size_t)*off);
+ if (copy_to_user(buf, s, ret)) {
+ ret = -EFAULT;
+ } else {
+ *off += ret;
+ }
+ }
+ printk(KERN_INFO "ret = %lld\n", (long long)ret);
+ return ret;
}
ssize_t fop_write(struct file *file, const char __user *buf, size_t len, loff_t *off)
@@ -41,6 +60,7 @@ ssize_t fop_write(struct file *file, const char __user *buf, size_t len, loff_t
printk(KERN_INFO "write\n");
printk(KERN_INFO "buf = %.*s\n", (int)len, buf);
printk(KERN_INFO "len = %zu\n", len);
+ printk(KERN_INFO "off = %lld\n", (long long)*off);
return len;
}
diff --git a/rootfs_overlay/fops.sh b/rootfs_overlay/fops.sh
index e394d0e..552f93f 100755
--- a/rootfs_overlay/fops.sh
+++ b/rootfs_overlay/fops.sh
@@ -6,14 +6,20 @@ mount -t debugfs none /fops
cd /fops/kernel_module_cheat
cat fops
-# => open
-# => read
-# => len = [0-9]+
-# => close
+# => abcd
+# dmesg => open
+# dmesg => read
+# dmesg => len = [0-9]+
+# dmesg => close
printf a >fops
-# => open
-# => write
-# => len = a
-# => len = 1
-# => close
+# dmesg => open
+# dmesg => write
+# dmesg => len = 1
+# dmesg => buf = a
+# dmesg => close
+
+cd /
+umount /fops
+rmdir /fops
+rmmod fops
diff --git a/run b/run
index c8e3c26..84a8344 100755
--- a/run
+++ b/run
@@ -4,8 +4,16 @@ cd buildroot
make BR2_EXTERNAL="$(pwd)/../kernel_module" qemu_x86_64_defconfig
echo '
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="../kernel_config_fragment"
+BR2_PACKAGE_BUSYBOX_CONFIG_FRAGMENT_FILES="../busybox_config_fragment"
BR2_PACKAGE_KERNEL_MODULE=y
BR2_ROOTFS_OVERLAY="../rootfs_overlay"
' >> .config
env -u LD_LIBRARY_PATH make BR2_JLEVEL="$(($(nproc) - 2))" kernel_module-rebuild all
-qemu-system-x86_64 -M pc -kernel output/images/bzImage -drive file=output/images/rootfs.ext2,if=virtio,format=raw -append root=/dev/vda -net nic,model=virtio -net user
+qemu-system-x86_64 \
+ -M pc \
+ -append 'root=/dev/vda' \
+ -drive file=output/images/rootfs.ext2,if=virtio,format=raw \
+ -kernel output/images/bzImage \
+ -net nic,model=virtio \
+ -net user \
+;