From 8a9208612eec8ddae4c418485d848ecfa0613699 Mon Sep 17 00:00:00 2001 From: Anton Kling Date: Mon, 30 Oct 2023 22:12:14 +0100 Subject: Meta: Move kernel and userland to their own folders. This is to allow both the kernel and the userland to share certain header files and to make the folder structure a bit more clear. --- .gitmodules | 2 +- Makefile | 33 -- arch/i386/boot.s | 128 ------- arch/i386/mmu.c | 565 ---------------------------- cpu/gdt.c | 72 ---- cpu/gdt.h | 76 ---- cpu/idt.c | 195 ---------- cpu/idt.h | 70 ---- cpu/int_syscall.s | 20 - cpu/io.h | 15 - cpu/io.s | 147 -------- cpu/reload_gdt.s | 17 - cpu/spinlock.c | 2 - cpu/spinlock.h | 5 - cpu/syscall.c | 183 --------- cpu/syscall.h | 59 --- crypto/ChaCha20/chacha20.c | 29 -- crypto/ChaCha20/chacha20.h | 15 - crypto/SHA1 | 1 - drivers/ata.c | 253 ------------- drivers/ata.h | 16 - drivers/keyboard.c | 188 ---------- drivers/keyboard.h | 11 - drivers/mouse.c | 144 ------- drivers/mouse.h | 5 - drivers/pci.c | 69 ---- drivers/pci.h | 26 -- drivers/pit.c | 55 --- drivers/pit.h | 12 - drivers/pst.c | 17 - drivers/pst.h | 7 - drivers/rtl8139.c | 182 --------- drivers/rtl8139.h | 4 - drivers/serial.c | 35 -- drivers/serial.h | 2 - drivers/vbe.c | 73 ---- drivers/vbe.h | 7 - elf.c | 73 ---- elf.h | 99 ----- fs/devfs.c | 91 ----- fs/devfs.h | 26 -- fs/ext2.c | 763 -------------------------------------- fs/ext2.h | 140 ------- fs/fifo.c | 97 ----- fs/fifo.h | 27 -- fs/shm.c | 94 ----- fs/shm.h | 13 - fs/tmpfs.c | 96 ----- fs/tmpfs.h | 16 - fs/vfs.c | 318 ---------------- fs/vfs.h | 100 ----- halts.c | 102 ----- halts.h | 21 -- hashmap/hashmap.c | 212 ----------- hashmap/hashmap.h | 39 -- includes/defs.h | 5 - includes/math.h | 2 - includes/mmu.h | 61 --- includes/signal.h | 46 --- includes/sys/types.h | 2 - init/kernel.c | 103 ----- isodir/boot/grub/grub.cfg | 3 - kernel/Makefile | 33 ++ kernel/arch/i386/boot.s | 128 +++++++ kernel/arch/i386/mmu.c | 565 ++++++++++++++++++++++++++++ kernel/cpu/gdt.c | 72 ++++ kernel/cpu/gdt.h | 76 ++++ kernel/cpu/idt.c | 195 ++++++++++ kernel/cpu/idt.h | 70 ++++ kernel/cpu/int_syscall.s | 20 + kernel/cpu/io.h | 15 + kernel/cpu/io.s | 147 ++++++++ kernel/cpu/reload_gdt.s | 17 + kernel/cpu/spinlock.c | 2 + kernel/cpu/spinlock.h | 5 + kernel/cpu/syscall.c | 183 +++++++++ kernel/cpu/syscall.h | 59 +++ kernel/crypto/ChaCha20/chacha20.c | 29 ++ kernel/crypto/ChaCha20/chacha20.h | 15 + kernel/crypto/SHA1 | 1 + kernel/drivers/ata.c | 253 +++++++++++++ kernel/drivers/ata.h | 16 + kernel/drivers/keyboard.c | 188 ++++++++++ kernel/drivers/keyboard.h | 11 + kernel/drivers/mouse.c | 144 +++++++ kernel/drivers/mouse.h | 5 + kernel/drivers/pci.c | 69 ++++ kernel/drivers/pci.h | 26 ++ kernel/drivers/pit.c | 55 +++ kernel/drivers/pit.h | 12 + kernel/drivers/pst.c | 17 + kernel/drivers/pst.h | 7 + kernel/drivers/rtl8139.c | 182 +++++++++ kernel/drivers/rtl8139.h | 4 + kernel/drivers/serial.c | 35 ++ kernel/drivers/serial.h | 2 + kernel/drivers/vbe.c | 73 ++++ kernel/drivers/vbe.h | 7 + kernel/elf.c | 73 ++++ kernel/elf.h | 99 +++++ kernel/fs/devfs.c | 91 +++++ kernel/fs/devfs.h | 26 ++ kernel/fs/ext2.c | 763 ++++++++++++++++++++++++++++++++++++++ kernel/fs/ext2.h | 140 +++++++ kernel/fs/fifo.c | 97 +++++ kernel/fs/fifo.h | 27 ++ kernel/fs/shm.c | 94 +++++ kernel/fs/shm.h | 13 + kernel/fs/tmpfs.c | 96 +++++ kernel/fs/tmpfs.h | 16 + kernel/fs/vfs.c | 318 ++++++++++++++++ kernel/fs/vfs.h | 100 +++++ kernel/halts.c | 102 +++++ kernel/halts.h | 21 ++ kernel/hashmap/hashmap.c | 212 +++++++++++ kernel/hashmap/hashmap.h | 39 ++ kernel/includes/defs.h | 5 + kernel/includes/math.h | 2 + kernel/includes/mmu.h | 61 +++ kernel/includes/signal.h | 46 +++ kernel/includes/sys/types.h | 2 + kernel/init/kernel.c | 103 +++++ kernel/isodir/boot/grub/grub.cfg | 3 + kernel/kmalloc.c | 230 ++++++++++++ kernel/kmalloc.h | 21 ++ kernel/ksbrk.c | 40 ++ kernel/ksbrk.h | 8 + kernel/kubsan.c | 58 +++ kernel/kubsan.h | 79 ++++ kernel/libc/exit/assert.c | 12 + kernel/libc/include/assert.h | 19 + kernel/libc/include/errno.h | 85 +++++ kernel/libc/include/limits.h | 1 + kernel/libc/include/stdio.h | 9 + kernel/libc/include/stdlib.h | 0 kernel/libc/include/string.h | 19 + kernel/libc/include/time.h | 6 + kernel/libc/include/types.h | 27 ++ kernel/libc/stdio/print.c | 97 +++++ kernel/libc/string/copy.c | 26 ++ kernel/libc/string/isequal.c | 15 + kernel/libc/string/memcmp.c | 12 + kernel/libc/string/memcpy.c | 20 + kernel/libc/string/memset.c | 9 + kernel/libc/string/strcat.c | 6 + kernel/libc/string/strcmp.c | 8 + kernel/libc/string/strcpy.c | 8 + kernel/libc/string/strlcpy.c | 21 ++ kernel/libc/string/strlen.c | 8 + kernel/libc/string/strncpy.c | 11 + kernel/linker.ld | 41 ++ kernel/log.c | 40 ++ kernel/log.h | 10 + kernel/math.c | 3 + kernel/mount/cat | 1 + kernel/mount/init | 1 + kernel/mount/pid1 | Bin 0 -> 2396 bytes kernel/mount/program | Bin 0 -> 1744 bytes kernel/mount/sh | Bin 0 -> 45660 bytes kernel/multiboot.h | 243 ++++++++++++ kernel/network/arp.c | 153 ++++++++ kernel/network/arp.h | 4 + kernel/network/bytes.c | 10 + kernel/network/bytes.h | 5 + kernel/network/ethernet.c | 93 +++++ kernel/network/ethernet.h | 5 + kernel/network/ipv4.c | 98 +++++ kernel/network/ipv4.h | 5 + kernel/network/udp.c | 64 ++++ kernel/network/udp.h | 7 + kernel/poll.c | 54 +++ kernel/poll.h | 15 + kernel/process.s | 33 ++ kernel/random.c | 142 +++++++ kernel/random.h | 7 + kernel/read_eip.s | 5 + kernel/scalls/accept.c | 5 + kernel/scalls/accept.h | 9 + kernel/scalls/bind.c | 5 + kernel/scalls/bind.h | 9 + kernel/scalls/clock_gettime.c | 10 + kernel/scalls/clock_gettime.h | 8 + kernel/scalls/ftruncate.c | 6 + kernel/scalls/ftruncate.h | 2 + kernel/scalls/kill.c | 5 + kernel/scalls/kill.h | 2 + kernel/scalls/mkdir.c | 5 + kernel/scalls/mkdir.h | 2 + kernel/scalls/mmap.c | 7 + kernel/scalls/mmap.h | 13 + kernel/scalls/msleep.c | 9 + kernel/scalls/msleep.h | 5 + kernel/scalls/ppoll.c | 11 + kernel/scalls/ppoll.h | 9 + kernel/scalls/recvfrom.c | 59 +++ kernel/scalls/recvfrom.h | 11 + kernel/scalls/sendto.c | 23 ++ kernel/scalls/sendto.h | 11 + kernel/scalls/shm.c | 6 + kernel/scalls/shm.h | 14 + kernel/scalls/socket.c | 5 + kernel/scalls/socket.h | 9 + kernel/scalls/stat.c | 13 + kernel/scalls/stat.h | 33 ++ kernel/scalls/uptime.c | 4 + kernel/scalls/uptime.h | 2 + kernel/sched/scheduler.c | 449 ++++++++++++++++++++++ kernel/sched/scheduler.h | 65 ++++ kernel/signal.s | 18 + kernel/socket.c | 180 +++++++++ kernel/socket.h | 72 ++++ kernel/time.h | 10 + kmalloc.c | 230 ------------ kmalloc.h | 21 -- ksbrk.c | 40 -- ksbrk.h | 8 - kubsan.c | 58 --- kubsan.h | 79 ---- libc/exit/assert.c | 12 - libc/include/assert.h | 19 - libc/include/errno.h | 85 ----- libc/include/limits.h | 1 - libc/include/stdio.h | 9 - libc/include/stdlib.h | 0 libc/include/string.h | 19 - libc/include/time.h | 6 - libc/include/types.h | 27 -- libc/stdio/print.c | 97 ----- libc/string/copy.c | 26 -- libc/string/isequal.c | 15 - libc/string/memcmp.c | 12 - libc/string/memcpy.c | 20 - libc/string/memset.c | 9 - libc/string/strcat.c | 6 - libc/string/strcmp.c | 8 - libc/string/strcpy.c | 8 - libc/string/strlcpy.c | 21 -- libc/string/strlen.c | 8 - libc/string/strncpy.c | 11 - linker.ld | 41 -- log.c | 40 -- log.h | 10 - math.c | 3 - mount/cat | 1 - mount/init | 1 - mount/pid1 | Bin 2396 -> 0 bytes mount/program | Bin 1744 -> 0 bytes mount/sh | Bin 45660 -> 0 bytes multiboot.h | 243 ------------ network/arp.c | 153 -------- network/arp.h | 4 - network/bytes.c | 10 - network/bytes.h | 5 - network/ethernet.c | 93 ----- network/ethernet.h | 5 - network/ipv4.c | 98 ----- network/ipv4.h | 5 - network/udp.c | 64 ---- network/udp.h | 7 - poll.c | 54 --- poll.h | 15 - process.s | 33 -- random.c | 142 ------- random.h | 7 - read_eip.s | 5 - scalls/accept.c | 5 - scalls/accept.h | 9 - scalls/bind.c | 5 - scalls/bind.h | 9 - scalls/clock_gettime.c | 10 - scalls/clock_gettime.h | 8 - scalls/ftruncate.c | 6 - scalls/ftruncate.h | 2 - scalls/mkdir.c | 5 - scalls/mkdir.h | 2 - scalls/mmap.c | 7 - scalls/mmap.h | 13 - scalls/msleep.c | 9 - scalls/msleep.h | 5 - scalls/ppoll.c | 11 - scalls/ppoll.h | 9 - scalls/recvfrom.c | 59 --- scalls/recvfrom.h | 11 - scalls/sendto.c | 23 -- scalls/sendto.h | 11 - scalls/shm.c | 6 - scalls/shm.h | 14 - scalls/socket.c | 5 - scalls/socket.h | 9 - scalls/stat.c | 13 - scalls/stat.h | 33 -- scalls/uptime.c | 4 - scalls/uptime.h | 2 - sched/scheduler.c | 449 ---------------------- sched/scheduler.h | 65 ---- socket.c | 180 --------- socket.h | 72 ---- time.h | 10 - 298 files changed, 8288 insertions(+), 8263 deletions(-) delete mode 100644 Makefile delete mode 100644 arch/i386/boot.s delete mode 100644 arch/i386/mmu.c delete mode 100644 cpu/gdt.c delete mode 100644 cpu/gdt.h delete mode 100644 cpu/idt.c delete mode 100644 cpu/idt.h delete mode 100644 cpu/int_syscall.s delete mode 100644 cpu/io.h delete mode 100644 cpu/io.s delete mode 100644 cpu/reload_gdt.s delete mode 100644 cpu/spinlock.c delete mode 100644 cpu/spinlock.h delete mode 100644 cpu/syscall.c delete mode 100644 cpu/syscall.h delete mode 100644 crypto/ChaCha20/chacha20.c delete mode 100644 crypto/ChaCha20/chacha20.h delete mode 160000 crypto/SHA1 delete mode 100644 drivers/ata.c delete mode 100644 drivers/ata.h delete mode 100644 drivers/keyboard.c delete mode 100644 drivers/keyboard.h delete mode 100644 drivers/mouse.c delete mode 100644 drivers/mouse.h delete mode 100644 drivers/pci.c delete mode 100644 drivers/pci.h delete mode 100644 drivers/pit.c delete mode 100644 drivers/pit.h delete mode 100644 drivers/pst.c delete mode 100644 drivers/pst.h delete mode 100644 drivers/rtl8139.c delete mode 100644 drivers/rtl8139.h delete mode 100644 drivers/serial.c delete mode 100644 drivers/serial.h delete mode 100644 drivers/vbe.c delete mode 100644 drivers/vbe.h delete mode 100644 elf.c delete mode 100644 elf.h delete mode 100644 fs/devfs.c delete mode 100644 fs/devfs.h delete mode 100644 fs/ext2.c delete mode 100644 fs/ext2.h delete mode 100644 fs/fifo.c delete mode 100644 fs/fifo.h delete mode 100644 fs/shm.c delete mode 100644 fs/shm.h delete mode 100644 fs/tmpfs.c delete mode 100644 fs/tmpfs.h delete mode 100644 fs/vfs.c delete mode 100644 fs/vfs.h delete mode 100644 halts.c delete mode 100644 halts.h delete mode 100644 hashmap/hashmap.c delete mode 100644 hashmap/hashmap.h delete mode 100644 includes/defs.h delete mode 100644 includes/math.h delete mode 100644 includes/mmu.h delete mode 100644 includes/signal.h delete mode 100644 includes/sys/types.h delete mode 100644 init/kernel.c delete mode 100644 isodir/boot/grub/grub.cfg create mode 100644 kernel/Makefile create mode 100644 kernel/arch/i386/boot.s create mode 100644 kernel/arch/i386/mmu.c create mode 100644 kernel/cpu/gdt.c create mode 100644 kernel/cpu/gdt.h create mode 100644 kernel/cpu/idt.c create mode 100644 kernel/cpu/idt.h create mode 100644 kernel/cpu/int_syscall.s create mode 100644 kernel/cpu/io.h create mode 100644 kernel/cpu/io.s create mode 100644 kernel/cpu/reload_gdt.s create mode 100644 kernel/cpu/spinlock.c create mode 100644 kernel/cpu/spinlock.h create mode 100644 kernel/cpu/syscall.c create mode 100644 kernel/cpu/syscall.h create mode 100644 kernel/crypto/ChaCha20/chacha20.c create mode 100644 kernel/crypto/ChaCha20/chacha20.h create mode 160000 kernel/crypto/SHA1 create mode 100644 kernel/drivers/ata.c create mode 100644 kernel/drivers/ata.h create mode 100644 kernel/drivers/keyboard.c create mode 100644 kernel/drivers/keyboard.h create mode 100644 kernel/drivers/mouse.c create mode 100644 kernel/drivers/mouse.h create mode 100644 kernel/drivers/pci.c create mode 100644 kernel/drivers/pci.h create mode 100644 kernel/drivers/pit.c create mode 100644 kernel/drivers/pit.h create mode 100644 kernel/drivers/pst.c create mode 100644 kernel/drivers/pst.h create mode 100644 kernel/drivers/rtl8139.c create mode 100644 kernel/drivers/rtl8139.h create mode 100644 kernel/drivers/serial.c create mode 100644 kernel/drivers/serial.h create mode 100644 kernel/drivers/vbe.c create mode 100644 kernel/drivers/vbe.h create mode 100644 kernel/elf.c create mode 100644 kernel/elf.h create mode 100644 kernel/fs/devfs.c create mode 100644 kernel/fs/devfs.h create mode 100644 kernel/fs/ext2.c create mode 100644 kernel/fs/ext2.h create mode 100644 kernel/fs/fifo.c create mode 100644 kernel/fs/fifo.h create mode 100644 kernel/fs/shm.c create mode 100644 kernel/fs/shm.h create mode 100644 kernel/fs/tmpfs.c create mode 100644 kernel/fs/tmpfs.h create mode 100644 kernel/fs/vfs.c create mode 100644 kernel/fs/vfs.h create mode 100644 kernel/halts.c create mode 100644 kernel/halts.h create mode 100644 kernel/hashmap/hashmap.c create mode 100644 kernel/hashmap/hashmap.h create mode 100644 kernel/includes/defs.h create mode 100644 kernel/includes/math.h create mode 100644 kernel/includes/mmu.h create mode 100644 kernel/includes/signal.h create mode 100644 kernel/includes/sys/types.h create mode 100644 kernel/init/kernel.c create mode 100644 kernel/isodir/boot/grub/grub.cfg create mode 100644 kernel/kmalloc.c create mode 100644 kernel/kmalloc.h create mode 100644 kernel/ksbrk.c create mode 100644 kernel/ksbrk.h create mode 100644 kernel/kubsan.c create mode 100644 kernel/kubsan.h create mode 100644 kernel/libc/exit/assert.c create mode 100644 kernel/libc/include/assert.h create mode 100644 kernel/libc/include/errno.h create mode 100644 kernel/libc/include/limits.h create mode 100644 kernel/libc/include/stdio.h create mode 100644 kernel/libc/include/stdlib.h create mode 100644 kernel/libc/include/string.h create mode 100644 kernel/libc/include/time.h create mode 100644 kernel/libc/include/types.h create mode 100644 kernel/libc/stdio/print.c create mode 100644 kernel/libc/string/copy.c create mode 100644 kernel/libc/string/isequal.c create mode 100644 kernel/libc/string/memcmp.c create mode 100644 kernel/libc/string/memcpy.c create mode 100644 kernel/libc/string/memset.c create mode 100644 kernel/libc/string/strcat.c create mode 100644 kernel/libc/string/strcmp.c create mode 100644 kernel/libc/string/strcpy.c create mode 100644 kernel/libc/string/strlcpy.c create mode 100644 kernel/libc/string/strlen.c create mode 100644 kernel/libc/string/strncpy.c create mode 100644 kernel/linker.ld create mode 100644 kernel/log.c create mode 100644 kernel/log.h create mode 100644 kernel/math.c create mode 120000 kernel/mount/cat create mode 120000 kernel/mount/init create mode 100755 kernel/mount/pid1 create mode 100755 kernel/mount/program create mode 100755 kernel/mount/sh create mode 100644 kernel/multiboot.h create mode 100644 kernel/network/arp.c create mode 100644 kernel/network/arp.h create mode 100644 kernel/network/bytes.c create mode 100644 kernel/network/bytes.h create mode 100644 kernel/network/ethernet.c create mode 100644 kernel/network/ethernet.h create mode 100644 kernel/network/ipv4.c create mode 100644 kernel/network/ipv4.h create mode 100644 kernel/network/udp.c create mode 100644 kernel/network/udp.h create mode 100644 kernel/poll.c create mode 100644 kernel/poll.h create mode 100644 kernel/process.s create mode 100644 kernel/random.c create mode 100644 kernel/random.h create mode 100644 kernel/read_eip.s create mode 100644 kernel/scalls/accept.c create mode 100644 kernel/scalls/accept.h create mode 100644 kernel/scalls/bind.c create mode 100644 kernel/scalls/bind.h create mode 100644 kernel/scalls/clock_gettime.c create mode 100644 kernel/scalls/clock_gettime.h create mode 100644 kernel/scalls/ftruncate.c create mode 100644 kernel/scalls/ftruncate.h create mode 100644 kernel/scalls/kill.c create mode 100644 kernel/scalls/kill.h create mode 100644 kernel/scalls/mkdir.c create mode 100644 kernel/scalls/mkdir.h create mode 100644 kernel/scalls/mmap.c create mode 100644 kernel/scalls/mmap.h create mode 100644 kernel/scalls/msleep.c create mode 100644 kernel/scalls/msleep.h create mode 100644 kernel/scalls/ppoll.c create mode 100644 kernel/scalls/ppoll.h create mode 100644 kernel/scalls/recvfrom.c create mode 100644 kernel/scalls/recvfrom.h create mode 100644 kernel/scalls/sendto.c create mode 100644 kernel/scalls/sendto.h create mode 100644 kernel/scalls/shm.c create mode 100644 kernel/scalls/shm.h create mode 100644 kernel/scalls/socket.c create mode 100644 kernel/scalls/socket.h create mode 100644 kernel/scalls/stat.c create mode 100644 kernel/scalls/stat.h create mode 100644 kernel/scalls/uptime.c create mode 100644 kernel/scalls/uptime.h create mode 100644 kernel/sched/scheduler.c create mode 100644 kernel/sched/scheduler.h create mode 100644 kernel/signal.s create mode 100644 kernel/socket.c create mode 100644 kernel/socket.h create mode 100644 kernel/time.h delete mode 100644 kmalloc.c delete mode 100644 kmalloc.h delete mode 100644 ksbrk.c delete mode 100644 ksbrk.h delete mode 100644 kubsan.c delete mode 100644 kubsan.h delete mode 100644 libc/exit/assert.c delete mode 100644 libc/include/assert.h delete mode 100644 libc/include/errno.h delete mode 100644 libc/include/limits.h delete mode 100644 libc/include/stdio.h delete mode 100644 libc/include/stdlib.h delete mode 100644 libc/include/string.h delete mode 100644 libc/include/time.h delete mode 100644 libc/include/types.h delete mode 100644 libc/stdio/print.c delete mode 100644 libc/string/copy.c delete mode 100644 libc/string/isequal.c delete mode 100644 libc/string/memcmp.c delete mode 100644 libc/string/memcpy.c delete mode 100644 libc/string/memset.c delete mode 100644 libc/string/strcat.c delete mode 100644 libc/string/strcmp.c delete mode 100644 libc/string/strcpy.c delete mode 100644 libc/string/strlcpy.c delete mode 100644 libc/string/strlen.c delete mode 100644 libc/string/strncpy.c delete mode 100644 linker.ld delete mode 100644 log.c delete mode 100644 log.h delete mode 100644 math.c delete mode 120000 mount/cat delete mode 120000 mount/init delete mode 100755 mount/pid1 delete mode 100755 mount/program delete mode 100755 mount/sh delete mode 100644 multiboot.h delete mode 100644 network/arp.c delete mode 100644 network/arp.h delete mode 100644 network/bytes.c delete mode 100644 network/bytes.h delete mode 100644 network/ethernet.c delete mode 100644 network/ethernet.h delete mode 100644 network/ipv4.c delete mode 100644 network/ipv4.h delete mode 100644 network/udp.c delete mode 100644 network/udp.h delete mode 100644 poll.c delete mode 100644 poll.h delete mode 100644 process.s delete mode 100644 random.c delete mode 100644 random.h delete mode 100644 read_eip.s delete mode 100644 scalls/accept.c delete mode 100644 scalls/accept.h delete mode 100644 scalls/bind.c delete mode 100644 scalls/bind.h delete mode 100644 scalls/clock_gettime.c delete mode 100644 scalls/clock_gettime.h delete mode 100644 scalls/ftruncate.c delete mode 100644 scalls/ftruncate.h delete mode 100644 scalls/mkdir.c delete mode 100644 scalls/mkdir.h delete mode 100644 scalls/mmap.c delete mode 100644 scalls/mmap.h delete mode 100644 scalls/msleep.c delete mode 100644 scalls/msleep.h delete mode 100644 scalls/ppoll.c delete mode 100644 scalls/ppoll.h delete mode 100644 scalls/recvfrom.c delete mode 100644 scalls/recvfrom.h delete mode 100644 scalls/sendto.c delete mode 100644 scalls/sendto.h delete mode 100644 scalls/shm.c delete mode 100644 scalls/shm.h delete mode 100644 scalls/socket.c delete mode 100644 scalls/socket.h delete mode 100644 scalls/stat.c delete mode 100644 scalls/stat.h delete mode 100644 scalls/uptime.c delete mode 100644 scalls/uptime.h delete mode 100644 sched/scheduler.c delete mode 100644 sched/scheduler.h delete mode 100644 socket.c delete mode 100644 socket.h delete mode 100644 time.h diff --git a/.gitmodules b/.gitmodules index 5283f8e..6ce58bd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,5 +1,5 @@ [submodule "crypto/SHA1"] - path = crypto/SHA1 + path = kernel/crypto/SHA1 url = git@github.com:elttil/SHA1.git [submodule "userland/json/hashmap"] path = userland/json/hashmap diff --git a/Makefile b/Makefile deleted file mode 100644 index d106a75..0000000 --- a/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -CC="./sysroot/bin/i686-sb-gcc" -AS="./sysroot/bin/i686-sb-as" -OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o scalls/ppoll.o scalls/ftruncate.o kubsan.o scalls/mmap.o drivers/serial.o scalls/accept.o scalls/bind.o scalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o scalls/shm.o elf.o ksbrk.o sched/scheduler.o scalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o scalls/msleep.o scalls/uptime.o scalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o scalls/recvfrom.o math.o scalls/sendto.o signal.o scalls/kill.o scalls/sigaction.o -CFLAGS = -O2 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -INCLUDE=-I./includes/ -I./libc/include/ - -all: myos.iso - -%.o: %.c - $(CC) $(INCLUDE) -c -o $@ $< $(CFLAGS) - -%.o: %.s - $(AS) $< -o $@ - -myos.bin: $(OBJ) - $(CC) $(INCLUDE) -shared -T linker.ld -o myos.bin -ffreestanding -nostdlib $(CFLAGS) $^ -lgcc - -debug: - qemu-system-i386 -no-reboot -no-shutdown -serial file:./serial.log -hda ext2.img -m 1G -cdrom myos.iso -s -S & - gdb -x .gdbinit - -nk: - qemu-system-i386 -d int -netdev user,id=n0,hostfwd=udp:127.0.0.1:6001-:6000 -device rtl8139,netdev=n0 -no-reboot -no-shutdown -serial file:./serial.log -hda ext2.img -m 1G -cdrom myos.iso -s - -run: - qemu-system-i386 -enable-kvm -netdev user,id=n0,hostfwd=udp:127.0.0.1:6001-:6000 -device rtl8139,netdev=n0 -object filter-dump,id=id,netdev=n0,file=netout -d int -no-reboot -no-shutdown -chardev stdio,id=char0,logfile=serial.log,signal=off -serial chardev:char0 -hda ext2.img -m 1G -cdrom myos.iso -s - -myos.iso: myos.bin - cp myos.bin isodir/boot - grub-mkrescue -o myos.iso isodir - -clean: - rm myos.bin myos.iso $(OBJ) diff --git a/arch/i386/boot.s b/arch/i386/boot.s deleted file mode 100644 index 61bbfbb..0000000 --- a/arch/i386/boot.s +++ /dev/null @@ -1,128 +0,0 @@ -.set ALIGN, 1<<0 -.set MEMINFO, 1<<1 -.set VIDEO_MODE, 1<<2 -.set FLAGS, VIDEO_MODE|ALIGN | MEMINFO -.set MAGIC, 0x1BADB002 -.set CHECKSUM, -(MAGIC + FLAGS) - -#.section .multiboot -.align 16, 0 -.section .multiboot.data, "aw" - .align 4 - .long MAGIC - .long FLAGS - .long CHECKSUM - # unused(padding) - .long 0,0,0,0,0 - # Video mode - .long 0 # Linear graphics - .long 0 # Preferred width - .long 0 # Preferred height - .long 32 # Preferred pixel depth - -# Allocate the initial stack. -.section .bootstrap_stack, "aw", @nobits -stack_bottom: -.skip 16384 # 16 KiB -stack_top: - -.global boot_page_directory -.global boot_page_table1 -.section .bss, "aw", @nobits - .align 4096 -boot_page_directory: - .skip 4096 -boot_page_table1: - .skip 4096 - -.section .multiboot.text, "a" -.global _start -.extern _kernel_end -.type _start, @function -# Kernel entry -_start: - # edi contains the buffer we wish to modify - movl $(boot_page_table1 - 0xC0000000), %edi - - # for loop - movl $0, %esi - movl $1024, %ecx -1: - # esi = address - # If we are in kernel range jump to "label 2" - cmpl $_kernel_start, %esi - jl 2f - - # If we are past the kernel jump to the final stage - # "label 3" - cmpl $(_kernel_end - 0xC0000000), %esi - jge 3f - -2: - # Add permission to the pages - movl %esi, %edx - orl $0x003, %edx - movl %edx, (%edi) - - # Size of page is 4096 bytes. - addl $4096, %esi - # Size of entries in boot_page_table1 is 4 bytes. - addl $4, %edi - # Loop to the next entry if we haven't finished. - loop 1b - -3: - # Map the page table to both virtual addresses 0x00000000 and 0xC0000000. - movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0 - movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4 - - # Set cr3 to the address of the boot_page_directory. - movl $(boot_page_directory - 0xC0000000), %ecx - movl %ecx, %cr3 - - # Enable paging - movl %cr0, %ecx - orl $0x80000000, %ecx - movl %ecx, %cr0 - - # Jump to higher half with an absolute jump. - lea 4f, %ecx - jmp *%ecx - -.size _start, . - _start - -.section .text - -4: - # At this point, paging is fully set up and enabled. - - # Unmap the identity mapping as it is now unnecessary. - movl $0, boot_page_directory + 0 - - # Reload crc3 to force a TLB flush so the changes to take effect. - movl %cr3, %ecx - movl %ecx, %cr3 - - # Set up the stack. - mov $stack_top, %esp - - # Reset EFLAGS. - pushl $0 - popf - - pushl %esp - - /* Push the pointer to the Multiboot information structure. */ - pushl %ebx - /* Push the magic value. */ - pushl %eax - - mov $_kernel_end, %eax - pushl %eax - # Enter the high-level kernel. - call kernel_main - - # Infinite loop if the system has nothing more to do. - cli -1: hlt - jmp 1b diff --git a/arch/i386/mmu.c b/arch/i386/mmu.c deleted file mode 100644 index ccfe894..0000000 --- a/arch/i386/mmu.c +++ /dev/null @@ -1,565 +0,0 @@ -#include -#include -#include -#include - -#define INDEX_FROM_BIT(a) (a / (32)) -#define OFFSET_FROM_BIT(a) (a % (32)) -#define PAGE_SIZE ((uintptr_t)0x1000) - -#define PAGE_ALLOCATE 1 -#define PAGE_NO_ALLOCATE 0 - -PageDirectory *kernel_directory; -PageDirectory real_kernel_directory; -PageDirectory *active_directory = 0; - -#define END_OF_MEMORY 0x8000000 * 15 -const uint32_t num_of_frames = END_OF_MEMORY / PAGE_SIZE; -uint32_t frames[END_OF_MEMORY / PAGE_SIZE] = {0}; -uint32_t num_allocated_frames = 0; - -#define KERNEL_START 0xc0000000 -extern uintptr_t data_end; - -void write_to_frame(uint32_t frame_address, uint8_t on); - -void *ksbrk(size_t s) { - uintptr_t rc = (uintptr_t)align_page((void *)data_end); - data_end += s; - data_end = (uintptr_t)align_page((void *)data_end); - - if (!get_active_pagedirectory()) { - // If there is no active pagedirectory we - // just assume that the memory is - // already mapped. - return (void *)rc; - } - // Determine whether we are approaching a unallocated table - int table_index = 1 + (rc / (1024 * 0x1000)); - if (!active_directory->tables[table_index]) { - uint32_t physical; - active_directory->tables[table_index] = (PageTable *)0xDEADBEEF; - active_directory->tables[table_index] = - (PageTable *)ksbrk_physical(sizeof(PageTable), (void **)&physical); - memset(active_directory->tables[table_index], 0, sizeof(PageTable)); - active_directory->physical_tables[table_index] = (uint32_t)physical | 0x3; - - kernel_directory->tables[table_index] = - active_directory->tables[table_index]; - kernel_directory->physical_tables[table_index] = - active_directory->physical_tables[table_index]; - return ksbrk(s); - } - mmu_allocate_shared_kernel_region((void *)rc, (data_end - (uintptr_t)rc)); - assert(((uintptr_t)rc % PAGE_SIZE) == 0); - memset((void *)rc, 0x00, s); - - return (void *)rc; -} - -void *ksbrk_physical(size_t s, void **physical) { - void *r = ksbrk(s); - if (physical) { - *physical = (void *)virtual_to_physical(r, 0); - } - return r; -} - -uint32_t mmu_get_number_of_allocated_frames(void) { - return num_allocated_frames; -} - -Page *get_page(void *ptr, PageDirectory *directory, int create_new_page, - int set_user) { - uintptr_t address = (uintptr_t)ptr; - if (!directory) - directory = get_active_pagedirectory(); - address /= 0x1000; - - uint32_t table_index = address / 1024; - if (!directory->tables[table_index]) { - if (!create_new_page) - return 0; - - uint32_t physical; - directory->tables[table_index] = - (PageTable *)ksbrk_physical(sizeof(PageTable), (void **)&physical); - memset(directory->tables[table_index], 0, sizeof(PageTable)); - directory->physical_tables[table_index] = - (uint32_t)physical | ((set_user) ? 0x7 : 0x3); - - if (!set_user) { - kernel_directory->tables[table_index] = directory->tables[table_index]; - kernel_directory->physical_tables[table_index] = - directory->physical_tables[table_index]; - } - } - Page *p = &directory->tables[table_index]->pages[address % 1024]; - if (create_new_page) { - p->present = 0; - } - return &directory->tables[table_index]->pages[address % 1024]; -} - -void mmu_free_pages(void *a, uint32_t n) { - for (; n > 0; n--) { - Page *p = get_page(a, NULL, PAGE_NO_ALLOCATE, 0); - p->present = 0; - write_to_frame(p->frame * 0x1000, 0); - a += 0x1000; - } -} - -void *next_page(void *ptr) { - uintptr_t a = (uintptr_t)ptr; - return (void *)(a + (PAGE_SIZE - ((uint32_t)a & (PAGE_SIZE - 1)))); -} - -void *align_page(void *a) { - if ((uintptr_t)a & (PAGE_SIZE - 1)) - return next_page(a); - - return a; -} - -void flush_tlb(void) { - asm volatile("\ - mov %cr3, %eax;\ - mov %eax, %cr3"); -} - -uint32_t first_free_frame(void) { - for (uint32_t i = 1; i < INDEX_FROM_BIT(num_of_frames); i++) { - if (frames[i] == 0xFFFFFFFF) - continue; - - for (uint32_t c = 0; c < 32; c++) - if (!(frames[i] & ((uint32_t)1 << c))) - return i * 32 + c; - } - - kprintf("ERROR Num frames: %x\n", mmu_get_number_of_allocated_frames()); - klog("No free frames, uh oh.", LOG_ERROR); - assert(0); - return 0; -} - -void write_to_frame(uint32_t frame_address, uint8_t on) { - uint32_t frame = frame_address / 0x1000; - assert(INDEX_FROM_BIT(frame) < sizeof(frames) / sizeof(frames[0])); - if (on) { - num_allocated_frames++; - frames[INDEX_FROM_BIT(frame)] |= ((uint32_t)0x1 << OFFSET_FROM_BIT(frame)); - return; - } - num_allocated_frames--; - frames[INDEX_FROM_BIT(frame)] &= ~((uint32_t)0x1 << OFFSET_FROM_BIT(frame)); -} - -PageDirectory *get_active_pagedirectory(void) { return active_directory; } - -PageTable *clone_table(uint32_t src_index, PageDirectory *src_directory, - uint32_t *physical_address) { - PageTable *new_table = - ksbrk_physical(sizeof(PageTable), (void **)physical_address); - PageTable *src = src_directory->tables[src_index]; - - // Copy all the pages - for (uint16_t i = 0; i < 1024; i++) { - if (!src->pages[i].present) { - new_table->pages[i].present = 0; - continue; - } - uint32_t frame_address = first_free_frame(); - write_to_frame(frame_address * 0x1000, 1); - new_table->pages[i].frame = frame_address; - - new_table->pages[i].present |= src->pages[i].present; - new_table->pages[i].rw |= src->pages[i].rw; - new_table->pages[i].user |= src->pages[i].user; - new_table->pages[i].accessed |= src->pages[i].accessed; - new_table->pages[i].dirty |= src->pages[i].dirty; - } - - // Now copy all of the data to the new table. This is done by creating a - // virutal pointer to this newly created tables physical frame so we can - // copy data to it. - for (uint32_t i = 0; i < 1024; i++) { - // Find a unused table - if (src_directory->tables[i]) - continue; - - // Link the table to the new table temporarily - src_directory->tables[i] = new_table; - src_directory->physical_tables[i] = *physical_address | 0x7; - PageDirectory *tmp = get_active_pagedirectory(); - switch_page_directory(src_directory); - - // For each page in the table copy all the data over. - for (uint32_t c = 0; c < 1024; c++) { - // Only copy pages that are used. - if (!src->pages[c].frame || !src->pages[c].present) - continue; - - uint32_t table_data_pointer = i << 22 | c << 12; - uint32_t src_data_pointer = src_index << 22 | c << 12; - memcpy((void *)table_data_pointer, (void *)src_data_pointer, 0x1000); - } - src_directory->tables[i] = 0; - src_directory->physical_tables[i] = 0; - switch_page_directory(tmp); - return new_table; - } - ASSERT_NOT_REACHED; - return 0; -} - -PageTable *copy_table(PageTable *src, uint32_t *physical_address) { - PageTable *new_table = - ksbrk_physical(sizeof(PageTable), (void **)physical_address); - - // copy all the pages - for (uint16_t i = 0; i < 1024; i++) { - if (!src->pages[i].present) { - new_table->pages[i].present = 0; - continue; - } - new_table->pages[i].frame = src->pages[i].frame; - new_table->pages[i].present = src->pages[i].present; - new_table->pages[i].rw = src->pages[i].rw; - new_table->pages[i].user = src->pages[i].user; - new_table->pages[i].accessed = src->pages[i].accessed; - new_table->pages[i].dirty = src->pages[i].dirty; - } - return new_table; -} - -PageDirectory *clone_directory(PageDirectory *original) { - if (!original) - original = get_active_pagedirectory(); - - uint32_t physical_address; - PageDirectory *new_directory = - ksbrk_physical(sizeof(PageDirectory), (void **)&physical_address); - uint32_t offset = - (uint32_t)new_directory->physical_tables - (uint32_t)new_directory; - new_directory->physical_address = physical_address + offset; - - for (int i = 0; i < 1024; i++) { - if (!original->tables[i]) { - new_directory->tables[i] = NULL; - new_directory->physical_tables[i] = (uint32_t)NULL; - continue; - } - - // Make sure to copy instead of cloning the stack. - if (i >= 635 && i <= 641) { - uint32_t physical; - new_directory->tables[i] = clone_table(i, original, &physical); - new_directory->physical_tables[i] = - physical | (original->physical_tables[i] & 0xFFF); - continue; - } - - // if (original->tables[i] == kernel_directory->tables[i]) { - if (i > 641) { - new_directory->tables[i] = kernel_directory->tables[i]; - new_directory->physical_tables[i] = kernel_directory->physical_tables[i]; - continue; - } - - uint32_t physical; - new_directory->tables[i] = clone_table(i, original, &physical); - new_directory->physical_tables[i] = - physical | (original->physical_tables[i] & 0xFFF); - } - - return new_directory; -} - -void mmu_allocate_shared_kernel_region(void *rc, size_t n) { - size_t num_pages = n / PAGE_SIZE; - for (size_t i = 0; i <= num_pages; i++) { - Page *p = get_page((void *)(rc + i * 0x1000), NULL, PAGE_NO_ALLOCATE, 0); - if (!p) { - kprintf("don't have: %x\n", rc + i * 0x1000); - p = get_page((void *)(rc + i * 0x1000), NULL, PAGE_ALLOCATE, 0); - } - if (!p->present || !p->frame) - allocate_frame(p, 0, 1); - } -} - -void mmu_remove_virtual_physical_address_mapping(void *ptr, size_t length) { - size_t num_pages = (uintptr_t)align_page((void *)length) / PAGE_SIZE; - for (size_t i = 0; i < num_pages; i++) { - Page *p = get_page(ptr + (i * PAGE_SIZE), NULL, PAGE_NO_ALLOCATE, 0); - if (!p) - return; - p->frame = 0; - p->present = 0; - } -} - -void *mmu_find_unallocated_virtual_range(void *addr, size_t length) { - addr = align_page(addr); - // Check if the pages already exist - for (size_t i = 0; i < length; i += 0x1000) { - if (get_page(addr + i, NULL, PAGE_NO_ALLOCATE, 0)) { - // Page already exists - return mmu_find_unallocated_virtual_range(addr + 0x1000, length); - } - } - return addr; -} - -int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags, - PageDirectory *pd) { - pd = (pd) ? pd : get_active_pagedirectory(); - size_t num_pages = n / 0x1000; - for (size_t i = 0; i <= num_pages; i++) { - Page *p = get_page((void *)(ptr + i * 0x1000), pd, PAGE_ALLOCATE, 1); - assert(p); - int rw = (flags & MMU_FLAG_RW); - int kernel = (flags & MMU_FLAG_KERNEL); - if (!allocate_frame(p, rw, kernel)) { - klog("MMU: Frame allocation failed", LOG_WARN); - return 0; - } - } - return 1; -} - -void *mmu_map_frames(void *const ptr, size_t s) { - void *const r = mmu_find_unallocated_virtual_range((void *)0xEF000000, s); - kprintf("r: %x\n", r); - size_t num_pages = s / 0x1000; - for (size_t i = 0; i <= num_pages; i++) { - Page *p = get_page((void *)(r + i * 0x1000), NULL, PAGE_ALLOCATE, 1); - assert(p); - int rw = 1; - int is_kernel = 1; - p->present = 1; - p->rw = rw; - p->user = !is_kernel; - p->frame = (uintptr_t)(ptr + i * 0x1000) / 0x1000; - write_to_frame((uintptr_t)ptr + i * 0x1000, 1); - } - flush_tlb(); - return r; -} - -void *allocate_frame(Page *page, int rw, int is_kernel) { - if (page->present) { - dump_backtrace(5); - klog("Page is already set", 1); - for (;;) - ; - return 0; - } - uint32_t frame_address = first_free_frame(); - assert(frame_address < sizeof(frames) / sizeof(frames[0])); - write_to_frame(frame_address * 0x1000, 1); - - page->present = 1; - page->rw = rw; - page->user = !is_kernel; - page->frame = frame_address; - return (void *)(frame_address * 0x1000); -} - -void mmu_free_address_range(void *ptr, size_t length) { - size_t num_pages = (size_t)align_page((void *)length) / PAGE_SIZE; - for (size_t i = 0; i < num_pages; i++, ptr += PAGE_SIZE) { - Page *page = get_page(ptr, NULL, PAGE_NO_ALLOCATE, 0); - if (!page) - continue; - if (!page->present) - continue; - if (!page->frame) - continue; - // Sanity check that none of the frames are invalid - assert(page->frame < sizeof(frames) / sizeof(frames[0])); - write_to_frame(((uint32_t)page->frame) * 0x1000, 0); - page->present = 0; - page->rw = 0; - page->user = 0; - page->frame = 0; - } -} - -void mmu_map_directories(void *dst, PageDirectory *d, void *src, - PageDirectory *s, size_t length) { - d = (!d) ? get_active_pagedirectory() : d; - s = (!s) ? get_active_pagedirectory() : s; - size_t num_pages = (uint32_t)align_page((void *)length) / 0x1000; - for (size_t i = 0; i < num_pages; i++, dst += 0x1000, src += 0x1000) { - Page *p = get_page(dst, d, PAGE_ALLOCATE, 1); - p->present = 1; - p->rw = 1; - p->user = 1; - void *physical = virtual_to_physical(src, s); - p->frame = (uint32_t)physical / PAGE_SIZE; - } - flush_tlb(); -} - -void mmu_map_physical(void *dst, PageDirectory *d, void *physical, - size_t length) { - d = (!d) ? get_active_pagedirectory() : d; - size_t num_pages = (uint32_t)align_page((void *)length) / 0x1000; - for (size_t i = 0; i < num_pages; i++, dst += 0x1000, physical += 0x1000) { - Page *p = get_page(dst, d, PAGE_ALLOCATE, 1); - p->present = 1; - p->rw = 1; - p->user = 1; - p->frame = (uintptr_t)physical / PAGE_SIZE; - write_to_frame((uintptr_t)physical, 1); - } - flush_tlb(); -} - -void *virtual_to_physical(void *address, PageDirectory *directory) { - if (0 == directory) - directory = get_active_pagedirectory(); - return (void *)((get_page((void *)address, directory, PAGE_NO_ALLOCATE, 0) - ->frame * - 0x1000) + - (((uintptr_t)address) & 0xFFF)); -} - -extern uint32_t inital_esp; -void __attribute__((optimize("O0"))) -move_stack(uint32_t new_stack_address, uint32_t size) { - mmu_allocate_region((void *)(new_stack_address - size), size, - MMU_FLAG_KERNEL, NULL); - - uint32_t old_stack_pointer, old_base_pointer; - - register uint32_t eax asm("eax"); - asm volatile("mov %esp, %eax"); - old_stack_pointer = eax; - asm volatile("mov %ebp, %eax"); - old_base_pointer = eax; - - uint32_t new_stack_pointer = - old_stack_pointer + ((uint32_t)new_stack_address - inital_esp); - uint32_t new_base_pointer = - old_base_pointer + ((uint32_t)new_stack_address - inital_esp); - - // Copy the stack - memcpy((void *)new_stack_pointer, (void *)old_stack_pointer, - inital_esp - old_stack_pointer); - for (uint32_t i = (uint32_t)new_stack_address; i > new_stack_address - size; - i -= 4) { - uint32_t tmp = *(uint32_t *)i; - if (old_stack_pointer < tmp && tmp < inital_esp) { - tmp = tmp + (new_stack_address - inital_esp); - uint32_t *tmp2 = (uint32_t *)i; - *tmp2 = tmp; - } - } - - inital_esp = new_stack_pointer; - // Actually change the stack - eax = new_stack_pointer; - asm volatile("mov %eax, %esp"); - eax = new_base_pointer; - asm volatile("mov %eax, %ebp"); -} - -// C strings have a unknown length so it does not makes sense to check -// for a size on the pointer. Instead we check whether the page it -// resides in is accessible to the user. -void *is_valid_user_c_string(const char *ptr, size_t *size) { - void *r = (void *)ptr; - size_t s = 0; - for (;;) { - void *page = (void *)((uintptr_t)ptr & (uintptr_t)(~(PAGE_SIZE - 1))); - if (!is_valid_userpointer(page, PAGE_SIZE)) - return NULL; - for (; (uintptr_t)ptr & (PAGE_SIZE - 1); ptr++, s++) - if (!*ptr) { - if (size) - *size = s; - return r; - } - } -} - -void *is_valid_userpointer(const void *ptr, size_t s) { - uintptr_t t = (uintptr_t)ptr; - size_t num_pages = (uintptr_t)align_page((void *)s) / 0x1000; - for (size_t i = 0; i < num_pages; i++, t += 0x1000) { - Page *page = get_page((void *)t, NULL, PAGE_NO_ALLOCATE, 0); - if (!page) - return NULL; - if (!page->present) - return NULL; - if (!page->user) - return NULL; - } - return (void *)ptr; -} - -void switch_page_directory(PageDirectory *directory) { - active_directory = directory; - asm("mov %0, %%cr3" ::"r"(directory->physical_address)); -} - -void enable_paging(void) { - asm("mov %cr0, %eax\n" - "or 0b10000000000000000000000000000000, %eax\n" - "mov %eax, %cr0\n"); -} - -extern uint32_t boot_page_directory; -extern uint32_t boot_page_table1; - -void paging_init(void) { - uint32_t *cr3; - asm volatile("mov %%cr3, %0" : "=r"(cr3)); - uint32_t *virtual = (uint32_t *)((uint32_t)cr3 + 0xC0000000); - - kernel_directory = &real_kernel_directory; - kernel_directory->physical_address = (uint32_t)cr3; - for (uint32_t i = 0; i < 1024; i++) { - kernel_directory->physical_tables[i] = virtual[i]; - - if (!kernel_directory->physical_tables[i]) { - kernel_directory->tables[i] = NULL; - continue; - } - - kernel_directory->tables[i] = - (PageTable *)(0xC0000000 + (virtual[i] & ~(0xFFF))); - - // Loop through the pages in the table - PageTable *table = kernel_directory->tables[i]; - for (size_t j = 0; j < 1024; j++) { - if (!table->pages[j].present) - continue; - // Add the frame to our bitmap to ensure it does not get used by - // another newly created page. - write_to_frame(table->pages[j].frame * 0x1000, 1); - } - } - - switch_page_directory(kernel_directory); - kernel_directory = clone_directory(kernel_directory); - - // Make null dereferences crash. - switch_page_directory(kernel_directory); - get_page(NULL, kernel_directory, PAGE_ALLOCATE, 0)->present = 0; - switch_page_directory(clone_directory(kernel_directory)); - // FIXME: Really hacky solution. Since page table creation needs to - // allocate memory but memory allocation requires page table creation - // they depend on eachother. The bad/current solution is just to - // allocate a bunch of tables so the memory allocator has enough. - for (uintptr_t i = 0; i < 140; i++) - allocate_frame( - get_page((void *)((0x302 + i) * 0x1000 * 1024), NULL, PAGE_ALLOCATE, 0), - 1, 1); - move_stack(0xA0000000, 0xC00000); -} diff --git a/cpu/gdt.c b/cpu/gdt.c deleted file mode 100644 index 28853cf..0000000 --- a/cpu/gdt.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "gdt.h" - -extern void flush_tss(void); -extern void load_gdt(void *); - -typedef struct tss_entry_struct tss_entry_t; - -tss_entry_t tss_entry; - -typedef union { - struct GDT_Entry s; - uint64_t raw; -} GDT_Entry; - -GDT_Entry gdt_entries[6] = {0}; -GDT_Pointer gdtr; - -extern uint32_t inital_esp; -void write_tss(struct GDT_Entry *gdt_entry) { - uint32_t base = (uint32_t)&tss_entry; - uint32_t limit = sizeof(tss_entry); - - gdt_entry->limit_low = limit; - gdt_entry->base_low = base; - gdt_entry->accessed = 1; - gdt_entry->read_write = 0; - gdt_entry->conforming_expand_down = 0; - gdt_entry->code = 1; - gdt_entry->code_data_segment = 0; - gdt_entry->DPL = 0; - gdt_entry->present = 1; - gdt_entry->limit_high = limit >> 16; - gdt_entry->available = 0; - gdt_entry->long_mode = 0; - gdt_entry->big = 0; - gdt_entry->gran = 0; - gdt_entry->base_high = (base & ((uint32_t)0xff << 24)) >> 24; - - memset(&tss_entry, 0, sizeof tss_entry); - tss_entry.ss0 = GDT_KERNEL_DATA_SEGMENT * GDT_ENTRY_SIZE; - register uint32_t esp asm("esp"); - tss_entry.esp0 = esp; -} - -void gdt_init() { - gdt_entries[GDT_NULL_SEGMENT].raw = 0x0; - gdt_entries[GDT_KERNEL_CODE_SEGMENT].raw = - 0xCF9A000000FFFF; // Kernel code segment - gdt_entries[GDT_KERNEL_DATA_SEGMENT].raw = - 0xCF92000000FFFF; // Kernel data segment - - // Usermode code segment - memcpy(&gdt_entries[GDT_USERMODE_CODE_SEGMENT], - &gdt_entries[GDT_KERNEL_CODE_SEGMENT], GDT_ENTRY_SIZE); - - // Usermode data segment - memcpy(&gdt_entries[GDT_USERMODE_DATA_SEGMENT], - &gdt_entries[GDT_KERNEL_DATA_SEGMENT], GDT_ENTRY_SIZE); - - // Set DPL to 3 to indicate that the segment is in ring 3 - gdt_entries[GDT_USERMODE_CODE_SEGMENT].s.DPL = 3; - gdt_entries[GDT_USERMODE_DATA_SEGMENT].s.DPL = 3; - - write_tss((struct GDT_Entry *)&gdt_entries[GDT_TSS_SEGMENT]); - - gdtr.offset = (uint32_t)&gdt_entries; - gdtr.size = sizeof(gdt_entries) - 1; - - asm("cli"); - load_gdt(&gdtr); - flush_tss(); -} diff --git a/cpu/gdt.h b/cpu/gdt.h deleted file mode 100644 index a490dea..0000000 --- a/cpu/gdt.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef GDT_H -#define GDT_H -#include -#include - -#define GDT_ENTRY_SIZE 0x8 -#define GDT_NULL_SEGMENT 0x0 -#define GDT_KERNEL_CODE_SEGMENT 0x1 -#define GDT_KERNEL_DATA_SEGMENT 0x2 -#define GDT_USERMODE_CODE_SEGMENT 0x3 -#define GDT_USERMODE_DATA_SEGMENT 0x4 -#define GDT_TSS_SEGMENT 0x5 - -struct GDT_Entry -{ - uint16_t limit_low; - uint32_t base_low : 24; - uint32_t accessed : 1; - uint32_t read_write : 1; // readable for code, writable for data - uint32_t conforming_expand_down : 1; // conforming for code, expand down for data - uint32_t code : 1; // 1 for code, 0 for data - uint32_t code_data_segment : 1; // should be 1 for everything but TSS and LDT - uint32_t DPL : 2; // privilege level - uint32_t present : 1; - uint32_t limit_high : 4; - uint32_t available : 1; // only used in software; has no effect on hardware - uint32_t long_mode : 1; - uint32_t big : 1; // 32-bit opcodes for code, uint32_t stack for data - uint32_t gran : 1; // 1 to use 4k page addressing, 0 for byte addressing - uint8_t base_high; -}__attribute__((packed)); - -typedef struct GDT_Pointer -{ - uint16_t size; - uint32_t offset; -}__attribute__((packed)) GDT_Pointer; - -struct tss_entry_struct -{ - uint32_t prev_tss; // The previous TSS - with hardware task switching these form a kind of backward linked list. - uint32_t esp0; // The stack pointer to load when changing to kernel mode. - uint32_t ss0; // The stack segment to load when changing to kernel mode. - // Everything below here is unused. - uint32_t esp1; // esp and ss 1 and 2 would be used when switching to rings 1 or 2. - uint32_t ss1; - uint32_t esp2; - uint32_t ss2; - uint32_t cr3; - uint32_t eip; - uint32_t eflags; - uint32_t eax; - uint32_t ecx; - uint32_t edx; - uint32_t ebx; - uint32_t esp; - uint32_t ebp; - uint32_t esi; - uint32_t edi; - uint32_t es; - uint32_t cs; - uint32_t ss; - uint32_t ds; - uint32_t fs; - uint32_t gs; - uint32_t ldt; - uint16_t trap; - uint16_t iomap_base; -} __attribute__((packed)); - -void gdt_init(); - -uint8_t gen_access_byte(uint8_t priv, uint8_t s, uint8_t ex, uint8_t dc, uint8_t rw); -uint64_t gen_gdt_entry(uint32_t base, uint32_t limit, uint8_t access_byte, uint8_t flag); -uint8_t gen_flag(uint8_t gr, uint8_t sz); -#endif diff --git a/cpu/idt.c b/cpu/idt.c deleted file mode 100644 index abcafad..0000000 --- a/cpu/idt.c +++ /dev/null @@ -1,195 +0,0 @@ -#include -#include -#include - -#define MASTER_PIC_COMMAND_PORT 0x20 -#define MASTER_PIC_DATA_PORT 0x21 -#define SLAVE_PIC_COMMAND_PORT 0xA0 -#define SLAVE_PIC_DATA_PORT 0xA1 -#define KEYBOARD_DATA_PORT 0x60 -#define KEYBOARD_STATUS_PORT 0x64 -#define KERNEL_CODE_SEGMENT_OFFSET GDT_ENTRY_SIZE *GDT_KERNEL_CODE_SEGMENT - -#define IDT_MAX_ENTRY 256 - -struct IDT_Descriptor { - uint16_t low_offset; - uint16_t code_segment_selector; - uint8_t zero; // Always should be zero - uint8_t type_attribute; - uint16_t high_offset; -} __attribute__((packed)) __attribute__((aligned(4))); - -struct IDT_Pointer { - uint16_t size; - struct IDT_Descriptor **interrupt_table; -} __attribute__((packed)); - -struct IDT_Descriptor IDT_Entry[IDT_MAX_ENTRY]; -struct IDT_Pointer idtr; - -extern void load_idtr(void *idtr); - -void format_descriptor(uint32_t offset, uint16_t code_segment, - uint8_t type_attribute, - struct IDT_Descriptor *descriptor) { - descriptor->low_offset = offset & 0xFFFF; - descriptor->high_offset = offset >> 16; - descriptor->type_attribute = type_attribute; - descriptor->code_segment_selector = code_segment; - descriptor->zero = 0; -} - -void install_handler(void (*handler_function)(), uint16_t type_attribute, - uint8_t entry) { - format_descriptor((uint32_t)handler_function, KERNEL_CODE_SEGMENT_OFFSET, - type_attribute, &IDT_Entry[entry]); -} - -__attribute__((no_caller_saved_registers)) void EOI(uint8_t irq) { - if (irq > 7) - outb(SLAVE_PIC_COMMAND_PORT, 0x20); - - outb(MASTER_PIC_COMMAND_PORT, 0x20); -} - -__attribute__((interrupt)) void general_protection_fault(registers_t *regs) { - klog("General Protetion Fault", 0x1); - kprintf(" Error Code: %x\n", regs->error_code); - kprintf("Instruction Pointer: %x\n", regs->eip); - dump_backtrace(12); - asm("hlt"); - for (;;) - ; - EOI(0xD - 8); -} - -__attribute__((interrupt)) void double_fault(registers_t *regs) { - (void)regs; - klog("DOUBLE FAULT", LOG_ERROR); - asm("hlt"); - for (;;) - ; -} -__attribute__((interrupt)) void page_fault(registers_t *regs) { - if (0xFFFFDEAD == regs->eip) { - asm("sti"); - for (;;) - switch_task(); - } - klog("Page Fault", LOG_ERROR); - if (get_current_task()) { - kprintf("PID: %x\n", get_current_task()->pid); - kprintf("Name: %s\n", get_current_task()->program_name); - } - kprintf("Error Code: %x\n", regs->error_code); - kprintf("Instruction Pointer: %x\n", regs->eip); - - if (regs->error_code & (1 << 0)) - kprintf("page-protection violation\n"); - else - kprintf("non-present page\n"); - - if (regs->error_code & (1 << 1)) - kprintf("write access\n"); - else - kprintf("read access\n"); - - if (regs->error_code & (1 << 2)) - kprintf("CPL = 3\n"); - - if (regs->error_code & (1 << 4)) - kprintf("Attempted instruction fetch\n"); - - dump_backtrace(5); - asm("hlt"); - for (;;) - ; -} - -static inline void io_wait(void) { outb(0x80, 0); } - -#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ -#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ -#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ -#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ -#define ICW1_INIT 0x10 /* Initialization - required! */ - -#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ -#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ -#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ -#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ -#define ICW4_SFNM 0x10 /* Special fully nested (not) */ - -void PIC_remap(int offset) { - unsigned char a1, a2; - a1 = inb(MASTER_PIC_DATA_PORT); - a2 = inb(SLAVE_PIC_DATA_PORT); - - // Send ICW1 and tell the PIC that we will issue a ICW4 - // Since there is no ICW1_SINGLE sent to indicate it is cascaded - // it means we will issue a ICW3. - outb(MASTER_PIC_COMMAND_PORT, ICW1_INIT | ICW1_ICW4); - io_wait(); - outb(SLAVE_PIC_COMMAND_PORT, ICW1_INIT | ICW1_ICW4); - io_wait(); - - // As a part of ICW2 this sends the offsets(the position to put IRQ0) of the - // vector tables. - outb(MASTER_PIC_DATA_PORT, offset); - io_wait(); - outb(SLAVE_PIC_DATA_PORT, offset + 0x8); - io_wait(); - - // This tells the master on which lines it is having slaves - outb(MASTER_PIC_DATA_PORT, 4); - io_wait(); - // This tells the slave the cascading identity. - outb(SLAVE_PIC_DATA_PORT, 2); - io_wait(); - - outb(MASTER_PIC_DATA_PORT, ICW4_8086); - io_wait(); - outb(SLAVE_PIC_DATA_PORT, ICW4_8086); - io_wait(); - - outb(MASTER_PIC_DATA_PORT, a1); - outb(SLAVE_PIC_DATA_PORT, a2); -} - -void IRQ_set_mask(unsigned char IRQline) { - uint16_t port; - uint8_t value; - port = (IRQline < 8) ? MASTER_PIC_DATA_PORT : SLAVE_PIC_DATA_PORT; - if (IRQline >= 8) - IRQline -= 8; - value = inb(port) | (1 << IRQline); - outb(port, value); -} - -void IRQ_clear_mask(unsigned char IRQline) { - uint16_t port; - uint8_t value; - port = (IRQline < 8) ? MASTER_PIC_DATA_PORT : SLAVE_PIC_DATA_PORT; - if (IRQline >= 8) { - IRQline -= 8; - } - value = inb(port) & ~(1 << IRQline); - outb(port, value); -} - -void idt_init(void) { - install_handler(page_fault, INT_32_INTERRUPT_GATE(0x0), 0xE); - install_handler(double_fault, INT_32_INTERRUPT_GATE(0x0), 0x8); - install_handler(general_protection_fault, INT_32_INTERRUPT_GATE(0x0), 0xD); - - PIC_remap(0x20); - IRQ_clear_mask(0xb); - IRQ_set_mask(0xe); - IRQ_set_mask(0xf); - IRQ_clear_mask(2); - - idtr.interrupt_table = (struct IDT_Descriptor **)&IDT_Entry; - idtr.size = (sizeof(struct IDT_Descriptor) * IDT_MAX_ENTRY) - 1; - load_idtr(&idtr); -} diff --git a/cpu/idt.h b/cpu/idt.h deleted file mode 100644 index 025ba75..0000000 --- a/cpu/idt.h +++ /dev/null @@ -1,70 +0,0 @@ -typedef struct kernel_registers kernel_registers_t; -typedef struct registers registers_t; -#ifndef IDT_H -#define IDT_H -#include -#include -#include -#include -#include - -/* - * the type_attribute in the IDT_Entry struct - * is divded like this - * 7 0 - * +---+---+---+---+---+---+---+---+ - * | P | DPL | S | GateType | - * +---+---+---+---+---+---+---+---+ - * It is 8 bits(1 byte) long - * - * P - * Present bit. Should be zero for unused - * interrupts. - * - * DPL - * Specifices the maximum ring(0 to 3) the - * interrupt can be called from. - * - * S - * Storage segment. This should be set to - * zero for all interrupt and trap gates. - * - * GateType - * Possible IDT gate types: - * 0b0101 0x5 5 80386 32 bit task gate - * 0b0110 0x6 6 80286 16-bit interrupt gate - * 0b0111 0x7 7 80286 16-bit trap gate - * 0b1110 0xE 14 80386 32-bit interrupt gate - * 0b1111 0xF 15 80386 32-bit trap gate - */ - -// This enables the present bit. -#define INT_PRESENT 0x80 /* 0b10000000 */ - -#define INT_32_TASK_GATE(min_privlege) \ - (INT_PRESENT | 0x05 | (min_privlege << 5)) -#define INT_16_INTERRUPT_GATE(min_privlege) \ - (INT_PRESENT | 0x06 | (min_privlege << 5)) -#define INT_16_TRAP_GATE(min_privlege) \ - (INT_PRESENT | 0x07 | (min_privlege << 5)) -#define INT_32_INTERRUPT_GATE(min_privlege) \ - (INT_PRESENT | 0x0E | (min_privlege << 5)) -#define INT_32_TRAP_GATE(min_privlege) \ - (INT_PRESENT | 0x0F | (min_privlege << 5)) - -struct interrupt_frame; - -struct registers { - uint32_t error_code; - uint32_t eip; - uint32_t cs; - uint32_t eflags; - uint32_t esp; - uint32_t ss; -}; - -void idt_init(void); -__attribute__((no_caller_saved_registers)) void EOI(unsigned char irq); -void install_handler(void (*handler_function)(), uint16_t type_attribute, - uint8_t entry); -#endif diff --git a/cpu/int_syscall.s b/cpu/int_syscall.s deleted file mode 100644 index 8c3c25f..0000000 --- a/cpu/int_syscall.s +++ /dev/null @@ -1,20 +0,0 @@ -.intel_syntax noprefix -.global int_syscall -.extern syscall_function_handler -int_syscall: - push ebp - push edi - push esi - push edx - push ecx - push ebx - push eax - call syscall_function_handler - add esp, 4 - pop ebx - pop ecx - pop edx - pop esi - pop edi - pop ebp - iretd diff --git a/cpu/io.h b/cpu/io.h deleted file mode 100644 index 38858a4..0000000 --- a/cpu/io.h +++ /dev/null @@ -1,15 +0,0 @@ -#include - -extern void outsw(uint16_t, uint32_t); -extern void outb(uint16_t, uint8_t); -extern void outw(uint16_t, uint16_t); -extern void outl(uint16_t, uint32_t); - -extern uint32_t inl(uint16_t); -extern uint16_t inw(uint16_t); -extern uint16_t inb(uint16_t); - -extern void rep_outsw(uint16_t count, uint16_t port, volatile void *addy); -__attribute__((no_caller_saved_registers)) extern void -rep_insw(uint16_t count, uint16_t port, volatile void *addy); -extern void jump_usermode(void (*address)(), uint32_t stack_pointer); diff --git a/cpu/io.s b/cpu/io.s deleted file mode 100644 index 31e9df0..0000000 --- a/cpu/io.s +++ /dev/null @@ -1,147 +0,0 @@ -.intel_syntax noprefix -.global outsw -.global outb -.global outw -.global outl -.global inb -.global inw -.global inl -.global rep_outsw -.global rep_insw -.global flush_tss -.global load_idtr - -# ebx, esi, edi, ebp, and esp; -outsw: - push ebp - mov ebp, esp - push esi - mov dx, [ebp + 4+4] - mov esi, [ebp + 8+4] - outsw - pop esi - mov esp, ebp - pop ebp - ret - -outl: - mov eax, [esp + 8] - mov dx, [esp + 4] - out dx, eax - ret - -outb: - mov al, [esp + 8] - mov dx, [esp + 4] - out dx, al - ret - -outw: - mov ax, [esp + 8] - mov dx, [esp + 4] - out dx, ax - ret - -inl: - mov dx, [esp + 4] - in eax, dx - ret - -inw: - mov dx, [esp + 4] - in ax, dx - ret - -inb: - mov dx, [esp + 4] - in al, dx - ret - -rep_outsw: - push ebp - mov ebp, esp - push edi - mov ecx, [ebp + 4+4] #ECX is counter for OUTSW - mov edx, [ebp + 8+4] #Data port, in and out - mov edi, [ebp + 12+4] #Memory area - rep outsw #in to [RDI] - pop edi - mov esp, ebp - pop ebp - ret - -rep_insw: - push ebp - mov ebp, esp - push edi - mov ecx, [ebp + 4+4] #ECX is counter for INSW - mov edx, [ebp + 8+4] #Data port, in and out - mov edi, [ebp + 12+4] #Memory area - rep insw #in to [RDI] - pop edi - mov esp, ebp - pop ebp - ret - -flush_tss: - mov ax, 40 - ltr ax - ret - -load_idtr: - mov edx, [esp + 4] - lidt [edx] - ret - -test_user_function: - mov eax, 0x00 - int 0x80 - mov ecx, 0x03 - mov ebx, 0x04 - mov eax, 0x02 - int 0x80 - mov ebx, eax - mov eax, 0x01 - int 0x80 -loop: - jmp loop - ret - -.global spin_lock -.global spin_unlock -.extern locked - -spin_lock: - mov eax, 1 - xchg eax, ebx - test eax, eax - jnz spin_lock - ret - -spin_unlock: - xor eax, eax - xchg eax, ebx - ret - - -.global jump_usermode -jump_usermode: - mov ax, (4 * 8) | 3 # user data segment with RPL 3 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax # sysexit sets SS - - # setup wrmsr inputs - xor edx, edx # not necessary; set to 0 - mov eax, 0x100008 # SS=0x10+0x10=0x20, CS=0x8+0x10=0x18 - mov ecx, 0x174 # MSR specifier: IA32_SYSENTER_CS - wrmsr # set sysexit segments - - # setup sysexit inputs - mov edx, [esp + 4] # to be loaded into EIP - mov ecx, [esp + 8] # to be loaded into ESP - mov esp, ecx - mov ebp, ecx - sti - sysexit diff --git a/cpu/reload_gdt.s b/cpu/reload_gdt.s deleted file mode 100644 index 3a0119b..0000000 --- a/cpu/reload_gdt.s +++ /dev/null @@ -1,17 +0,0 @@ -.section .text -.global load_gdt - -load_gdt: - mov 4(%esp), %eax - lgdt (%eax) - - mov $0x10, %eax - mov %eax, %ds - mov %eax, %es - mov %eax, %fs - mov %eax, %gs - mov %eax, %ss - jmp $0x8, $.long_jump -.long_jump: - ret - diff --git a/cpu/spinlock.c b/cpu/spinlock.c deleted file mode 100644 index 3f87423..0000000 --- a/cpu/spinlock.c +++ /dev/null @@ -1,2 +0,0 @@ -#include -uint8_t locked; diff --git a/cpu/spinlock.h b/cpu/spinlock.h deleted file mode 100644 index 93290c4..0000000 --- a/cpu/spinlock.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef SPINLOCK_H -#define SPINLOCK_H -void spin_lock(int *l); -void spin_unlock(int *l); -#endif diff --git a/cpu/syscall.c b/cpu/syscall.c deleted file mode 100644 index 4978732..0000000 --- a/cpu/syscall.c +++ /dev/null @@ -1,183 +0,0 @@ -// FIXME: Make sure that the args variabel actually points to something -// valid. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma GCC diagnostic ignored "-Wpedantic" - -int syscall_open(SYS_OPEN_PARAMS *args) { - char file[256]; - strcpy(file, args->file); - // const char *file = copy_and_allocate_user_string(args->file); - int flags = args->flags; - int mode = args->mode; - int rc = vfs_open(file, flags, mode); - // kfree((void *)file); - return rc; -} - -int syscall_exec(SYS_EXEC_PARAMS *args) { - const char *filename = copy_and_allocate_user_string(args->path); - - int argc = 0; - for (; args->argv[argc];) { - argc++; - } - - char **new_argv = kallocarray(argc + 1, sizeof(char *)); - for (int i = 0; i < argc; i++) - new_argv[i] = copy_and_allocate_user_string(args->argv[i]); - - new_argv[argc] = NULL; - - exec(filename, new_argv); - kfree((void *)filename); - for (int i = 0; i < argc; i++) - kfree(new_argv[i]); - kfree(new_argv); - return -1; -} - -int syscall_pipe(int fd[2]) { - pipe(fd); // FIXME: Error checking - return 0; -} - -int syscall_pread(SYS_PREAD_PARAMS *args) { - return vfs_pread(args->fd, args->buf, args->count, args->offset); -} - -int syscall_read(SYS_READ_PARAMS *args) { - if (!get_vfs_fd(args->fd)) - return -EBADF; - int rc = vfs_pread(args->fd, args->buf, args->count, - get_current_task()->file_descriptors[args->fd]->offset); - get_current_task()->file_descriptors[args->fd]->offset += rc; - return rc; -} - -int syscall_pwrite(SYS_PWRITE_PARAMS *args) { - return vfs_pwrite(args->fd, args->buf, args->count, args->offset); -} - -int syscall_write(int fd, const char *buf, size_t count) { - if (!get_vfs_fd(fd)) - return -EBADF; - int rc = vfs_pwrite(fd, (char *)buf, count, - get_current_task()->file_descriptors[fd]->offset); - get_current_task()->file_descriptors[fd]->offset += rc; - return rc; -} - -int syscall_dup2(SYS_DUP2_PARAMS *args) { - return vfs_dup2(args->org_fd, args->new_fd); -} - -void syscall_exit(int status) { - exit(status); - assert(0); -} - -void syscall_wait(int *status) { - asm("cli"); - if (!get_current_task()->child) { - if (status) - *status = -1; - return; - } - if (get_current_task()->child->dead) { - if (status) - *status = get_current_task()->child_rc; - return; - } - get_current_task()->halts[WAIT_CHILD_HALT] = 1; - switch_task(); - if (status) - *status = get_current_task()->child_rc; -} - -int syscall_fork(void) { return fork(); } - -int syscall_getpid(void) { return get_current_task()->pid; } - -void *align_page(void *a); - -int syscall_brk(void *addr) { - void *end = get_current_task()->data_segment_end; - if (!mmu_allocate_region(end, addr - end, MMU_FLAG_RW, NULL)) - return -ENOMEM; - get_current_task()->data_segment_end = align_page(addr); - return 0; -} - -void *syscall_sbrk(uintptr_t increment) { - asm("cli"); - void *rc = get_current_task()->data_segment_end; - void *n = - (void *)((uintptr_t)(get_current_task()->data_segment_end) + increment); - int rc2; - if (0 > (rc2 = syscall_brk(n))) - return (void *)rc2; - return rc; -} - -int syscall_close(int fd) { return vfs_close(fd); } - -int syscall_openpty(SYS_OPENPTY_PARAMS *args) { - assert(is_valid_userpointer(args, sizeof(SYS_OPENPTY_PARAMS))); - return openpty(args->amaster, args->aslave, args->name, args->termp, - args->winp); -} - -void (*syscall_functions[])() = { - (void(*))syscall_open, (void(*))syscall_read, - (void(*))syscall_write, (void(*))syscall_pread, - (void(*))syscall_pwrite, (void(*))syscall_fork, - (void(*))syscall_exec, (void(*))syscall_getpid, - (void(*))syscall_exit, (void(*))syscall_wait, - (void(*))syscall_brk, (void(*))syscall_sbrk, - (void(*))syscall_pipe, (void(*))syscall_dup2, - (void(*))syscall_close, (void(*))syscall_openpty, - (void(*))syscall_poll, (void(*))syscall_mmap, - (void(*))syscall_accept, (void(*))syscall_bind, - (void(*))syscall_socket, (void(*))syscall_shm_open, - (void(*))syscall_ftruncate, (void(*))syscall_stat, - (void(*))syscall_msleep, (void(*))syscall_uptime, - (void(*))syscall_mkdir, (void(*))syscall_recvfrom, - (void(*))syscall_sendto, (void(*))syscall_kill, - (void(*))syscall_sigaction, -}; - -void syscall_function_handler(uint32_t eax, uint32_t arg1, uint32_t arg2, - uint32_t arg3, uint32_t arg4, uint32_t arg5) { - assert(eax < sizeof(syscall_functions) / sizeof(syscall_functions[0])); - syscall_functions[eax](arg1, arg2, arg3, arg4, arg5); -} - -extern void int_syscall(void); - -void syscalls_init(void) { - install_handler(int_syscall, INT_32_INTERRUPT_GATE(0x3), 0x80); -} diff --git a/cpu/syscall.h b/cpu/syscall.h deleted file mode 100644 index 51d50f2..0000000 --- a/cpu/syscall.h +++ /dev/null @@ -1,59 +0,0 @@ -#include "idt.h" -#include -#include - -void syscalls_init(void); - -typedef struct SYS_OPEN_PARAMS { - char *file; - int flags; - int mode; -} __attribute__((packed)) SYS_OPEN_PARAMS; - -typedef struct SYS_PREAD_PARAMS { - int fd; - void *buf; - size_t count; - size_t offset; -} __attribute__((packed)) SYS_PREAD_PARAMS; - -typedef struct SYS_READ_PARAMS { - int fd; - void *buf; - size_t count; -} __attribute__((packed)) SYS_READ_PARAMS; - -typedef struct SYS_PWRITE_PARAMS { - int fd; - void *buf; - size_t count; - size_t offset; -} __attribute__((packed)) SYS_PWRITE_PARAMS; - -typedef struct SYS_WRITE_PARAMS { - int fd; - void *buf; - size_t count; -} __attribute__((packed)) SYS_WRITE_PARAMS; - -typedef struct SYS_EXEC_PARAMS { - char *path; - char **argv; -} __attribute__((packed)) SYS_EXEC_PARAMS; - -typedef struct SYS_WAIT_PARAMS { - int *status; -} __attribute__((packed)) SYS_WAIT_PARAMS; - -typedef struct SYS_DUP2_PARAMS { - int org_fd; - int new_fd; -} __attribute__((packed)) SYS_DUP2_PARAMS; - -typedef struct SYS_OPENPTY_PARAMS { - int *amaster; - int *aslave; - char *name; - /*const struct termios*/ void *termp; - /*const struct winsize*/ void *winp; -} __attribute__((packed)) SYS_OPENPTY_PARAMS; diff --git a/crypto/ChaCha20/chacha20.c b/crypto/ChaCha20/chacha20.c deleted file mode 100644 index 5bf7aa2..0000000 --- a/crypto/ChaCha20/chacha20.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "chacha20.h" - -#define ROTL(a, b) (((a) << (b)) | ((a) >> (32 - (b)))) -#define QR(a, b, c, d) \ - (a += b, d ^= a, d = ROTL(d, 16), c += d, b ^= c, b = ROTL(b, 12), \ - a += b, d ^= a, d = ROTL(d, 8), c += d, b ^= c, b = ROTL(b, 7)) -#define ROUNDS 20 - -void chacha_block(uint32_t out[16], uint32_t const in[16]) -{ - int i; - uint32_t x[16]; - - for (i = 0; i < 16; ++i) - x[i] = in[i]; - for (i = 0; i < ROUNDS; i += 2) { - QR(x[0], x[4], x[8], x[12]); - QR(x[1], x[5], x[9], x[13]); - QR(x[2], x[6], x[10], x[14]); - QR(x[3], x[7], x[11], x[15]); - - QR(x[0], x[5], x[10], x[15]); - QR(x[1], x[6], x[11], x[12]); - QR(x[2], x[7], x[8], x[13]); - QR(x[3], x[4], x[9], x[14]); - } - for (i = 0; i < 16; ++i) - out[i] = x[i] + in[i]; -} diff --git a/crypto/ChaCha20/chacha20.h b/crypto/ChaCha20/chacha20.h deleted file mode 100644 index 17532f3..0000000 --- a/crypto/ChaCha20/chacha20.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef CHACHA20_H -#define CHACHA20_H -#include - -#define KEY 4 -#define KEY_SIZE 8*sizeof(uint32_t) -#define COUNT 12 -#define COUNT_SIZE sizeof(uint32_t) -#define COUNT_MAX (0x100000000-1) // 2^32 - 1 -#define NONCE 13 -#define NONCE_SIZE 2*sizeof(uint32_t) -#define BLOCK_SIZE 16*sizeof(uint32_t) - -void chacha_block(uint32_t out[16], uint32_t const in[16]); -#endif diff --git a/crypto/SHA1 b/crypto/SHA1 deleted file mode 160000 index 237ea70..0000000 --- a/crypto/SHA1 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 237ea7023cad8402932dfbde337d69e5f4d515f6 diff --git a/drivers/ata.c b/drivers/ata.c deleted file mode 100644 index fd9b504..0000000 --- a/drivers/ata.c +++ /dev/null @@ -1,253 +0,0 @@ -#include -#include -#include -#include - -#define PRIMARY_BUS_BASEPORT 0x1F0 -#define SECONDAY_BUS_BASEPORT 0x170 - -#define PRIMARY_BUS_IRQ 14 -#define SECONDAY_BUS_IRQ 15 - -#define STATUS_PORT 7 -#define COMMAND_PORT 7 -#define DRIVE_SELECT 6 -#define LBAhi 5 -#define LBAmid 4 -#define LBAlo 3 -#define SECTOR_COUNT 2 -#define DATA_PORT 0 - -#define IDENTIFY 0xEC -#define READ_SECTORS 0x20 -#define WRITE_SECTORS 0x30 -#define CACHE_FLUSH 0xE7 - -#define STATUS_BSY ((1 << 7)) -#define STATUS_DF ((1 << 5)) -#define STATUS_DRQ ((1 << 3)) -#define STATUS_ERR ((1 << 0)) - -uint32_t io_base; - -unsigned char read_buffer[SECTOR_SIZE]; - -void select_drive(uint8_t master_slave) { - outb(io_base + DRIVE_SELECT, (master_slave) ? 0xA0 : 0xB0); -} - -int identify(int master_slave) { - select_drive(master_slave); - outb(io_base + SECTOR_COUNT, 0); - outb(io_base + LBAlo, 0); - outb(io_base + LBAmid, 0); - outb(io_base + LBAhi, 0); - outb(io_base + COMMAND_PORT, IDENTIFY); - if (0 == inb(io_base + STATUS_PORT)) - return 0; // Drive does not exist - - for (; 0 != (inb(io_base + STATUS_PORT) & STATUS_BSY);) - ; - - // Because of some ATAPI drives that do not - // follow spec, at this point we need to check - // the LBAmid and LBAhi ports to see if they are - // non-zero. If so, the drive is not ATA, and we - // should stop polling. - if (0 != inb(io_base + LBAmid) || 0 != inb(io_base + LBAhi)) { - klog("Drive is not ATA.", LOG_ERROR); - return -1; - } - - for (uint16_t status;;) { - status = inb(io_base + STATUS_PORT); - - if (1 == (status & STATUS_ERR)) { - klog("Drive ERR set.", LOG_ERROR); - return -2; - } - - if ((status & STATUS_DRQ)) - break; - } - - // The data is ready to read from the Data - // port (0x1F0). Read 256 16-bit values, - // and store them. - // TODO: This returns some intreasting information. - // https://wiki.osdev.org/ATA_PIO_Mode#Interesting_information_returned_by_IDENTIFY - uint16_t array[256]; - rep_insw(1 * SECTOR_SIZE / 16, io_base + DATA_PORT, array); - return 1; -} - -int poll_status(void) { - for (uint16_t status;;) { - // Read the Regular Status port until... - // We read this 15 times to give some - // time for the drive to catch up. - for (int n = 0; n < 15; n++) - status = inb(io_base + STATUS_PORT); - - // ERR or - // DF sets - if ((status & STATUS_ERR) || (status & STATUS_DF)) { - klog("Drive error set.", LOG_ERROR); - return 0; - } - - // BSY clears - // DRQ sets - if (0 == (status & STATUS_BSY) && 0 != (status & STATUS_DRQ)) - break; - } - return 1; -} - -// Instructions from: https://wiki.osdev.org/ATA_PIO_Mode#28_bit_PIO -void __attribute__((optimize("O0"))) -setup_drive_for_command(uint32_t lba, uint32_t sector_count) { - // 1. Send 0xE0 for the "master" or 0xF0 for - // the "slave", ORed with the highest 4 bits - // of the LBA to port 0x1F6 - outb(io_base + DRIVE_SELECT, 0xE0 | (0 << 4) | ((lba >> 24) & 0x0F)); - - // 2. Send a NULL byte to port 0x1F1, if you - // like (it is ignored and wastes - // lots of CPU time) - - // NOP - - // 3. Send the sectorcount to port 0x1F2 - outb(io_base + SECTOR_COUNT, sector_count); - - // 4. Send the low 8 bits of the LBA to port 0x1F3 - outb(io_base + LBAlo, (lba >> 0) & 0xFF); - - // 5. Send the next 8 bits of the LBA to port 0x1F4 - outb(io_base + LBAmid, (lba >> 8) & 0xFF); - - // 6. Send the next 8 bits of the LBA to port 0x1F5 - outb(io_base + LBAhi, (lba >> 16) & 0xFF); -} - -void delayed_rep_outsw(size_t n, uint16_t port, volatile uint8_t *buffer) { - for (volatile size_t i = 0; i < n; i++) { - outsw(port, (uint32_t)buffer); - buffer += 2; - // outsw(port, buffer); - } -} - -void __attribute__((optimize("O0"))) -ata_write_lba28(uint32_t lba, uint32_t sector_count, - volatile const uint8_t *buffer) { - setup_drive_for_command(lba, sector_count); - - outb(io_base + COMMAND_PORT, WRITE_SECTORS); - - for (volatile uint32_t i = 0; i < sector_count; i++) { - if (!poll_status()) { - // FIXME: Fail properly - for (;;) - ; - } - - delayed_rep_outsw(256, io_base + DATA_PORT, - (void *)((uint32_t)buffer + i * 256)); - } - - // Cache flush - outb(io_base + COMMAND_PORT, CACHE_FLUSH); - - // Wait for BSY to clear - for (;;) { - uint16_t status = inb(io_base + STATUS_PORT); - if (!(status & STATUS_BSY)) - break; - } -} - -// Instructions from: https://wiki.osdev.org/ATA_PIO_Mode#28_bit_PIO -void __attribute__((optimize("O0"))) -ata_read_lba28(uint32_t lba, uint32_t sector_count, volatile void *address) { - // Step 1-6 is done in this function. - setup_drive_for_command(lba, sector_count); - - // 7. Send the "READ SECTORS" command to port 0x17F - outb(io_base + COMMAND_PORT, READ_SECTORS); - - // 8. Wait for an IRQ or poll. - - // This step can be found in the for loop - - // 9. Transfer 256 16-bit values, a uint16_t at a time, - // into your buffer from I/O port 0x1F0 - for (volatile uint32_t i = 0; i < sector_count; i++) { - // 10. Then loop back to waiting for the next IRQ - // or poll again for each successive sector. - // 8. Wait for an IRQ or poll. - if (!poll_status()) { - // FIXME: Fail properly - for (;;) - ; - } - rep_insw(256, io_base + DATA_PORT, (void *)((uint32_t)address + i * 256)); - } -} - -void ata_init(void) { - io_base = PRIMARY_BUS_BASEPORT; - - // Before sending any data to the IO ports, - // read the Regular Status byte. The value - // 0xFF is an illegal status value, and - // indicates that the bus has no drives - if (0xFF == inb(io_base + STATUS_PORT)) { - klog("Bus has no drives", LOG_ERROR); - } - - // Issue IDENTIFY command - select_drive(1); -} - -void __attribute__((optimize("O0"))) -read_lba(uint32_t lba, void *address, size_t size, size_t offset) { - uintptr_t ptr = (uintptr_t)address; - lba += offset / SECTOR_SIZE; - offset = offset % SECTOR_SIZE; - asm("cli"); - size_t total_read = 0; - for (int i = 0; size > 0; i++) { - uint32_t read_len = - (SECTOR_SIZE < (size + offset)) ? (SECTOR_SIZE - offset) : size; - ata_read_lba28(lba + i, 1, read_buffer); - memcpy((void *)ptr, read_buffer + offset, read_len); - size -= read_len; - total_read += read_len; - ptr += read_len; - offset = 0; - } -} - -void write_lba(uint32_t lba, volatile void *address, size_t size, - size_t offset) { - uintptr_t ptr = (uintptr_t)address; - lba += offset / SECTOR_SIZE; - offset = offset % SECTOR_SIZE; - size_t total_write = 0; - uint8_t sector_buffer[512]; - for (int i = 0; size > 0; i++) { - ata_read_lba28(lba + i, 1, sector_buffer); - uint32_t write_len = - (SECTOR_SIZE < (size + offset)) ? (SECTOR_SIZE - offset) : size; - - memcpy(sector_buffer + offset, (void *)ptr, write_len); - ata_write_lba28(lba + i, 1, sector_buffer); - - size -= write_len; - total_write += write_len; - ptr += write_len; - offset = 0; - } -} diff --git a/drivers/ata.h b/drivers/ata.h deleted file mode 100644 index 3e88d7f..0000000 --- a/drivers/ata.h +++ /dev/null @@ -1,16 +0,0 @@ -#include "../cpu/idt.h" -#include - -#define SECTOR_SIZE 512 - -void ata_init(void); - -void read_drive_chs(uint8_t head_index, uint8_t sector_count, - uint8_t sector_index, uint8_t cylinder_low_value, - uint8_t cylinder_high_value, void *address); -void read_drive_lba(uint32_t lba, uint8_t sector_count, void *address); -void read_lba(uint32_t lba, void *address, size_t size, size_t offset); -void write_lba(uint32_t lba, volatile void *address, size_t size, - size_t offset); -void ata_write_lba28(uint32_t lba, uint32_t sector_count, - volatile const uint8_t *buffer); diff --git a/drivers/keyboard.c b/drivers/keyboard.c deleted file mode 100644 index 8c96606..0000000 --- a/drivers/keyboard.c +++ /dev/null @@ -1,188 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define PS2_REG_DATA 0x60 -#define PS2_REG_STATUS 0x64 -#define PS2_REG_COMMAND 0x64 - -#define PS2_CMD_ENABLE_FIRST_PORT 0xAE // no rsp - -#define PS2_CMD_TEST_CONTROLLER 0xAA // has rsp - -#define PS2_RSP_TEST_PASSED 0x55 -#define PS2_RSP_TEST_FAILED 0xFC - -#define PS2_CMD_SET_SCANCODE 0xF0 // has rsp -#define PS2_KB_ACK 0xFA -#define PS2_KB_RESEND 0xFE - -#define PS2_CMD_SET_MAKE_RELEASE 0xF8 // has rsp - -uint8_t kb_scancodes[3] = {0x43, 0x41, 0x3f}; - -FIFO_FILE *keyboard_fifo; - -uint8_t ascii_table[] = { - 'e', '\x1B', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, - '\t', - - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', - // 0, // [ - // 0, // ] - // 0, - // 0, // ? - '[', ']', - '\n', // ENTER - 'C', - - 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', - ';', // ; - '\'', // ; - '`', // ; - 'D', // LEFT SHIFT - '\\', // ; - 'z', 'x', 'c', 'v', 'b', 'n', 'm', - ',', // ; - '.', // ; - '/', // ; - 'U', // ; - 'U', // ; - 'U', // ; - ' ', // ; -}; - -uint8_t capital_ascii_table[] = { - 'e', '\x1B', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 8, - '\t', - - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', - // 0, // [ - // 0, // ] - // 0, - // 0, // ? - '{', '}', - '\n', // ENTER - 'C', - - 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', - ':', // ; - '\"', // ; - '~', // ; - 'D', // LEFT SHIFT - '\\', // ; - 'Z', 'X', 'C', 'V', 'B', 'N', 'M', - '<', // ; - '>', // ; - '?', // ; - 'U', // ; - 'U', // ; - 'U', // ; - ' ', // ; -}; - -vfs_inode_t *kb_inode; - -uint8_t keyboard_to_ascii(uint16_t key, uint8_t capital) { - if ((key & 0xFF) > sizeof(ascii_table)) - return 'U'; - if (capital) - return capital_ascii_table[key & 0xFF]; - else - return ascii_table[key & 0xFF]; -} - -uint8_t is_shift_down = 0; -uint8_t is_alt_down = 0; - -struct KEY_EVENT { - char c; - uint8_t mode; // (shift (0 bit)) (alt (1 bit)) - uint8_t release; // 0 pressed, 1 released -}; - -extern process_t *ready_queue; -__attribute__((interrupt)) void -int_keyboard(__attribute__((unused)) struct interrupt_frame *frame) { - outb(0x20, 0x20); - uint16_t c; - c = inb(PS2_REG_DATA); - int released = 0; - if (c & 0x80) { - switch ((c & ~(0x80)) & 0xFF) { - case 0x2A: // Left shift - case 0x36: // Right shift - is_shift_down = 0; - return; - case 0x38: - is_alt_down = 0; - return; - } - released = 1; - } else { - switch (c & 0xFF) { - case 0x2A: // Left shift - case 0x36: // Right shift - is_shift_down = 1; - return; - case 0x38: - is_alt_down = 1; - return; - } - released = 0; - } - unsigned char a = keyboard_to_ascii((c & ~(0x80)) & 0xFF, is_shift_down); - struct KEY_EVENT ev; - ev.c = a; - ev.release = released; - ev.mode = 0; - ev.mode |= is_shift_down << 0; - ev.mode |= is_alt_down << 1; - fifo_object_write((uint8_t *)&ev, 0, sizeof(ev), keyboard_fifo); - kb_inode->has_data = keyboard_fifo->has_data; -} - -#define PS2_WAIT_RECV \ - { \ - for (;;) { \ - uint8_t status = inb(PS2_REG_STATUS); \ - if (status & 0x1) \ - break; \ - } \ - } - -#define PS2_WAIT_SEND \ - { \ - for (;;) { \ - uint8_t status = inb(PS2_REG_STATUS); \ - if (!(status & (0x1 << 1))) \ - break; \ - } \ - } - -void install_keyboard(void) { - keyboard_fifo = create_fifo_object(); - install_handler(int_keyboard, INT_32_INTERRUPT_GATE(0x3), 0x21); -} - -int keyboard_read(uint8_t *buffer, uint64_t offset, uint64_t len, - vfs_fd_t *fd) { - (void)offset; - - if (0 == fd->inode->has_data) { - return -EAGAIN; - } - int rc = fifo_object_read(buffer, 0, len, keyboard_fifo); - fd->inode->has_data = keyboard_fifo->has_data; - return rc; -} - -void add_keyboard(void) { - kb_inode = devfs_add_file("/keyboard", keyboard_read, NULL, NULL, 0, 0, - FS_TYPE_CHAR_DEVICE); -} diff --git a/drivers/keyboard.h b/drivers/keyboard.h deleted file mode 100644 index 4b76f22..0000000 --- a/drivers/keyboard.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef KEYBOARD_H -#define KEYBOARD_H - -#include -#include -#include - -void install_keyboard(void); -void add_keyboard(void); - -#endif diff --git a/drivers/mouse.c b/drivers/mouse.c deleted file mode 100644 index 23619a0..0000000 --- a/drivers/mouse.c +++ /dev/null @@ -1,144 +0,0 @@ -#include -#include -#include -#include -#include -#include - -uint8_t mouse_cycle = 0; // unsigned char -uint8_t mouse_uint8_t[3]; // signed char -uint8_t mouse_x = 0; // signed char -uint8_t mouse_y = 0; // signed char -vfs_inode_t *mouse_inode; -vfs_fd_t *mouse_fd; - -struct mouse_event { - uint8_t buttons; - uint8_t x; - uint8_t y; -}; - -int fs_mouse_write(uint8_t *buffer, uint64_t offset, uint64_t len, - vfs_fd_t *fd) { - int rc = fifo_object_write(buffer, offset, len, fd->inode->internal_object); - FIFO_FILE *f = fd->inode->internal_object; - mouse_inode->has_data = f->has_data; - return rc; -} - -int fs_mouse_read(uint8_t *buffer, uint64_t offset, uint64_t len, - vfs_fd_t *fd) { - FIFO_FILE *f = fd->inode->internal_object; - if (!mouse_inode->has_data) - return 0; - int rc = fifo_object_read(buffer, offset, len, f); - mouse_inode->has_data = f->has_data; - return rc; -} - -void add_mouse(void) { - mouse_inode = devfs_add_file("/mouse", fs_mouse_read, fs_mouse_write, NULL, 0, - 0, FS_TYPE_CHAR_DEVICE); - mouse_inode->internal_object = create_fifo_object(); - // Don't look at this - int fd = vfs_open("/dev/mouse", O_RDWR, 0); - mouse_fd = get_vfs_fd(fd); - get_current_task()->file_descriptors[fd] = NULL; -} - -__attribute__((interrupt)) void what(registers_t *r) { EOI(0xe); } - -__attribute__((interrupt)) void int_mouse(registers_t *r) { - (void)r; - EOI(12); - switch (mouse_cycle) { - case 0: - mouse_uint8_t[0] = inb(0x60); - if(!(mouse_uint8_t[0] & (1 << 3))) { - mouse_cycle = 0; - return; - } - mouse_cycle++; - break; - case 1: - mouse_uint8_t[1] = inb(0x60); - mouse_cycle++; - break; - case 2: - mouse_uint8_t[2] = inb(0x60); - mouse_x = mouse_uint8_t[1]; - mouse_y = mouse_uint8_t[2]; - mouse_cycle = 0; - struct mouse_event e; - e.buttons = mouse_uint8_t[0]; - e.x = mouse_x; - e.y = mouse_y; - raw_vfs_pwrite(mouse_fd, &e, sizeof(e), 0); - break; - } -} - -void mouse_wait(uint8_t a_type) { - uint32_t _time_out = 100000; - if (a_type == 0) { - while (_time_out--) { - if ((inb(0x64) & 1) == 1) { - return; - } - } - return; - } else { - while (_time_out--) { - if ((inb(0x64) & 2) == 0) { - return; - } - } - return; - } -} - -void mouse_write(uint8_t a_write) { - // Wait to be able to send a command - mouse_wait(1); - // Tell the mouse we are sending a command - outb(0x64, 0xD4); - // Wait for the final part - mouse_wait(1); - // Finally write - outb(0x60, a_write); -} - -uint8_t mouse_read() { - // Get's response from mouse - mouse_wait(0); - return inb(0x60); -} - -void install_mouse(void) { - uint8_t _status; // unsigned char - asm("cli"); - // Enable the auxiliary mouse device - mouse_wait(1); - outb(0x64, 0xA8); - - // Enable the interrupts - mouse_wait(1); - outb(0x64, 0x20); - mouse_wait(0); - _status = (inb(0x60) | 2); - mouse_wait(1); - outb(0x64, 0x60); - mouse_wait(1); - outb(0x60, _status); - - // Tell the mouse to use default settings - mouse_write(0xF6); - mouse_read(); // Acknowledge - - // Enable the mouse - mouse_write(0xF4); - mouse_read(); // Acknowledge - - install_handler(int_mouse, INT_32_INTERRUPT_GATE(0x3), 12 + 0x20); - install_handler(what, INT_32_INTERRUPT_GATE(0x3), 0xe + 0x20); -} diff --git a/drivers/mouse.h b/drivers/mouse.h deleted file mode 100644 index 5248143..0000000 --- a/drivers/mouse.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef MOUSE_H -#define MOUSE_H -void install_mouse(void); -void add_mouse(void); -#endif diff --git a/drivers/pci.c b/drivers/pci.c deleted file mode 100644 index 5fe14bd..0000000 --- a/drivers/pci.c +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include - -#define CONFIG_ADDRESS 0xCF8 -#define CONFIG_DATA 0xCFC - -void pci_config_write32(const struct PCI_DEVICE *device, uint8_t func, - uint8_t offset, uint32_t data) { - uint32_t address; - uint32_t lbus = (uint32_t)device->bus; - uint32_t lslot = (uint32_t)device->slot; - uint32_t lfunc = (uint32_t)func; - - // Create configuration address as per Figure 1 - address = (uint32_t)((lbus << 16) | (lslot << 11) | (lfunc << 8) | - (offset & 0xFC) | ((uint32_t)0x80000000)); - - // Write out the address - outl(CONFIG_ADDRESS, address); - outl(CONFIG_DATA, data); -} - -uint32_t pci_config_read32(const struct PCI_DEVICE *device, uint8_t func, - uint8_t offset) { - uint32_t address; - uint32_t lbus = (uint32_t)device->bus; - uint32_t lslot = (uint32_t)device->slot; - uint32_t lfunc = (uint32_t)func; - - // Create configuration address as per Figure 1 - address = (uint32_t)((lbus << 16) | (lslot << 11) | (lfunc << 8) | - (offset & 0xFC) | ((uint32_t)0x80000000)); - - // Write out the address - outl(CONFIG_ADDRESS, address); - return inl(CONFIG_DATA); -} - -int pci_populate_device_struct(uint16_t vendor, uint16_t device, - struct PCI_DEVICE *pci_device) { - pci_device->vendor = vendor; - pci_device->device = device; - - for (int bus = 0; bus < 256; bus++) { - for (int slot = 0; slot < 256; slot++) { - struct PCI_DEVICE tmp; - tmp.bus = bus; - tmp.slot = slot; - uint32_t device_vendor = pci_config_read32(&tmp, 0, 0); - if (vendor != (device_vendor & 0xFFFF)) - continue; - if (device != (device_vendor >> 16)) - continue; - pci_device->bus = bus; - pci_device->slot = slot; - uint32_t bar0 = pci_config_read32(pci_device, 0, 0x10); - assert(bar0 & 0x1 && "Only support memory IO"); - pci_device->gen.base_mem_io = bar0 & (~0x3); - return 1; - } - } - return 0; -} - -uint8_t pci_get_interrupt_line(const struct PCI_DEVICE *device) { - return pci_config_read32(device, 0, 0x3C) & 0xFF; -} diff --git a/drivers/pci.h b/drivers/pci.h deleted file mode 100644 index 7511cee..0000000 --- a/drivers/pci.h +++ /dev/null @@ -1,26 +0,0 @@ -#include - -struct GENERAL_DEVICE { - uint32_t base_mem_io; - uint8_t interrupt_line; -}; - -struct PCI_DEVICE { - uint16_t vendor; - uint16_t device; - uint8_t bus; - uint8_t slot; - union { - struct GENERAL_DEVICE gen; - }; -}; - -uint32_t pci_config_read32(const struct PCI_DEVICE *device, uint8_t func, - uint8_t offset); -void pci_config_write32(const struct PCI_DEVICE *device, uint8_t func, - uint8_t offset, uint32_t data); - -int pci_populate_device_struct(uint16_t vendor, uint16_t device, - struct PCI_DEVICE *pci_device); - -uint8_t pci_get_interrupt_line(const struct PCI_DEVICE *device); diff --git a/drivers/pit.c b/drivers/pit.c deleted file mode 100644 index 711883c..0000000 --- a/drivers/pit.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "pit.h" - -#define PIT_IO_CHANNEL_0 0x40 -#define PIT_IO_MODE_COMMAND 0x43 - -uint64_t clock_num_ms_ticks = 0; -uint64_t pit_counter = 0; -uint16_t hertz; - -uint64_t pit_num_ms(void) { return clock_num_ms_ticks; } - -uint16_t read_pit_count(void) { - uint16_t count = 0; - - outb(PIT_IO_MODE_COMMAND, 0x0 /*0b00000000*/); - - count = inb(PIT_IO_CHANNEL_0); - count |= inb(PIT_IO_CHANNEL_0) << 8; - - return count; -} - -void set_pit_count(uint16_t hertz) { - uint16_t divisor = 1193180 / hertz; - - /* - * 0b00110110 - * ^^ - * channel - 0 - * ^^ - * r/w mode - LSB then MSB - * ^^^ - * mode - 3 Square Wave Mode - * ^ - * BCD - no - */ - outb(PIT_IO_MODE_COMMAND, 0x36 /*0b00110110*/); - outb(PIT_IO_CHANNEL_0, divisor & 0xFF); - outb(PIT_IO_CHANNEL_0, (divisor & 0xFF00) >> 8); -} - -__attribute__((interrupt)) void -int_clock(__attribute__((unused)) struct interrupt_frame *frame) { - outb(0x20, 0x20); - pit_counter++; - if (pit_counter >= hertz / 1000) { - pit_counter = 0; - clock_num_ms_ticks++; - } - switch_task(); -} - -void pit_install(void) { - install_handler(int_clock, INT_32_INTERRUPT_GATE(0x0), 0x20); -} diff --git a/drivers/pit.h b/drivers/pit.h deleted file mode 100644 index 8d9ce98..0000000 --- a/drivers/pit.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef PIT_H -#define PIT_H -#include -#include -#include -#include -#include - -void pit_install(void); -void set_pit_count(uint16_t hertz); -uint64_t pit_num_ms(void); -#endif diff --git a/drivers/pst.c b/drivers/pst.c deleted file mode 100644 index d063ec9..0000000 --- a/drivers/pst.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -int openpty(int *amaster, int *aslave, char *name, - /*const struct termios*/ void *termp, - /*const struct winsize*/ void *winp) { - (void)name; - (void)termp; - (void) winp; - int fd[2]; - pipe(fd); // This depends upon that pipe will support read and write - // through the same fd. In reality this should not be the - // case. - *amaster = fd[0]; - *aslave = fd[1]; - return 0; -} diff --git a/drivers/pst.h b/drivers/pst.h deleted file mode 100644 index e8fdfaa..0000000 --- a/drivers/pst.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef PST_H -#define PST_H -#include "../fs/vfs.h" - -int openpty(int *amaster, int *aslave, char *name, /*const struct termios*/ void *termp, - /*const struct winsize*/ void *winp); -#endif diff --git a/drivers/rtl8139.c b/drivers/rtl8139.c deleted file mode 100644 index 3853eab..0000000 --- a/drivers/rtl8139.c +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define RBSTART 0x30 -#define CMD 0x37 -#define IMR 0x3C - -#define TSD0 0x10 // transmit status -#define TSAD0 0x20 // transmit start address - -struct PCI_DEVICE rtl8139; -uint8_t *device_buffer; - -uint8_t *send_buffers[4]; - -struct _INT_PACKET_HEADER { - uint8_t ROK : 1; - uint8_t FAE : 1; - uint8_t CRC : 1; - uint8_t LONG : 1; - uint8_t RUNT : 1; - uint8_t ISE : 1; - uint8_t reserved : 5; - uint8_t BAR : 1; - uint8_t PAM : 1; - uint8_t MAR : 1; -}; - -struct PACKET_HEADER { - union { - uint16_t raw; - struct _INT_PACKET_HEADER data; - }; -}; - -uint16_t current_packet_read = 0; - -void handle_packet(void) { - assert(sizeof(struct _INT_PACKET_HEADER) == sizeof(uint16_t)); - - uint16_t *buf = (uint16_t *)(device_buffer + current_packet_read); - struct PACKET_HEADER packet_header; - packet_header.raw = *buf; - assert(packet_header.data.ROK); - kprintf("packet_header.raw: %x\n", packet_header.raw); - uint16_t packet_length = *(buf + 1); - kprintf("packet_length: %x\n", packet_length); - - uint8_t packet_buffer[8192 + 16]; - if (current_packet_read + packet_length >= 8192 + 16) { - uint32_t first_run = ((uint8_t *)buf + (8192 + 16)) - device_buffer; - memcpy(packet_buffer, buf, first_run); - memcpy(packet_buffer, device_buffer, packet_length - first_run); - } else { - memcpy(packet_buffer, buf, packet_length); - } - - handle_ethernet((uint8_t *)packet_buffer + 4, packet_length); - - // Thanks to exscape - // https://github.com/exscape/exscapeOS/blob/master/src/kernel/net/rtl8139.c - // and the programmers guide - // https://www.cs.usfca.edu/~cruse/cs326f04/RTL8139_ProgrammersGuide.pdf I - // have no clue what this calculation, I can't find anything possibly relating - // to this in the manual, but it does work I guess. - current_packet_read = (current_packet_read + packet_length + 4 + 3) & (~3); - current_packet_read %= 8192 + 16; - outw(rtl8139.gen.base_mem_io + 0x38, current_packet_read - 0x10); -} - -__attribute__((interrupt)) void rtl8139_handler(void *regs) { - (void)regs; - uint16_t status = inw(rtl8139.gen.base_mem_io + 0x3e); - kprintf("status: %x\n", status); - - outw(rtl8139.gen.base_mem_io + 0x3E, 0x5); - if (status & (1 << 2)) { - kprintf("Packet sent\n"); - } - if (status & (1 << 0)) { - kprintf("Received packet\n"); - handle_packet(); - } - - EOI(0xB); -} - -int rtl8139_send_data(uint8_t *data, uint16_t data_size) { - const struct PCI_DEVICE *device = &rtl8139; - // FIXME: It should block or fail if there is too little space for the - // buffer - if (data_size > 0x1000) - return 0; - static int loop = 0; - if (loop > 3) { - loop = 0; - } - memcpy(send_buffers[loop], data, data_size); - outl(device->gen.base_mem_io + 0x20 + loop * 4, - (uint32_t)virtual_to_physical(send_buffers[loop], NULL)); - outl(device->gen.base_mem_io + 0x10 + loop * 4, data_size); - loop += 1; - return 1; -} - -void get_mac_address(uint8_t mac[6]) { - uint32_t base_address = rtl8139.gen.base_mem_io; - // Read the MAC address - uint64_t mac_address; - { - uint32_t low_mac = inl(base_address); - uint16_t high_mac = inw(base_address + 0x4); - mac_address = ((uint64_t)high_mac << 32) | low_mac; - } - kprintf("mac_address: %x\n", mac_address); - memcpy(mac, &mac_address, sizeof(uint8_t[6])); -} - -uint8_t rtl8139_get_transmit_status(uint32_t base_address) { - uint32_t status_register = inl(base_address + 0x3E); - if ((status_register >> 3) & 0x1) - kprintf("transmit error :(\n"); - uint8_t status = (status_register >> 2) & 0x1; - outl(base_address + 0x3E, 0x5); - return status; -} - -void rtl8139_init(void) { - if (!pci_populate_device_struct(0x10EC, 0x8139, &rtl8139)) { - kprintf("RTL8139 not found :(\n"); - return; - } - kprintf("RTL8139 found at bus: %x slot: %x\n", rtl8139.bus, rtl8139.slot); - - uint8_t header_type = (pci_config_read32(&rtl8139, 0, 0xC) >> 16) & 0xFF; - assert(0 == header_type); - - uint32_t base_address = rtl8139.gen.base_mem_io; - uint8_t interrupt_line = pci_get_interrupt_line(&rtl8139); - - // Enable bus mastering - uint32_t register1 = pci_config_read32(&rtl8139, 0, 0x4); - register1 |= (1 << 2); - pci_config_write32(&rtl8139, 0, 0x4, register1); - - // Turning on the device - outb(base_address + 0x52, 0x0); - - // Reset the device and clear the RX and TX buffers - outb(base_address + CMD, 0x10); - for (; 0 != (inb(base_address + CMD) & 0x10);) - ; - device_buffer = ksbrk(8192 + 16); - memset(device_buffer, 0, 8192 + 16); - // Setupt the recieve buffer - uint32_t rx_buffer = (uint32_t)virtual_to_physical(device_buffer, NULL); - outl(base_address + RBSTART, rx_buffer); - - // Set IMR + ISR - outw(base_address + IMR, (1 << 2) | (1 << 3) | (1 << 0)); - - // Set transmit and reciever enable - outb(base_address + 0x37, (1 << 2) | (1 << 3)); - - // Configure the recieve buffer - outl(base_address + 0x44, - 0xf); // 0xf is AB+AM+APM+AAP - - install_handler(rtl8139_handler, INT_32_INTERRUPT_GATE(0x0), - 0x20 + interrupt_line); - - // ksbrk() seems to have the magical ability of disabling interrupts? - // I have no fucking clue why that happens and it was a pain to debug. - for (int i = 0; i < 4; i++) - send_buffers[i] = ksbrk(0x1000); -} diff --git a/drivers/rtl8139.h b/drivers/rtl8139.h deleted file mode 100644 index 6e13fdd..0000000 --- a/drivers/rtl8139.h +++ /dev/null @@ -1,4 +0,0 @@ -#include -void get_mac_address(uint8_t mac[6]); -void rtl8139_init(void); -int rtl8139_send_data(uint8_t *data, uint16_t data_size); diff --git a/drivers/serial.c b/drivers/serial.c deleted file mode 100644 index 549d852..0000000 --- a/drivers/serial.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "cpu/io.h" - -#define PORT 0x3f8 // COM1 - -int serial_init(void) { - outb(PORT + 1, 0x00); // Disable all interrupts - outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) - outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud - outb(PORT + 1, 0x00); // (hi byte) - outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit - outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold - outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set - outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip - outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial - // returns same byte) - - // Check if serial is faulty (i.e: not same byte as sent) - if (inb(PORT + 0) != 0xAE) { - return 1; - } - - // If serial is not faulty set it in normal operation mode - // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) - outb(PORT + 4, 0x0F); - return 0; -} - -int is_transmit_empty() { return inb(PORT + 5) & 0x20; } - -void write_serial(char a) { - while (is_transmit_empty() == 0) - ; - - outb(PORT, a); -} diff --git a/drivers/serial.h b/drivers/serial.h deleted file mode 100644 index 327765b..0000000 --- a/drivers/serial.h +++ /dev/null @@ -1,2 +0,0 @@ -int serial_init(void); -void write_serial(char a); diff --git a/drivers/vbe.c b/drivers/vbe.c deleted file mode 100644 index c67b7b4..0000000 --- a/drivers/vbe.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include -#include -#include -#include - -uint8_t *framebuffer; -uint32_t framebuffer_physical; -uint32_t framebuffer_width; -uint32_t framebuffer_height; -uint64_t framebuffer_size; - -vfs_vm_object_t vbe_vm_object; - -#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit))) -#define min(_a, _b) (((_a) > (_b)) ? (_b) : (_a)) - -struct DISPLAY_INFO { - uint32_t width; - uint32_t height; - uint8_t bpp; -}; - -struct DISPLAY_INFO vbe_info; - -void display_driver_init(multiboot_info_t *mbi) { - assert(CHECK_FLAG(mbi->flags, 12)); - framebuffer_width = mbi->framebuffer_width; - framebuffer_height = mbi->framebuffer_height; - - uint32_t bits_pp = mbi->framebuffer_bpp; - uint32_t bytes_pp = (bits_pp / 8) + (8 - (bits_pp % 8)); - - framebuffer_size = bytes_pp * framebuffer_width * framebuffer_height; - - framebuffer_physical = mbi->framebuffer_addr; - framebuffer = - mmu_map_frames((void *)(uint32_t)mbi->framebuffer_addr, framebuffer_size); - - vbe_info.width = framebuffer_width; - vbe_info.height = framebuffer_height; - vbe_info.bpp = mbi->framebuffer_bpp; -} - -vfs_vm_object_t *vbe_get_vm_object(uint64_t length, uint64_t offset, - vfs_fd_t *fd) { - (void)fd; - (void)length; - (void)offset; - vbe_vm_object.size = framebuffer_size; - int n = (uintptr_t)align_page((void *)(uint32_t)framebuffer_size) / 0x1000; - vbe_vm_object.object = kmalloc(sizeof(void *) * n); - for (int i = 0; i < n; i++) { - vbe_vm_object.object[i] = (void *)framebuffer_physical + (i * 0x1000); - } - return &vbe_vm_object; -} - -int display_info_read(uint8_t *buffer, uint64_t offset, uint64_t len, - vfs_fd_t *fd) { - (void)offset; - int read_len = min(sizeof(struct DISPLAY_INFO), len); - memcpy(buffer, &vbe_info, read_len); - return read_len; -} - -void add_vbe_device(void) { - devfs_add_file("/vbe", NULL, NULL, vbe_get_vm_object, 1, 1, - FS_TYPE_BLOCK_DEVICE); - devfs_add_file("/display_info", display_info_read, NULL, NULL, 1, 0, - FS_TYPE_BLOCK_DEVICE); -} diff --git a/drivers/vbe.h b/drivers/vbe.h deleted file mode 100644 index 4df2221..0000000 --- a/drivers/vbe.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef VBE_H -#define VBE_H -#include -void display_driver_init(multiboot_info_t *mb); -void display_driver_cross(multiboot_info_t *mbi); -void add_vbe_device(void); -#endif // VBE_H diff --git a/elf.c b/elf.c deleted file mode 100644 index 7316a0c..0000000 --- a/elf.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void *load_elf_file(const char *f, uint32_t *ds) { - // ELFHeader *header = kmalloc(sizeof(ELFHeader)); - ELFHeader header; - int fd = vfs_open(f, O_RDONLY, 0); - if (fd < 0) { - return NULL; - } - - if (sizeof(header) != vfs_pread(fd, &header, sizeof(header), 0)) { - return NULL; - } - - if (0 != memcmp(header.e_ident, "\x7F\x45\x4C\x46" /* "\x7FELF" */, 4)) { - klog("Incorrect ELF signature", LOG_ERROR); - return NULL; - } - - if (0 > fd) { - return NULL; - } - Elf32_Phdr program_header; - assert(sizeof(program_header) == header.e_phentsize); - uint32_t header_offset = header.e_phoff; - uintptr_t end_of_code = 0; - for (int i = 0; i < header.e_phnum; - i++, header_offset += header.e_phentsize) { - if (0 >= - vfs_pread(fd, &program_header, sizeof(program_header), header_offset)) { - return NULL; - } - - // FIXME: Only one type is supported, which is 1(load). More should be - // added. - assert(1 == program_header.p_type); - - // 1. Clear p_memsz bytes at p_vaddr to 0.(We also allocate frames for - // that range) - uint32_t p_memsz = program_header.p_memsz; - uint32_t p_vaddr = program_header.p_vaddr; - - uint32_t pages_to_allocate = - (uint32_t)align_page((void *)(p_vaddr + p_memsz)); - pages_to_allocate -= p_vaddr - (p_vaddr % 0x1000); - pages_to_allocate /= 0x1000; - - mmu_allocate_region((void *)p_vaddr, pages_to_allocate * 0x1000, - MMU_FLAG_RW, NULL); - - flush_tlb(); - - uintptr_t e = program_header.p_vaddr + program_header.p_memsz; - if (e > end_of_code) - end_of_code = e; - - memset((void *)program_header.p_vaddr, 0, program_header.p_memsz); - - // 2. Copy p_filesz bytes from p_offset to p_vaddr - int rc = vfs_pread(fd, (void *)program_header.p_vaddr, - program_header.p_filesz, program_header.p_offset); - - assert(rc == (int)program_header.p_filesz); - } - *ds = end_of_code; - vfs_close(fd); - return (void *)header.e_entry; -} diff --git a/elf.h b/elf.h deleted file mode 100644 index 452ddbd..0000000 --- a/elf.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef ELF_H -#define ELF_H -#include -#include -#include -#include - -#define ET_NONE 0 // No file type -#define ET_REL 1 // Relocatable file -#define ET_EXEC 2 // Executable file -#define ET_DYN 3 // Shared object file -#define ET_CORE 4 // Core file -#define ET_LOPROC 0xff00 // Processor-specific -#define ET_HIPROC 0xffff // Processor-specific - -#define EM_NONE 0 // No machine -#define EM_M32 1 // AT&T WE 32100 -#define EM_SPARC 2 // SPARC -#define EM_386 3 // Intel 80386 -#define EM_68K 4 // Motorola 68000 -#define EM_88K 5 // Motorola 88000 -#define EM_860 7 // Intel 80860 -#define EM_MIPS 8 // MIPS RS3000 - -#define EV_NONE 0 // Invalid version -#define EV_CURRENT 1 // Current version - -#define ELF_EXECUTABLE (1 << 0) -#define ELF_WRITABLE (1 << 1) -#define ELF_READABLE (1 << 2) - -#define Elf32_Addr uint32_t // Unsigned program address -#define Elf32_Half uint16_t // Unsigned medium integer -#define Elf32_Off uint32_t // Unsigned file offset -#define Elf32_Sword uint32_t // Signed large integer -#define Elf32_Word uint32_t // Unsigned large integer - -#define ELF_EXEC (1 << 0) -#define ELF_WRITE (1 << 1) -#define ELF_READ (1 << 2) - -// ELF header -typedef struct { - unsigned char e_ident[16]; - Elf32_Half e_type; // Object file type (ET_*) - Elf32_Half e_machine; // Required architecture (EM_*) - Elf32_Word e_version; // Object file version (EV_*) - Elf32_Addr e_entry; // File entry point - Elf32_Off e_phoff; // Program header table's offset(bytes) - Elf32_Off e_shoff; // Section header table's offset(bytes) - Elf32_Word e_flags; - Elf32_Half e_ehsize; // ELF Header size - Elf32_Half - e_phentsize; // Size of program's header tables(all are the same size) - Elf32_Half e_phnum; // Amount of program headers - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} __attribute__((packed)) ELFHeader; - -// Section header -typedef struct { - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -enum ShT_Types { - SHT_NULL = 0, // Null section - SHT_PROGBITS = 1, // Program information - SHT_SYMTAB = 2, // Symbol table - SHT_STRTAB = 3, // String table - SHT_RELA = 4, // Relocation (w/ addend) - SHT_NOBITS = 8, // Not present in file - SHT_REL = 9, // Relocation (no addend) -}; - -// Program header -typedef struct { - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} __attribute__((packed)) Elf32_Phdr; - - -void *load_elf_file(const char *f, uint32_t *ds); -#endif diff --git a/fs/devfs.c b/fs/devfs.c deleted file mode 100644 index 14748a7..0000000 --- a/fs/devfs.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include -#include -#include - -devfs_file files[20]; -int num_files = 0; - -vfs_inode_t *devfs_add_file( - char *path, - int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), - int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), - vfs_vm_object_t *(get_vm_object)(uint64_t length, uint64_t offset, - vfs_fd_t *fd), - uint8_t has_data, uint8_t can_write, int type) { - files[num_files].name = copy_and_allocate_string(path); - - vfs_inode_t *i = kmalloc(sizeof(vfs_inode_t)); - files[num_files].inode = i; - i->type = type; - i->read = read; - i->write = write; - i->close = NULL; - i->get_vm_object = get_vm_object; - i->has_data = has_data; - i->is_open = 1; - i->can_write = can_write; - num_files++; - return i; -} - -vfs_inode_t *devfs_open(const char *file) { - for (int i = 0; i < num_files; i++) - if (isequal_n(files[i].name, file, strlen(files[i].name))) - return files[i].inode; - - return 0; -} - -int devfs_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - return fd->inode->read(buffer, offset, len, fd); -} - -int devfs_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - return fd->inode->write(buffer, offset, len, fd); -} - -vfs_vm_object_t *devfs_get_vm_object(uint64_t length, uint64_t offset, - vfs_fd_t *fd) { - return fd->inode->get_vm_object(length, offset, fd); -} - -int stdout_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - (void)offset; - (void)fd; - - int rc = len; - for (; len--;) - putc(*buffer++); - return rc; -} - -int serial_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - (void)offset; - (void)fd; - - int rc = len; - for (; len--;) - write_serial(*buffer++); - return rc; -} - -void add_serial(void) { - devfs_add_file("/serial", NULL, serial_write, NULL, 0, 1, - FS_TYPE_CHAR_DEVICE); -} - -void add_stdout(void) { - devfs_add_file("/stdout", NULL, stdout_write, NULL, 0, 1, - FS_TYPE_CHAR_DEVICE); -} - -vfs_inode_t *devfs_mount(void) { - vfs_inode_t *root = kmalloc_eternal(sizeof(vfs_inode_t)); - root->open = devfs_open; - root->read = devfs_read; - root->write = devfs_write; - root->close = NULL; - return root; -} diff --git a/fs/devfs.h b/fs/devfs.h deleted file mode 100644 index 23a499e..0000000 --- a/fs/devfs.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef DEVFS_H -#define DEVFS_H -#include -#include -#include - -typedef struct devfs_file { - char *name; - vfs_inode_t *inode; -} devfs_file; - -vfs_inode_t *devfs_mount(void); -vfs_inode_t *devfs_open(const char *file); -int devfs_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd); -int devfs_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd); -void add_stdout(void); -void add_serial(void); -vfs_inode_t *devfs_add_file( - char *path, - int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), - int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), - vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset, - vfs_fd_t *fd), - uint8_t has_data, uint8_t can_write, int type); - -#endif diff --git a/fs/ext2.c b/fs/ext2.c deleted file mode 100644 index bd0fb07..0000000 --- a/fs/ext2.c +++ /dev/null @@ -1,763 +0,0 @@ -#include -#include -#include -#include -#include - -#define EXT2_SUPERBLOCK_SECTOR 2 -#define EXT2_ROOT_INODE 2 - -#define BLOCKS_REQUIRED(_a, _b) ((_a) / (_b) + (((_a) % (_b)) != 0)) - -superblock_t *superblock; -uint32_t block_byte_size; -uint32_t inode_size; -uint32_t inodes_per_block; - -#define BLOCK_SIZE (block_byte_size) - -void ext2_close(vfs_fd_t *fd) { - return; // There is nothing to clear -} - -int read_inode(int inode_num, unsigned char *data, uint64_t size, - uint64_t offset, uint64_t *file_size); - -struct BLOCK_CACHE { - uint32_t block_num; - uint8_t block[1024]; -}; - -#define NUM_BLOCK_CACHE 30 -struct BLOCK_CACHE cache[NUM_BLOCK_CACHE] = {0}; -uint8_t last_taken_cache = 0; - -void cached_read_block(uint32_t block, void *address, size_t size, - size_t offset) { - int free_found = -1; - for (int i = 0; i < NUM_BLOCK_CACHE; i++) { - if (cache[i].block_num == block) { - memcpy(address, cache[i].block + offset, size); - return; - } - if (0 == cache[i].block_num) - free_found = i; - } - - if (-1 == free_found) { - free_found = last_taken_cache; - last_taken_cache++; - if (last_taken_cache >= NUM_BLOCK_CACHE) - last_taken_cache = 0; - } - - struct BLOCK_CACHE *c = &cache[free_found]; - c->block_num = block; - read_lba(block * block_byte_size / 512, c->block, 1024, 0); - return cached_read_block(block, address, size, offset); -} - -void ext2_read_block(uint32_t block, void *address, size_t size, - size_t offset) { - cached_read_block(block, address, size, offset); -} - -void ext2_write_block(uint32_t block, void *address, size_t size, - size_t offset) { - // Invalidate a old cache - for (int i = 0; i < NUM_BLOCK_CACHE; i++) { - if (cache[i].block_num == block) { - cache[i].block_num = 0; - break; - } - } - write_lba(block * block_byte_size / 512, address, size, offset); -} - -void write_group_descriptor(uint32_t group_index, bgdt_t *block_group) { - int starting_block = (1024 == block_byte_size) ? 2 : 1; - ext2_write_block(starting_block, block_group, sizeof(bgdt_t), - group_index * sizeof(bgdt_t)); -} - -void get_group_descriptor(uint32_t group_index, bgdt_t *block_group) { - int starting_block = (1024 == block_byte_size) ? 2 : 1; - ext2_read_block(starting_block, block_group, sizeof(bgdt_t), - group_index * sizeof(bgdt_t)); -} - -uint32_t num_block_groups(void) { - // Determining the Number of Block Groups - - // From the Superblock, extract the size of each block, the total - // number of inodes, the total number of blocks, the number of blocks - // per block group, and the number of inodes in each block group. From - // this information we can infer the number of block groups there are - // by: - - // Rounding up the total number of blocks divided by the number of - // blocks per block group - uint32_t num_blocks = superblock->num_blocks; - uint32_t num_blocks_in_group = superblock->num_blocks_in_group; - uint32_t b = num_blocks / num_blocks_in_group; - if (num_blocks % num_blocks_in_group != 0) - b++; - - // Rounding up the total number of inodes divided by the number of - // inodes per block group - uint32_t num_inodes = superblock->num_inodes; - uint32_t num_inodes_in_group = superblock->num_inodes_in_group; - uint32_t i = num_inodes / num_inodes_in_group; - if (num_inodes % num_inodes_in_group != 0) - i++; - // Both (and check them against each other) - assert(i == b); - return i; -} - -void ext2_block_containing_inode(uint32_t inode_index, uint32_t *block_index, - uint32_t *offset) { - assert(0 != inode_index); - bgdt_t block_group; - get_group_descriptor((inode_index - 1) / superblock->num_inodes_in_group, - &block_group); - - uint64_t full_offset = - ((inode_index - 1) % superblock->num_inodes_in_group) * inode_size; - *block_index = block_group.starting_inode_table + - (full_offset >> (superblock->block_size + 10)); - *offset = full_offset & (block_byte_size - 1); -} - -int ext2_last_inode_read = -1; -inode_t ext2_last_inode; - -void ext2_get_inode_header(int inode_index, inode_t *data) { - // Very simple cache. If the inode_index is a inode already read then - // just copy the old data. - if (ext2_last_inode_read == inode_index) { - memcpy(data, &ext2_last_inode, sizeof(inode_t)); - return; - } - uint32_t block_index; - uint32_t block_offset; - ext2_block_containing_inode(inode_index, &block_index, &block_offset); - - uint8_t mem_block[inode_size]; - ext2_read_block(block_index, mem_block, inode_size, block_offset); - - memcpy(data, mem_block, inode_size); - memcpy(&ext2_last_inode, mem_block, sizeof(inode_t)); - ext2_last_inode_read = inode_index; -} - -void ext2_write_inode(int inode_index, inode_t *data) { - if (ext2_last_inode_read == inode_index) - ext2_last_inode_read = -1; // Invalidate the cache - uint32_t block_index; - uint32_t block_offset; - ext2_block_containing_inode(inode_index, &block_index, &block_offset); - - uint8_t mem_block[inode_size]; - memcpy(mem_block, data, inode_size); - ext2_write_block(block_index, mem_block, inode_size, block_offset); -} - -int ext2_get_inode_in_directory(int dir_inode, char *file, - direntry_header_t *entry) { - // FIXME: Allocate sufficent size each time - unsigned char *data = kmalloc(block_byte_size * 5); - ASSERT_BUT_FIXME_PROPOGATE( - -1 != read_inode(dir_inode, data, block_byte_size * 5, 0, 0)); - - direntry_header_t *dir; - unsigned char *data_p = data; - for (; (dir = (direntry_header_t *)data_p)->inode; data_p += dir->size) { - if (0 == dir->size) - break; - if (0 == dir->name_length) - continue; - if (0 == - memcmp(data_p + sizeof(direntry_header_t), file, dir->name_length)) { - if (strlen(file) > dir->name_length) - continue; - if (entry) - memcpy(entry, data_p, sizeof(direntry_header_t)); - return dir->inode; - } - } - return 0; -} - -int ext2_read_dir(int dir_inode, unsigned char *buffer, size_t len, - size_t offset) { - unsigned char data[block_byte_size]; - read_inode(dir_inode, data, block_byte_size, 0, 0); - - direntry_header_t *dir; - struct dirent tmp_entry; - size_t n_dir = 0; - int rc = 0; - unsigned char *data_p = data; - for (; (dir = (direntry_header_t *)data_p)->inode && len > 0; - data_p += dir->size, n_dir++) { - if (0 == dir->size) - break; - if (0 == dir->name_length) - continue; - if (n_dir < (offset / sizeof(struct dirent))) - continue; - - memcpy(tmp_entry.d_name, data_p + sizeof(direntry_header_t), - dir->name_length); - tmp_entry.d_name[dir->name_length] = '\0'; - uint8_t *p = (uint8_t *)&tmp_entry; - size_t l = sizeof(struct dirent); - - l = (len < l) ? len : l; - memcpy(buffer, p, l); - len -= l; - rc += l; - } - return rc; -} - -uint32_t ext2_find_inode(const char *file) { - int cur_path_inode = EXT2_ROOT_INODE; - - if (*file == '/' && *(file + 1) == '\0') - return cur_path_inode; - - char *str = copy_and_allocate_string(file); - char *orig_str = str; - - char *start; - for (;;) { - int final = 0; - start = str + 1; - str++; - - for (; '/' != *str && '\0' != *str; str++) - ; - if ('\0' == *str) - final = 1; - - *str = '\0'; - - direntry_header_t a; - if (0 == (cur_path_inode = - ext2_get_inode_in_directory(cur_path_inode, start, &a))) { - kfree(orig_str); - return 0; - } - - if (final) - break; - - // The expected returned entry is a directory - if (TYPE_INDICATOR_DIRECTORY != a.type_indicator) { - kfree(orig_str); - kprintf("FAILED\n"); - return 0; - } - } - kfree(orig_str); - return cur_path_inode; -} - -uint32_t get_singly_block_index(uint32_t singly_block_ptr, uint32_t i) { - uint8_t block[block_byte_size]; - ext2_read_block(singly_block_ptr, block, block_byte_size, 0); - uint32_t index = *(uint32_t *)(block + (i * (32 / 8))); - return index; -} - -int get_block(inode_t *inode, uint32_t i) { - if (i < 12) - return inode->block_pointers[i]; - - i -= 12; - uint32_t singly_block_size = block_byte_size / (32 / 8); - uint32_t double_block_size = (singly_block_size * singly_block_size); - if (i < singly_block_size) { - return get_singly_block_index(inode->single_indirect_block_pointer, i); - } else if (i < double_block_size) { - i -= singly_block_size; - uint32_t singly_entry = get_singly_block_index( - inode->double_indirect_block_pointer, i / singly_block_size); - uint32_t offset_in_entry = i % singly_block_size; - int block = get_singly_block_index(singly_entry, offset_in_entry); - return block; - } - assert(0); - return 0; -} - -int get_free_block(int allocate) { - bgdt_t block_group; - uint8_t bitmap[BLOCK_SIZE]; - assert(0 < superblock->num_blocks_unallocated); - for (uint32_t g = 0; g < num_block_groups(); g++) { - get_group_descriptor(g, &block_group); - - if (block_group.num_unallocated_blocks_in_group == 0) { - kprintf("skip\n"); - continue; - } - - ext2_read_block(block_group.block_usage_bitmap, bitmap, BLOCK_SIZE, 0); - for (uint32_t i = 0; i < superblock->num_blocks_in_group; i++) { - if (!(bitmap[i >> 3] & (1 << (i % 8)))) { - if (allocate) { - bitmap[i >> 3] |= (1 << (i % 8)); - ext2_write_block(block_group.block_usage_bitmap, bitmap, BLOCK_SIZE, - 0); - block_group.num_unallocated_blocks_in_group--; - write_group_descriptor(g, &block_group); - superblock->num_blocks_unallocated--; - write_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE, - 0); - } - return i + g * superblock->num_blocks_in_group + 1; - } - } - } - return -1; -} - -int get_free_inode(int allocate) { - bgdt_t block_group; - assert(0 < superblock->num_inodes_unallocated); - for (uint32_t g = 0; g < num_block_groups(); g++) { - get_group_descriptor(g, &block_group); - - if (0 == block_group.num_unallocated_inodes_in_group) - continue; - - uint8_t bitmap[BLOCK_SIZE]; - ext2_read_block(block_group.inode_usage_bitmap, bitmap, BLOCK_SIZE, 0); - for (uint32_t i = 0; i < superblock->num_inodes_in_group; i++) { - if (!(bitmap[i / 8] & (1 << (i % 8)))) { - if (allocate) { - bitmap[i / 8] |= (1 << (i % 8)); - ext2_write_block(block_group.inode_usage_bitmap, bitmap, BLOCK_SIZE, - 0); - block_group.num_unallocated_inodes_in_group--; - write_group_descriptor(g, &block_group); - superblock->num_inodes_unallocated--; - write_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE, - 0); - } - return i + g * superblock->num_inodes_in_group + 1; - } - } - } - return -1; -} - -int write_inode(int inode_num, unsigned char *data, uint64_t size, - uint64_t offset, uint64_t *file_size, int append) { - (void)file_size; - uint8_t inode_buffer[inode_size]; - ext2_get_inode_header(inode_num, (inode_t *)inode_buffer); - inode_t *inode = (inode_t *)inode_buffer; - - uint64_t fsize = (uint64_t)(((uint64_t)inode->_upper_32size << 32) | - (uint64_t)inode->low_32size); - if (append) - offset = fsize; - - uint32_t block_start = offset / block_byte_size; - uint32_t block_offset = offset % block_byte_size; - - int num_blocks_used = inode->num_disk_sectors / (BLOCK_SIZE / SECTOR_SIZE); - - if (size + offset > fsize) - fsize = size + offset; - - int num_blocks_required = BLOCKS_REQUIRED(fsize, BLOCK_SIZE); - - for (int i = num_blocks_used; i < num_blocks_required; i++) { - if (i > 12) - assert(0); - int b = get_free_block(1 /*true*/); - assert(-1 != b); - inode->block_pointers[i] = b; - } - - inode->num_disk_sectors = num_blocks_required * (BLOCK_SIZE / SECTOR_SIZE); - - int bytes_written = 0; - for (int i = block_start; size; i++) { - uint32_t block = get_block(inode, i); - if (0 == block) { - kprintf("block_not_found\n"); - break; - } - - int write_len = ((size + block_offset) > block_byte_size) - ? (block_byte_size - block_offset) - : size; - ext2_write_block(block, data + bytes_written, write_len, block_offset); - block_offset = 0; - bytes_written += write_len; - size -= write_len; - } - inode->low_32size = fsize; - inode->_upper_32size = (fsize >> 32); - ext2_write_inode(inode_num, inode); - return bytes_written; -} - -int read_inode(int inode_num, unsigned char *data, uint64_t size, - uint64_t offset, uint64_t *file_size) { - // TODO: Fail if size is lower than the size of the file being read, and - // return the size of the file the callers is trying to read. - uint8_t inode_buffer[inode_size]; - ext2_get_inode_header(inode_num, (inode_t *)inode_buffer); - inode_t *inode = (inode_t *)inode_buffer; - - uint64_t fsize = (uint64_t)(((uint64_t)inode->_upper_32size << 32) | - (uint64_t)inode->low_32size); - - if (file_size) - *file_size = fsize; - - if (size > fsize - offset) - size -= ((size + offset) - fsize); - - if (size == 0) - return 0; - - if (offset > fsize) - return 0; - - uint32_t block_start = offset / block_byte_size; - uint32_t block_offset = offset % block_byte_size; - - int bytes_read = 0; - for (int i = block_start; size; i++) { - uint32_t block = get_block(inode, i); - if (0 == block) { - klog("Filesystem EXT2: Unable to find block", LOG_WARN); - return -1; - } - - int read_len = ((size + block_offset) > block_byte_size) - ? (block_byte_size - block_offset) - : size; - ext2_read_block(block, data + bytes_read, read_len, block_offset); - block_offset = 0; - bytes_read += read_len; - size -= read_len; - } - return bytes_read; -} - -size_t ext2_read_file_offset(const char *file, unsigned char *data, - uint64_t size, uint64_t offset, - uint64_t *file_size) { - // TODO: Fail if the file does not exist. - uint32_t inode = ext2_find_inode(file); - return read_inode(inode, data, size, offset, file_size); -} - -size_t ext2_read_file(const char *file, unsigned char *data, size_t size, - uint64_t *file_size) { - return ext2_read_file_offset(file, data, size, 0, file_size); -} - -int resolve_link(int inode_num) { - uint8_t tmp[inode_size]; - inode_t *inode = (inode_t *)tmp; - uint64_t inode_size = - (((uint64_t)inode->_upper_32size) << 32) & inode->low_32size; - assert(inode_size <= 60); - ext2_get_inode_header(inode_num, inode); - char *path = (char *)(tmp + (10 * 4)); - path--; - *path = '/'; - return ext2_find_inode(path); -} - -int ext2_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - uint64_t file_size; - int rc; - int inode_num = fd->inode->inode_num; - assert(fd->inode->type != FS_TYPE_DIRECTORY); - if (fd->inode->type == FS_TYPE_LINK) { - inode_num = resolve_link(inode_num); - } - rc = write_inode(inode_num, buffer, len, offset, &file_size, 0); - return rc; -} - -int ext2_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - uint64_t file_size; - int rc; - int inode_num = fd->inode->inode_num; - if (fd->inode->type == FS_TYPE_DIRECTORY) { - rc = ext2_read_dir(inode_num, buffer, len, offset); - return rc; - } - if (fd->inode->type == FS_TYPE_LINK) { - inode_num = resolve_link(inode_num); - } - rc = read_inode(inode_num, buffer, len, offset, &file_size); - return rc; -} - -int ext2_truncate(vfs_fd_t *fd, size_t length) { - // TODO: Blocks that are no longer used should be freed. - char inode_buffer[inode_size]; - inode_t *ext2_inode = (inode_t *)inode_buffer; - - ext2_get_inode_header(fd->inode->inode_num, ext2_inode); - - // FIXME: ftruncate should support 64 bit lengths - ext2_inode->_upper_32size = 0; - ext2_inode->low_32size = length; - - ext2_write_inode(fd->inode->inode_num, ext2_inode); - return 0; -} - -vfs_inode_t *ext2_open(const char *path) { - uint32_t inode_num = ext2_find_inode(path); - if (0 == inode_num) - return NULL; - - inode_t ext2_inode[inode_size]; - ext2_get_inode_header(inode_num, ext2_inode); - uint64_t file_size = - ((uint64_t)(ext2_inode->_upper_32size) << 32) | ext2_inode->low_32size; - - uint8_t type; - switch ((ext2_inode->types_permissions / 0x1000)) { - case 0xA: - type = FS_TYPE_LINK; - break; - case 0x4: - type = FS_TYPE_DIRECTORY; - break; - default: - type = FS_TYPE_FILE; - break; - } - - return vfs_create_inode(inode_num, type, 1 /*has_data*/, 1 /*can_write*/, - 1 /*is_open*/, NULL /*internal_object*/, file_size, - ext2_open, ext2_create_file, ext2_read, ext2_write, - ext2_close, ext2_create_directory, - NULL /*get_vm_object*/, ext2_truncate /*truncate*/); -} - -uint64_t end_of_last_entry_position(int dir_inode, uint64_t *entry_offset, - direntry_header_t *meta) { - // FIXME: Allocate sufficent size each time - unsigned char data[block_byte_size * 5]; - uint64_t file_size = 0; - read_inode(dir_inode, data, block_byte_size * 5, 0, &file_size); - assert(block_byte_size * 5 > file_size); - - direntry_header_t *dir; - unsigned char *data_p = data; - uint64_t pos = 0; - uint64_t prev = pos; - for (; pos < file_size && (dir = (direntry_header_t *)data_p)->size; - data_p += dir->size, prev = pos, pos += dir->size) - ; - if (entry_offset) - *entry_offset = prev; - if (meta) - memcpy(meta, ((char *)data) + prev, sizeof(direntry_header_t)); - return pos; -} - -void ext2_create_entry(int directory_inode, direntry_header_t entry_header, - const char *name) { - uint64_t entry_offset = 0; - direntry_header_t meta; - end_of_last_entry_position(directory_inode, &entry_offset, &meta); - - uint32_t padding_in_use = block_byte_size - entry_offset; - - // assert(padding_in_use == meta.size); - assert(padding_in_use >= - (sizeof(direntry_header_t) + entry_header.name_length)); - - // Modify the entry to have its real size - meta.size = sizeof(direntry_header_t) + meta.name_length; - meta.size += (4 - (meta.size % 4)); - write_inode(directory_inode, (unsigned char *)&meta, - sizeof(direntry_header_t), entry_offset, NULL, 0); - - // Create new entry - uint32_t new_entry_offset = entry_offset + meta.size; - entry_header.size = (sizeof(direntry_header_t) + entry_header.name_length); - entry_header.size += (4 - (entry_header.size % 4)); - - uint32_t length_till_next_block = 1024 - (new_entry_offset % 1024); - if (0 == length_till_next_block) - length_till_next_block = 1024; - assert(entry_header.size < length_till_next_block); - entry_header.size = length_till_next_block; - - uint8_t buffer[entry_header.size]; - memset(buffer, 0, entry_header.size); - memcpy(buffer, &entry_header, sizeof(entry_header)); - memcpy(buffer + sizeof(entry_header), name, entry_header.name_length); - write_inode(directory_inode, (unsigned char *)buffer, entry_header.size, - new_entry_offset, NULL, 0); -} - -int ext2_find_parent(char *path, uint32_t *parent_inode, char **filename) { - char *e = path; - for (; *e; e++) - ; - for (; *e != '/'; e--) - ; - *e = '\0'; - *filename = e + 1; - if (*path == '\0') { - *parent_inode = EXT2_ROOT_INODE; - return 1; - } else { - int r = ext2_find_inode(path); - if (0 == r) - return 0; - *parent_inode = r; - return 1; - } - return 0; -} - -int ext2_create_directory(const char *path, int mode) { - (void)mode; - // Check if the directory already exists - uint32_t inode_num = ext2_find_inode(path); - if (0 != inode_num) { - klog("ext2_create_directory: Directory already exists", LOG_WARN); - return inode_num; - } - - uint32_t parent_inode; - // Get the parent directory - char path_buffer[strlen(path) + 1]; - char *filename; - strcpy(path_buffer, path); - if (!ext2_find_parent(path_buffer, &parent_inode, &filename)) { - klog("ext2_create_file: Parent does not exist", LOG_WARN); - return -1; - } - - int new_file_inode = get_free_inode(1); - if (-1 == new_file_inode) { - klog("ext2_create_file: Unable to find free inode", LOG_WARN); - return -1; - } - assert(0 != new_file_inode); - - direntry_header_t entry_header; - entry_header.inode = new_file_inode; - entry_header.name_length = strlen(filename); - entry_header.type_indicator = TYPE_INDICATOR_DIRECTORY; - entry_header.size = sizeof(entry_header) + entry_header.name_length; - - ext2_create_entry(parent_inode, entry_header, filename); - // Create the inode header - uint8_t inode_buffer[inode_size]; - inode_t *new_inode = (inode_t *)inode_buffer; - memset(inode_buffer, 0, inode_size); - new_inode->types_permissions = DIRECTORY; - new_inode->num_hard_links = 2; // 2 since the directory references - // itself with the "." entry - ext2_write_inode(new_file_inode, new_inode); - - // Populate the new directory with "." and ".." - { - // "." - direntry_header_t child_entry_header; - child_entry_header.inode = new_file_inode; - child_entry_header.name_length = 1; - child_entry_header.type_indicator = TYPE_INDICATOR_DIRECTORY; - child_entry_header.size = sizeof(entry_header) + entry_header.name_length; - ext2_create_entry(new_file_inode, child_entry_header, "."); - // ".." - child_entry_header.inode = parent_inode; - child_entry_header.name_length = 2; - child_entry_header.type_indicator = TYPE_INDICATOR_DIRECTORY; - child_entry_header.size = sizeof(entry_header) + entry_header.name_length; - ext2_create_entry(new_file_inode, child_entry_header, ".."); - } - return new_file_inode; -} - -int ext2_create_file(const char *path, int mode) { - // Check if the file already exists - uint32_t inode_num = ext2_find_inode(path); - if (0 != inode_num) { - klog("ext2_create_file: File already exists", LOG_WARN); - return inode_num; - } - - uint32_t parent_inode; - // Get the parent directory - char path_buffer[strlen(path) + 1]; - char *filename; - strcpy(path_buffer, path); - if (!ext2_find_parent(path_buffer, &parent_inode, &filename)) { - klog("ext2_create_file: Parent does not exist", LOG_WARN); - return -1; - } - - int new_file_inode = get_free_inode(1); - if (-1 == new_file_inode) { - klog("ext2_create_file: Unable to find free inode", LOG_WARN); - return -1; - } - assert(0 != new_file_inode); - - direntry_header_t entry_header; - entry_header.inode = new_file_inode; - entry_header.name_length = strlen(filename); - entry_header.type_indicator = TYPE_INDICATOR_REGULAR; - entry_header.size = sizeof(entry_header) + entry_header.name_length; - - ext2_create_entry(parent_inode, entry_header, filename); - // Create the inode header - uint8_t inode_buffer[inode_size]; - inode_t *new_inode = (inode_t *)inode_buffer; - memset(inode_buffer, 0, inode_size); - new_inode->types_permissions = 0x8000; - new_inode->num_hard_links = 1; - ext2_write_inode(new_file_inode, new_inode); - return new_file_inode; -} - -vfs_inode_t *ext2_mount(void) { - parse_superblock(); - return vfs_create_inode(0 /*inode_num*/, 0 /*type*/, 0 /*has_data*/, - 0 /*can_write*/, 0 /*is_open*/, - NULL /*internal_object*/, 0 /*file_size*/, ext2_open, - ext2_create_file, ext2_read, ext2_write, ext2_close, - ext2_create_directory, NULL /*get_vm_object*/, - ext2_truncate /*truncate*/); -} - -void parse_superblock(void) { - superblock = ksbrk(2 * SECTOR_SIZE); - read_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE, 0); - block_byte_size = 1024 << superblock->block_size; - - if (0xEF53 != superblock->ext2_signature) { - klog("Incorrect ext2 signature in superblock.", LOG_ERROR); - for (;;) - ; // TODO: Fail properly - } - - if (1 <= superblock->major_version) - inode_size = ((ext_superblock_t *)superblock)->inode_size; - - inodes_per_block = block_byte_size / inode_size; -} diff --git a/fs/ext2.h b/fs/ext2.h deleted file mode 100644 index 3a2f800..0000000 --- a/fs/ext2.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef EXT2_H -#define EXT2_H -#include -#include -#include -#include - -typedef struct Superblock { - uint32_t num_inodes; - uint32_t num_blocks; - uint32_t num_blocks_reserved; - uint32_t num_blocks_unallocated; - uint32_t num_inodes_unallocated; - uint32_t superblock_block_num; - uint32_t block_size; - uint32_t fragment_size; - uint32_t num_blocks_in_group; - uint32_t num_fragments_in_group; - uint32_t num_inodes_in_group; - uint32_t last_mount; - uint32_t last_write; - uint16_t num_mounts_since_fsck; - uint16_t num_mounts_allowed; - uint16_t ext2_signature; // 0xEF53 - uint16_t fs_state; - uint16_t when_error; - uint16_t minor_version; - uint32_t last_fsck; - uint32_t interval_fsck; - uint32_t os_id; - uint32_t major_version; - uint16_t userid_reserved_blocks; - uint16_t groupid_reserved_blocks; -} __attribute__((packed)) superblock_t; - -typedef struct ExtendedSuperblock { - uint32_t num_inodes; - uint32_t num_blocks; - uint32_t num_blocks_reserved; - uint32_t num_blocks_unallocated; - uint32_t num_inodes_unallocated; - uint32_t superblock_block_num; - uint32_t block_size; - uint32_t fragment_size; - uint32_t num_blocks_group; - uint32_t num_fragments_group; - uint32_t num_inodes_group; - uint32_t last_mount; - uint32_t last_write; - uint16_t num_mounts_since_fsck; - uint16_t num_mounts_allowed; - uint16_t ext2_signature; // 0xEF53 - uint16_t fs_state; - uint16_t when_error; - uint16_t minor_version; - uint32_t last_fsck; - uint32_t interval_fsck; - uint32_t os_id; - uint32_t major_version; - uint16_t userid_reserved_blocks; - uint16_t groupid_reserved_blocks; - uint32_t pad; - uint16_t inode_size; -} __attribute__((packed)) ext_superblock_t; - -typedef struct BlockGroupDescriptorTable { - uint32_t block_usage_bitmap; - uint32_t inode_usage_bitmap; - uint32_t starting_inode_table; - uint16_t num_unallocated_blocks_in_group; - uint16_t num_unallocated_inodes_in_group; - uint16_t num_directories_group; -} __attribute__((packed)) bgdt_t; - -typedef struct INode { - uint16_t types_permissions; - uint16_t user_id; - uint32_t low_32size; - uint32_t last_access_time; - uint32_t creation_time; - uint32_t last_modification_time; - uint32_t deletion_time; - uint16_t group_id; - uint16_t num_hard_links; - uint32_t num_disk_sectors; - uint32_t flags; - uint32_t os_specific; - uint32_t block_pointers[12]; - uint32_t single_indirect_block_pointer; - uint32_t double_indirect_block_pointer; - uint32_t triple_indirect_block_pointer; - uint32_t gen_number; - uint32_t _extended_attribute_block; - uint32_t _upper_32size; - uint32_t address_fragment; - uint32_t os_specific2; -} __attribute__((packed)) inode_t; - -// 0 Unknown type -// 1 Regular file -// 2 Directory -// 3 Character device -// 4 Block device -// 5 FIFO -// 6 Socket -// 7 Symbolic link (soft link) -#define TYPE_INDICATOR_UNKOWN 0 -#define TYPE_INDICATOR_REGULAR 1 -#define TYPE_INDICATOR_DIRECTORY 2 -#define TYPE_INDICATOR_CHARACTER_DEVICE 3 -#define TYPE_INDICATOR_BLOCK_DEVICE 4 -#define TYPE_INDICATOR_FIFO 5 -#define TYPE_INDICATOR_SOCKET 6 -#define TYPE_INDICATOR_SOFT_LINK 7 - -#define FIFO 0x1000 -#define CHARACTER_DEVICE 0x2000 -#define DIRECTORY 0x4000 -#define BLOCK_DEVICE 0x6000 -#define REGULAR_FILE 0x8000 -#define SYMBOLIC_LINK 0xA000 -#define UNIX_SOCKET 0xC000 - -typedef struct DirectoryEntryHeader { - uint32_t inode; - uint16_t size; - uint8_t name_length; - uint8_t type_indicator; -} __attribute__((packed)) direntry_header_t; - -int ext2_create_file(const char *path, int mode); -vfs_inode_t *ext2_mount(void); -void parse_superblock(void); -size_t ext2_read_file_offset(const char *file, unsigned char *data, - uint64_t size, uint64_t offset, - uint64_t *file_size); -size_t ext2_read_file(const char *file, unsigned char *data, size_t size, - uint64_t *file_size); -int ext2_create_directory(const char *path, int mode); -#endif diff --git a/fs/fifo.c b/fs/fifo.c deleted file mode 100644 index d515ed7..0000000 --- a/fs/fifo.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "fifo.h" -#include - -#define STARTING_SIZE 4096 - -void fifo_close(vfs_fd_t *fd) { - // TODO: Implement - (void)fd; - return; -} - -int fifo_object_write(uint8_t *buffer, uint64_t offset, uint64_t len, - FIFO_FILE *file) { - (void)offset; - file->has_data = 1; - if (file->write_len + len >= file->buffer_len) { - file->can_write = 0; - return -EAGAIN; - } - memcpy(file->buffer + file->write_len, buffer, len); - file->write_len += len; - return len; -} - -int fifo_object_read(uint8_t *buffer, uint64_t offset, uint64_t len, - FIFO_FILE *file) { - (void)offset; - if (file->write_len == 0) { - file->has_data = 0; - return -EAGAIN; - } - - if (len == 0) - return 0; - - file->can_write = 1; - if (len > file->write_len) - len = file->write_len; - - memcpy(buffer, file->buffer, len); - // Shift bufffer to the left - memcpy(file->buffer, file->buffer + len, file->buffer_len - len); - - file->write_len -= len; - if (file->write_len == 0) { - file->has_data = 0; - } - return len; -} - -FIFO_FILE *create_fifo_object(void) { - FIFO_FILE *n = kmalloc(sizeof(FIFO_FILE)); - n->buffer = kmalloc(STARTING_SIZE); - n->buffer_len = STARTING_SIZE; - n->write_len = 0; - return n; -} - -int create_fifo(void) { - - int fd_n = 0; - for (; get_current_task()->file_descriptors[fd_n]; fd_n++) - ; - - vfs_fd_t *fd = kmalloc(sizeof(vfs_fd_t)); - fd->flags = O_RDWR | O_NONBLOCK; - get_current_task()->file_descriptors[fd_n] = fd; - fd->inode = kmalloc(sizeof(vfs_inode_t)); - - fd->inode->internal_object = (void *)create_fifo_object(); - fd->inode->open = NULL; - fd->inode->read = fifo_read; - fd->inode->write = fifo_write; - fd->inode->close = fifo_close; - fd->inode->get_vm_object = NULL; - fd->inode->is_open = 1; - - return fd_n; -} - -int fifo_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - (void)offset; - FIFO_FILE *file = (FIFO_FILE *)fd->inode->internal_object; - int rc = fifo_object_write(buffer, offset, len, file); - fd->inode->has_data = file->has_data; - fd->inode->can_write = file->can_write; - return rc; -} - -int fifo_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - FIFO_FILE *file = (FIFO_FILE *)fd->inode->internal_object; - file->is_blocking = !(fd->flags & O_NONBLOCK); - int rc = fifo_object_read(buffer, offset, len, file); - fd->inode->has_data = file->has_data; - fd->inode->can_write = file->can_write; - return rc; -} diff --git a/fs/fifo.h b/fs/fifo.h deleted file mode 100644 index 1ba7168..0000000 --- a/fs/fifo.h +++ /dev/null @@ -1,27 +0,0 @@ -typedef struct S_FIFO_FILE FIFO_FILE; -#ifndef FIFO_H -#define FIFO_H -#include "vfs.h" -#include -#include - -struct S_FIFO_FILE { - char *buffer; - uint64_t buffer_len; - uint64_t write_len; - uint8_t is_blocking; - uint8_t has_data; - uint8_t can_write; -}; - -int create_fifo(void); -FIFO_FILE *create_fifo_object(void); -int fifo_object_write(uint8_t *buffer, uint64_t offset, uint64_t len, - FIFO_FILE *file); -int fifo_object_read(uint8_t *buffer, uint64_t offset, uint64_t len, - FIFO_FILE *file); -int fifo_write(uint8_t *buffer, uint64_t offset, uint64_t len, - vfs_fd_t *fd); -int fifo_read(uint8_t *buffer, uint64_t offset, uint64_t len, - vfs_fd_t *fd); -#endif diff --git a/fs/shm.c b/fs/shm.c deleted file mode 100644 index 4d5f2ab..0000000 --- a/fs/shm.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -HashMap *shared_memory_objects; - -void shm_init(void) { shared_memory_objects = hashmap_create(10); } - -int shm_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - vfs_vm_object_t *p = fd->inode->internal_object; - - if (offset > p->size) - return -EFBIG; - - if (offset + len > p->size) - len = p->size - offset; - - memcpy((void *)((uintptr_t)((uintptr_t)p->virtual_object + offset)), buffer, - len); - return len; -} - -int shm_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - vfs_vm_object_t *p = fd->inode->internal_object; - - if (offset > p->size) - return -EFBIG; - - if (offset + len > p->size) - len = p->size - offset; - - memcpy((void *)buffer, - (void *)((uintptr_t)((uintptr_t)p->virtual_object + offset)), len); - return len; -} - -vfs_vm_object_t *shm_get_vm_object(uint64_t length, uint64_t offset, - vfs_fd_t *fd) { - (void)length; - (void)offset; - vfs_vm_object_t *p = fd->inode->internal_object; - return p; -} - -int shm_ftruncate(vfs_fd_t *fd, size_t length) { - vfs_vm_object_t *p = fd->inode->internal_object; - p->size = length; - p->virtual_object = ksbrk(length); - int n = (uintptr_t)align_page((void *)(uint32_t)length) / 0x1000; - p->object = kmalloc(sizeof(void *) * n); - for (int i = 0; i < n; i++) - p->object[i] = - (void *)(get_page(p->virtual_object + (i * 0x1000), NULL, 0, 0)->frame * - 0x1000); - return 0; -} - -int shm_open(const char *name, int oflag, mode_t mode) { - // Try to find or create a new shared memory object. - vfs_vm_object_t *internal_object = - hashmap_get_entry(shared_memory_objects, name); - if (!internal_object) { - // if (!(oflag & O_CREAT)) - // return -EMFILE; - internal_object = kmalloc(sizeof(vfs_vm_object_t)); - internal_object->object = NULL; - internal_object->size = 0; - hashmap_add_entry(shared_memory_objects, name, internal_object, NULL, 0); - } - - vfs_inode_t *inode = vfs_create_inode( - 0 /*inode_num*/, 0 /*type*/, 1 /*has_data*/, 1 /*can_write*/, - 1 /*is_open*/, internal_object, 0 /*file_size*/, NULL /*open*/, - NULL /*create_file*/, shm_read, shm_write, NULL /*close*/, - NULL /*create_directory*/, shm_get_vm_object, shm_ftruncate); - - vfs_fd_t *fd_ptr; - int fd = vfs_create_fd(oflag, mode, inode, &fd_ptr); - if (-1 == fd) { - kfree(inode); - return -EMFILE; - } - return fd; -} - -int shm_unlink(const char *name) { - (void)name; - return 0; -} diff --git a/fs/shm.h b/fs/shm.h deleted file mode 100644 index fbbdb5c..0000000 --- a/fs/shm.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SHM_H -#define SHM_H -#include -#include - -typedef int mode_t; - -void shm_init(void); -int shm_open(const char *name, int oflag, mode_t mode); -int shm_unlink(const char *name); -int ftruncate(int fildes, uint64_t length); - -#endif diff --git a/fs/tmpfs.c b/fs/tmpfs.c deleted file mode 100644 index a9a3c1f..0000000 --- a/fs/tmpfs.c +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -void tmp_close(vfs_fd_t *fd) { - fd->inode->is_open = 0; - ((tmp_inode *)fd->inode->internal_object)->read_inode->is_open = 0; -} - -int tmp_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - tmp_inode *calling_file = fd->inode->internal_object; - tmp_inode *child_file = calling_file->read_inode->internal_object; - if (child_file->is_closed) - return -EPIPE; - - int rc = fifo_object_write(buffer, offset, len, child_file->fifo); - calling_file->read_inode->has_data = child_file->fifo->has_data; - fd->inode->can_write = child_file->fifo->can_write; - return rc; -} - -int tmp_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - tmp_inode *calling_file = fd->inode->internal_object; - tmp_inode *child_file = calling_file->read_inode->internal_object; - if (calling_file->is_closed) - return -EPIPE; - - int rc = fifo_object_read(buffer, offset, len, calling_file->fifo); - fd->inode->has_data = calling_file->fifo->has_data; - calling_file->read_inode->can_write = child_file->fifo->can_write; - return rc; -} - -void dual_pipe(int fd[2]) { - for (int i = 0; i < 2; i++) { - tmp_inode *pipe = kmalloc(sizeof(tmp_inode)); - pipe->fifo = create_fifo_object(); - - int has_data = 0; - int can_write = 1; - int is_open = 1; - void *internal_object = pipe; - vfs_inode_t *inode = vfs_create_inode( - 0 /*inode_num*/, 0 /*type*/, has_data, can_write, is_open, - internal_object, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/, - tmp_read, tmp_write, tmp_close, NULL /*create_directory*/, - NULL /*get_vm_object*/, NULL /*truncate*/); - assert(inode); - - vfs_fd_t *fd_ptr; - fd[i] = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, inode, &fd_ptr); - assert(-1 != fd[i]); - } - vfs_inode_t *f_inode = get_current_task()->file_descriptors[fd[0]]->inode; - vfs_inode_t *s_inode = get_current_task()->file_descriptors[fd[1]]->inode; - tmp_inode *f_pipe = f_inode->internal_object; - tmp_inode *s_pipe = s_inode->internal_object; - f_pipe->read_inode = s_inode; - s_pipe->read_inode = f_inode; - f_pipe->is_closed = 0; - s_pipe->is_closed = 0; -} - -void pipe(int fd[2]) { - for (int i = 0; i < 2; i++) { - tmp_inode *pipe = kmalloc(sizeof(tmp_inode)); - pipe->fifo = create_fifo_object(); - - int has_data = 0; - int can_write = 1; - int is_open = 1; - void *internal_object = pipe; - vfs_inode_t *inode = vfs_create_inode( - 0 /*inode_num*/, 0 /*type*/, has_data, can_write, is_open, - internal_object, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/, - tmp_read, tmp_write, tmp_close, NULL /*create_directory*/, - NULL /*get_vm_object*/, NULL/*truncate*/); - assert(inode); - - vfs_fd_t *fd_ptr; - fd[i] = vfs_create_fd(O_RDWR, 0, inode, &fd_ptr); - assert(-1 != fd[i]); - } - vfs_inode_t *f_inode = get_current_task()->file_descriptors[fd[0]]->inode; - vfs_inode_t *s_inode = get_current_task()->file_descriptors[fd[1]]->inode; - tmp_inode *f_pipe = f_inode->internal_object; - tmp_inode *s_pipe = s_inode->internal_object; - f_pipe->read_inode = s_inode; - s_pipe->read_inode = f_inode; - f_pipe->is_closed = 0; - s_pipe->is_closed = 0; -} diff --git a/fs/tmpfs.h b/fs/tmpfs.h deleted file mode 100644 index 4052bd5..0000000 --- a/fs/tmpfs.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef TMP_H -#define TMP_H -#include -#include - -#define TMP_BUFFER_SIZE (1024 * 10) - -typedef struct { - FIFO_FILE *fifo; - uint8_t is_closed; - vfs_inode_t *read_inode; -} tmp_inode; - -void pipe(int fd[2]); -void dual_pipe(int fd[2]); -#endif diff --git a/fs/vfs.c b/fs/vfs.c deleted file mode 100644 index 0c616a2..0000000 --- a/fs/vfs.c +++ /dev/null @@ -1,318 +0,0 @@ -#include -#include -#include -#include -#include - -vfs_inode_t *root_dir; -vfs_mounts_t mounts[10]; -int num_mounts = 0; - -vfs_fd_t *get_vfs_fd(int fd) { - if (fd >= 100) { - klog("get_vfs_fd(): Tried to get out of range fd", LOG_WARN); - dump_backtrace(12); - return NULL; - } - if (fd < 0) { - klog("get_vfs_fd(): Tried to get out of range fd", LOG_WARN); - dump_backtrace(12); - return NULL; - } - return get_current_task()->file_descriptors[fd]; -} - -vfs_inode_t *vfs_create_inode( - int inode_num, int type, uint8_t has_data, uint8_t can_write, - uint8_t is_open, void *internal_object, uint64_t file_size, - vfs_inode_t *(*open)(const char *path), - int (*create_file)(const char *path, int mode), - int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), - int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), - void (*close)(vfs_fd_t *fd), - int (*create_directory)(const char *path, int mode), - vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset, - vfs_fd_t *fd), - int (*truncate)(vfs_fd_t *fd, size_t length)) { - vfs_inode_t *r = kmalloc(sizeof(inode_t)); - r->inode_num = inode_num; - r->type = type; - r->has_data = has_data; - r->can_write = can_write; - r->is_open = is_open; - r->internal_object = internal_object; - r->file_size = file_size; - r->open = open; - r->create_file = create_file; - r->read = read; - r->write = write; - r->close = close; - r->create_directory = create_directory; - r->get_vm_object = get_vm_object; - r->truncate = truncate; - return r; -} - -int vfs_create_fd(int flags, int mode, vfs_inode_t *inode, vfs_fd_t **fd) { - process_t *p = (process_t *)get_current_task(); - int i; - for (i = 0; i < 100; i++) - if (!p->file_descriptors[i]) - break; - if (p->file_descriptors[i]) - return -1; - vfs_fd_t *r = kmalloc(sizeof(vfs_fd_t)); - r->flags = flags; - r->mode = mode; - r->inode = inode; - r->reference_count = 1; - p->file_descriptors[i] = r; - if (fd) - *fd = r; - return i; -} - -int vfs_create_file(const char *file) { - vfs_mounts_t *file_mount = 0; - int length = 0; - for (int i = 0; i < num_mounts; i++) { - int path_len = strlen(mounts[i].path); - if (path_len <= length) - continue; - - if (isequal_n(mounts[i].path, file, path_len)) { - length = path_len; - file_mount = &mounts[i]; - } - } - if (1 != length) - file += length; - - if (!file_mount) { - kprintf("vfs_internal_open could not find mounted path for file : %s\n", - file); - return 0; - } - // ext2_create_file("/etc/oscreated", 0); - assert(file_mount->local_root->create_file); - kprintf("Creating a file\n"); - return file_mount->local_root->create_file(file, 0); -} - -vfs_inode_t *vfs_internal_open(const char *file) { - vfs_mounts_t *file_mount = 0; - int length = 0; - for (int i = 0; i < num_mounts; i++) { - int path_len = strlen(mounts[i].path); - if (path_len <= length) - continue; - - if (isequal_n(mounts[i].path, file, path_len)) { - length = path_len; - file_mount = &mounts[i]; - } - } - if (1 != length) - file += length; - - if (!file_mount) { - kprintf("vfs_internal_open could not find mounted path for file : %s\n", - file); - return NULL; - } - - vfs_inode_t *ret = file_mount->local_root->open(file); - return ret; -} - -char *vfs_clean_path(const char *path, char *resolved_path) { - // char *const clean = kmalloc(strlen(path) + 1); - char *clean = resolved_path; - int prev_slash = 0; - char *ptr = clean; - for (; *path; path++) { - if (prev_slash && '/' == *path) { - continue; - } - prev_slash = ('/' == *path); - *ptr = *path; - ptr++; - } - *ptr = '\0'; - return clean; -} - -char *vfs_resolve_path(const char *file, char *resolved_path) { - if ('/' == *file) { - return vfs_clean_path(file, resolved_path); - } - const char *cwd = get_current_task()->current_working_directory; - size_t l = strlen(cwd); - assert(l > 0); - assert('/' == cwd[l - 1]); - // char *r = kmalloc(l + strlen(file) + 1); - char r[256]; - strcpy(r, cwd); - strcat(r, file); - char *final = vfs_clean_path(r, resolved_path); - // kfree(r); - return final; -} - -int vfs_mkdir(const char *path, int mode) { - vfs_mounts_t *file_mount = 0; - int length = 0; - for (int i = 0; i < num_mounts; i++) { - int path_len = strlen(mounts[i].path); - if (path_len <= length) - continue; - - if (isequal_n(mounts[i].path, path, path_len)) { - length = path_len; - file_mount = &mounts[i]; - } - } - if (1 != length) - path += length; - - if (!file_mount) { - kprintf("vfs_internal_open could not find mounted path for file : %s\n", - path); - return 0; - } - assert(file_mount->local_root->create_directory); - // TODO: Error checking, don't just assume it is fine - file_mount->local_root->create_directory(path, mode); - return 0; -} - -int vfs_open(const char *file, int flags, int mode) { - char resolved_path[256] = {0}; - vfs_resolve_path(file, resolved_path); - vfs_inode_t *inode = vfs_internal_open(resolved_path); - if (0 == inode) { - if (mode & O_CREAT) { - if (vfs_create_file(resolved_path)) { - klog("VFS: File created", LOG_NOTE); - return vfs_open(file, flags, mode); - } - klog("VFS: Could not create file", LOG_WARN); - } - return -ENOENT; - } - if (inode->type == FS_TYPE_UNIX_SOCKET) { - return uds_open(resolved_path); - } - - return vfs_create_fd(flags, mode, inode, NULL); -} - -int vfs_close(int fd) { - vfs_fd_t *fd_ptr = get_vfs_fd(fd); - if (NULL == fd_ptr) { - return -1; - } - assert(0 < fd_ptr->reference_count); - // Remove process reference - fd_ptr->reference_count--; - get_current_task()->file_descriptors[fd] = 0; - // If no references left then free the contents - if (0 == fd_ptr->reference_count) { - if (fd_ptr->inode->close) - fd_ptr->inode->close(fd_ptr); - - kfree(fd_ptr); - } - return 0; -} - -int raw_vfs_pread(vfs_fd_t *vfs_fd, void *buf, uint64_t count, - uint64_t offset) { - if (!(vfs_fd->flags & O_READ)) - return -EBADF; - return vfs_fd->inode->read(buf, offset, count, vfs_fd); -} - -int vfs_pread(int fd, void *buf, uint64_t count, uint64_t offset) { - if (fd >= 100) { - kprintf("EBADF : %x\n", fd); - return -EBADF; - } - if (fd < 0) { - dump_backtrace(12); - kprintf("EBADF : %x\n", fd); - return -EBADF; - } - vfs_fd_t *vfs_fd = get_current_task()->file_descriptors[fd]; - if (!vfs_fd) - return -EBADF; - int rc = raw_vfs_pread(vfs_fd, buf, count, offset); - if (-EAGAIN == rc && count > 0) { - if (!(vfs_fd->flags & O_NONBLOCK)) { - struct pollfd fds; - fds.fd = fd; - fds.events = POLLIN; - fds.revents = 0; - poll(&fds, 1, 0); - return vfs_pread(fd, buf, count, offset); - } - } - return rc; -} - -int raw_vfs_pwrite(vfs_fd_t *vfs_fd, void *buf, uint64_t count, - uint64_t offset) { - assert(vfs_fd); - assert(vfs_fd->inode); - assert(vfs_fd->inode->write); - return vfs_fd->inode->write(buf, offset, count, vfs_fd); -} - -int vfs_pwrite(int fd, void *buf, uint64_t count, uint64_t offset) { - vfs_fd_t *vfs_fd = get_vfs_fd(fd); - if (!vfs_fd) - return -EBADF; - if (!(vfs_fd->flags & O_WRITE)) { - return -EBADF; - } - return raw_vfs_pwrite(vfs_fd, buf, count, offset); -} - -vfs_vm_object_t *vfs_get_vm_object(int fd, uint64_t length, uint64_t offset) { - vfs_fd_t *vfs_fd = get_vfs_fd(fd); - if (!vfs_fd) - return NULL; - vfs_vm_object_t *r = vfs_fd->inode->get_vm_object(length, offset, vfs_fd); - return r; -} - -int vfs_dup2(int org_fd, int new_fd) { - get_current_task()->file_descriptors[new_fd] = - get_current_task()->file_descriptors[org_fd]; - get_current_task()->file_descriptors[new_fd]->reference_count++; - return 1; -} - -int vfs_ftruncate(int fd, size_t length) { - vfs_fd_t *fd_ptr = get_vfs_fd(fd); - if (!fd_ptr) - return -EBADF; - if (!(fd_ptr->flags & O_READ)) - return -EINVAL; - vfs_inode_t *inode = fd_ptr->inode; - if (!inode) - return -EINVAL; - if (!inode->truncate) - return -EINVAL; - - return inode->truncate(fd_ptr, length); -} - -void vfs_mount(char *path, vfs_inode_t *local_root) { - int len = strlen(path); - mounts[num_mounts].path = kmalloc_eternal(len + 1); - memcpy(mounts[num_mounts].path, path, len); - mounts[num_mounts].path[len] = '\0'; - mounts[num_mounts].local_root = local_root; - num_mounts++; -} diff --git a/fs/vfs.h b/fs/vfs.h deleted file mode 100644 index f8a4b19..0000000 --- a/fs/vfs.h +++ /dev/null @@ -1,100 +0,0 @@ -typedef struct vfs_fd vfs_fd_t; -typedef struct vfs_inode vfs_inode_t; -typedef struct vfs_vm_object vfs_vm_object_t; -typedef struct vfs_mounts vfs_mounts_t; -#ifndef VFS_H -#define VFS_H -#include -#include -#include -#include -#include - -// FIXME: Is there some standard value for this? -#define O_NONBLOCK (1 << 0) -#define O_READ (1 << 1) -#define O_WRITE (1 << 2) -#define O_CREAT (1 << 3) -#define O_RDONLY O_READ -#define O_WRONLY O_WRITE -#define O_RDWR (O_WRITE | O_READ) - -#define FS_TYPE_FILE 0 -#define FS_TYPE_UNIX_SOCKET 1 -#define FS_TYPE_CHAR_DEVICE 2 -#define FS_TYPE_BLOCK_DEVICE 3 -#define FS_TYPE_DIRECTORY 4 -#define FS_TYPE_LINK 7 - -struct vfs_vm_object { - void *virtual_object; - void **object; - uint64_t size; -}; - -struct vfs_mounts { - char *path; - vfs_inode_t *local_root; -}; - -struct dirent { - unsigned int d_ino; // File serial number. - char d_name[PATH_MAX]; // Filename string of entry. -}; - -struct vfs_fd { - size_t offset; - int flags; - int mode; - int reference_count; // Number of usages of this file descriptor, - // once it reaches zero then the contents can - // be freed. - vfs_inode_t *inode; -}; - -struct vfs_inode { - int inode_num; - int type; - uint8_t has_data; - uint8_t can_write; - uint8_t is_open; - void *internal_object; - uint64_t file_size; - vfs_inode_t *(*open)(const char *path); - int (*create_file)(const char *path, int mode); - int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd); - int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd); - void (*close)(vfs_fd_t *fd); - int (*create_directory)(const char *path, int mode); - vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset, - vfs_fd_t *fd); - int (*truncate)(vfs_fd_t *fd, size_t length); -}; - -int vfs_close(int fd); -vfs_fd_t *get_vfs_fd(int fd); -int vfs_open(const char *file, int flags, int mode); -void vfs_mount(char *path, vfs_inode_t *local_root); -int vfs_pwrite(int fd, void *buf, uint64_t count, uint64_t offset); -int raw_vfs_pwrite(vfs_fd_t *vfs_fd, void *buf, uint64_t count, - uint64_t offset); -int vfs_pread(int fd, void *buf, uint64_t count, uint64_t offset); -vfs_vm_object_t *vfs_get_vm_object(int fd, uint64_t length, uint64_t offset); -int vfs_dup2(int org_fd, int new_fd); -vfs_inode_t *vfs_internal_open(const char *file); -int vfs_mkdir(const char *path, int mode); -int vfs_create_fd(int flags, int mode, vfs_inode_t *inode, vfs_fd_t **fd); -int vfs_ftruncate(int fd, size_t length); -vfs_inode_t *vfs_create_inode( - int inode_num, int type, uint8_t has_data, uint8_t can_write, - uint8_t is_open, void *internal_object, uint64_t file_size, - vfs_inode_t *(*open)(const char *path), - int (*create_file)(const char *path, int mode), - int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), - int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), - void (*close)(vfs_fd_t *fd), - int (*create_directory)(const char *path, int mode), - vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset, - vfs_fd_t *fd), - int (*truncate)(vfs_fd_t *fd, size_t length)); -#endif diff --git a/halts.c b/halts.c deleted file mode 100644 index 821299d..0000000 --- a/halts.c +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include -#include - -int create_disconnect_inode_halt(vfs_inode_t *inode) { - volatile process_t *p = get_current_task(); - int i; - for (i = 0; i < 100; i++) - if (!p->disconnect_halt_inode[i]) - break; - - if (p->disconnect_halt_inode[i]) - return -1; - - p->disconnect_halt_inode[i] = inode; - - return i; -} - -int create_disconnect_fdhalt(vfs_fd_t *fd) { - assert(fd); - return create_disconnect_inode_halt(fd->inode); -} - -int create_read_inode_halt(vfs_inode_t *inode) { - volatile process_t *p = get_current_task(); - int i; - for (i = 0; i < 100; i++) - if (!p->read_halt_inode[i]) - break; - - if (p->read_halt_inode[i]) - return -1; - - p->read_halt_inode[i] = inode; - - return i; -} - -int create_read_fdhalt(vfs_fd_t *fd) { - assert(fd); - return create_read_inode_halt(fd->inode); -} - -int create_write_inode_halt(vfs_inode_t *inode) { - volatile process_t *p = get_current_task(); - int i; - for (i = 0; i < 100; i++) - if (!p->write_halt_inode[i]) - break; - - if (p->write_halt_inode[i]) - return -1; - - p->write_halt_inode[i] = inode; - - return i; -} - -int create_write_fdhalt(vfs_fd_t *fd) { - return create_write_inode_halt(fd->inode); -} - -void unset_read_fdhalt(int i) { get_current_task()->read_halt_inode[i] = NULL; } - -void unset_write_fdhalt(int i) { - get_current_task()->write_halt_inode[i] = NULL; -} - -void unset_disconnect_fdhalt(int i) { - get_current_task()->disconnect_halt_inode[i] = NULL; -} - -int isset_fdhalt(vfs_inode_t *read_halts[], vfs_inode_t *write_halts[], - vfs_inode_t *disconnect_halts[]) { - int blocked = 0; - for (int i = 0; i < 100; i++) { - if (!read_halts[i]) - continue; - if (read_halts[i]->has_data) { - return 0; - } - blocked = 1; - } - for (int i = 0; i < 100; i++) { - if (!write_halts[i]) - continue; - if (write_halts[i]->can_write) { - return 0; - } - blocked = 1; - } - for (int i = 0; i < 100; i++) { - if (!disconnect_halts[i]) - continue; - if (!disconnect_halts[i]->is_open) { - return 0; - } - blocked = 1; - } - return blocked; -} diff --git a/halts.h b/halts.h deleted file mode 100644 index bd71673..0000000 --- a/halts.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HALTS_H -#define HALTS_H -#include -#include - -typedef struct { - uint8_t *ptr; - uint8_t active; -} halt_t; - -int create_read_fdhalt(vfs_fd_t *fd); -int create_read_inode_halt(vfs_inode_t *inode); -void unset_read_fdhalt(int i); -int create_write_fdhalt(vfs_fd_t *fd); -int create_write_inode_halt(vfs_inode_t *inode); -void unset_write_fdhalt(int i); -int create_disconnect_fdhalt(vfs_fd_t *fd); -void unset_disconnect_fdhalt(int i); -int isset_fdhalt(vfs_inode_t *read_halts[], vfs_inode_t *write_halts[], - vfs_inode_t *disconnect_halts[]); -#endif diff --git a/hashmap/hashmap.c b/hashmap/hashmap.c deleted file mode 100644 index 2eeef98..0000000 --- a/hashmap/hashmap.c +++ /dev/null @@ -1,212 +0,0 @@ -// -// Copyright (C) 2022 by Anton Kling -// -// SPDX-License-Identifier: BSD-2-Clause -// -/* - * HashMap - * ------- - * This hashmap works by creating a array of linked lists and associating - * the "key" with a specific entry in the array. This is done through a - * hash. Once the linked list is found it goes through it until it finds - * a entry that has the "key" provided. - * - * Changing the hashing function - * ----------------------------- - * The default hashing function in this library is a custom made - * one that can be found in hash.c. But it should be possible to use any - * other hashing algorithm should you want to as long as it uses these - * types: - * uint32_t hash_function(uint8_t*, size_t) - * - * The hashing algorithm can be changed via changing the "hash_function" - * pointer in the HashMap structure. - * - * Important to note that the hashing function shall not be changed - * after having added entries to the hashmap as the key to linked list - * pairing will change. - */ -#include "hashmap.h" - -#include -#include -#include -#include - -#define CONSTANT 0x031b5515 - -uint32_t mix(uint32_t x) { - x ^= CONSTANT; - x ^= (x << 13); - x ^= (x >> 7); - x ^= (x << 17); - return x; -} - -uint32_t hash(const uint8_t *data, size_t len) { - uint32_t hash = 0; - for (; len;) { - uint32_t value = 0; - uint8_t read_len = (sizeof(uint32_t) < len) ? sizeof(uint32_t) : len; - memcpy(&value, data, read_len); - hash ^= mix(value); - data += read_len; - len -= read_len; - } - return hash; -} - -char *copy_c_string(const char *str) { - char *ret_string; - size_t len = strlen(str); - ret_string = kmalloc(len + 1); - if (!ret_string) - return NULL; - memcpy(ret_string, str, len); - ret_string[len] = '\0'; - return ret_string; -} - -uint32_t limit_hash(HashMap *m, uint32_t hash) { return hash % m->size; } - -void free_linkedlist_entry(LinkedList *entry) { - if (entry->key_allocated) { - // If the key is allocated by the hashmap library then it owns the - // key and can safley discard the const qualifier and override its - // contents - kfree((char *)entry->key); - } - kfree(entry); -} - -LinkedList *get_linkedlist_entry(LinkedList *list, const char *key, - LinkedList **prev) { - if (prev) - *prev = NULL; - for (; list; list = list->next) { - const char *str1 = key; - const char *str2 = list->key; - for (; *str1 && *str2; str1++, str2++) - if (*str1 != *str2) - break; - if (*str1 == *str2) - return list; - if (prev) - prev = &list; - } - return NULL; -} - -void *get_linkedlist_value(LinkedList *list, const char *key) { - LinkedList *entry = get_linkedlist_entry(list, key, NULL); - if (!entry) - return NULL; - return entry->value; -} - -uint32_t find_index(HashMap *m, const char *key) { - return limit_hash(m, m->hash_function((uint8_t *)key, strlen(key))); -} - -int hashmap_add_entry(HashMap *m, const char *key, void *value, - void (*upon_deletion)(const char *, void *), - int do_not_allocate_key) { - // Create the entry - LinkedList *entry = kmalloc(sizeof(LinkedList)); - if (!entry) - return 0; - - entry->key_allocated = !do_not_allocate_key; - if (do_not_allocate_key) { - entry->key = key; - } else { - if (!(entry->key = copy_c_string(key))) - return 0; - } - entry->value = value; - entry->next = NULL; - entry->upon_deletion = upon_deletion; - - // Add the new entry to the list. - uint32_t index = find_index(m, key); - LinkedList **list_pointer = &m->entries[index]; - for (; *list_pointer;) - list_pointer = &(*list_pointer)->next; - - *list_pointer = entry; - m->num_entries++; - return 1; -} - -void *hashmap_get_entry(HashMap *m, const char *key) { - uint32_t index = find_index(m, key); - if (!m->entries[index]) - return NULL; - return get_linkedlist_value(m->entries[index], key); -} - -int hashmap_delete_entry(HashMap *m, const char *key) { - LinkedList *list = m->entries[find_index(m, key)]; - if (!list) - return 0; - LinkedList **prev = NULL; - LinkedList *entry = get_linkedlist_entry(list, key, prev); - if (!entry) - return 0; - if (!prev) - prev = &m->entries[find_index(m, key)]; - - if (entry->upon_deletion) - entry->upon_deletion(entry->key, entry->value); - - LinkedList *next = entry->next; - free_linkedlist_entry(entry); - if (*prev != entry) - (*prev)->next = next; - else - *prev = NULL; - - // Redo the delete process incase there are multiple - // entires that have the same key. - hashmap_delete_entry(m, key); - m->num_entries--; - return 1; -} - -void hashmap_free(HashMap *m) { - for (int i = 0; i < m->size; i++) { - if (!m->entries[i]) - continue; - LinkedList *list = m->entries[i]; - for (; list;) { - if (list->upon_deletion) - list->upon_deletion(list->key, list->value); - LinkedList *old = list; - list = list->next; - free_linkedlist_entry(old); - } - } - kfree(m->entries); - kfree(m); -} - -HashMap *hashmap_create(size_t size) { - HashMap *m = kmalloc(sizeof(HashMap)); - if (!m) - return NULL; - - m->size = size; - m->num_entries = 0; - - // Create a array of pointers to linkedlists but don't create them - // yet. - m->entries = kcalloc(size, sizeof(LinkedList **)); - if (!m->entries) - return NULL; - - for (size_t i = 0; i < m->size; i++) - m->entries[i] = NULL; - - m->hash_function = hash; - return m; -} diff --git a/hashmap/hashmap.h b/hashmap/hashmap.h deleted file mode 100644 index 40f146a..0000000 --- a/hashmap/hashmap.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (C) 2022 by Anton Kling -// -// SPDX-License-Identifier: BSD-2-Clause -// -#ifndef HASHMAP_H -#define HASHMAP_H -#include -#include - -typedef struct LinkedList { - const char *key; - int key_allocated; - void *value; - void (*upon_deletion)(const char *, void *); - struct LinkedList *next; -} LinkedList; - -typedef struct HashMap { - LinkedList **entries; - size_t size; - size_t num_entries; - uint32_t (*hash_function)(const uint8_t *data, size_t len); -} HashMap; - -HashMap *hashmap_create(size_t size); -void hashmap_free(HashMap *m); - -// hashmap_add_entry() -// ------------------- -// This function adds a entry to the hashmap. The "key" passed to the -// hashmap will be allocated by default unless (do_not_allocate_key) is -// set to 1. -int hashmap_add_entry(HashMap *m, const char *key, void *value, - void (*upon_deletion)(const char *, void *), - int do_not_allocate_key); -void *hashmap_get_entry(HashMap *m, const char *key); -int hashmap_delete_entry(HashMap *m, const char *key); -#endif diff --git a/includes/defs.h b/includes/defs.h deleted file mode 100644 index 3a373b3..0000000 --- a/includes/defs.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef DEFS_H -#define DEFS_H -#define BYTE unsigned char -#define BYTEPTR BYTE* -#endif diff --git a/includes/math.h b/includes/math.h deleted file mode 100644 index 19fc595..0000000 --- a/includes/math.h +++ /dev/null @@ -1,2 +0,0 @@ -int min(int a, int b); -int max(int a, int b); diff --git a/includes/mmu.h b/includes/mmu.h deleted file mode 100644 index 1df337d..0000000 --- a/includes/mmu.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef PAGING_H -#define PAGING_H -#include "kmalloc.h" -#include - -typedef uint8_t mmu_flags; - -#define MMU_FLAG_RW (1 << 0) -#define MMU_FLAG_KERNEL (1 << 1) - -void *next_page(void *a); -void *align_page(void *a); - -typedef struct Page { - uint32_t present : 1; - uint32_t rw : 1; - uint32_t user : 1; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t unused : 7; - uint32_t frame : 20; -} __attribute__((packed)) Page; - -typedef struct PageTable { - Page pages[1024]; -} __attribute__((packed)) PageTable; - -typedef struct PageDirectory { - PageTable *tables[1024]; - uint32_t physical_tables[1024]; - uint32_t physical_address; -} PageDirectory; - -int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags, PageDirectory *pd); -void mmu_allocate_shared_kernel_region(void *rc, size_t n); -void *mmu_find_unallocated_virtual_range(void *addr, size_t length); -void mmu_remove_virtual_physical_address_mapping(void *ptr, size_t length); -void mmu_free_address_range(void *ptr, size_t length); -void mmu_map_directories(void *dst, PageDirectory *d, void *src, - PageDirectory *s, size_t length); -uint32_t mmu_get_number_of_allocated_frames(void); -void *mmu_map_frames(void *ptr, size_t s); -void mmu_map_physical(void *dst, PageDirectory *d, void *physical, - size_t length); -void mmu_free_pages(void *a, uint32_t n); - -void flush_tlb(void); -void paging_init(void); -PageDirectory *get_active_pagedirectory(void); -void move_stack(uint32_t new_stack_address, uint32_t size); -void switch_page_directory(PageDirectory *directory); -void *allocate_frame(Page *page, int rw, int is_kernel); -PageDirectory *clone_directory(PageDirectory *original); -void *virtual_to_physical(void *address, PageDirectory *directory); -void *is_valid_userpointer(const void *const p, size_t s); -void *is_valid_user_c_string(const char *ptr, size_t *size); -void *ksbrk(size_t s); - -Page *get_page(void *ptr, PageDirectory *directory, int create_new_page, - int set_user); -#endif diff --git a/includes/signal.h b/includes/signal.h deleted file mode 100644 index 3de9998..0000000 --- a/includes/signal.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SIGNAL_H -#define SIGNAL_H -#include -#define SIGHUP 0 -#define SIGINT 1 -#define SIGWINCH 2 -#define SIGQUIT 3 -#define SIG_IGN 4 -typedef int pid_t; -typedef int uid_t; -typedef int sigset_t; - -union sigval { - int sival_int; // Integer signal value. - void *sival_ptr; // Pointer signal value. -}; - -struct siginfo { - int si_signo; // Signal number. - int si_code; // Signal code. - int si_errno; // If non-zero, an errno value associated with - // this signal, as described in . - pid_t si_pid; // Sending process ID. - uid_t si_uid; // Real user ID of sending process. - void *si_addr; // Address of faulting instruction. - int si_status; // Exit value or signal. - long si_band; // Band event for SIGPOLL. - union sigval si_value; // Signal value. -}; - -typedef struct siginfo siginfo_t; - -int kill(pid_t pid, int sig); - -struct sigaction { - void (*sa_handler)(int); // Pointer to a signal-catching function or one of - // the macros SIG_IGN or SIG_DFL. - sigset_t sa_mask; // Additional set of signals to be blocked during execution - // of signal-catching function. - int sa_flags; // Special flags to affect behavior of signal. - void (*sa_sigaction)(int, siginfo_t *, - void *); // Pointer to a signal-catching function. -}; - -int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); -#endif // SIGNAL_H diff --git a/includes/sys/types.h b/includes/sys/types.h deleted file mode 100644 index 1ccbf63..0000000 --- a/includes/sys/types.h +++ /dev/null @@ -1,2 +0,0 @@ -typedef int time_t; -typedef int pid_t; diff --git a/init/kernel.c b/init/kernel.c deleted file mode 100644 index 8c0f70c..0000000 --- a/init/kernel.c +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__linux__) -#error "You are not using a cross-compiler." -#endif - -#if !defined(__i386__) -#error "This OS needs to be compiled with a ix86-elf compiler" -#endif - -uint32_t inital_esp; -uintptr_t data_end; - -void kernel_main(uint32_t kernel_end, unsigned long magic, unsigned long addr, - uint32_t inital_stack) { - data_end = kernel_end; - inital_esp = inital_stack; - - asm("cli"); - kprintf("If you see this then the serial driver works :D.\n"); - assert(magic == MULTIBOOT_BOOTLOADER_MAGIC); - - paging_init(); - klog("Paging Initalized", LOG_SUCCESS); - multiboot_info_t *mb = - mmu_map_frames((multiboot_info_t *)addr, sizeof(multiboot_info_t)); - - gdt_init(); - klog("GDT Initalized", LOG_SUCCESS); - - idt_init(); - klog("IDT Initalized", LOG_SUCCESS); - - syscalls_init(); - klog("Syscalls Initalized", LOG_SUCCESS); - - pit_install(); - set_pit_count(2000); - klog("PIT driver installed", LOG_SUCCESS); - - ata_init(); - klog("ATA Initalized", LOG_SUCCESS); - - tasking_init(); - klog("Tasking Initalized", LOG_SUCCESS); - - install_mouse(); - klog("PS2 Mouse driver installed", LOG_SUCCESS); - - install_keyboard(); - klog("PS2 Keyboard driver installed", LOG_SUCCESS); - - vfs_mount("/", ext2_mount()); - vfs_mount("/dev", devfs_mount()); - add_stdout(); - add_serial(); - add_random_devices(); - shm_init(); - - setup_random(); - - add_keyboard(); - add_mouse(); - rtl8139_init(); - - display_driver_init(mb); - add_vbe_device(); - int pid; - if (0 == (pid = fork())) { - char *argv[] = {"/init", NULL}; - if (0 == exec("/init", argv)) { - kprintf("exec() failed\n"); - } - } - for (;;) - ; -} diff --git a/isodir/boot/grub/grub.cfg b/isodir/boot/grub/grub.cfg deleted file mode 100644 index b2f8404..0000000 --- a/isodir/boot/grub/grub.cfg +++ /dev/null @@ -1,3 +0,0 @@ -menuentry "myos" { - multiboot /boot/myos.bin -} diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..5098944 --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,33 @@ +CC="i686-sb-gcc" +AS="i686-sb-as" +OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o scalls/ppoll.o scalls/ftruncate.o kubsan.o scalls/mmap.o drivers/serial.o scalls/accept.o scalls/bind.o scalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o scalls/shm.o elf.o ksbrk.o sched/scheduler.o scalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o scalls/msleep.o scalls/uptime.o scalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o scalls/recvfrom.o math.o scalls/sendto.o signal.o scalls/kill.o scalls/sigaction.o +CFLAGS = -O2 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. +INCLUDE=-I./includes/ -I./libc/include/ + +all: myos.iso + +%.o: %.c + $(CC) $(INCLUDE) -c -o $@ $< $(CFLAGS) + +%.o: %.s + $(AS) $< -o $@ + +myos.bin: $(OBJ) + $(CC) $(INCLUDE) -shared -T linker.ld -o myos.bin -ffreestanding -nostdlib $(CFLAGS) $^ -lgcc + +debug: + qemu-system-i386 -no-reboot -no-shutdown -serial file:./serial.log -hda ext2.img -m 1G -cdrom myos.iso -s -S & + gdb -x .gdbinit + +nk: + qemu-system-i386 -d int -netdev user,id=n0,hostfwd=udp:127.0.0.1:6001-:6000 -device rtl8139,netdev=n0 -no-reboot -no-shutdown -serial file:./serial.log -hda ext2.img -m 1G -cdrom myos.iso -s + +run: + qemu-system-i386 -enable-kvm -netdev user,id=n0,hostfwd=udp:127.0.0.1:6001-:6000 -device rtl8139,netdev=n0 -object filter-dump,id=id,netdev=n0,file=netout -d int -no-reboot -no-shutdown -chardev stdio,id=char0,logfile=serial.log,signal=off -serial chardev:char0 -hda ext2.img -m 1G -cdrom myos.iso -s + +myos.iso: myos.bin + cp myos.bin isodir/boot + grub-mkrescue -o myos.iso isodir + +clean: + rm myos.bin myos.iso $(OBJ) diff --git a/kernel/arch/i386/boot.s b/kernel/arch/i386/boot.s new file mode 100644 index 0000000..61bbfbb --- /dev/null +++ b/kernel/arch/i386/boot.s @@ -0,0 +1,128 @@ +.set ALIGN, 1<<0 +.set MEMINFO, 1<<1 +.set VIDEO_MODE, 1<<2 +.set FLAGS, VIDEO_MODE|ALIGN | MEMINFO +.set MAGIC, 0x1BADB002 +.set CHECKSUM, -(MAGIC + FLAGS) + +#.section .multiboot +.align 16, 0 +.section .multiboot.data, "aw" + .align 4 + .long MAGIC + .long FLAGS + .long CHECKSUM + # unused(padding) + .long 0,0,0,0,0 + # Video mode + .long 0 # Linear graphics + .long 0 # Preferred width + .long 0 # Preferred height + .long 32 # Preferred pixel depth + +# Allocate the initial stack. +.section .bootstrap_stack, "aw", @nobits +stack_bottom: +.skip 16384 # 16 KiB +stack_top: + +.global boot_page_directory +.global boot_page_table1 +.section .bss, "aw", @nobits + .align 4096 +boot_page_directory: + .skip 4096 +boot_page_table1: + .skip 4096 + +.section .multiboot.text, "a" +.global _start +.extern _kernel_end +.type _start, @function +# Kernel entry +_start: + # edi contains the buffer we wish to modify + movl $(boot_page_table1 - 0xC0000000), %edi + + # for loop + movl $0, %esi + movl $1024, %ecx +1: + # esi = address + # If we are in kernel range jump to "label 2" + cmpl $_kernel_start, %esi + jl 2f + + # If we are past the kernel jump to the final stage + # "label 3" + cmpl $(_kernel_end - 0xC0000000), %esi + jge 3f + +2: + # Add permission to the pages + movl %esi, %edx + orl $0x003, %edx + movl %edx, (%edi) + + # Size of page is 4096 bytes. + addl $4096, %esi + # Size of entries in boot_page_table1 is 4 bytes. + addl $4, %edi + # Loop to the next entry if we haven't finished. + loop 1b + +3: + # Map the page table to both virtual addresses 0x00000000 and 0xC0000000. + movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0 + movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4 + + # Set cr3 to the address of the boot_page_directory. + movl $(boot_page_directory - 0xC0000000), %ecx + movl %ecx, %cr3 + + # Enable paging + movl %cr0, %ecx + orl $0x80000000, %ecx + movl %ecx, %cr0 + + # Jump to higher half with an absolute jump. + lea 4f, %ecx + jmp *%ecx + +.size _start, . - _start + +.section .text + +4: + # At this point, paging is fully set up and enabled. + + # Unmap the identity mapping as it is now unnecessary. + movl $0, boot_page_directory + 0 + + # Reload crc3 to force a TLB flush so the changes to take effect. + movl %cr3, %ecx + movl %ecx, %cr3 + + # Set up the stack. + mov $stack_top, %esp + + # Reset EFLAGS. + pushl $0 + popf + + pushl %esp + + /* Push the pointer to the Multiboot information structure. */ + pushl %ebx + /* Push the magic value. */ + pushl %eax + + mov $_kernel_end, %eax + pushl %eax + # Enter the high-level kernel. + call kernel_main + + # Infinite loop if the system has nothing more to do. + cli +1: hlt + jmp 1b diff --git a/kernel/arch/i386/mmu.c b/kernel/arch/i386/mmu.c new file mode 100644 index 0000000..ccfe894 --- /dev/null +++ b/kernel/arch/i386/mmu.c @@ -0,0 +1,565 @@ +#include +#include +#include +#include + +#define INDEX_FROM_BIT(a) (a / (32)) +#define OFFSET_FROM_BIT(a) (a % (32)) +#define PAGE_SIZE ((uintptr_t)0x1000) + +#define PAGE_ALLOCATE 1 +#define PAGE_NO_ALLOCATE 0 + +PageDirectory *kernel_directory; +PageDirectory real_kernel_directory; +PageDirectory *active_directory = 0; + +#define END_OF_MEMORY 0x8000000 * 15 +const uint32_t num_of_frames = END_OF_MEMORY / PAGE_SIZE; +uint32_t frames[END_OF_MEMORY / PAGE_SIZE] = {0}; +uint32_t num_allocated_frames = 0; + +#define KERNEL_START 0xc0000000 +extern uintptr_t data_end; + +void write_to_frame(uint32_t frame_address, uint8_t on); + +void *ksbrk(size_t s) { + uintptr_t rc = (uintptr_t)align_page((void *)data_end); + data_end += s; + data_end = (uintptr_t)align_page((void *)data_end); + + if (!get_active_pagedirectory()) { + // If there is no active pagedirectory we + // just assume that the memory is + // already mapped. + return (void *)rc; + } + // Determine whether we are approaching a unallocated table + int table_index = 1 + (rc / (1024 * 0x1000)); + if (!active_directory->tables[table_index]) { + uint32_t physical; + active_directory->tables[table_index] = (PageTable *)0xDEADBEEF; + active_directory->tables[table_index] = + (PageTable *)ksbrk_physical(sizeof(PageTable), (void **)&physical); + memset(active_directory->tables[table_index], 0, sizeof(PageTable)); + active_directory->physical_tables[table_index] = (uint32_t)physical | 0x3; + + kernel_directory->tables[table_index] = + active_directory->tables[table_index]; + kernel_directory->physical_tables[table_index] = + active_directory->physical_tables[table_index]; + return ksbrk(s); + } + mmu_allocate_shared_kernel_region((void *)rc, (data_end - (uintptr_t)rc)); + assert(((uintptr_t)rc % PAGE_SIZE) == 0); + memset((void *)rc, 0x00, s); + + return (void *)rc; +} + +void *ksbrk_physical(size_t s, void **physical) { + void *r = ksbrk(s); + if (physical) { + *physical = (void *)virtual_to_physical(r, 0); + } + return r; +} + +uint32_t mmu_get_number_of_allocated_frames(void) { + return num_allocated_frames; +} + +Page *get_page(void *ptr, PageDirectory *directory, int create_new_page, + int set_user) { + uintptr_t address = (uintptr_t)ptr; + if (!directory) + directory = get_active_pagedirectory(); + address /= 0x1000; + + uint32_t table_index = address / 1024; + if (!directory->tables[table_index]) { + if (!create_new_page) + return 0; + + uint32_t physical; + directory->tables[table_index] = + (PageTable *)ksbrk_physical(sizeof(PageTable), (void **)&physical); + memset(directory->tables[table_index], 0, sizeof(PageTable)); + directory->physical_tables[table_index] = + (uint32_t)physical | ((set_user) ? 0x7 : 0x3); + + if (!set_user) { + kernel_directory->tables[table_index] = directory->tables[table_index]; + kernel_directory->physical_tables[table_index] = + directory->physical_tables[table_index]; + } + } + Page *p = &directory->tables[table_index]->pages[address % 1024]; + if (create_new_page) { + p->present = 0; + } + return &directory->tables[table_index]->pages[address % 1024]; +} + +void mmu_free_pages(void *a, uint32_t n) { + for (; n > 0; n--) { + Page *p = get_page(a, NULL, PAGE_NO_ALLOCATE, 0); + p->present = 0; + write_to_frame(p->frame * 0x1000, 0); + a += 0x1000; + } +} + +void *next_page(void *ptr) { + uintptr_t a = (uintptr_t)ptr; + return (void *)(a + (PAGE_SIZE - ((uint32_t)a & (PAGE_SIZE - 1)))); +} + +void *align_page(void *a) { + if ((uintptr_t)a & (PAGE_SIZE - 1)) + return next_page(a); + + return a; +} + +void flush_tlb(void) { + asm volatile("\ + mov %cr3, %eax;\ + mov %eax, %cr3"); +} + +uint32_t first_free_frame(void) { + for (uint32_t i = 1; i < INDEX_FROM_BIT(num_of_frames); i++) { + if (frames[i] == 0xFFFFFFFF) + continue; + + for (uint32_t c = 0; c < 32; c++) + if (!(frames[i] & ((uint32_t)1 << c))) + return i * 32 + c; + } + + kprintf("ERROR Num frames: %x\n", mmu_get_number_of_allocated_frames()); + klog("No free frames, uh oh.", LOG_ERROR); + assert(0); + return 0; +} + +void write_to_frame(uint32_t frame_address, uint8_t on) { + uint32_t frame = frame_address / 0x1000; + assert(INDEX_FROM_BIT(frame) < sizeof(frames) / sizeof(frames[0])); + if (on) { + num_allocated_frames++; + frames[INDEX_FROM_BIT(frame)] |= ((uint32_t)0x1 << OFFSET_FROM_BIT(frame)); + return; + } + num_allocated_frames--; + frames[INDEX_FROM_BIT(frame)] &= ~((uint32_t)0x1 << OFFSET_FROM_BIT(frame)); +} + +PageDirectory *get_active_pagedirectory(void) { return active_directory; } + +PageTable *clone_table(uint32_t src_index, PageDirectory *src_directory, + uint32_t *physical_address) { + PageTable *new_table = + ksbrk_physical(sizeof(PageTable), (void **)physical_address); + PageTable *src = src_directory->tables[src_index]; + + // Copy all the pages + for (uint16_t i = 0; i < 1024; i++) { + if (!src->pages[i].present) { + new_table->pages[i].present = 0; + continue; + } + uint32_t frame_address = first_free_frame(); + write_to_frame(frame_address * 0x1000, 1); + new_table->pages[i].frame = frame_address; + + new_table->pages[i].present |= src->pages[i].present; + new_table->pages[i].rw |= src->pages[i].rw; + new_table->pages[i].user |= src->pages[i].user; + new_table->pages[i].accessed |= src->pages[i].accessed; + new_table->pages[i].dirty |= src->pages[i].dirty; + } + + // Now copy all of the data to the new table. This is done by creating a + // virutal pointer to this newly created tables physical frame so we can + // copy data to it. + for (uint32_t i = 0; i < 1024; i++) { + // Find a unused table + if (src_directory->tables[i]) + continue; + + // Link the table to the new table temporarily + src_directory->tables[i] = new_table; + src_directory->physical_tables[i] = *physical_address | 0x7; + PageDirectory *tmp = get_active_pagedirectory(); + switch_page_directory(src_directory); + + // For each page in the table copy all the data over. + for (uint32_t c = 0; c < 1024; c++) { + // Only copy pages that are used. + if (!src->pages[c].frame || !src->pages[c].present) + continue; + + uint32_t table_data_pointer = i << 22 | c << 12; + uint32_t src_data_pointer = src_index << 22 | c << 12; + memcpy((void *)table_data_pointer, (void *)src_data_pointer, 0x1000); + } + src_directory->tables[i] = 0; + src_directory->physical_tables[i] = 0; + switch_page_directory(tmp); + return new_table; + } + ASSERT_NOT_REACHED; + return 0; +} + +PageTable *copy_table(PageTable *src, uint32_t *physical_address) { + PageTable *new_table = + ksbrk_physical(sizeof(PageTable), (void **)physical_address); + + // copy all the pages + for (uint16_t i = 0; i < 1024; i++) { + if (!src->pages[i].present) { + new_table->pages[i].present = 0; + continue; + } + new_table->pages[i].frame = src->pages[i].frame; + new_table->pages[i].present = src->pages[i].present; + new_table->pages[i].rw = src->pages[i].rw; + new_table->pages[i].user = src->pages[i].user; + new_table->pages[i].accessed = src->pages[i].accessed; + new_table->pages[i].dirty = src->pages[i].dirty; + } + return new_table; +} + +PageDirectory *clone_directory(PageDirectory *original) { + if (!original) + original = get_active_pagedirectory(); + + uint32_t physical_address; + PageDirectory *new_directory = + ksbrk_physical(sizeof(PageDirectory), (void **)&physical_address); + uint32_t offset = + (uint32_t)new_directory->physical_tables - (uint32_t)new_directory; + new_directory->physical_address = physical_address + offset; + + for (int i = 0; i < 1024; i++) { + if (!original->tables[i]) { + new_directory->tables[i] = NULL; + new_directory->physical_tables[i] = (uint32_t)NULL; + continue; + } + + // Make sure to copy instead of cloning the stack. + if (i >= 635 && i <= 641) { + uint32_t physical; + new_directory->tables[i] = clone_table(i, original, &physical); + new_directory->physical_tables[i] = + physical | (original->physical_tables[i] & 0xFFF); + continue; + } + + // if (original->tables[i] == kernel_directory->tables[i]) { + if (i > 641) { + new_directory->tables[i] = kernel_directory->tables[i]; + new_directory->physical_tables[i] = kernel_directory->physical_tables[i]; + continue; + } + + uint32_t physical; + new_directory->tables[i] = clone_table(i, original, &physical); + new_directory->physical_tables[i] = + physical | (original->physical_tables[i] & 0xFFF); + } + + return new_directory; +} + +void mmu_allocate_shared_kernel_region(void *rc, size_t n) { + size_t num_pages = n / PAGE_SIZE; + for (size_t i = 0; i <= num_pages; i++) { + Page *p = get_page((void *)(rc + i * 0x1000), NULL, PAGE_NO_ALLOCATE, 0); + if (!p) { + kprintf("don't have: %x\n", rc + i * 0x1000); + p = get_page((void *)(rc + i * 0x1000), NULL, PAGE_ALLOCATE, 0); + } + if (!p->present || !p->frame) + allocate_frame(p, 0, 1); + } +} + +void mmu_remove_virtual_physical_address_mapping(void *ptr, size_t length) { + size_t num_pages = (uintptr_t)align_page((void *)length) / PAGE_SIZE; + for (size_t i = 0; i < num_pages; i++) { + Page *p = get_page(ptr + (i * PAGE_SIZE), NULL, PAGE_NO_ALLOCATE, 0); + if (!p) + return; + p->frame = 0; + p->present = 0; + } +} + +void *mmu_find_unallocated_virtual_range(void *addr, size_t length) { + addr = align_page(addr); + // Check if the pages already exist + for (size_t i = 0; i < length; i += 0x1000) { + if (get_page(addr + i, NULL, PAGE_NO_ALLOCATE, 0)) { + // Page already exists + return mmu_find_unallocated_virtual_range(addr + 0x1000, length); + } + } + return addr; +} + +int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags, + PageDirectory *pd) { + pd = (pd) ? pd : get_active_pagedirectory(); + size_t num_pages = n / 0x1000; + for (size_t i = 0; i <= num_pages; i++) { + Page *p = get_page((void *)(ptr + i * 0x1000), pd, PAGE_ALLOCATE, 1); + assert(p); + int rw = (flags & MMU_FLAG_RW); + int kernel = (flags & MMU_FLAG_KERNEL); + if (!allocate_frame(p, rw, kernel)) { + klog("MMU: Frame allocation failed", LOG_WARN); + return 0; + } + } + return 1; +} + +void *mmu_map_frames(void *const ptr, size_t s) { + void *const r = mmu_find_unallocated_virtual_range((void *)0xEF000000, s); + kprintf("r: %x\n", r); + size_t num_pages = s / 0x1000; + for (size_t i = 0; i <= num_pages; i++) { + Page *p = get_page((void *)(r + i * 0x1000), NULL, PAGE_ALLOCATE, 1); + assert(p); + int rw = 1; + int is_kernel = 1; + p->present = 1; + p->rw = rw; + p->user = !is_kernel; + p->frame = (uintptr_t)(ptr + i * 0x1000) / 0x1000; + write_to_frame((uintptr_t)ptr + i * 0x1000, 1); + } + flush_tlb(); + return r; +} + +void *allocate_frame(Page *page, int rw, int is_kernel) { + if (page->present) { + dump_backtrace(5); + klog("Page is already set", 1); + for (;;) + ; + return 0; + } + uint32_t frame_address = first_free_frame(); + assert(frame_address < sizeof(frames) / sizeof(frames[0])); + write_to_frame(frame_address * 0x1000, 1); + + page->present = 1; + page->rw = rw; + page->user = !is_kernel; + page->frame = frame_address; + return (void *)(frame_address * 0x1000); +} + +void mmu_free_address_range(void *ptr, size_t length) { + size_t num_pages = (size_t)align_page((void *)length) / PAGE_SIZE; + for (size_t i = 0; i < num_pages; i++, ptr += PAGE_SIZE) { + Page *page = get_page(ptr, NULL, PAGE_NO_ALLOCATE, 0); + if (!page) + continue; + if (!page->present) + continue; + if (!page->frame) + continue; + // Sanity check that none of the frames are invalid + assert(page->frame < sizeof(frames) / sizeof(frames[0])); + write_to_frame(((uint32_t)page->frame) * 0x1000, 0); + page->present = 0; + page->rw = 0; + page->user = 0; + page->frame = 0; + } +} + +void mmu_map_directories(void *dst, PageDirectory *d, void *src, + PageDirectory *s, size_t length) { + d = (!d) ? get_active_pagedirectory() : d; + s = (!s) ? get_active_pagedirectory() : s; + size_t num_pages = (uint32_t)align_page((void *)length) / 0x1000; + for (size_t i = 0; i < num_pages; i++, dst += 0x1000, src += 0x1000) { + Page *p = get_page(dst, d, PAGE_ALLOCATE, 1); + p->present = 1; + p->rw = 1; + p->user = 1; + void *physical = virtual_to_physical(src, s); + p->frame = (uint32_t)physical / PAGE_SIZE; + } + flush_tlb(); +} + +void mmu_map_physical(void *dst, PageDirectory *d, void *physical, + size_t length) { + d = (!d) ? get_active_pagedirectory() : d; + size_t num_pages = (uint32_t)align_page((void *)length) / 0x1000; + for (size_t i = 0; i < num_pages; i++, dst += 0x1000, physical += 0x1000) { + Page *p = get_page(dst, d, PAGE_ALLOCATE, 1); + p->present = 1; + p->rw = 1; + p->user = 1; + p->frame = (uintptr_t)physical / PAGE_SIZE; + write_to_frame((uintptr_t)physical, 1); + } + flush_tlb(); +} + +void *virtual_to_physical(void *address, PageDirectory *directory) { + if (0 == directory) + directory = get_active_pagedirectory(); + return (void *)((get_page((void *)address, directory, PAGE_NO_ALLOCATE, 0) + ->frame * + 0x1000) + + (((uintptr_t)address) & 0xFFF)); +} + +extern uint32_t inital_esp; +void __attribute__((optimize("O0"))) +move_stack(uint32_t new_stack_address, uint32_t size) { + mmu_allocate_region((void *)(new_stack_address - size), size, + MMU_FLAG_KERNEL, NULL); + + uint32_t old_stack_pointer, old_base_pointer; + + register uint32_t eax asm("eax"); + asm volatile("mov %esp, %eax"); + old_stack_pointer = eax; + asm volatile("mov %ebp, %eax"); + old_base_pointer = eax; + + uint32_t new_stack_pointer = + old_stack_pointer + ((uint32_t)new_stack_address - inital_esp); + uint32_t new_base_pointer = + old_base_pointer + ((uint32_t)new_stack_address - inital_esp); + + // Copy the stack + memcpy((void *)new_stack_pointer, (void *)old_stack_pointer, + inital_esp - old_stack_pointer); + for (uint32_t i = (uint32_t)new_stack_address; i > new_stack_address - size; + i -= 4) { + uint32_t tmp = *(uint32_t *)i; + if (old_stack_pointer < tmp && tmp < inital_esp) { + tmp = tmp + (new_stack_address - inital_esp); + uint32_t *tmp2 = (uint32_t *)i; + *tmp2 = tmp; + } + } + + inital_esp = new_stack_pointer; + // Actually change the stack + eax = new_stack_pointer; + asm volatile("mov %eax, %esp"); + eax = new_base_pointer; + asm volatile("mov %eax, %ebp"); +} + +// C strings have a unknown length so it does not makes sense to check +// for a size on the pointer. Instead we check whether the page it +// resides in is accessible to the user. +void *is_valid_user_c_string(const char *ptr, size_t *size) { + void *r = (void *)ptr; + size_t s = 0; + for (;;) { + void *page = (void *)((uintptr_t)ptr & (uintptr_t)(~(PAGE_SIZE - 1))); + if (!is_valid_userpointer(page, PAGE_SIZE)) + return NULL; + for (; (uintptr_t)ptr & (PAGE_SIZE - 1); ptr++, s++) + if (!*ptr) { + if (size) + *size = s; + return r; + } + } +} + +void *is_valid_userpointer(const void *ptr, size_t s) { + uintptr_t t = (uintptr_t)ptr; + size_t num_pages = (uintptr_t)align_page((void *)s) / 0x1000; + for (size_t i = 0; i < num_pages; i++, t += 0x1000) { + Page *page = get_page((void *)t, NULL, PAGE_NO_ALLOCATE, 0); + if (!page) + return NULL; + if (!page->present) + return NULL; + if (!page->user) + return NULL; + } + return (void *)ptr; +} + +void switch_page_directory(PageDirectory *directory) { + active_directory = directory; + asm("mov %0, %%cr3" ::"r"(directory->physical_address)); +} + +void enable_paging(void) { + asm("mov %cr0, %eax\n" + "or 0b10000000000000000000000000000000, %eax\n" + "mov %eax, %cr0\n"); +} + +extern uint32_t boot_page_directory; +extern uint32_t boot_page_table1; + +void paging_init(void) { + uint32_t *cr3; + asm volatile("mov %%cr3, %0" : "=r"(cr3)); + uint32_t *virtual = (uint32_t *)((uint32_t)cr3 + 0xC0000000); + + kernel_directory = &real_kernel_directory; + kernel_directory->physical_address = (uint32_t)cr3; + for (uint32_t i = 0; i < 1024; i++) { + kernel_directory->physical_tables[i] = virtual[i]; + + if (!kernel_directory->physical_tables[i]) { + kernel_directory->tables[i] = NULL; + continue; + } + + kernel_directory->tables[i] = + (PageTable *)(0xC0000000 + (virtual[i] & ~(0xFFF))); + + // Loop through the pages in the table + PageTable *table = kernel_directory->tables[i]; + for (size_t j = 0; j < 1024; j++) { + if (!table->pages[j].present) + continue; + // Add the frame to our bitmap to ensure it does not get used by + // another newly created page. + write_to_frame(table->pages[j].frame * 0x1000, 1); + } + } + + switch_page_directory(kernel_directory); + kernel_directory = clone_directory(kernel_directory); + + // Make null dereferences crash. + switch_page_directory(kernel_directory); + get_page(NULL, kernel_directory, PAGE_ALLOCATE, 0)->present = 0; + switch_page_directory(clone_directory(kernel_directory)); + // FIXME: Really hacky solution. Since page table creation needs to + // allocate memory but memory allocation requires page table creation + // they depend on eachother. The bad/current solution is just to + // allocate a bunch of tables so the memory allocator has enough. + for (uintptr_t i = 0; i < 140; i++) + allocate_frame( + get_page((void *)((0x302 + i) * 0x1000 * 1024), NULL, PAGE_ALLOCATE, 0), + 1, 1); + move_stack(0xA0000000, 0xC00000); +} diff --git a/kernel/cpu/gdt.c b/kernel/cpu/gdt.c new file mode 100644 index 0000000..28853cf --- /dev/null +++ b/kernel/cpu/gdt.c @@ -0,0 +1,72 @@ +#include "gdt.h" + +extern void flush_tss(void); +extern void load_gdt(void *); + +typedef struct tss_entry_struct tss_entry_t; + +tss_entry_t tss_entry; + +typedef union { + struct GDT_Entry s; + uint64_t raw; +} GDT_Entry; + +GDT_Entry gdt_entries[6] = {0}; +GDT_Pointer gdtr; + +extern uint32_t inital_esp; +void write_tss(struct GDT_Entry *gdt_entry) { + uint32_t base = (uint32_t)&tss_entry; + uint32_t limit = sizeof(tss_entry); + + gdt_entry->limit_low = limit; + gdt_entry->base_low = base; + gdt_entry->accessed = 1; + gdt_entry->read_write = 0; + gdt_entry->conforming_expand_down = 0; + gdt_entry->code = 1; + gdt_entry->code_data_segment = 0; + gdt_entry->DPL = 0; + gdt_entry->present = 1; + gdt_entry->limit_high = limit >> 16; + gdt_entry->available = 0; + gdt_entry->long_mode = 0; + gdt_entry->big = 0; + gdt_entry->gran = 0; + gdt_entry->base_high = (base & ((uint32_t)0xff << 24)) >> 24; + + memset(&tss_entry, 0, sizeof tss_entry); + tss_entry.ss0 = GDT_KERNEL_DATA_SEGMENT * GDT_ENTRY_SIZE; + register uint32_t esp asm("esp"); + tss_entry.esp0 = esp; +} + +void gdt_init() { + gdt_entries[GDT_NULL_SEGMENT].raw = 0x0; + gdt_entries[GDT_KERNEL_CODE_SEGMENT].raw = + 0xCF9A000000FFFF; // Kernel code segment + gdt_entries[GDT_KERNEL_DATA_SEGMENT].raw = + 0xCF92000000FFFF; // Kernel data segment + + // Usermode code segment + memcpy(&gdt_entries[GDT_USERMODE_CODE_SEGMENT], + &gdt_entries[GDT_KERNEL_CODE_SEGMENT], GDT_ENTRY_SIZE); + + // Usermode data segment + memcpy(&gdt_entries[GDT_USERMODE_DATA_SEGMENT], + &gdt_entries[GDT_KERNEL_DATA_SEGMENT], GDT_ENTRY_SIZE); + + // Set DPL to 3 to indicate that the segment is in ring 3 + gdt_entries[GDT_USERMODE_CODE_SEGMENT].s.DPL = 3; + gdt_entries[GDT_USERMODE_DATA_SEGMENT].s.DPL = 3; + + write_tss((struct GDT_Entry *)&gdt_entries[GDT_TSS_SEGMENT]); + + gdtr.offset = (uint32_t)&gdt_entries; + gdtr.size = sizeof(gdt_entries) - 1; + + asm("cli"); + load_gdt(&gdtr); + flush_tss(); +} diff --git a/kernel/cpu/gdt.h b/kernel/cpu/gdt.h new file mode 100644 index 0000000..a490dea --- /dev/null +++ b/kernel/cpu/gdt.h @@ -0,0 +1,76 @@ +#ifndef GDT_H +#define GDT_H +#include +#include + +#define GDT_ENTRY_SIZE 0x8 +#define GDT_NULL_SEGMENT 0x0 +#define GDT_KERNEL_CODE_SEGMENT 0x1 +#define GDT_KERNEL_DATA_SEGMENT 0x2 +#define GDT_USERMODE_CODE_SEGMENT 0x3 +#define GDT_USERMODE_DATA_SEGMENT 0x4 +#define GDT_TSS_SEGMENT 0x5 + +struct GDT_Entry +{ + uint16_t limit_low; + uint32_t base_low : 24; + uint32_t accessed : 1; + uint32_t read_write : 1; // readable for code, writable for data + uint32_t conforming_expand_down : 1; // conforming for code, expand down for data + uint32_t code : 1; // 1 for code, 0 for data + uint32_t code_data_segment : 1; // should be 1 for everything but TSS and LDT + uint32_t DPL : 2; // privilege level + uint32_t present : 1; + uint32_t limit_high : 4; + uint32_t available : 1; // only used in software; has no effect on hardware + uint32_t long_mode : 1; + uint32_t big : 1; // 32-bit opcodes for code, uint32_t stack for data + uint32_t gran : 1; // 1 to use 4k page addressing, 0 for byte addressing + uint8_t base_high; +}__attribute__((packed)); + +typedef struct GDT_Pointer +{ + uint16_t size; + uint32_t offset; +}__attribute__((packed)) GDT_Pointer; + +struct tss_entry_struct +{ + uint32_t prev_tss; // The previous TSS - with hardware task switching these form a kind of backward linked list. + uint32_t esp0; // The stack pointer to load when changing to kernel mode. + uint32_t ss0; // The stack segment to load when changing to kernel mode. + // Everything below here is unused. + uint32_t esp1; // esp and ss 1 and 2 would be used when switching to rings 1 or 2. + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; +} __attribute__((packed)); + +void gdt_init(); + +uint8_t gen_access_byte(uint8_t priv, uint8_t s, uint8_t ex, uint8_t dc, uint8_t rw); +uint64_t gen_gdt_entry(uint32_t base, uint32_t limit, uint8_t access_byte, uint8_t flag); +uint8_t gen_flag(uint8_t gr, uint8_t sz); +#endif diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c new file mode 100644 index 0000000..abcafad --- /dev/null +++ b/kernel/cpu/idt.c @@ -0,0 +1,195 @@ +#include +#include +#include + +#define MASTER_PIC_COMMAND_PORT 0x20 +#define MASTER_PIC_DATA_PORT 0x21 +#define SLAVE_PIC_COMMAND_PORT 0xA0 +#define SLAVE_PIC_DATA_PORT 0xA1 +#define KEYBOARD_DATA_PORT 0x60 +#define KEYBOARD_STATUS_PORT 0x64 +#define KERNEL_CODE_SEGMENT_OFFSET GDT_ENTRY_SIZE *GDT_KERNEL_CODE_SEGMENT + +#define IDT_MAX_ENTRY 256 + +struct IDT_Descriptor { + uint16_t low_offset; + uint16_t code_segment_selector; + uint8_t zero; // Always should be zero + uint8_t type_attribute; + uint16_t high_offset; +} __attribute__((packed)) __attribute__((aligned(4))); + +struct IDT_Pointer { + uint16_t size; + struct IDT_Descriptor **interrupt_table; +} __attribute__((packed)); + +struct IDT_Descriptor IDT_Entry[IDT_MAX_ENTRY]; +struct IDT_Pointer idtr; + +extern void load_idtr(void *idtr); + +void format_descriptor(uint32_t offset, uint16_t code_segment, + uint8_t type_attribute, + struct IDT_Descriptor *descriptor) { + descriptor->low_offset = offset & 0xFFFF; + descriptor->high_offset = offset >> 16; + descriptor->type_attribute = type_attribute; + descriptor->code_segment_selector = code_segment; + descriptor->zero = 0; +} + +void install_handler(void (*handler_function)(), uint16_t type_attribute, + uint8_t entry) { + format_descriptor((uint32_t)handler_function, KERNEL_CODE_SEGMENT_OFFSET, + type_attribute, &IDT_Entry[entry]); +} + +__attribute__((no_caller_saved_registers)) void EOI(uint8_t irq) { + if (irq > 7) + outb(SLAVE_PIC_COMMAND_PORT, 0x20); + + outb(MASTER_PIC_COMMAND_PORT, 0x20); +} + +__attribute__((interrupt)) void general_protection_fault(registers_t *regs) { + klog("General Protetion Fault", 0x1); + kprintf(" Error Code: %x\n", regs->error_code); + kprintf("Instruction Pointer: %x\n", regs->eip); + dump_backtrace(12); + asm("hlt"); + for (;;) + ; + EOI(0xD - 8); +} + +__attribute__((interrupt)) void double_fault(registers_t *regs) { + (void)regs; + klog("DOUBLE FAULT", LOG_ERROR); + asm("hlt"); + for (;;) + ; +} +__attribute__((interrupt)) void page_fault(registers_t *regs) { + if (0xFFFFDEAD == regs->eip) { + asm("sti"); + for (;;) + switch_task(); + } + klog("Page Fault", LOG_ERROR); + if (get_current_task()) { + kprintf("PID: %x\n", get_current_task()->pid); + kprintf("Name: %s\n", get_current_task()->program_name); + } + kprintf("Error Code: %x\n", regs->error_code); + kprintf("Instruction Pointer: %x\n", regs->eip); + + if (regs->error_code & (1 << 0)) + kprintf("page-protection violation\n"); + else + kprintf("non-present page\n"); + + if (regs->error_code & (1 << 1)) + kprintf("write access\n"); + else + kprintf("read access\n"); + + if (regs->error_code & (1 << 2)) + kprintf("CPL = 3\n"); + + if (regs->error_code & (1 << 4)) + kprintf("Attempted instruction fetch\n"); + + dump_backtrace(5); + asm("hlt"); + for (;;) + ; +} + +static inline void io_wait(void) { outb(0x80, 0); } + +#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ + +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ + +void PIC_remap(int offset) { + unsigned char a1, a2; + a1 = inb(MASTER_PIC_DATA_PORT); + a2 = inb(SLAVE_PIC_DATA_PORT); + + // Send ICW1 and tell the PIC that we will issue a ICW4 + // Since there is no ICW1_SINGLE sent to indicate it is cascaded + // it means we will issue a ICW3. + outb(MASTER_PIC_COMMAND_PORT, ICW1_INIT | ICW1_ICW4); + io_wait(); + outb(SLAVE_PIC_COMMAND_PORT, ICW1_INIT | ICW1_ICW4); + io_wait(); + + // As a part of ICW2 this sends the offsets(the position to put IRQ0) of the + // vector tables. + outb(MASTER_PIC_DATA_PORT, offset); + io_wait(); + outb(SLAVE_PIC_DATA_PORT, offset + 0x8); + io_wait(); + + // This tells the master on which lines it is having slaves + outb(MASTER_PIC_DATA_PORT, 4); + io_wait(); + // This tells the slave the cascading identity. + outb(SLAVE_PIC_DATA_PORT, 2); + io_wait(); + + outb(MASTER_PIC_DATA_PORT, ICW4_8086); + io_wait(); + outb(SLAVE_PIC_DATA_PORT, ICW4_8086); + io_wait(); + + outb(MASTER_PIC_DATA_PORT, a1); + outb(SLAVE_PIC_DATA_PORT, a2); +} + +void IRQ_set_mask(unsigned char IRQline) { + uint16_t port; + uint8_t value; + port = (IRQline < 8) ? MASTER_PIC_DATA_PORT : SLAVE_PIC_DATA_PORT; + if (IRQline >= 8) + IRQline -= 8; + value = inb(port) | (1 << IRQline); + outb(port, value); +} + +void IRQ_clear_mask(unsigned char IRQline) { + uint16_t port; + uint8_t value; + port = (IRQline < 8) ? MASTER_PIC_DATA_PORT : SLAVE_PIC_DATA_PORT; + if (IRQline >= 8) { + IRQline -= 8; + } + value = inb(port) & ~(1 << IRQline); + outb(port, value); +} + +void idt_init(void) { + install_handler(page_fault, INT_32_INTERRUPT_GATE(0x0), 0xE); + install_handler(double_fault, INT_32_INTERRUPT_GATE(0x0), 0x8); + install_handler(general_protection_fault, INT_32_INTERRUPT_GATE(0x0), 0xD); + + PIC_remap(0x20); + IRQ_clear_mask(0xb); + IRQ_set_mask(0xe); + IRQ_set_mask(0xf); + IRQ_clear_mask(2); + + idtr.interrupt_table = (struct IDT_Descriptor **)&IDT_Entry; + idtr.size = (sizeof(struct IDT_Descriptor) * IDT_MAX_ENTRY) - 1; + load_idtr(&idtr); +} diff --git a/kernel/cpu/idt.h b/kernel/cpu/idt.h new file mode 100644 index 0000000..025ba75 --- /dev/null +++ b/kernel/cpu/idt.h @@ -0,0 +1,70 @@ +typedef struct kernel_registers kernel_registers_t; +typedef struct registers registers_t; +#ifndef IDT_H +#define IDT_H +#include +#include +#include +#include +#include + +/* + * the type_attribute in the IDT_Entry struct + * is divded like this + * 7 0 + * +---+---+---+---+---+---+---+---+ + * | P | DPL | S | GateType | + * +---+---+---+---+---+---+---+---+ + * It is 8 bits(1 byte) long + * + * P + * Present bit. Should be zero for unused + * interrupts. + * + * DPL + * Specifices the maximum ring(0 to 3) the + * interrupt can be called from. + * + * S + * Storage segment. This should be set to + * zero for all interrupt and trap gates. + * + * GateType + * Possible IDT gate types: + * 0b0101 0x5 5 80386 32 bit task gate + * 0b0110 0x6 6 80286 16-bit interrupt gate + * 0b0111 0x7 7 80286 16-bit trap gate + * 0b1110 0xE 14 80386 32-bit interrupt gate + * 0b1111 0xF 15 80386 32-bit trap gate + */ + +// This enables the present bit. +#define INT_PRESENT 0x80 /* 0b10000000 */ + +#define INT_32_TASK_GATE(min_privlege) \ + (INT_PRESENT | 0x05 | (min_privlege << 5)) +#define INT_16_INTERRUPT_GATE(min_privlege) \ + (INT_PRESENT | 0x06 | (min_privlege << 5)) +#define INT_16_TRAP_GATE(min_privlege) \ + (INT_PRESENT | 0x07 | (min_privlege << 5)) +#define INT_32_INTERRUPT_GATE(min_privlege) \ + (INT_PRESENT | 0x0E | (min_privlege << 5)) +#define INT_32_TRAP_GATE(min_privlege) \ + (INT_PRESENT | 0x0F | (min_privlege << 5)) + +struct interrupt_frame; + +struct registers { + uint32_t error_code; + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; +}; + +void idt_init(void); +__attribute__((no_caller_saved_registers)) void EOI(unsigned char irq); +void install_handler(void (*handler_function)(), uint16_t type_attribute, + uint8_t entry); +#endif diff --git a/kernel/cpu/int_syscall.s b/kernel/cpu/int_syscall.s new file mode 100644 index 0000000..8c3c25f --- /dev/null +++ b/kernel/cpu/int_syscall.s @@ -0,0 +1,20 @@ +.intel_syntax noprefix +.global int_syscall +.extern syscall_function_handler +int_syscall: + push ebp + push edi + push esi + push edx + push ecx + push ebx + push eax + call syscall_function_handler + add esp, 4 + pop ebx + pop ecx + pop edx + pop esi + pop edi + pop ebp + iretd diff --git a/kernel/cpu/io.h b/kernel/cpu/io.h new file mode 100644 index 0000000..38858a4 --- /dev/null +++ b/kernel/cpu/io.h @@ -0,0 +1,15 @@ +#include + +extern void outsw(uint16_t, uint32_t); +extern void outb(uint16_t, uint8_t); +extern void outw(uint16_t, uint16_t); +extern void outl(uint16_t, uint32_t); + +extern uint32_t inl(uint16_t); +extern uint16_t inw(uint16_t); +extern uint16_t inb(uint16_t); + +extern void rep_outsw(uint16_t count, uint16_t port, volatile void *addy); +__attribute__((no_caller_saved_registers)) extern void +rep_insw(uint16_t count, uint16_t port, volatile void *addy); +extern void jump_usermode(void (*address)(), uint32_t stack_pointer); diff --git a/kernel/cpu/io.s b/kernel/cpu/io.s new file mode 100644 index 0000000..31e9df0 --- /dev/null +++ b/kernel/cpu/io.s @@ -0,0 +1,147 @@ +.intel_syntax noprefix +.global outsw +.global outb +.global outw +.global outl +.global inb +.global inw +.global inl +.global rep_outsw +.global rep_insw +.global flush_tss +.global load_idtr + +# ebx, esi, edi, ebp, and esp; +outsw: + push ebp + mov ebp, esp + push esi + mov dx, [ebp + 4+4] + mov esi, [ebp + 8+4] + outsw + pop esi + mov esp, ebp + pop ebp + ret + +outl: + mov eax, [esp + 8] + mov dx, [esp + 4] + out dx, eax + ret + +outb: + mov al, [esp + 8] + mov dx, [esp + 4] + out dx, al + ret + +outw: + mov ax, [esp + 8] + mov dx, [esp + 4] + out dx, ax + ret + +inl: + mov dx, [esp + 4] + in eax, dx + ret + +inw: + mov dx, [esp + 4] + in ax, dx + ret + +inb: + mov dx, [esp + 4] + in al, dx + ret + +rep_outsw: + push ebp + mov ebp, esp + push edi + mov ecx, [ebp + 4+4] #ECX is counter for OUTSW + mov edx, [ebp + 8+4] #Data port, in and out + mov edi, [ebp + 12+4] #Memory area + rep outsw #in to [RDI] + pop edi + mov esp, ebp + pop ebp + ret + +rep_insw: + push ebp + mov ebp, esp + push edi + mov ecx, [ebp + 4+4] #ECX is counter for INSW + mov edx, [ebp + 8+4] #Data port, in and out + mov edi, [ebp + 12+4] #Memory area + rep insw #in to [RDI] + pop edi + mov esp, ebp + pop ebp + ret + +flush_tss: + mov ax, 40 + ltr ax + ret + +load_idtr: + mov edx, [esp + 4] + lidt [edx] + ret + +test_user_function: + mov eax, 0x00 + int 0x80 + mov ecx, 0x03 + mov ebx, 0x04 + mov eax, 0x02 + int 0x80 + mov ebx, eax + mov eax, 0x01 + int 0x80 +loop: + jmp loop + ret + +.global spin_lock +.global spin_unlock +.extern locked + +spin_lock: + mov eax, 1 + xchg eax, ebx + test eax, eax + jnz spin_lock + ret + +spin_unlock: + xor eax, eax + xchg eax, ebx + ret + + +.global jump_usermode +jump_usermode: + mov ax, (4 * 8) | 3 # user data segment with RPL 3 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax # sysexit sets SS + + # setup wrmsr inputs + xor edx, edx # not necessary; set to 0 + mov eax, 0x100008 # SS=0x10+0x10=0x20, CS=0x8+0x10=0x18 + mov ecx, 0x174 # MSR specifier: IA32_SYSENTER_CS + wrmsr # set sysexit segments + + # setup sysexit inputs + mov edx, [esp + 4] # to be loaded into EIP + mov ecx, [esp + 8] # to be loaded into ESP + mov esp, ecx + mov ebp, ecx + sti + sysexit diff --git a/kernel/cpu/reload_gdt.s b/kernel/cpu/reload_gdt.s new file mode 100644 index 0000000..3a0119b --- /dev/null +++ b/kernel/cpu/reload_gdt.s @@ -0,0 +1,17 @@ +.section .text +.global load_gdt + +load_gdt: + mov 4(%esp), %eax + lgdt (%eax) + + mov $0x10, %eax + mov %eax, %ds + mov %eax, %es + mov %eax, %fs + mov %eax, %gs + mov %eax, %ss + jmp $0x8, $.long_jump +.long_jump: + ret + diff --git a/kernel/cpu/spinlock.c b/kernel/cpu/spinlock.c new file mode 100644 index 0000000..3f87423 --- /dev/null +++ b/kernel/cpu/spinlock.c @@ -0,0 +1,2 @@ +#include +uint8_t locked; diff --git a/kernel/cpu/spinlock.h b/kernel/cpu/spinlock.h new file mode 100644 index 0000000..93290c4 --- /dev/null +++ b/kernel/cpu/spinlock.h @@ -0,0 +1,5 @@ +#ifndef SPINLOCK_H +#define SPINLOCK_H +void spin_lock(int *l); +void spin_unlock(int *l); +#endif diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c new file mode 100644 index 0000000..4978732 --- /dev/null +++ b/kernel/cpu/syscall.c @@ -0,0 +1,183 @@ +// FIXME: Make sure that the args variabel actually points to something +// valid. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wpedantic" + +int syscall_open(SYS_OPEN_PARAMS *args) { + char file[256]; + strcpy(file, args->file); + // const char *file = copy_and_allocate_user_string(args->file); + int flags = args->flags; + int mode = args->mode; + int rc = vfs_open(file, flags, mode); + // kfree((void *)file); + return rc; +} + +int syscall_exec(SYS_EXEC_PARAMS *args) { + const char *filename = copy_and_allocate_user_string(args->path); + + int argc = 0; + for (; args->argv[argc];) { + argc++; + } + + char **new_argv = kallocarray(argc + 1, sizeof(char *)); + for (int i = 0; i < argc; i++) + new_argv[i] = copy_and_allocate_user_string(args->argv[i]); + + new_argv[argc] = NULL; + + exec(filename, new_argv); + kfree((void *)filename); + for (int i = 0; i < argc; i++) + kfree(new_argv[i]); + kfree(new_argv); + return -1; +} + +int syscall_pipe(int fd[2]) { + pipe(fd); // FIXME: Error checking + return 0; +} + +int syscall_pread(SYS_PREAD_PARAMS *args) { + return vfs_pread(args->fd, args->buf, args->count, args->offset); +} + +int syscall_read(SYS_READ_PARAMS *args) { + if (!get_vfs_fd(args->fd)) + return -EBADF; + int rc = vfs_pread(args->fd, args->buf, args->count, + get_current_task()->file_descriptors[args->fd]->offset); + get_current_task()->file_descriptors[args->fd]->offset += rc; + return rc; +} + +int syscall_pwrite(SYS_PWRITE_PARAMS *args) { + return vfs_pwrite(args->fd, args->buf, args->count, args->offset); +} + +int syscall_write(int fd, const char *buf, size_t count) { + if (!get_vfs_fd(fd)) + return -EBADF; + int rc = vfs_pwrite(fd, (char *)buf, count, + get_current_task()->file_descriptors[fd]->offset); + get_current_task()->file_descriptors[fd]->offset += rc; + return rc; +} + +int syscall_dup2(SYS_DUP2_PARAMS *args) { + return vfs_dup2(args->org_fd, args->new_fd); +} + +void syscall_exit(int status) { + exit(status); + assert(0); +} + +void syscall_wait(int *status) { + asm("cli"); + if (!get_current_task()->child) { + if (status) + *status = -1; + return; + } + if (get_current_task()->child->dead) { + if (status) + *status = get_current_task()->child_rc; + return; + } + get_current_task()->halts[WAIT_CHILD_HALT] = 1; + switch_task(); + if (status) + *status = get_current_task()->child_rc; +} + +int syscall_fork(void) { return fork(); } + +int syscall_getpid(void) { return get_current_task()->pid; } + +void *align_page(void *a); + +int syscall_brk(void *addr) { + void *end = get_current_task()->data_segment_end; + if (!mmu_allocate_region(end, addr - end, MMU_FLAG_RW, NULL)) + return -ENOMEM; + get_current_task()->data_segment_end = align_page(addr); + return 0; +} + +void *syscall_sbrk(uintptr_t increment) { + asm("cli"); + void *rc = get_current_task()->data_segment_end; + void *n = + (void *)((uintptr_t)(get_current_task()->data_segment_end) + increment); + int rc2; + if (0 > (rc2 = syscall_brk(n))) + return (void *)rc2; + return rc; +} + +int syscall_close(int fd) { return vfs_close(fd); } + +int syscall_openpty(SYS_OPENPTY_PARAMS *args) { + assert(is_valid_userpointer(args, sizeof(SYS_OPENPTY_PARAMS))); + return openpty(args->amaster, args->aslave, args->name, args->termp, + args->winp); +} + +void (*syscall_functions[])() = { + (void(*))syscall_open, (void(*))syscall_read, + (void(*))syscall_write, (void(*))syscall_pread, + (void(*))syscall_pwrite, (void(*))syscall_fork, + (void(*))syscall_exec, (void(*))syscall_getpid, + (void(*))syscall_exit, (void(*))syscall_wait, + (void(*))syscall_brk, (void(*))syscall_sbrk, + (void(*))syscall_pipe, (void(*))syscall_dup2, + (void(*))syscall_close, (void(*))syscall_openpty, + (void(*))syscall_poll, (void(*))syscall_mmap, + (void(*))syscall_accept, (void(*))syscall_bind, + (void(*))syscall_socket, (void(*))syscall_shm_open, + (void(*))syscall_ftruncate, (void(*))syscall_stat, + (void(*))syscall_msleep, (void(*))syscall_uptime, + (void(*))syscall_mkdir, (void(*))syscall_recvfrom, + (void(*))syscall_sendto, (void(*))syscall_kill, + (void(*))syscall_sigaction, +}; + +void syscall_function_handler(uint32_t eax, uint32_t arg1, uint32_t arg2, + uint32_t arg3, uint32_t arg4, uint32_t arg5) { + assert(eax < sizeof(syscall_functions) / sizeof(syscall_functions[0])); + syscall_functions[eax](arg1, arg2, arg3, arg4, arg5); +} + +extern void int_syscall(void); + +void syscalls_init(void) { + install_handler(int_syscall, INT_32_INTERRUPT_GATE(0x3), 0x80); +} diff --git a/kernel/cpu/syscall.h b/kernel/cpu/syscall.h new file mode 100644 index 0000000..51d50f2 --- /dev/null +++ b/kernel/cpu/syscall.h @@ -0,0 +1,59 @@ +#include "idt.h" +#include +#include + +void syscalls_init(void); + +typedef struct SYS_OPEN_PARAMS { + char *file; + int flags; + int mode; +} __attribute__((packed)) SYS_OPEN_PARAMS; + +typedef struct SYS_PREAD_PARAMS { + int fd; + void *buf; + size_t count; + size_t offset; +} __attribute__((packed)) SYS_PREAD_PARAMS; + +typedef struct SYS_READ_PARAMS { + int fd; + void *buf; + size_t count; +} __attribute__((packed)) SYS_READ_PARAMS; + +typedef struct SYS_PWRITE_PARAMS { + int fd; + void *buf; + size_t count; + size_t offset; +} __attribute__((packed)) SYS_PWRITE_PARAMS; + +typedef struct SYS_WRITE_PARAMS { + int fd; + void *buf; + size_t count; +} __attribute__((packed)) SYS_WRITE_PARAMS; + +typedef struct SYS_EXEC_PARAMS { + char *path; + char **argv; +} __attribute__((packed)) SYS_EXEC_PARAMS; + +typedef struct SYS_WAIT_PARAMS { + int *status; +} __attribute__((packed)) SYS_WAIT_PARAMS; + +typedef struct SYS_DUP2_PARAMS { + int org_fd; + int new_fd; +} __attribute__((packed)) SYS_DUP2_PARAMS; + +typedef struct SYS_OPENPTY_PARAMS { + int *amaster; + int *aslave; + char *name; + /*const struct termios*/ void *termp; + /*const struct winsize*/ void *winp; +} __attribute__((packed)) SYS_OPENPTY_PARAMS; diff --git a/kernel/crypto/ChaCha20/chacha20.c b/kernel/crypto/ChaCha20/chacha20.c new file mode 100644 index 0000000..5bf7aa2 --- /dev/null +++ b/kernel/crypto/ChaCha20/chacha20.c @@ -0,0 +1,29 @@ +#include "chacha20.h" + +#define ROTL(a, b) (((a) << (b)) | ((a) >> (32 - (b)))) +#define QR(a, b, c, d) \ + (a += b, d ^= a, d = ROTL(d, 16), c += d, b ^= c, b = ROTL(b, 12), \ + a += b, d ^= a, d = ROTL(d, 8), c += d, b ^= c, b = ROTL(b, 7)) +#define ROUNDS 20 + +void chacha_block(uint32_t out[16], uint32_t const in[16]) +{ + int i; + uint32_t x[16]; + + for (i = 0; i < 16; ++i) + x[i] = in[i]; + for (i = 0; i < ROUNDS; i += 2) { + QR(x[0], x[4], x[8], x[12]); + QR(x[1], x[5], x[9], x[13]); + QR(x[2], x[6], x[10], x[14]); + QR(x[3], x[7], x[11], x[15]); + + QR(x[0], x[5], x[10], x[15]); + QR(x[1], x[6], x[11], x[12]); + QR(x[2], x[7], x[8], x[13]); + QR(x[3], x[4], x[9], x[14]); + } + for (i = 0; i < 16; ++i) + out[i] = x[i] + in[i]; +} diff --git a/kernel/crypto/ChaCha20/chacha20.h b/kernel/crypto/ChaCha20/chacha20.h new file mode 100644 index 0000000..17532f3 --- /dev/null +++ b/kernel/crypto/ChaCha20/chacha20.h @@ -0,0 +1,15 @@ +#ifndef CHACHA20_H +#define CHACHA20_H +#include + +#define KEY 4 +#define KEY_SIZE 8*sizeof(uint32_t) +#define COUNT 12 +#define COUNT_SIZE sizeof(uint32_t) +#define COUNT_MAX (0x100000000-1) // 2^32 - 1 +#define NONCE 13 +#define NONCE_SIZE 2*sizeof(uint32_t) +#define BLOCK_SIZE 16*sizeof(uint32_t) + +void chacha_block(uint32_t out[16], uint32_t const in[16]); +#endif diff --git a/kernel/crypto/SHA1 b/kernel/crypto/SHA1 new file mode 160000 index 0000000..237ea70 --- /dev/null +++ b/kernel/crypto/SHA1 @@ -0,0 +1 @@ +Subproject commit 237ea7023cad8402932dfbde337d69e5f4d515f6 diff --git a/kernel/drivers/ata.c b/kernel/drivers/ata.c new file mode 100644 index 0000000..fd9b504 --- /dev/null +++ b/kernel/drivers/ata.c @@ -0,0 +1,253 @@ +#include +#include +#include +#include + +#define PRIMARY_BUS_BASEPORT 0x1F0 +#define SECONDAY_BUS_BASEPORT 0x170 + +#define PRIMARY_BUS_IRQ 14 +#define SECONDAY_BUS_IRQ 15 + +#define STATUS_PORT 7 +#define COMMAND_PORT 7 +#define DRIVE_SELECT 6 +#define LBAhi 5 +#define LBAmid 4 +#define LBAlo 3 +#define SECTOR_COUNT 2 +#define DATA_PORT 0 + +#define IDENTIFY 0xEC +#define READ_SECTORS 0x20 +#define WRITE_SECTORS 0x30 +#define CACHE_FLUSH 0xE7 + +#define STATUS_BSY ((1 << 7)) +#define STATUS_DF ((1 << 5)) +#define STATUS_DRQ ((1 << 3)) +#define STATUS_ERR ((1 << 0)) + +uint32_t io_base; + +unsigned char read_buffer[SECTOR_SIZE]; + +void select_drive(uint8_t master_slave) { + outb(io_base + DRIVE_SELECT, (master_slave) ? 0xA0 : 0xB0); +} + +int identify(int master_slave) { + select_drive(master_slave); + outb(io_base + SECTOR_COUNT, 0); + outb(io_base + LBAlo, 0); + outb(io_base + LBAmid, 0); + outb(io_base + LBAhi, 0); + outb(io_base + COMMAND_PORT, IDENTIFY); + if (0 == inb(io_base + STATUS_PORT)) + return 0; // Drive does not exist + + for (; 0 != (inb(io_base + STATUS_PORT) & STATUS_BSY);) + ; + + // Because of some ATAPI drives that do not + // follow spec, at this point we need to check + // the LBAmid and LBAhi ports to see if they are + // non-zero. If so, the drive is not ATA, and we + // should stop polling. + if (0 != inb(io_base + LBAmid) || 0 != inb(io_base + LBAhi)) { + klog("Drive is not ATA.", LOG_ERROR); + return -1; + } + + for (uint16_t status;;) { + status = inb(io_base + STATUS_PORT); + + if (1 == (status & STATUS_ERR)) { + klog("Drive ERR set.", LOG_ERROR); + return -2; + } + + if ((status & STATUS_DRQ)) + break; + } + + // The data is ready to read from the Data + // port (0x1F0). Read 256 16-bit values, + // and store them. + // TODO: This returns some intreasting information. + // https://wiki.osdev.org/ATA_PIO_Mode#Interesting_information_returned_by_IDENTIFY + uint16_t array[256]; + rep_insw(1 * SECTOR_SIZE / 16, io_base + DATA_PORT, array); + return 1; +} + +int poll_status(void) { + for (uint16_t status;;) { + // Read the Regular Status port until... + // We read this 15 times to give some + // time for the drive to catch up. + for (int n = 0; n < 15; n++) + status = inb(io_base + STATUS_PORT); + + // ERR or + // DF sets + if ((status & STATUS_ERR) || (status & STATUS_DF)) { + klog("Drive error set.", LOG_ERROR); + return 0; + } + + // BSY clears + // DRQ sets + if (0 == (status & STATUS_BSY) && 0 != (status & STATUS_DRQ)) + break; + } + return 1; +} + +// Instructions from: https://wiki.osdev.org/ATA_PIO_Mode#28_bit_PIO +void __attribute__((optimize("O0"))) +setup_drive_for_command(uint32_t lba, uint32_t sector_count) { + // 1. Send 0xE0 for the "master" or 0xF0 for + // the "slave", ORed with the highest 4 bits + // of the LBA to port 0x1F6 + outb(io_base + DRIVE_SELECT, 0xE0 | (0 << 4) | ((lba >> 24) & 0x0F)); + + // 2. Send a NULL byte to port 0x1F1, if you + // like (it is ignored and wastes + // lots of CPU time) + + // NOP + + // 3. Send the sectorcount to port 0x1F2 + outb(io_base + SECTOR_COUNT, sector_count); + + // 4. Send the low 8 bits of the LBA to port 0x1F3 + outb(io_base + LBAlo, (lba >> 0) & 0xFF); + + // 5. Send the next 8 bits of the LBA to port 0x1F4 + outb(io_base + LBAmid, (lba >> 8) & 0xFF); + + // 6. Send the next 8 bits of the LBA to port 0x1F5 + outb(io_base + LBAhi, (lba >> 16) & 0xFF); +} + +void delayed_rep_outsw(size_t n, uint16_t port, volatile uint8_t *buffer) { + for (volatile size_t i = 0; i < n; i++) { + outsw(port, (uint32_t)buffer); + buffer += 2; + // outsw(port, buffer); + } +} + +void __attribute__((optimize("O0"))) +ata_write_lba28(uint32_t lba, uint32_t sector_count, + volatile const uint8_t *buffer) { + setup_drive_for_command(lba, sector_count); + + outb(io_base + COMMAND_PORT, WRITE_SECTORS); + + for (volatile uint32_t i = 0; i < sector_count; i++) { + if (!poll_status()) { + // FIXME: Fail properly + for (;;) + ; + } + + delayed_rep_outsw(256, io_base + DATA_PORT, + (void *)((uint32_t)buffer + i * 256)); + } + + // Cache flush + outb(io_base + COMMAND_PORT, CACHE_FLUSH); + + // Wait for BSY to clear + for (;;) { + uint16_t status = inb(io_base + STATUS_PORT); + if (!(status & STATUS_BSY)) + break; + } +} + +// Instructions from: https://wiki.osdev.org/ATA_PIO_Mode#28_bit_PIO +void __attribute__((optimize("O0"))) +ata_read_lba28(uint32_t lba, uint32_t sector_count, volatile void *address) { + // Step 1-6 is done in this function. + setup_drive_for_command(lba, sector_count); + + // 7. Send the "READ SECTORS" command to port 0x17F + outb(io_base + COMMAND_PORT, READ_SECTORS); + + // 8. Wait for an IRQ or poll. + + // This step can be found in the for loop + + // 9. Transfer 256 16-bit values, a uint16_t at a time, + // into your buffer from I/O port 0x1F0 + for (volatile uint32_t i = 0; i < sector_count; i++) { + // 10. Then loop back to waiting for the next IRQ + // or poll again for each successive sector. + // 8. Wait for an IRQ or poll. + if (!poll_status()) { + // FIXME: Fail properly + for (;;) + ; + } + rep_insw(256, io_base + DATA_PORT, (void *)((uint32_t)address + i * 256)); + } +} + +void ata_init(void) { + io_base = PRIMARY_BUS_BASEPORT; + + // Before sending any data to the IO ports, + // read the Regular Status byte. The value + // 0xFF is an illegal status value, and + // indicates that the bus has no drives + if (0xFF == inb(io_base + STATUS_PORT)) { + klog("Bus has no drives", LOG_ERROR); + } + + // Issue IDENTIFY command + select_drive(1); +} + +void __attribute__((optimize("O0"))) +read_lba(uint32_t lba, void *address, size_t size, size_t offset) { + uintptr_t ptr = (uintptr_t)address; + lba += offset / SECTOR_SIZE; + offset = offset % SECTOR_SIZE; + asm("cli"); + size_t total_read = 0; + for (int i = 0; size > 0; i++) { + uint32_t read_len = + (SECTOR_SIZE < (size + offset)) ? (SECTOR_SIZE - offset) : size; + ata_read_lba28(lba + i, 1, read_buffer); + memcpy((void *)ptr, read_buffer + offset, read_len); + size -= read_len; + total_read += read_len; + ptr += read_len; + offset = 0; + } +} + +void write_lba(uint32_t lba, volatile void *address, size_t size, + size_t offset) { + uintptr_t ptr = (uintptr_t)address; + lba += offset / SECTOR_SIZE; + offset = offset % SECTOR_SIZE; + size_t total_write = 0; + uint8_t sector_buffer[512]; + for (int i = 0; size > 0; i++) { + ata_read_lba28(lba + i, 1, sector_buffer); + uint32_t write_len = + (SECTOR_SIZE < (size + offset)) ? (SECTOR_SIZE - offset) : size; + + memcpy(sector_buffer + offset, (void *)ptr, write_len); + ata_write_lba28(lba + i, 1, sector_buffer); + + size -= write_len; + total_write += write_len; + ptr += write_len; + offset = 0; + } +} diff --git a/kernel/drivers/ata.h b/kernel/drivers/ata.h new file mode 100644 index 0000000..3e88d7f --- /dev/null +++ b/kernel/drivers/ata.h @@ -0,0 +1,16 @@ +#include "../cpu/idt.h" +#include + +#define SECTOR_SIZE 512 + +void ata_init(void); + +void read_drive_chs(uint8_t head_index, uint8_t sector_count, + uint8_t sector_index, uint8_t cylinder_low_value, + uint8_t cylinder_high_value, void *address); +void read_drive_lba(uint32_t lba, uint8_t sector_count, void *address); +void read_lba(uint32_t lba, void *address, size_t size, size_t offset); +void write_lba(uint32_t lba, volatile void *address, size_t size, + size_t offset); +void ata_write_lba28(uint32_t lba, uint32_t sector_count, + volatile const uint8_t *buffer); diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c new file mode 100644 index 0000000..8c96606 --- /dev/null +++ b/kernel/drivers/keyboard.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define PS2_REG_DATA 0x60 +#define PS2_REG_STATUS 0x64 +#define PS2_REG_COMMAND 0x64 + +#define PS2_CMD_ENABLE_FIRST_PORT 0xAE // no rsp + +#define PS2_CMD_TEST_CONTROLLER 0xAA // has rsp + +#define PS2_RSP_TEST_PASSED 0x55 +#define PS2_RSP_TEST_FAILED 0xFC + +#define PS2_CMD_SET_SCANCODE 0xF0 // has rsp +#define PS2_KB_ACK 0xFA +#define PS2_KB_RESEND 0xFE + +#define PS2_CMD_SET_MAKE_RELEASE 0xF8 // has rsp + +uint8_t kb_scancodes[3] = {0x43, 0x41, 0x3f}; + +FIFO_FILE *keyboard_fifo; + +uint8_t ascii_table[] = { + 'e', '\x1B', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, + '\t', + + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', + // 0, // [ + // 0, // ] + // 0, + // 0, // ? + '[', ']', + '\n', // ENTER + 'C', + + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', + ';', // ; + '\'', // ; + '`', // ; + 'D', // LEFT SHIFT + '\\', // ; + 'z', 'x', 'c', 'v', 'b', 'n', 'm', + ',', // ; + '.', // ; + '/', // ; + 'U', // ; + 'U', // ; + 'U', // ; + ' ', // ; +}; + +uint8_t capital_ascii_table[] = { + 'e', '\x1B', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 8, + '\t', + + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', + // 0, // [ + // 0, // ] + // 0, + // 0, // ? + '{', '}', + '\n', // ENTER + 'C', + + 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', + ':', // ; + '\"', // ; + '~', // ; + 'D', // LEFT SHIFT + '\\', // ; + 'Z', 'X', 'C', 'V', 'B', 'N', 'M', + '<', // ; + '>', // ; + '?', // ; + 'U', // ; + 'U', // ; + 'U', // ; + ' ', // ; +}; + +vfs_inode_t *kb_inode; + +uint8_t keyboard_to_ascii(uint16_t key, uint8_t capital) { + if ((key & 0xFF) > sizeof(ascii_table)) + return 'U'; + if (capital) + return capital_ascii_table[key & 0xFF]; + else + return ascii_table[key & 0xFF]; +} + +uint8_t is_shift_down = 0; +uint8_t is_alt_down = 0; + +struct KEY_EVENT { + char c; + uint8_t mode; // (shift (0 bit)) (alt (1 bit)) + uint8_t release; // 0 pressed, 1 released +}; + +extern process_t *ready_queue; +__attribute__((interrupt)) void +int_keyboard(__attribute__((unused)) struct interrupt_frame *frame) { + outb(0x20, 0x20); + uint16_t c; + c = inb(PS2_REG_DATA); + int released = 0; + if (c & 0x80) { + switch ((c & ~(0x80)) & 0xFF) { + case 0x2A: // Left shift + case 0x36: // Right shift + is_shift_down = 0; + return; + case 0x38: + is_alt_down = 0; + return; + } + released = 1; + } else { + switch (c & 0xFF) { + case 0x2A: // Left shift + case 0x36: // Right shift + is_shift_down = 1; + return; + case 0x38: + is_alt_down = 1; + return; + } + released = 0; + } + unsigned char a = keyboard_to_ascii((c & ~(0x80)) & 0xFF, is_shift_down); + struct KEY_EVENT ev; + ev.c = a; + ev.release = released; + ev.mode = 0; + ev.mode |= is_shift_down << 0; + ev.mode |= is_alt_down << 1; + fifo_object_write((uint8_t *)&ev, 0, sizeof(ev), keyboard_fifo); + kb_inode->has_data = keyboard_fifo->has_data; +} + +#define PS2_WAIT_RECV \ + { \ + for (;;) { \ + uint8_t status = inb(PS2_REG_STATUS); \ + if (status & 0x1) \ + break; \ + } \ + } + +#define PS2_WAIT_SEND \ + { \ + for (;;) { \ + uint8_t status = inb(PS2_REG_STATUS); \ + if (!(status & (0x1 << 1))) \ + break; \ + } \ + } + +void install_keyboard(void) { + keyboard_fifo = create_fifo_object(); + install_handler(int_keyboard, INT_32_INTERRUPT_GATE(0x3), 0x21); +} + +int keyboard_read(uint8_t *buffer, uint64_t offset, uint64_t len, + vfs_fd_t *fd) { + (void)offset; + + if (0 == fd->inode->has_data) { + return -EAGAIN; + } + int rc = fifo_object_read(buffer, 0, len, keyboard_fifo); + fd->inode->has_data = keyboard_fifo->has_data; + return rc; +} + +void add_keyboard(void) { + kb_inode = devfs_add_file("/keyboard", keyboard_read, NULL, NULL, 0, 0, + FS_TYPE_CHAR_DEVICE); +} diff --git a/kernel/drivers/keyboard.h b/kernel/drivers/keyboard.h new file mode 100644 index 0000000..4b76f22 --- /dev/null +++ b/kernel/drivers/keyboard.h @@ -0,0 +1,11 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H + +#include +#include +#include + +void install_keyboard(void); +void add_keyboard(void); + +#endif diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c new file mode 100644 index 0000000..23619a0 --- /dev/null +++ b/kernel/drivers/mouse.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include + +uint8_t mouse_cycle = 0; // unsigned char +uint8_t mouse_uint8_t[3]; // signed char +uint8_t mouse_x = 0; // signed char +uint8_t mouse_y = 0; // signed char +vfs_inode_t *mouse_inode; +vfs_fd_t *mouse_fd; + +struct mouse_event { + uint8_t buttons; + uint8_t x; + uint8_t y; +}; + +int fs_mouse_write(uint8_t *buffer, uint64_t offset, uint64_t len, + vfs_fd_t *fd) { + int rc = fifo_object_write(buffer, offset, len, fd->inode->internal_object); + FIFO_FILE *f = fd->inode->internal_object; + mouse_inode->has_data = f->has_data; + return rc; +} + +int fs_mouse_read(uint8_t *buffer, uint64_t offset, uint64_t len, + vfs_fd_t *fd) { + FIFO_FILE *f = fd->inode->internal_object; + if (!mouse_inode->has_data) + return 0; + int rc = fifo_object_read(buffer, offset, len, f); + mouse_inode->has_data = f->has_data; + return rc; +} + +void add_mouse(void) { + mouse_inode = devfs_add_file("/mouse", fs_mouse_read, fs_mouse_write, NULL, 0, + 0, FS_TYPE_CHAR_DEVICE); + mouse_inode->internal_object = create_fifo_object(); + // Don't look at this + int fd = vfs_open("/dev/mouse", O_RDWR, 0); + mouse_fd = get_vfs_fd(fd); + get_current_task()->file_descriptors[fd] = NULL; +} + +__attribute__((interrupt)) void what(registers_t *r) { EOI(0xe); } + +__attribute__((interrupt)) void int_mouse(registers_t *r) { + (void)r; + EOI(12); + switch (mouse_cycle) { + case 0: + mouse_uint8_t[0] = inb(0x60); + if(!(mouse_uint8_t[0] & (1 << 3))) { + mouse_cycle = 0; + return; + } + mouse_cycle++; + break; + case 1: + mouse_uint8_t[1] = inb(0x60); + mouse_cycle++; + break; + case 2: + mouse_uint8_t[2] = inb(0x60); + mouse_x = mouse_uint8_t[1]; + mouse_y = mouse_uint8_t[2]; + mouse_cycle = 0; + struct mouse_event e; + e.buttons = mouse_uint8_t[0]; + e.x = mouse_x; + e.y = mouse_y; + raw_vfs_pwrite(mouse_fd, &e, sizeof(e), 0); + break; + } +} + +void mouse_wait(uint8_t a_type) { + uint32_t _time_out = 100000; + if (a_type == 0) { + while (_time_out--) { + if ((inb(0x64) & 1) == 1) { + return; + } + } + return; + } else { + while (_time_out--) { + if ((inb(0x64) & 2) == 0) { + return; + } + } + return; + } +} + +void mouse_write(uint8_t a_write) { + // Wait to be able to send a command + mouse_wait(1); + // Tell the mouse we are sending a command + outb(0x64, 0xD4); + // Wait for the final part + mouse_wait(1); + // Finally write + outb(0x60, a_write); +} + +uint8_t mouse_read() { + // Get's response from mouse + mouse_wait(0); + return inb(0x60); +} + +void install_mouse(void) { + uint8_t _status; // unsigned char + asm("cli"); + // Enable the auxiliary mouse device + mouse_wait(1); + outb(0x64, 0xA8); + + // Enable the interrupts + mouse_wait(1); + outb(0x64, 0x20); + mouse_wait(0); + _status = (inb(0x60) | 2); + mouse_wait(1); + outb(0x64, 0x60); + mouse_wait(1); + outb(0x60, _status); + + // Tell the mouse to use default settings + mouse_write(0xF6); + mouse_read(); // Acknowledge + + // Enable the mouse + mouse_write(0xF4); + mouse_read(); // Acknowledge + + install_handler(int_mouse, INT_32_INTERRUPT_GATE(0x3), 12 + 0x20); + install_handler(what, INT_32_INTERRUPT_GATE(0x3), 0xe + 0x20); +} diff --git a/kernel/drivers/mouse.h b/kernel/drivers/mouse.h new file mode 100644 index 0000000..5248143 --- /dev/null +++ b/kernel/drivers/mouse.h @@ -0,0 +1,5 @@ +#ifndef MOUSE_H +#define MOUSE_H +void install_mouse(void); +void add_mouse(void); +#endif diff --git a/kernel/drivers/pci.c b/kernel/drivers/pci.c new file mode 100644 index 0000000..5fe14bd --- /dev/null +++ b/kernel/drivers/pci.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +#define CONFIG_ADDRESS 0xCF8 +#define CONFIG_DATA 0xCFC + +void pci_config_write32(const struct PCI_DEVICE *device, uint8_t func, + uint8_t offset, uint32_t data) { + uint32_t address; + uint32_t lbus = (uint32_t)device->bus; + uint32_t lslot = (uint32_t)device->slot; + uint32_t lfunc = (uint32_t)func; + + // Create configuration address as per Figure 1 + address = (uint32_t)((lbus << 16) | (lslot << 11) | (lfunc << 8) | + (offset & 0xFC) | ((uint32_t)0x80000000)); + + // Write out the address + outl(CONFIG_ADDRESS, address); + outl(CONFIG_DATA, data); +} + +uint32_t pci_config_read32(const struct PCI_DEVICE *device, uint8_t func, + uint8_t offset) { + uint32_t address; + uint32_t lbus = (uint32_t)device->bus; + uint32_t lslot = (uint32_t)device->slot; + uint32_t lfunc = (uint32_t)func; + + // Create configuration address as per Figure 1 + address = (uint32_t)((lbus << 16) | (lslot << 11) | (lfunc << 8) | + (offset & 0xFC) | ((uint32_t)0x80000000)); + + // Write out the address + outl(CONFIG_ADDRESS, address); + return inl(CONFIG_DATA); +} + +int pci_populate_device_struct(uint16_t vendor, uint16_t device, + struct PCI_DEVICE *pci_device) { + pci_device->vendor = vendor; + pci_device->device = device; + + for (int bus = 0; bus < 256; bus++) { + for (int slot = 0; slot < 256; slot++) { + struct PCI_DEVICE tmp; + tmp.bus = bus; + tmp.slot = slot; + uint32_t device_vendor = pci_config_read32(&tmp, 0, 0); + if (vendor != (device_vendor & 0xFFFF)) + continue; + if (device != (device_vendor >> 16)) + continue; + pci_device->bus = bus; + pci_device->slot = slot; + uint32_t bar0 = pci_config_read32(pci_device, 0, 0x10); + assert(bar0 & 0x1 && "Only support memory IO"); + pci_device->gen.base_mem_io = bar0 & (~0x3); + return 1; + } + } + return 0; +} + +uint8_t pci_get_interrupt_line(const struct PCI_DEVICE *device) { + return pci_config_read32(device, 0, 0x3C) & 0xFF; +} diff --git a/kernel/drivers/pci.h b/kernel/drivers/pci.h new file mode 100644 index 0000000..7511cee --- /dev/null +++ b/kernel/drivers/pci.h @@ -0,0 +1,26 @@ +#include + +struct GENERAL_DEVICE { + uint32_t base_mem_io; + uint8_t interrupt_line; +}; + +struct PCI_DEVICE { + uint16_t vendor; + uint16_t device; + uint8_t bus; + uint8_t slot; + union { + struct GENERAL_DEVICE gen; + }; +}; + +uint32_t pci_config_read32(const struct PCI_DEVICE *device, uint8_t func, + uint8_t offset); +void pci_config_write32(const struct PCI_DEVICE *device, uint8_t func, + uint8_t offset, uint32_t data); + +int pci_populate_device_struct(uint16_t vendor, uint16_t device, + struct PCI_DEVICE *pci_device); + +uint8_t pci_get_interrupt_line(const struct PCI_DEVICE *device); diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c new file mode 100644 index 0000000..711883c --- /dev/null +++ b/kernel/drivers/pit.c @@ -0,0 +1,55 @@ +#include "pit.h" + +#define PIT_IO_CHANNEL_0 0x40 +#define PIT_IO_MODE_COMMAND 0x43 + +uint64_t clock_num_ms_ticks = 0; +uint64_t pit_counter = 0; +uint16_t hertz; + +uint64_t pit_num_ms(void) { return clock_num_ms_ticks; } + +uint16_t read_pit_count(void) { + uint16_t count = 0; + + outb(PIT_IO_MODE_COMMAND, 0x0 /*0b00000000*/); + + count = inb(PIT_IO_CHANNEL_0); + count |= inb(PIT_IO_CHANNEL_0) << 8; + + return count; +} + +void set_pit_count(uint16_t hertz) { + uint16_t divisor = 1193180 / hertz; + + /* + * 0b00110110 + * ^^ + * channel - 0 + * ^^ + * r/w mode - LSB then MSB + * ^^^ + * mode - 3 Square Wave Mode + * ^ + * BCD - no + */ + outb(PIT_IO_MODE_COMMAND, 0x36 /*0b00110110*/); + outb(PIT_IO_CHANNEL_0, divisor & 0xFF); + outb(PIT_IO_CHANNEL_0, (divisor & 0xFF00) >> 8); +} + +__attribute__((interrupt)) void +int_clock(__attribute__((unused)) struct interrupt_frame *frame) { + outb(0x20, 0x20); + pit_counter++; + if (pit_counter >= hertz / 1000) { + pit_counter = 0; + clock_num_ms_ticks++; + } + switch_task(); +} + +void pit_install(void) { + install_handler(int_clock, INT_32_INTERRUPT_GATE(0x0), 0x20); +} diff --git a/kernel/drivers/pit.h b/kernel/drivers/pit.h new file mode 100644 index 0000000..8d9ce98 --- /dev/null +++ b/kernel/drivers/pit.h @@ -0,0 +1,12 @@ +#ifndef PIT_H +#define PIT_H +#include +#include +#include +#include +#include + +void pit_install(void); +void set_pit_count(uint16_t hertz); +uint64_t pit_num_ms(void); +#endif diff --git a/kernel/drivers/pst.c b/kernel/drivers/pst.c new file mode 100644 index 0000000..d063ec9 --- /dev/null +++ b/kernel/drivers/pst.c @@ -0,0 +1,17 @@ +#include +#include + +int openpty(int *amaster, int *aslave, char *name, + /*const struct termios*/ void *termp, + /*const struct winsize*/ void *winp) { + (void)name; + (void)termp; + (void) winp; + int fd[2]; + pipe(fd); // This depends upon that pipe will support read and write + // through the same fd. In reality this should not be the + // case. + *amaster = fd[0]; + *aslave = fd[1]; + return 0; +} diff --git a/kernel/drivers/pst.h b/kernel/drivers/pst.h new file mode 100644 index 0000000..e8fdfaa --- /dev/null +++ b/kernel/drivers/pst.h @@ -0,0 +1,7 @@ +#ifndef PST_H +#define PST_H +#include "../fs/vfs.h" + +int openpty(int *amaster, int *aslave, char *name, /*const struct termios*/ void *termp, + /*const struct winsize*/ void *winp); +#endif diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c new file mode 100644 index 0000000..3853eab --- /dev/null +++ b/kernel/drivers/rtl8139.c @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define RBSTART 0x30 +#define CMD 0x37 +#define IMR 0x3C + +#define TSD0 0x10 // transmit status +#define TSAD0 0x20 // transmit start address + +struct PCI_DEVICE rtl8139; +uint8_t *device_buffer; + +uint8_t *send_buffers[4]; + +struct _INT_PACKET_HEADER { + uint8_t ROK : 1; + uint8_t FAE : 1; + uint8_t CRC : 1; + uint8_t LONG : 1; + uint8_t RUNT : 1; + uint8_t ISE : 1; + uint8_t reserved : 5; + uint8_t BAR : 1; + uint8_t PAM : 1; + uint8_t MAR : 1; +}; + +struct PACKET_HEADER { + union { + uint16_t raw; + struct _INT_PACKET_HEADER data; + }; +}; + +uint16_t current_packet_read = 0; + +void handle_packet(void) { + assert(sizeof(struct _INT_PACKET_HEADER) == sizeof(uint16_t)); + + uint16_t *buf = (uint16_t *)(device_buffer + current_packet_read); + struct PACKET_HEADER packet_header; + packet_header.raw = *buf; + assert(packet_header.data.ROK); + kprintf("packet_header.raw: %x\n", packet_header.raw); + uint16_t packet_length = *(buf + 1); + kprintf("packet_length: %x\n", packet_length); + + uint8_t packet_buffer[8192 + 16]; + if (current_packet_read + packet_length >= 8192 + 16) { + uint32_t first_run = ((uint8_t *)buf + (8192 + 16)) - device_buffer; + memcpy(packet_buffer, buf, first_run); + memcpy(packet_buffer, device_buffer, packet_length - first_run); + } else { + memcpy(packet_buffer, buf, packet_length); + } + + handle_ethernet((uint8_t *)packet_buffer + 4, packet_length); + + // Thanks to exscape + // https://github.com/exscape/exscapeOS/blob/master/src/kernel/net/rtl8139.c + // and the programmers guide + // https://www.cs.usfca.edu/~cruse/cs326f04/RTL8139_ProgrammersGuide.pdf I + // have no clue what this calculation, I can't find anything possibly relating + // to this in the manual, but it does work I guess. + current_packet_read = (current_packet_read + packet_length + 4 + 3) & (~3); + current_packet_read %= 8192 + 16; + outw(rtl8139.gen.base_mem_io + 0x38, current_packet_read - 0x10); +} + +__attribute__((interrupt)) void rtl8139_handler(void *regs) { + (void)regs; + uint16_t status = inw(rtl8139.gen.base_mem_io + 0x3e); + kprintf("status: %x\n", status); + + outw(rtl8139.gen.base_mem_io + 0x3E, 0x5); + if (status & (1 << 2)) { + kprintf("Packet sent\n"); + } + if (status & (1 << 0)) { + kprintf("Received packet\n"); + handle_packet(); + } + + EOI(0xB); +} + +int rtl8139_send_data(uint8_t *data, uint16_t data_size) { + const struct PCI_DEVICE *device = &rtl8139; + // FIXME: It should block or fail if there is too little space for the + // buffer + if (data_size > 0x1000) + return 0; + static int loop = 0; + if (loop > 3) { + loop = 0; + } + memcpy(send_buffers[loop], data, data_size); + outl(device->gen.base_mem_io + 0x20 + loop * 4, + (uint32_t)virtual_to_physical(send_buffers[loop], NULL)); + outl(device->gen.base_mem_io + 0x10 + loop * 4, data_size); + loop += 1; + return 1; +} + +void get_mac_address(uint8_t mac[6]) { + uint32_t base_address = rtl8139.gen.base_mem_io; + // Read the MAC address + uint64_t mac_address; + { + uint32_t low_mac = inl(base_address); + uint16_t high_mac = inw(base_address + 0x4); + mac_address = ((uint64_t)high_mac << 32) | low_mac; + } + kprintf("mac_address: %x\n", mac_address); + memcpy(mac, &mac_address, sizeof(uint8_t[6])); +} + +uint8_t rtl8139_get_transmit_status(uint32_t base_address) { + uint32_t status_register = inl(base_address + 0x3E); + if ((status_register >> 3) & 0x1) + kprintf("transmit error :(\n"); + uint8_t status = (status_register >> 2) & 0x1; + outl(base_address + 0x3E, 0x5); + return status; +} + +void rtl8139_init(void) { + if (!pci_populate_device_struct(0x10EC, 0x8139, &rtl8139)) { + kprintf("RTL8139 not found :(\n"); + return; + } + kprintf("RTL8139 found at bus: %x slot: %x\n", rtl8139.bus, rtl8139.slot); + + uint8_t header_type = (pci_config_read32(&rtl8139, 0, 0xC) >> 16) & 0xFF; + assert(0 == header_type); + + uint32_t base_address = rtl8139.gen.base_mem_io; + uint8_t interrupt_line = pci_get_interrupt_line(&rtl8139); + + // Enable bus mastering + uint32_t register1 = pci_config_read32(&rtl8139, 0, 0x4); + register1 |= (1 << 2); + pci_config_write32(&rtl8139, 0, 0x4, register1); + + // Turning on the device + outb(base_address + 0x52, 0x0); + + // Reset the device and clear the RX and TX buffers + outb(base_address + CMD, 0x10); + for (; 0 != (inb(base_address + CMD) & 0x10);) + ; + device_buffer = ksbrk(8192 + 16); + memset(device_buffer, 0, 8192 + 16); + // Setupt the recieve buffer + uint32_t rx_buffer = (uint32_t)virtual_to_physical(device_buffer, NULL); + outl(base_address + RBSTART, rx_buffer); + + // Set IMR + ISR + outw(base_address + IMR, (1 << 2) | (1 << 3) | (1 << 0)); + + // Set transmit and reciever enable + outb(base_address + 0x37, (1 << 2) | (1 << 3)); + + // Configure the recieve buffer + outl(base_address + 0x44, + 0xf); // 0xf is AB+AM+APM+AAP + + install_handler(rtl8139_handler, INT_32_INTERRUPT_GATE(0x0), + 0x20 + interrupt_line); + + // ksbrk() seems to have the magical ability of disabling interrupts? + // I have no fucking clue why that happens and it was a pain to debug. + for (int i = 0; i < 4; i++) + send_buffers[i] = ksbrk(0x1000); +} diff --git a/kernel/drivers/rtl8139.h b/kernel/drivers/rtl8139.h new file mode 100644 index 0000000..6e13fdd --- /dev/null +++ b/kernel/drivers/rtl8139.h @@ -0,0 +1,4 @@ +#include +void get_mac_address(uint8_t mac[6]); +void rtl8139_init(void); +int rtl8139_send_data(uint8_t *data, uint16_t data_size); diff --git a/kernel/drivers/serial.c b/kernel/drivers/serial.c new file mode 100644 index 0000000..549d852 --- /dev/null +++ b/kernel/drivers/serial.c @@ -0,0 +1,35 @@ +#include "cpu/io.h" + +#define PORT 0x3f8 // COM1 + +int serial_init(void) { + outb(PORT + 1, 0x00); // Disable all interrupts + outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud + outb(PORT + 1, 0x00); // (hi byte) + outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit + outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip + outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial + // returns same byte) + + // Check if serial is faulty (i.e: not same byte as sent) + if (inb(PORT + 0) != 0xAE) { + return 1; + } + + // If serial is not faulty set it in normal operation mode + // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) + outb(PORT + 4, 0x0F); + return 0; +} + +int is_transmit_empty() { return inb(PORT + 5) & 0x20; } + +void write_serial(char a) { + while (is_transmit_empty() == 0) + ; + + outb(PORT, a); +} diff --git a/kernel/drivers/serial.h b/kernel/drivers/serial.h new file mode 100644 index 0000000..327765b --- /dev/null +++ b/kernel/drivers/serial.h @@ -0,0 +1,2 @@ +int serial_init(void); +void write_serial(char a); diff --git a/kernel/drivers/vbe.c b/kernel/drivers/vbe.c new file mode 100644 index 0000000..c67b7b4 --- /dev/null +++ b/kernel/drivers/vbe.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include + +uint8_t *framebuffer; +uint32_t framebuffer_physical; +uint32_t framebuffer_width; +uint32_t framebuffer_height; +uint64_t framebuffer_size; + +vfs_vm_object_t vbe_vm_object; + +#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit))) +#define min(_a, _b) (((_a) > (_b)) ? (_b) : (_a)) + +struct DISPLAY_INFO { + uint32_t width; + uint32_t height; + uint8_t bpp; +}; + +struct DISPLAY_INFO vbe_info; + +void display_driver_init(multiboot_info_t *mbi) { + assert(CHECK_FLAG(mbi->flags, 12)); + framebuffer_width = mbi->framebuffer_width; + framebuffer_height = mbi->framebuffer_height; + + uint32_t bits_pp = mbi->framebuffer_bpp; + uint32_t bytes_pp = (bits_pp / 8) + (8 - (bits_pp % 8)); + + framebuffer_size = bytes_pp * framebuffer_width * framebuffer_height; + + framebuffer_physical = mbi->framebuffer_addr; + framebuffer = + mmu_map_frames((void *)(uint32_t)mbi->framebuffer_addr, framebuffer_size); + + vbe_info.width = framebuffer_width; + vbe_info.height = framebuffer_height; + vbe_info.bpp = mbi->framebuffer_bpp; +} + +vfs_vm_object_t *vbe_get_vm_object(uint64_t length, uint64_t offset, + vfs_fd_t *fd) { + (void)fd; + (void)length; + (void)offset; + vbe_vm_object.size = framebuffer_size; + int n = (uintptr_t)align_page((void *)(uint32_t)framebuffer_size) / 0x1000; + vbe_vm_object.object = kmalloc(sizeof(void *) * n); + for (int i = 0; i < n; i++) { + vbe_vm_object.object[i] = (void *)framebuffer_physical + (i * 0x1000); + } + return &vbe_vm_object; +} + +int display_info_read(uint8_t *buffer, uint64_t offset, uint64_t len, + vfs_fd_t *fd) { + (void)offset; + int read_len = min(sizeof(struct DISPLAY_INFO), len); + memcpy(buffer, &vbe_info, read_len); + return read_len; +} + +void add_vbe_device(void) { + devfs_add_file("/vbe", NULL, NULL, vbe_get_vm_object, 1, 1, + FS_TYPE_BLOCK_DEVICE); + devfs_add_file("/display_info", display_info_read, NULL, NULL, 1, 0, + FS_TYPE_BLOCK_DEVICE); +} diff --git a/kernel/drivers/vbe.h b/kernel/drivers/vbe.h new file mode 100644 index 0000000..4df2221 --- /dev/null +++ b/kernel/drivers/vbe.h @@ -0,0 +1,7 @@ +#ifndef VBE_H +#define VBE_H +#include +void display_driver_init(multiboot_info_t *mb); +void display_driver_cross(multiboot_info_t *mbi); +void add_vbe_device(void); +#endif // VBE_H diff --git a/kernel/elf.c b/kernel/elf.c new file mode 100644 index 0000000..7316a0c --- /dev/null +++ b/kernel/elf.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include + +void *load_elf_file(const char *f, uint32_t *ds) { + // ELFHeader *header = kmalloc(sizeof(ELFHeader)); + ELFHeader header; + int fd = vfs_open(f, O_RDONLY, 0); + if (fd < 0) { + return NULL; + } + + if (sizeof(header) != vfs_pread(fd, &header, sizeof(header), 0)) { + return NULL; + } + + if (0 != memcmp(header.e_ident, "\x7F\x45\x4C\x46" /* "\x7FELF" */, 4)) { + klog("Incorrect ELF signature", LOG_ERROR); + return NULL; + } + + if (0 > fd) { + return NULL; + } + Elf32_Phdr program_header; + assert(sizeof(program_header) == header.e_phentsize); + uint32_t header_offset = header.e_phoff; + uintptr_t end_of_code = 0; + for (int i = 0; i < header.e_phnum; + i++, header_offset += header.e_phentsize) { + if (0 >= + vfs_pread(fd, &program_header, sizeof(program_header), header_offset)) { + return NULL; + } + + // FIXME: Only one type is supported, which is 1(load). More should be + // added. + assert(1 == program_header.p_type); + + // 1. Clear p_memsz bytes at p_vaddr to 0.(We also allocate frames for + // that range) + uint32_t p_memsz = program_header.p_memsz; + uint32_t p_vaddr = program_header.p_vaddr; + + uint32_t pages_to_allocate = + (uint32_t)align_page((void *)(p_vaddr + p_memsz)); + pages_to_allocate -= p_vaddr - (p_vaddr % 0x1000); + pages_to_allocate /= 0x1000; + + mmu_allocate_region((void *)p_vaddr, pages_to_allocate * 0x1000, + MMU_FLAG_RW, NULL); + + flush_tlb(); + + uintptr_t e = program_header.p_vaddr + program_header.p_memsz; + if (e > end_of_code) + end_of_code = e; + + memset((void *)program_header.p_vaddr, 0, program_header.p_memsz); + + // 2. Copy p_filesz bytes from p_offset to p_vaddr + int rc = vfs_pread(fd, (void *)program_header.p_vaddr, + program_header.p_filesz, program_header.p_offset); + + assert(rc == (int)program_header.p_filesz); + } + *ds = end_of_code; + vfs_close(fd); + return (void *)header.e_entry; +} diff --git a/kernel/elf.h b/kernel/elf.h new file mode 100644 index 0000000..452ddbd --- /dev/null +++ b/kernel/elf.h @@ -0,0 +1,99 @@ +#ifndef ELF_H +#define ELF_H +#include +#include +#include +#include + +#define ET_NONE 0 // No file type +#define ET_REL 1 // Relocatable file +#define ET_EXEC 2 // Executable file +#define ET_DYN 3 // Shared object file +#define ET_CORE 4 // Core file +#define ET_LOPROC 0xff00 // Processor-specific +#define ET_HIPROC 0xffff // Processor-specific + +#define EM_NONE 0 // No machine +#define EM_M32 1 // AT&T WE 32100 +#define EM_SPARC 2 // SPARC +#define EM_386 3 // Intel 80386 +#define EM_68K 4 // Motorola 68000 +#define EM_88K 5 // Motorola 88000 +#define EM_860 7 // Intel 80860 +#define EM_MIPS 8 // MIPS RS3000 + +#define EV_NONE 0 // Invalid version +#define EV_CURRENT 1 // Current version + +#define ELF_EXECUTABLE (1 << 0) +#define ELF_WRITABLE (1 << 1) +#define ELF_READABLE (1 << 2) + +#define Elf32_Addr uint32_t // Unsigned program address +#define Elf32_Half uint16_t // Unsigned medium integer +#define Elf32_Off uint32_t // Unsigned file offset +#define Elf32_Sword uint32_t // Signed large integer +#define Elf32_Word uint32_t // Unsigned large integer + +#define ELF_EXEC (1 << 0) +#define ELF_WRITE (1 << 1) +#define ELF_READ (1 << 2) + +// ELF header +typedef struct { + unsigned char e_ident[16]; + Elf32_Half e_type; // Object file type (ET_*) + Elf32_Half e_machine; // Required architecture (EM_*) + Elf32_Word e_version; // Object file version (EV_*) + Elf32_Addr e_entry; // File entry point + Elf32_Off e_phoff; // Program header table's offset(bytes) + Elf32_Off e_shoff; // Section header table's offset(bytes) + Elf32_Word e_flags; + Elf32_Half e_ehsize; // ELF Header size + Elf32_Half + e_phentsize; // Size of program's header tables(all are the same size) + Elf32_Half e_phnum; // Amount of program headers + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} __attribute__((packed)) ELFHeader; + +// Section header +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +enum ShT_Types { + SHT_NULL = 0, // Null section + SHT_PROGBITS = 1, // Program information + SHT_SYMTAB = 2, // Symbol table + SHT_STRTAB = 3, // String table + SHT_RELA = 4, // Relocation (w/ addend) + SHT_NOBITS = 8, // Not present in file + SHT_REL = 9, // Relocation (no addend) +}; + +// Program header +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} __attribute__((packed)) Elf32_Phdr; + + +void *load_elf_file(const char *f, uint32_t *ds); +#endif diff --git a/kernel/fs/devfs.c b/kernel/fs/devfs.c new file mode 100644 index 0000000..14748a7 --- /dev/null +++ b/kernel/fs/devfs.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +devfs_file files[20]; +int num_files = 0; + +vfs_inode_t *devfs_add_file( + char *path, + int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), + int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), + vfs_vm_object_t *(get_vm_object)(uint64_t length, uint64_t offset, + vfs_fd_t *fd), + uint8_t has_data, uint8_t can_write, int type) { + files[num_files].name = copy_and_allocate_string(path); + + vfs_inode_t *i = kmalloc(sizeof(vfs_inode_t)); + files[num_files].inode = i; + i->type = type; + i->read = read; + i->write = write; + i->close = NULL; + i->get_vm_object = get_vm_object; + i->has_data = has_data; + i->is_open = 1; + i->can_write = can_write; + num_files++; + return i; +} + +vfs_inode_t *devfs_open(const char *file) { + for (int i = 0; i < num_files; i++) + if (isequal_n(files[i].name, file, strlen(files[i].name))) + return files[i].inode; + + return 0; +} + +int devfs_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + return fd->inode->read(buffer, offset, len, fd); +} + +int devfs_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + return fd->inode->write(buffer, offset, len, fd); +} + +vfs_vm_object_t *devfs_get_vm_object(uint64_t length, uint64_t offset, + vfs_fd_t *fd) { + return fd->inode->get_vm_object(length, offset, fd); +} + +int stdout_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + (void)offset; + (void)fd; + + int rc = len; + for (; len--;) + putc(*buffer++); + return rc; +} + +int serial_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + (void)offset; + (void)fd; + + int rc = len; + for (; len--;) + write_serial(*buffer++); + return rc; +} + +void add_serial(void) { + devfs_add_file("/serial", NULL, serial_write, NULL, 0, 1, + FS_TYPE_CHAR_DEVICE); +} + +void add_stdout(void) { + devfs_add_file("/stdout", NULL, stdout_write, NULL, 0, 1, + FS_TYPE_CHAR_DEVICE); +} + +vfs_inode_t *devfs_mount(void) { + vfs_inode_t *root = kmalloc_eternal(sizeof(vfs_inode_t)); + root->open = devfs_open; + root->read = devfs_read; + root->write = devfs_write; + root->close = NULL; + return root; +} diff --git a/kernel/fs/devfs.h b/kernel/fs/devfs.h new file mode 100644 index 0000000..23a499e --- /dev/null +++ b/kernel/fs/devfs.h @@ -0,0 +1,26 @@ +#ifndef DEVFS_H +#define DEVFS_H +#include +#include +#include + +typedef struct devfs_file { + char *name; + vfs_inode_t *inode; +} devfs_file; + +vfs_inode_t *devfs_mount(void); +vfs_inode_t *devfs_open(const char *file); +int devfs_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd); +int devfs_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd); +void add_stdout(void); +void add_serial(void); +vfs_inode_t *devfs_add_file( + char *path, + int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), + int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), + vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset, + vfs_fd_t *fd), + uint8_t has_data, uint8_t can_write, int type); + +#endif diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c new file mode 100644 index 0000000..bd0fb07 --- /dev/null +++ b/kernel/fs/ext2.c @@ -0,0 +1,763 @@ +#include +#include +#include +#include +#include + +#define EXT2_SUPERBLOCK_SECTOR 2 +#define EXT2_ROOT_INODE 2 + +#define BLOCKS_REQUIRED(_a, _b) ((_a) / (_b) + (((_a) % (_b)) != 0)) + +superblock_t *superblock; +uint32_t block_byte_size; +uint32_t inode_size; +uint32_t inodes_per_block; + +#define BLOCK_SIZE (block_byte_size) + +void ext2_close(vfs_fd_t *fd) { + return; // There is nothing to clear +} + +int read_inode(int inode_num, unsigned char *data, uint64_t size, + uint64_t offset, uint64_t *file_size); + +struct BLOCK_CACHE { + uint32_t block_num; + uint8_t block[1024]; +}; + +#define NUM_BLOCK_CACHE 30 +struct BLOCK_CACHE cache[NUM_BLOCK_CACHE] = {0}; +uint8_t last_taken_cache = 0; + +void cached_read_block(uint32_t block, void *address, size_t size, + size_t offset) { + int free_found = -1; + for (int i = 0; i < NUM_BLOCK_CACHE; i++) { + if (cache[i].block_num == block) { + memcpy(address, cache[i].block + offset, size); + return; + } + if (0 == cache[i].block_num) + free_found = i; + } + + if (-1 == free_found) { + free_found = last_taken_cache; + last_taken_cache++; + if (last_taken_cache >= NUM_BLOCK_CACHE) + last_taken_cache = 0; + } + + struct BLOCK_CACHE *c = &cache[free_found]; + c->block_num = block; + read_lba(block * block_byte_size / 512, c->block, 1024, 0); + return cached_read_block(block, address, size, offset); +} + +void ext2_read_block(uint32_t block, void *address, size_t size, + size_t offset) { + cached_read_block(block, address, size, offset); +} + +void ext2_write_block(uint32_t block, void *address, size_t size, + size_t offset) { + // Invalidate a old cache + for (int i = 0; i < NUM_BLOCK_CACHE; i++) { + if (cache[i].block_num == block) { + cache[i].block_num = 0; + break; + } + } + write_lba(block * block_byte_size / 512, address, size, offset); +} + +void write_group_descriptor(uint32_t group_index, bgdt_t *block_group) { + int starting_block = (1024 == block_byte_size) ? 2 : 1; + ext2_write_block(starting_block, block_group, sizeof(bgdt_t), + group_index * sizeof(bgdt_t)); +} + +void get_group_descriptor(uint32_t group_index, bgdt_t *block_group) { + int starting_block = (1024 == block_byte_size) ? 2 : 1; + ext2_read_block(starting_block, block_group, sizeof(bgdt_t), + group_index * sizeof(bgdt_t)); +} + +uint32_t num_block_groups(void) { + // Determining the Number of Block Groups + + // From the Superblock, extract the size of each block, the total + // number of inodes, the total number of blocks, the number of blocks + // per block group, and the number of inodes in each block group. From + // this information we can infer the number of block groups there are + // by: + + // Rounding up the total number of blocks divided by the number of + // blocks per block group + uint32_t num_blocks = superblock->num_blocks; + uint32_t num_blocks_in_group = superblock->num_blocks_in_group; + uint32_t b = num_blocks / num_blocks_in_group; + if (num_blocks % num_blocks_in_group != 0) + b++; + + // Rounding up the total number of inodes divided by the number of + // inodes per block group + uint32_t num_inodes = superblock->num_inodes; + uint32_t num_inodes_in_group = superblock->num_inodes_in_group; + uint32_t i = num_inodes / num_inodes_in_group; + if (num_inodes % num_inodes_in_group != 0) + i++; + // Both (and check them against each other) + assert(i == b); + return i; +} + +void ext2_block_containing_inode(uint32_t inode_index, uint32_t *block_index, + uint32_t *offset) { + assert(0 != inode_index); + bgdt_t block_group; + get_group_descriptor((inode_index - 1) / superblock->num_inodes_in_group, + &block_group); + + uint64_t full_offset = + ((inode_index - 1) % superblock->num_inodes_in_group) * inode_size; + *block_index = block_group.starting_inode_table + + (full_offset >> (superblock->block_size + 10)); + *offset = full_offset & (block_byte_size - 1); +} + +int ext2_last_inode_read = -1; +inode_t ext2_last_inode; + +void ext2_get_inode_header(int inode_index, inode_t *data) { + // Very simple cache. If the inode_index is a inode already read then + // just copy the old data. + if (ext2_last_inode_read == inode_index) { + memcpy(data, &ext2_last_inode, sizeof(inode_t)); + return; + } + uint32_t block_index; + uint32_t block_offset; + ext2_block_containing_inode(inode_index, &block_index, &block_offset); + + uint8_t mem_block[inode_size]; + ext2_read_block(block_index, mem_block, inode_size, block_offset); + + memcpy(data, mem_block, inode_size); + memcpy(&ext2_last_inode, mem_block, sizeof(inode_t)); + ext2_last_inode_read = inode_index; +} + +void ext2_write_inode(int inode_index, inode_t *data) { + if (ext2_last_inode_read == inode_index) + ext2_last_inode_read = -1; // Invalidate the cache + uint32_t block_index; + uint32_t block_offset; + ext2_block_containing_inode(inode_index, &block_index, &block_offset); + + uint8_t mem_block[inode_size]; + memcpy(mem_block, data, inode_size); + ext2_write_block(block_index, mem_block, inode_size, block_offset); +} + +int ext2_get_inode_in_directory(int dir_inode, char *file, + direntry_header_t *entry) { + // FIXME: Allocate sufficent size each time + unsigned char *data = kmalloc(block_byte_size * 5); + ASSERT_BUT_FIXME_PROPOGATE( + -1 != read_inode(dir_inode, data, block_byte_size * 5, 0, 0)); + + direntry_header_t *dir; + unsigned char *data_p = data; + for (; (dir = (direntry_header_t *)data_p)->inode; data_p += dir->size) { + if (0 == dir->size) + break; + if (0 == dir->name_length) + continue; + if (0 == + memcmp(data_p + sizeof(direntry_header_t), file, dir->name_length)) { + if (strlen(file) > dir->name_length) + continue; + if (entry) + memcpy(entry, data_p, sizeof(direntry_header_t)); + return dir->inode; + } + } + return 0; +} + +int ext2_read_dir(int dir_inode, unsigned char *buffer, size_t len, + size_t offset) { + unsigned char data[block_byte_size]; + read_inode(dir_inode, data, block_byte_size, 0, 0); + + direntry_header_t *dir; + struct dirent tmp_entry; + size_t n_dir = 0; + int rc = 0; + unsigned char *data_p = data; + for (; (dir = (direntry_header_t *)data_p)->inode && len > 0; + data_p += dir->size, n_dir++) { + if (0 == dir->size) + break; + if (0 == dir->name_length) + continue; + if (n_dir < (offset / sizeof(struct dirent))) + continue; + + memcpy(tmp_entry.d_name, data_p + sizeof(direntry_header_t), + dir->name_length); + tmp_entry.d_name[dir->name_length] = '\0'; + uint8_t *p = (uint8_t *)&tmp_entry; + size_t l = sizeof(struct dirent); + + l = (len < l) ? len : l; + memcpy(buffer, p, l); + len -= l; + rc += l; + } + return rc; +} + +uint32_t ext2_find_inode(const char *file) { + int cur_path_inode = EXT2_ROOT_INODE; + + if (*file == '/' && *(file + 1) == '\0') + return cur_path_inode; + + char *str = copy_and_allocate_string(file); + char *orig_str = str; + + char *start; + for (;;) { + int final = 0; + start = str + 1; + str++; + + for (; '/' != *str && '\0' != *str; str++) + ; + if ('\0' == *str) + final = 1; + + *str = '\0'; + + direntry_header_t a; + if (0 == (cur_path_inode = + ext2_get_inode_in_directory(cur_path_inode, start, &a))) { + kfree(orig_str); + return 0; + } + + if (final) + break; + + // The expected returned entry is a directory + if (TYPE_INDICATOR_DIRECTORY != a.type_indicator) { + kfree(orig_str); + kprintf("FAILED\n"); + return 0; + } + } + kfree(orig_str); + return cur_path_inode; +} + +uint32_t get_singly_block_index(uint32_t singly_block_ptr, uint32_t i) { + uint8_t block[block_byte_size]; + ext2_read_block(singly_block_ptr, block, block_byte_size, 0); + uint32_t index = *(uint32_t *)(block + (i * (32 / 8))); + return index; +} + +int get_block(inode_t *inode, uint32_t i) { + if (i < 12) + return inode->block_pointers[i]; + + i -= 12; + uint32_t singly_block_size = block_byte_size / (32 / 8); + uint32_t double_block_size = (singly_block_size * singly_block_size); + if (i < singly_block_size) { + return get_singly_block_index(inode->single_indirect_block_pointer, i); + } else if (i < double_block_size) { + i -= singly_block_size; + uint32_t singly_entry = get_singly_block_index( + inode->double_indirect_block_pointer, i / singly_block_size); + uint32_t offset_in_entry = i % singly_block_size; + int block = get_singly_block_index(singly_entry, offset_in_entry); + return block; + } + assert(0); + return 0; +} + +int get_free_block(int allocate) { + bgdt_t block_group; + uint8_t bitmap[BLOCK_SIZE]; + assert(0 < superblock->num_blocks_unallocated); + for (uint32_t g = 0; g < num_block_groups(); g++) { + get_group_descriptor(g, &block_group); + + if (block_group.num_unallocated_blocks_in_group == 0) { + kprintf("skip\n"); + continue; + } + + ext2_read_block(block_group.block_usage_bitmap, bitmap, BLOCK_SIZE, 0); + for (uint32_t i = 0; i < superblock->num_blocks_in_group; i++) { + if (!(bitmap[i >> 3] & (1 << (i % 8)))) { + if (allocate) { + bitmap[i >> 3] |= (1 << (i % 8)); + ext2_write_block(block_group.block_usage_bitmap, bitmap, BLOCK_SIZE, + 0); + block_group.num_unallocated_blocks_in_group--; + write_group_descriptor(g, &block_group); + superblock->num_blocks_unallocated--; + write_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE, + 0); + } + return i + g * superblock->num_blocks_in_group + 1; + } + } + } + return -1; +} + +int get_free_inode(int allocate) { + bgdt_t block_group; + assert(0 < superblock->num_inodes_unallocated); + for (uint32_t g = 0; g < num_block_groups(); g++) { + get_group_descriptor(g, &block_group); + + if (0 == block_group.num_unallocated_inodes_in_group) + continue; + + uint8_t bitmap[BLOCK_SIZE]; + ext2_read_block(block_group.inode_usage_bitmap, bitmap, BLOCK_SIZE, 0); + for (uint32_t i = 0; i < superblock->num_inodes_in_group; i++) { + if (!(bitmap[i / 8] & (1 << (i % 8)))) { + if (allocate) { + bitmap[i / 8] |= (1 << (i % 8)); + ext2_write_block(block_group.inode_usage_bitmap, bitmap, BLOCK_SIZE, + 0); + block_group.num_unallocated_inodes_in_group--; + write_group_descriptor(g, &block_group); + superblock->num_inodes_unallocated--; + write_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE, + 0); + } + return i + g * superblock->num_inodes_in_group + 1; + } + } + } + return -1; +} + +int write_inode(int inode_num, unsigned char *data, uint64_t size, + uint64_t offset, uint64_t *file_size, int append) { + (void)file_size; + uint8_t inode_buffer[inode_size]; + ext2_get_inode_header(inode_num, (inode_t *)inode_buffer); + inode_t *inode = (inode_t *)inode_buffer; + + uint64_t fsize = (uint64_t)(((uint64_t)inode->_upper_32size << 32) | + (uint64_t)inode->low_32size); + if (append) + offset = fsize; + + uint32_t block_start = offset / block_byte_size; + uint32_t block_offset = offset % block_byte_size; + + int num_blocks_used = inode->num_disk_sectors / (BLOCK_SIZE / SECTOR_SIZE); + + if (size + offset > fsize) + fsize = size + offset; + + int num_blocks_required = BLOCKS_REQUIRED(fsize, BLOCK_SIZE); + + for (int i = num_blocks_used; i < num_blocks_required; i++) { + if (i > 12) + assert(0); + int b = get_free_block(1 /*true*/); + assert(-1 != b); + inode->block_pointers[i] = b; + } + + inode->num_disk_sectors = num_blocks_required * (BLOCK_SIZE / SECTOR_SIZE); + + int bytes_written = 0; + for (int i = block_start; size; i++) { + uint32_t block = get_block(inode, i); + if (0 == block) { + kprintf("block_not_found\n"); + break; + } + + int write_len = ((size + block_offset) > block_byte_size) + ? (block_byte_size - block_offset) + : size; + ext2_write_block(block, data + bytes_written, write_len, block_offset); + block_offset = 0; + bytes_written += write_len; + size -= write_len; + } + inode->low_32size = fsize; + inode->_upper_32size = (fsize >> 32); + ext2_write_inode(inode_num, inode); + return bytes_written; +} + +int read_inode(int inode_num, unsigned char *data, uint64_t size, + uint64_t offset, uint64_t *file_size) { + // TODO: Fail if size is lower than the size of the file being read, and + // return the size of the file the callers is trying to read. + uint8_t inode_buffer[inode_size]; + ext2_get_inode_header(inode_num, (inode_t *)inode_buffer); + inode_t *inode = (inode_t *)inode_buffer; + + uint64_t fsize = (uint64_t)(((uint64_t)inode->_upper_32size << 32) | + (uint64_t)inode->low_32size); + + if (file_size) + *file_size = fsize; + + if (size > fsize - offset) + size -= ((size + offset) - fsize); + + if (size == 0) + return 0; + + if (offset > fsize) + return 0; + + uint32_t block_start = offset / block_byte_size; + uint32_t block_offset = offset % block_byte_size; + + int bytes_read = 0; + for (int i = block_start; size; i++) { + uint32_t block = get_block(inode, i); + if (0 == block) { + klog("Filesystem EXT2: Unable to find block", LOG_WARN); + return -1; + } + + int read_len = ((size + block_offset) > block_byte_size) + ? (block_byte_size - block_offset) + : size; + ext2_read_block(block, data + bytes_read, read_len, block_offset); + block_offset = 0; + bytes_read += read_len; + size -= read_len; + } + return bytes_read; +} + +size_t ext2_read_file_offset(const char *file, unsigned char *data, + uint64_t size, uint64_t offset, + uint64_t *file_size) { + // TODO: Fail if the file does not exist. + uint32_t inode = ext2_find_inode(file); + return read_inode(inode, data, size, offset, file_size); +} + +size_t ext2_read_file(const char *file, unsigned char *data, size_t size, + uint64_t *file_size) { + return ext2_read_file_offset(file, data, size, 0, file_size); +} + +int resolve_link(int inode_num) { + uint8_t tmp[inode_size]; + inode_t *inode = (inode_t *)tmp; + uint64_t inode_size = + (((uint64_t)inode->_upper_32size) << 32) & inode->low_32size; + assert(inode_size <= 60); + ext2_get_inode_header(inode_num, inode); + char *path = (char *)(tmp + (10 * 4)); + path--; + *path = '/'; + return ext2_find_inode(path); +} + +int ext2_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + uint64_t file_size; + int rc; + int inode_num = fd->inode->inode_num; + assert(fd->inode->type != FS_TYPE_DIRECTORY); + if (fd->inode->type == FS_TYPE_LINK) { + inode_num = resolve_link(inode_num); + } + rc = write_inode(inode_num, buffer, len, offset, &file_size, 0); + return rc; +} + +int ext2_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + uint64_t file_size; + int rc; + int inode_num = fd->inode->inode_num; + if (fd->inode->type == FS_TYPE_DIRECTORY) { + rc = ext2_read_dir(inode_num, buffer, len, offset); + return rc; + } + if (fd->inode->type == FS_TYPE_LINK) { + inode_num = resolve_link(inode_num); + } + rc = read_inode(inode_num, buffer, len, offset, &file_size); + return rc; +} + +int ext2_truncate(vfs_fd_t *fd, size_t length) { + // TODO: Blocks that are no longer used should be freed. + char inode_buffer[inode_size]; + inode_t *ext2_inode = (inode_t *)inode_buffer; + + ext2_get_inode_header(fd->inode->inode_num, ext2_inode); + + // FIXME: ftruncate should support 64 bit lengths + ext2_inode->_upper_32size = 0; + ext2_inode->low_32size = length; + + ext2_write_inode(fd->inode->inode_num, ext2_inode); + return 0; +} + +vfs_inode_t *ext2_open(const char *path) { + uint32_t inode_num = ext2_find_inode(path); + if (0 == inode_num) + return NULL; + + inode_t ext2_inode[inode_size]; + ext2_get_inode_header(inode_num, ext2_inode); + uint64_t file_size = + ((uint64_t)(ext2_inode->_upper_32size) << 32) | ext2_inode->low_32size; + + uint8_t type; + switch ((ext2_inode->types_permissions / 0x1000)) { + case 0xA: + type = FS_TYPE_LINK; + break; + case 0x4: + type = FS_TYPE_DIRECTORY; + break; + default: + type = FS_TYPE_FILE; + break; + } + + return vfs_create_inode(inode_num, type, 1 /*has_data*/, 1 /*can_write*/, + 1 /*is_open*/, NULL /*internal_object*/, file_size, + ext2_open, ext2_create_file, ext2_read, ext2_write, + ext2_close, ext2_create_directory, + NULL /*get_vm_object*/, ext2_truncate /*truncate*/); +} + +uint64_t end_of_last_entry_position(int dir_inode, uint64_t *entry_offset, + direntry_header_t *meta) { + // FIXME: Allocate sufficent size each time + unsigned char data[block_byte_size * 5]; + uint64_t file_size = 0; + read_inode(dir_inode, data, block_byte_size * 5, 0, &file_size); + assert(block_byte_size * 5 > file_size); + + direntry_header_t *dir; + unsigned char *data_p = data; + uint64_t pos = 0; + uint64_t prev = pos; + for (; pos < file_size && (dir = (direntry_header_t *)data_p)->size; + data_p += dir->size, prev = pos, pos += dir->size) + ; + if (entry_offset) + *entry_offset = prev; + if (meta) + memcpy(meta, ((char *)data) + prev, sizeof(direntry_header_t)); + return pos; +} + +void ext2_create_entry(int directory_inode, direntry_header_t entry_header, + const char *name) { + uint64_t entry_offset = 0; + direntry_header_t meta; + end_of_last_entry_position(directory_inode, &entry_offset, &meta); + + uint32_t padding_in_use = block_byte_size - entry_offset; + + // assert(padding_in_use == meta.size); + assert(padding_in_use >= + (sizeof(direntry_header_t) + entry_header.name_length)); + + // Modify the entry to have its real size + meta.size = sizeof(direntry_header_t) + meta.name_length; + meta.size += (4 - (meta.size % 4)); + write_inode(directory_inode, (unsigned char *)&meta, + sizeof(direntry_header_t), entry_offset, NULL, 0); + + // Create new entry + uint32_t new_entry_offset = entry_offset + meta.size; + entry_header.size = (sizeof(direntry_header_t) + entry_header.name_length); + entry_header.size += (4 - (entry_header.size % 4)); + + uint32_t length_till_next_block = 1024 - (new_entry_offset % 1024); + if (0 == length_till_next_block) + length_till_next_block = 1024; + assert(entry_header.size < length_till_next_block); + entry_header.size = length_till_next_block; + + uint8_t buffer[entry_header.size]; + memset(buffer, 0, entry_header.size); + memcpy(buffer, &entry_header, sizeof(entry_header)); + memcpy(buffer + sizeof(entry_header), name, entry_header.name_length); + write_inode(directory_inode, (unsigned char *)buffer, entry_header.size, + new_entry_offset, NULL, 0); +} + +int ext2_find_parent(char *path, uint32_t *parent_inode, char **filename) { + char *e = path; + for (; *e; e++) + ; + for (; *e != '/'; e--) + ; + *e = '\0'; + *filename = e + 1; + if (*path == '\0') { + *parent_inode = EXT2_ROOT_INODE; + return 1; + } else { + int r = ext2_find_inode(path); + if (0 == r) + return 0; + *parent_inode = r; + return 1; + } + return 0; +} + +int ext2_create_directory(const char *path, int mode) { + (void)mode; + // Check if the directory already exists + uint32_t inode_num = ext2_find_inode(path); + if (0 != inode_num) { + klog("ext2_create_directory: Directory already exists", LOG_WARN); + return inode_num; + } + + uint32_t parent_inode; + // Get the parent directory + char path_buffer[strlen(path) + 1]; + char *filename; + strcpy(path_buffer, path); + if (!ext2_find_parent(path_buffer, &parent_inode, &filename)) { + klog("ext2_create_file: Parent does not exist", LOG_WARN); + return -1; + } + + int new_file_inode = get_free_inode(1); + if (-1 == new_file_inode) { + klog("ext2_create_file: Unable to find free inode", LOG_WARN); + return -1; + } + assert(0 != new_file_inode); + + direntry_header_t entry_header; + entry_header.inode = new_file_inode; + entry_header.name_length = strlen(filename); + entry_header.type_indicator = TYPE_INDICATOR_DIRECTORY; + entry_header.size = sizeof(entry_header) + entry_header.name_length; + + ext2_create_entry(parent_inode, entry_header, filename); + // Create the inode header + uint8_t inode_buffer[inode_size]; + inode_t *new_inode = (inode_t *)inode_buffer; + memset(inode_buffer, 0, inode_size); + new_inode->types_permissions = DIRECTORY; + new_inode->num_hard_links = 2; // 2 since the directory references + // itself with the "." entry + ext2_write_inode(new_file_inode, new_inode); + + // Populate the new directory with "." and ".." + { + // "." + direntry_header_t child_entry_header; + child_entry_header.inode = new_file_inode; + child_entry_header.name_length = 1; + child_entry_header.type_indicator = TYPE_INDICATOR_DIRECTORY; + child_entry_header.size = sizeof(entry_header) + entry_header.name_length; + ext2_create_entry(new_file_inode, child_entry_header, "."); + // ".." + child_entry_header.inode = parent_inode; + child_entry_header.name_length = 2; + child_entry_header.type_indicator = TYPE_INDICATOR_DIRECTORY; + child_entry_header.size = sizeof(entry_header) + entry_header.name_length; + ext2_create_entry(new_file_inode, child_entry_header, ".."); + } + return new_file_inode; +} + +int ext2_create_file(const char *path, int mode) { + // Check if the file already exists + uint32_t inode_num = ext2_find_inode(path); + if (0 != inode_num) { + klog("ext2_create_file: File already exists", LOG_WARN); + return inode_num; + } + + uint32_t parent_inode; + // Get the parent directory + char path_buffer[strlen(path) + 1]; + char *filename; + strcpy(path_buffer, path); + if (!ext2_find_parent(path_buffer, &parent_inode, &filename)) { + klog("ext2_create_file: Parent does not exist", LOG_WARN); + return -1; + } + + int new_file_inode = get_free_inode(1); + if (-1 == new_file_inode) { + klog("ext2_create_file: Unable to find free inode", LOG_WARN); + return -1; + } + assert(0 != new_file_inode); + + direntry_header_t entry_header; + entry_header.inode = new_file_inode; + entry_header.name_length = strlen(filename); + entry_header.type_indicator = TYPE_INDICATOR_REGULAR; + entry_header.size = sizeof(entry_header) + entry_header.name_length; + + ext2_create_entry(parent_inode, entry_header, filename); + // Create the inode header + uint8_t inode_buffer[inode_size]; + inode_t *new_inode = (inode_t *)inode_buffer; + memset(inode_buffer, 0, inode_size); + new_inode->types_permissions = 0x8000; + new_inode->num_hard_links = 1; + ext2_write_inode(new_file_inode, new_inode); + return new_file_inode; +} + +vfs_inode_t *ext2_mount(void) { + parse_superblock(); + return vfs_create_inode(0 /*inode_num*/, 0 /*type*/, 0 /*has_data*/, + 0 /*can_write*/, 0 /*is_open*/, + NULL /*internal_object*/, 0 /*file_size*/, ext2_open, + ext2_create_file, ext2_read, ext2_write, ext2_close, + ext2_create_directory, NULL /*get_vm_object*/, + ext2_truncate /*truncate*/); +} + +void parse_superblock(void) { + superblock = ksbrk(2 * SECTOR_SIZE); + read_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE, 0); + block_byte_size = 1024 << superblock->block_size; + + if (0xEF53 != superblock->ext2_signature) { + klog("Incorrect ext2 signature in superblock.", LOG_ERROR); + for (;;) + ; // TODO: Fail properly + } + + if (1 <= superblock->major_version) + inode_size = ((ext_superblock_t *)superblock)->inode_size; + + inodes_per_block = block_byte_size / inode_size; +} diff --git a/kernel/fs/ext2.h b/kernel/fs/ext2.h new file mode 100644 index 0000000..3a2f800 --- /dev/null +++ b/kernel/fs/ext2.h @@ -0,0 +1,140 @@ +#ifndef EXT2_H +#define EXT2_H +#include +#include +#include +#include + +typedef struct Superblock { + uint32_t num_inodes; + uint32_t num_blocks; + uint32_t num_blocks_reserved; + uint32_t num_blocks_unallocated; + uint32_t num_inodes_unallocated; + uint32_t superblock_block_num; + uint32_t block_size; + uint32_t fragment_size; + uint32_t num_blocks_in_group; + uint32_t num_fragments_in_group; + uint32_t num_inodes_in_group; + uint32_t last_mount; + uint32_t last_write; + uint16_t num_mounts_since_fsck; + uint16_t num_mounts_allowed; + uint16_t ext2_signature; // 0xEF53 + uint16_t fs_state; + uint16_t when_error; + uint16_t minor_version; + uint32_t last_fsck; + uint32_t interval_fsck; + uint32_t os_id; + uint32_t major_version; + uint16_t userid_reserved_blocks; + uint16_t groupid_reserved_blocks; +} __attribute__((packed)) superblock_t; + +typedef struct ExtendedSuperblock { + uint32_t num_inodes; + uint32_t num_blocks; + uint32_t num_blocks_reserved; + uint32_t num_blocks_unallocated; + uint32_t num_inodes_unallocated; + uint32_t superblock_block_num; + uint32_t block_size; + uint32_t fragment_size; + uint32_t num_blocks_group; + uint32_t num_fragments_group; + uint32_t num_inodes_group; + uint32_t last_mount; + uint32_t last_write; + uint16_t num_mounts_since_fsck; + uint16_t num_mounts_allowed; + uint16_t ext2_signature; // 0xEF53 + uint16_t fs_state; + uint16_t when_error; + uint16_t minor_version; + uint32_t last_fsck; + uint32_t interval_fsck; + uint32_t os_id; + uint32_t major_version; + uint16_t userid_reserved_blocks; + uint16_t groupid_reserved_blocks; + uint32_t pad; + uint16_t inode_size; +} __attribute__((packed)) ext_superblock_t; + +typedef struct BlockGroupDescriptorTable { + uint32_t block_usage_bitmap; + uint32_t inode_usage_bitmap; + uint32_t starting_inode_table; + uint16_t num_unallocated_blocks_in_group; + uint16_t num_unallocated_inodes_in_group; + uint16_t num_directories_group; +} __attribute__((packed)) bgdt_t; + +typedef struct INode { + uint16_t types_permissions; + uint16_t user_id; + uint32_t low_32size; + uint32_t last_access_time; + uint32_t creation_time; + uint32_t last_modification_time; + uint32_t deletion_time; + uint16_t group_id; + uint16_t num_hard_links; + uint32_t num_disk_sectors; + uint32_t flags; + uint32_t os_specific; + uint32_t block_pointers[12]; + uint32_t single_indirect_block_pointer; + uint32_t double_indirect_block_pointer; + uint32_t triple_indirect_block_pointer; + uint32_t gen_number; + uint32_t _extended_attribute_block; + uint32_t _upper_32size; + uint32_t address_fragment; + uint32_t os_specific2; +} __attribute__((packed)) inode_t; + +// 0 Unknown type +// 1 Regular file +// 2 Directory +// 3 Character device +// 4 Block device +// 5 FIFO +// 6 Socket +// 7 Symbolic link (soft link) +#define TYPE_INDICATOR_UNKOWN 0 +#define TYPE_INDICATOR_REGULAR 1 +#define TYPE_INDICATOR_DIRECTORY 2 +#define TYPE_INDICATOR_CHARACTER_DEVICE 3 +#define TYPE_INDICATOR_BLOCK_DEVICE 4 +#define TYPE_INDICATOR_FIFO 5 +#define TYPE_INDICATOR_SOCKET 6 +#define TYPE_INDICATOR_SOFT_LINK 7 + +#define FIFO 0x1000 +#define CHARACTER_DEVICE 0x2000 +#define DIRECTORY 0x4000 +#define BLOCK_DEVICE 0x6000 +#define REGULAR_FILE 0x8000 +#define SYMBOLIC_LINK 0xA000 +#define UNIX_SOCKET 0xC000 + +typedef struct DirectoryEntryHeader { + uint32_t inode; + uint16_t size; + uint8_t name_length; + uint8_t type_indicator; +} __attribute__((packed)) direntry_header_t; + +int ext2_create_file(const char *path, int mode); +vfs_inode_t *ext2_mount(void); +void parse_superblock(void); +size_t ext2_read_file_offset(const char *file, unsigned char *data, + uint64_t size, uint64_t offset, + uint64_t *file_size); +size_t ext2_read_file(const char *file, unsigned char *data, size_t size, + uint64_t *file_size); +int ext2_create_directory(const char *path, int mode); +#endif diff --git a/kernel/fs/fifo.c b/kernel/fs/fifo.c new file mode 100644 index 0000000..d515ed7 --- /dev/null +++ b/kernel/fs/fifo.c @@ -0,0 +1,97 @@ +#include "fifo.h" +#include + +#define STARTING_SIZE 4096 + +void fifo_close(vfs_fd_t *fd) { + // TODO: Implement + (void)fd; + return; +} + +int fifo_object_write(uint8_t *buffer, uint64_t offset, uint64_t len, + FIFO_FILE *file) { + (void)offset; + file->has_data = 1; + if (file->write_len + len >= file->buffer_len) { + file->can_write = 0; + return -EAGAIN; + } + memcpy(file->buffer + file->write_len, buffer, len); + file->write_len += len; + return len; +} + +int fifo_object_read(uint8_t *buffer, uint64_t offset, uint64_t len, + FIFO_FILE *file) { + (void)offset; + if (file->write_len == 0) { + file->has_data = 0; + return -EAGAIN; + } + + if (len == 0) + return 0; + + file->can_write = 1; + if (len > file->write_len) + len = file->write_len; + + memcpy(buffer, file->buffer, len); + // Shift bufffer to the left + memcpy(file->buffer, file->buffer + len, file->buffer_len - len); + + file->write_len -= len; + if (file->write_len == 0) { + file->has_data = 0; + } + return len; +} + +FIFO_FILE *create_fifo_object(void) { + FIFO_FILE *n = kmalloc(sizeof(FIFO_FILE)); + n->buffer = kmalloc(STARTING_SIZE); + n->buffer_len = STARTING_SIZE; + n->write_len = 0; + return n; +} + +int create_fifo(void) { + + int fd_n = 0; + for (; get_current_task()->file_descriptors[fd_n]; fd_n++) + ; + + vfs_fd_t *fd = kmalloc(sizeof(vfs_fd_t)); + fd->flags = O_RDWR | O_NONBLOCK; + get_current_task()->file_descriptors[fd_n] = fd; + fd->inode = kmalloc(sizeof(vfs_inode_t)); + + fd->inode->internal_object = (void *)create_fifo_object(); + fd->inode->open = NULL; + fd->inode->read = fifo_read; + fd->inode->write = fifo_write; + fd->inode->close = fifo_close; + fd->inode->get_vm_object = NULL; + fd->inode->is_open = 1; + + return fd_n; +} + +int fifo_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + (void)offset; + FIFO_FILE *file = (FIFO_FILE *)fd->inode->internal_object; + int rc = fifo_object_write(buffer, offset, len, file); + fd->inode->has_data = file->has_data; + fd->inode->can_write = file->can_write; + return rc; +} + +int fifo_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + FIFO_FILE *file = (FIFO_FILE *)fd->inode->internal_object; + file->is_blocking = !(fd->flags & O_NONBLOCK); + int rc = fifo_object_read(buffer, offset, len, file); + fd->inode->has_data = file->has_data; + fd->inode->can_write = file->can_write; + return rc; +} diff --git a/kernel/fs/fifo.h b/kernel/fs/fifo.h new file mode 100644 index 0000000..1ba7168 --- /dev/null +++ b/kernel/fs/fifo.h @@ -0,0 +1,27 @@ +typedef struct S_FIFO_FILE FIFO_FILE; +#ifndef FIFO_H +#define FIFO_H +#include "vfs.h" +#include +#include + +struct S_FIFO_FILE { + char *buffer; + uint64_t buffer_len; + uint64_t write_len; + uint8_t is_blocking; + uint8_t has_data; + uint8_t can_write; +}; + +int create_fifo(void); +FIFO_FILE *create_fifo_object(void); +int fifo_object_write(uint8_t *buffer, uint64_t offset, uint64_t len, + FIFO_FILE *file); +int fifo_object_read(uint8_t *buffer, uint64_t offset, uint64_t len, + FIFO_FILE *file); +int fifo_write(uint8_t *buffer, uint64_t offset, uint64_t len, + vfs_fd_t *fd); +int fifo_read(uint8_t *buffer, uint64_t offset, uint64_t len, + vfs_fd_t *fd); +#endif diff --git a/kernel/fs/shm.c b/kernel/fs/shm.c new file mode 100644 index 0000000..4d5f2ab --- /dev/null +++ b/kernel/fs/shm.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +HashMap *shared_memory_objects; + +void shm_init(void) { shared_memory_objects = hashmap_create(10); } + +int shm_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + vfs_vm_object_t *p = fd->inode->internal_object; + + if (offset > p->size) + return -EFBIG; + + if (offset + len > p->size) + len = p->size - offset; + + memcpy((void *)((uintptr_t)((uintptr_t)p->virtual_object + offset)), buffer, + len); + return len; +} + +int shm_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + vfs_vm_object_t *p = fd->inode->internal_object; + + if (offset > p->size) + return -EFBIG; + + if (offset + len > p->size) + len = p->size - offset; + + memcpy((void *)buffer, + (void *)((uintptr_t)((uintptr_t)p->virtual_object + offset)), len); + return len; +} + +vfs_vm_object_t *shm_get_vm_object(uint64_t length, uint64_t offset, + vfs_fd_t *fd) { + (void)length; + (void)offset; + vfs_vm_object_t *p = fd->inode->internal_object; + return p; +} + +int shm_ftruncate(vfs_fd_t *fd, size_t length) { + vfs_vm_object_t *p = fd->inode->internal_object; + p->size = length; + p->virtual_object = ksbrk(length); + int n = (uintptr_t)align_page((void *)(uint32_t)length) / 0x1000; + p->object = kmalloc(sizeof(void *) * n); + for (int i = 0; i < n; i++) + p->object[i] = + (void *)(get_page(p->virtual_object + (i * 0x1000), NULL, 0, 0)->frame * + 0x1000); + return 0; +} + +int shm_open(const char *name, int oflag, mode_t mode) { + // Try to find or create a new shared memory object. + vfs_vm_object_t *internal_object = + hashmap_get_entry(shared_memory_objects, name); + if (!internal_object) { + // if (!(oflag & O_CREAT)) + // return -EMFILE; + internal_object = kmalloc(sizeof(vfs_vm_object_t)); + internal_object->object = NULL; + internal_object->size = 0; + hashmap_add_entry(shared_memory_objects, name, internal_object, NULL, 0); + } + + vfs_inode_t *inode = vfs_create_inode( + 0 /*inode_num*/, 0 /*type*/, 1 /*has_data*/, 1 /*can_write*/, + 1 /*is_open*/, internal_object, 0 /*file_size*/, NULL /*open*/, + NULL /*create_file*/, shm_read, shm_write, NULL /*close*/, + NULL /*create_directory*/, shm_get_vm_object, shm_ftruncate); + + vfs_fd_t *fd_ptr; + int fd = vfs_create_fd(oflag, mode, inode, &fd_ptr); + if (-1 == fd) { + kfree(inode); + return -EMFILE; + } + return fd; +} + +int shm_unlink(const char *name) { + (void)name; + return 0; +} diff --git a/kernel/fs/shm.h b/kernel/fs/shm.h new file mode 100644 index 0000000..fbbdb5c --- /dev/null +++ b/kernel/fs/shm.h @@ -0,0 +1,13 @@ +#ifndef SHM_H +#define SHM_H +#include +#include + +typedef int mode_t; + +void shm_init(void); +int shm_open(const char *name, int oflag, mode_t mode); +int shm_unlink(const char *name); +int ftruncate(int fildes, uint64_t length); + +#endif diff --git a/kernel/fs/tmpfs.c b/kernel/fs/tmpfs.c new file mode 100644 index 0000000..a9a3c1f --- /dev/null +++ b/kernel/fs/tmpfs.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include + +void tmp_close(vfs_fd_t *fd) { + fd->inode->is_open = 0; + ((tmp_inode *)fd->inode->internal_object)->read_inode->is_open = 0; +} + +int tmp_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + tmp_inode *calling_file = fd->inode->internal_object; + tmp_inode *child_file = calling_file->read_inode->internal_object; + if (child_file->is_closed) + return -EPIPE; + + int rc = fifo_object_write(buffer, offset, len, child_file->fifo); + calling_file->read_inode->has_data = child_file->fifo->has_data; + fd->inode->can_write = child_file->fifo->can_write; + return rc; +} + +int tmp_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + tmp_inode *calling_file = fd->inode->internal_object; + tmp_inode *child_file = calling_file->read_inode->internal_object; + if (calling_file->is_closed) + return -EPIPE; + + int rc = fifo_object_read(buffer, offset, len, calling_file->fifo); + fd->inode->has_data = calling_file->fifo->has_data; + calling_file->read_inode->can_write = child_file->fifo->can_write; + return rc; +} + +void dual_pipe(int fd[2]) { + for (int i = 0; i < 2; i++) { + tmp_inode *pipe = kmalloc(sizeof(tmp_inode)); + pipe->fifo = create_fifo_object(); + + int has_data = 0; + int can_write = 1; + int is_open = 1; + void *internal_object = pipe; + vfs_inode_t *inode = vfs_create_inode( + 0 /*inode_num*/, 0 /*type*/, has_data, can_write, is_open, + internal_object, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/, + tmp_read, tmp_write, tmp_close, NULL /*create_directory*/, + NULL /*get_vm_object*/, NULL /*truncate*/); + assert(inode); + + vfs_fd_t *fd_ptr; + fd[i] = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, inode, &fd_ptr); + assert(-1 != fd[i]); + } + vfs_inode_t *f_inode = get_current_task()->file_descriptors[fd[0]]->inode; + vfs_inode_t *s_inode = get_current_task()->file_descriptors[fd[1]]->inode; + tmp_inode *f_pipe = f_inode->internal_object; + tmp_inode *s_pipe = s_inode->internal_object; + f_pipe->read_inode = s_inode; + s_pipe->read_inode = f_inode; + f_pipe->is_closed = 0; + s_pipe->is_closed = 0; +} + +void pipe(int fd[2]) { + for (int i = 0; i < 2; i++) { + tmp_inode *pipe = kmalloc(sizeof(tmp_inode)); + pipe->fifo = create_fifo_object(); + + int has_data = 0; + int can_write = 1; + int is_open = 1; + void *internal_object = pipe; + vfs_inode_t *inode = vfs_create_inode( + 0 /*inode_num*/, 0 /*type*/, has_data, can_write, is_open, + internal_object, 0 /*file_size*/, NULL /*open*/, NULL /*create_file*/, + tmp_read, tmp_write, tmp_close, NULL /*create_directory*/, + NULL /*get_vm_object*/, NULL/*truncate*/); + assert(inode); + + vfs_fd_t *fd_ptr; + fd[i] = vfs_create_fd(O_RDWR, 0, inode, &fd_ptr); + assert(-1 != fd[i]); + } + vfs_inode_t *f_inode = get_current_task()->file_descriptors[fd[0]]->inode; + vfs_inode_t *s_inode = get_current_task()->file_descriptors[fd[1]]->inode; + tmp_inode *f_pipe = f_inode->internal_object; + tmp_inode *s_pipe = s_inode->internal_object; + f_pipe->read_inode = s_inode; + s_pipe->read_inode = f_inode; + f_pipe->is_closed = 0; + s_pipe->is_closed = 0; +} diff --git a/kernel/fs/tmpfs.h b/kernel/fs/tmpfs.h new file mode 100644 index 0000000..4052bd5 --- /dev/null +++ b/kernel/fs/tmpfs.h @@ -0,0 +1,16 @@ +#ifndef TMP_H +#define TMP_H +#include +#include + +#define TMP_BUFFER_SIZE (1024 * 10) + +typedef struct { + FIFO_FILE *fifo; + uint8_t is_closed; + vfs_inode_t *read_inode; +} tmp_inode; + +void pipe(int fd[2]); +void dual_pipe(int fd[2]); +#endif diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c new file mode 100644 index 0000000..0c616a2 --- /dev/null +++ b/kernel/fs/vfs.c @@ -0,0 +1,318 @@ +#include +#include +#include +#include +#include + +vfs_inode_t *root_dir; +vfs_mounts_t mounts[10]; +int num_mounts = 0; + +vfs_fd_t *get_vfs_fd(int fd) { + if (fd >= 100) { + klog("get_vfs_fd(): Tried to get out of range fd", LOG_WARN); + dump_backtrace(12); + return NULL; + } + if (fd < 0) { + klog("get_vfs_fd(): Tried to get out of range fd", LOG_WARN); + dump_backtrace(12); + return NULL; + } + return get_current_task()->file_descriptors[fd]; +} + +vfs_inode_t *vfs_create_inode( + int inode_num, int type, uint8_t has_data, uint8_t can_write, + uint8_t is_open, void *internal_object, uint64_t file_size, + vfs_inode_t *(*open)(const char *path), + int (*create_file)(const char *path, int mode), + int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), + int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), + void (*close)(vfs_fd_t *fd), + int (*create_directory)(const char *path, int mode), + vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset, + vfs_fd_t *fd), + int (*truncate)(vfs_fd_t *fd, size_t length)) { + vfs_inode_t *r = kmalloc(sizeof(inode_t)); + r->inode_num = inode_num; + r->type = type; + r->has_data = has_data; + r->can_write = can_write; + r->is_open = is_open; + r->internal_object = internal_object; + r->file_size = file_size; + r->open = open; + r->create_file = create_file; + r->read = read; + r->write = write; + r->close = close; + r->create_directory = create_directory; + r->get_vm_object = get_vm_object; + r->truncate = truncate; + return r; +} + +int vfs_create_fd(int flags, int mode, vfs_inode_t *inode, vfs_fd_t **fd) { + process_t *p = (process_t *)get_current_task(); + int i; + for (i = 0; i < 100; i++) + if (!p->file_descriptors[i]) + break; + if (p->file_descriptors[i]) + return -1; + vfs_fd_t *r = kmalloc(sizeof(vfs_fd_t)); + r->flags = flags; + r->mode = mode; + r->inode = inode; + r->reference_count = 1; + p->file_descriptors[i] = r; + if (fd) + *fd = r; + return i; +} + +int vfs_create_file(const char *file) { + vfs_mounts_t *file_mount = 0; + int length = 0; + for (int i = 0; i < num_mounts; i++) { + int path_len = strlen(mounts[i].path); + if (path_len <= length) + continue; + + if (isequal_n(mounts[i].path, file, path_len)) { + length = path_len; + file_mount = &mounts[i]; + } + } + if (1 != length) + file += length; + + if (!file_mount) { + kprintf("vfs_internal_open could not find mounted path for file : %s\n", + file); + return 0; + } + // ext2_create_file("/etc/oscreated", 0); + assert(file_mount->local_root->create_file); + kprintf("Creating a file\n"); + return file_mount->local_root->create_file(file, 0); +} + +vfs_inode_t *vfs_internal_open(const char *file) { + vfs_mounts_t *file_mount = 0; + int length = 0; + for (int i = 0; i < num_mounts; i++) { + int path_len = strlen(mounts[i].path); + if (path_len <= length) + continue; + + if (isequal_n(mounts[i].path, file, path_len)) { + length = path_len; + file_mount = &mounts[i]; + } + } + if (1 != length) + file += length; + + if (!file_mount) { + kprintf("vfs_internal_open could not find mounted path for file : %s\n", + file); + return NULL; + } + + vfs_inode_t *ret = file_mount->local_root->open(file); + return ret; +} + +char *vfs_clean_path(const char *path, char *resolved_path) { + // char *const clean = kmalloc(strlen(path) + 1); + char *clean = resolved_path; + int prev_slash = 0; + char *ptr = clean; + for (; *path; path++) { + if (prev_slash && '/' == *path) { + continue; + } + prev_slash = ('/' == *path); + *ptr = *path; + ptr++; + } + *ptr = '\0'; + return clean; +} + +char *vfs_resolve_path(const char *file, char *resolved_path) { + if ('/' == *file) { + return vfs_clean_path(file, resolved_path); + } + const char *cwd = get_current_task()->current_working_directory; + size_t l = strlen(cwd); + assert(l > 0); + assert('/' == cwd[l - 1]); + // char *r = kmalloc(l + strlen(file) + 1); + char r[256]; + strcpy(r, cwd); + strcat(r, file); + char *final = vfs_clean_path(r, resolved_path); + // kfree(r); + return final; +} + +int vfs_mkdir(const char *path, int mode) { + vfs_mounts_t *file_mount = 0; + int length = 0; + for (int i = 0; i < num_mounts; i++) { + int path_len = strlen(mounts[i].path); + if (path_len <= length) + continue; + + if (isequal_n(mounts[i].path, path, path_len)) { + length = path_len; + file_mount = &mounts[i]; + } + } + if (1 != length) + path += length; + + if (!file_mount) { + kprintf("vfs_internal_open could not find mounted path for file : %s\n", + path); + return 0; + } + assert(file_mount->local_root->create_directory); + // TODO: Error checking, don't just assume it is fine + file_mount->local_root->create_directory(path, mode); + return 0; +} + +int vfs_open(const char *file, int flags, int mode) { + char resolved_path[256] = {0}; + vfs_resolve_path(file, resolved_path); + vfs_inode_t *inode = vfs_internal_open(resolved_path); + if (0 == inode) { + if (mode & O_CREAT) { + if (vfs_create_file(resolved_path)) { + klog("VFS: File created", LOG_NOTE); + return vfs_open(file, flags, mode); + } + klog("VFS: Could not create file", LOG_WARN); + } + return -ENOENT; + } + if (inode->type == FS_TYPE_UNIX_SOCKET) { + return uds_open(resolved_path); + } + + return vfs_create_fd(flags, mode, inode, NULL); +} + +int vfs_close(int fd) { + vfs_fd_t *fd_ptr = get_vfs_fd(fd); + if (NULL == fd_ptr) { + return -1; + } + assert(0 < fd_ptr->reference_count); + // Remove process reference + fd_ptr->reference_count--; + get_current_task()->file_descriptors[fd] = 0; + // If no references left then free the contents + if (0 == fd_ptr->reference_count) { + if (fd_ptr->inode->close) + fd_ptr->inode->close(fd_ptr); + + kfree(fd_ptr); + } + return 0; +} + +int raw_vfs_pread(vfs_fd_t *vfs_fd, void *buf, uint64_t count, + uint64_t offset) { + if (!(vfs_fd->flags & O_READ)) + return -EBADF; + return vfs_fd->inode->read(buf, offset, count, vfs_fd); +} + +int vfs_pread(int fd, void *buf, uint64_t count, uint64_t offset) { + if (fd >= 100) { + kprintf("EBADF : %x\n", fd); + return -EBADF; + } + if (fd < 0) { + dump_backtrace(12); + kprintf("EBADF : %x\n", fd); + return -EBADF; + } + vfs_fd_t *vfs_fd = get_current_task()->file_descriptors[fd]; + if (!vfs_fd) + return -EBADF; + int rc = raw_vfs_pread(vfs_fd, buf, count, offset); + if (-EAGAIN == rc && count > 0) { + if (!(vfs_fd->flags & O_NONBLOCK)) { + struct pollfd fds; + fds.fd = fd; + fds.events = POLLIN; + fds.revents = 0; + poll(&fds, 1, 0); + return vfs_pread(fd, buf, count, offset); + } + } + return rc; +} + +int raw_vfs_pwrite(vfs_fd_t *vfs_fd, void *buf, uint64_t count, + uint64_t offset) { + assert(vfs_fd); + assert(vfs_fd->inode); + assert(vfs_fd->inode->write); + return vfs_fd->inode->write(buf, offset, count, vfs_fd); +} + +int vfs_pwrite(int fd, void *buf, uint64_t count, uint64_t offset) { + vfs_fd_t *vfs_fd = get_vfs_fd(fd); + if (!vfs_fd) + return -EBADF; + if (!(vfs_fd->flags & O_WRITE)) { + return -EBADF; + } + return raw_vfs_pwrite(vfs_fd, buf, count, offset); +} + +vfs_vm_object_t *vfs_get_vm_object(int fd, uint64_t length, uint64_t offset) { + vfs_fd_t *vfs_fd = get_vfs_fd(fd); + if (!vfs_fd) + return NULL; + vfs_vm_object_t *r = vfs_fd->inode->get_vm_object(length, offset, vfs_fd); + return r; +} + +int vfs_dup2(int org_fd, int new_fd) { + get_current_task()->file_descriptors[new_fd] = + get_current_task()->file_descriptors[org_fd]; + get_current_task()->file_descriptors[new_fd]->reference_count++; + return 1; +} + +int vfs_ftruncate(int fd, size_t length) { + vfs_fd_t *fd_ptr = get_vfs_fd(fd); + if (!fd_ptr) + return -EBADF; + if (!(fd_ptr->flags & O_READ)) + return -EINVAL; + vfs_inode_t *inode = fd_ptr->inode; + if (!inode) + return -EINVAL; + if (!inode->truncate) + return -EINVAL; + + return inode->truncate(fd_ptr, length); +} + +void vfs_mount(char *path, vfs_inode_t *local_root) { + int len = strlen(path); + mounts[num_mounts].path = kmalloc_eternal(len + 1); + memcpy(mounts[num_mounts].path, path, len); + mounts[num_mounts].path[len] = '\0'; + mounts[num_mounts].local_root = local_root; + num_mounts++; +} diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h new file mode 100644 index 0000000..f8a4b19 --- /dev/null +++ b/kernel/fs/vfs.h @@ -0,0 +1,100 @@ +typedef struct vfs_fd vfs_fd_t; +typedef struct vfs_inode vfs_inode_t; +typedef struct vfs_vm_object vfs_vm_object_t; +typedef struct vfs_mounts vfs_mounts_t; +#ifndef VFS_H +#define VFS_H +#include +#include +#include +#include +#include + +// FIXME: Is there some standard value for this? +#define O_NONBLOCK (1 << 0) +#define O_READ (1 << 1) +#define O_WRITE (1 << 2) +#define O_CREAT (1 << 3) +#define O_RDONLY O_READ +#define O_WRONLY O_WRITE +#define O_RDWR (O_WRITE | O_READ) + +#define FS_TYPE_FILE 0 +#define FS_TYPE_UNIX_SOCKET 1 +#define FS_TYPE_CHAR_DEVICE 2 +#define FS_TYPE_BLOCK_DEVICE 3 +#define FS_TYPE_DIRECTORY 4 +#define FS_TYPE_LINK 7 + +struct vfs_vm_object { + void *virtual_object; + void **object; + uint64_t size; +}; + +struct vfs_mounts { + char *path; + vfs_inode_t *local_root; +}; + +struct dirent { + unsigned int d_ino; // File serial number. + char d_name[PATH_MAX]; // Filename string of entry. +}; + +struct vfs_fd { + size_t offset; + int flags; + int mode; + int reference_count; // Number of usages of this file descriptor, + // once it reaches zero then the contents can + // be freed. + vfs_inode_t *inode; +}; + +struct vfs_inode { + int inode_num; + int type; + uint8_t has_data; + uint8_t can_write; + uint8_t is_open; + void *internal_object; + uint64_t file_size; + vfs_inode_t *(*open)(const char *path); + int (*create_file)(const char *path, int mode); + int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd); + int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd); + void (*close)(vfs_fd_t *fd); + int (*create_directory)(const char *path, int mode); + vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset, + vfs_fd_t *fd); + int (*truncate)(vfs_fd_t *fd, size_t length); +}; + +int vfs_close(int fd); +vfs_fd_t *get_vfs_fd(int fd); +int vfs_open(const char *file, int flags, int mode); +void vfs_mount(char *path, vfs_inode_t *local_root); +int vfs_pwrite(int fd, void *buf, uint64_t count, uint64_t offset); +int raw_vfs_pwrite(vfs_fd_t *vfs_fd, void *buf, uint64_t count, + uint64_t offset); +int vfs_pread(int fd, void *buf, uint64_t count, uint64_t offset); +vfs_vm_object_t *vfs_get_vm_object(int fd, uint64_t length, uint64_t offset); +int vfs_dup2(int org_fd, int new_fd); +vfs_inode_t *vfs_internal_open(const char *file); +int vfs_mkdir(const char *path, int mode); +int vfs_create_fd(int flags, int mode, vfs_inode_t *inode, vfs_fd_t **fd); +int vfs_ftruncate(int fd, size_t length); +vfs_inode_t *vfs_create_inode( + int inode_num, int type, uint8_t has_data, uint8_t can_write, + uint8_t is_open, void *internal_object, uint64_t file_size, + vfs_inode_t *(*open)(const char *path), + int (*create_file)(const char *path, int mode), + int (*read)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), + int (*write)(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd), + void (*close)(vfs_fd_t *fd), + int (*create_directory)(const char *path, int mode), + vfs_vm_object_t *(*get_vm_object)(uint64_t length, uint64_t offset, + vfs_fd_t *fd), + int (*truncate)(vfs_fd_t *fd, size_t length)); +#endif diff --git a/kernel/halts.c b/kernel/halts.c new file mode 100644 index 0000000..821299d --- /dev/null +++ b/kernel/halts.c @@ -0,0 +1,102 @@ +#include +#include +#include + +int create_disconnect_inode_halt(vfs_inode_t *inode) { + volatile process_t *p = get_current_task(); + int i; + for (i = 0; i < 100; i++) + if (!p->disconnect_halt_inode[i]) + break; + + if (p->disconnect_halt_inode[i]) + return -1; + + p->disconnect_halt_inode[i] = inode; + + return i; +} + +int create_disconnect_fdhalt(vfs_fd_t *fd) { + assert(fd); + return create_disconnect_inode_halt(fd->inode); +} + +int create_read_inode_halt(vfs_inode_t *inode) { + volatile process_t *p = get_current_task(); + int i; + for (i = 0; i < 100; i++) + if (!p->read_halt_inode[i]) + break; + + if (p->read_halt_inode[i]) + return -1; + + p->read_halt_inode[i] = inode; + + return i; +} + +int create_read_fdhalt(vfs_fd_t *fd) { + assert(fd); + return create_read_inode_halt(fd->inode); +} + +int create_write_inode_halt(vfs_inode_t *inode) { + volatile process_t *p = get_current_task(); + int i; + for (i = 0; i < 100; i++) + if (!p->write_halt_inode[i]) + break; + + if (p->write_halt_inode[i]) + return -1; + + p->write_halt_inode[i] = inode; + + return i; +} + +int create_write_fdhalt(vfs_fd_t *fd) { + return create_write_inode_halt(fd->inode); +} + +void unset_read_fdhalt(int i) { get_current_task()->read_halt_inode[i] = NULL; } + +void unset_write_fdhalt(int i) { + get_current_task()->write_halt_inode[i] = NULL; +} + +void unset_disconnect_fdhalt(int i) { + get_current_task()->disconnect_halt_inode[i] = NULL; +} + +int isset_fdhalt(vfs_inode_t *read_halts[], vfs_inode_t *write_halts[], + vfs_inode_t *disconnect_halts[]) { + int blocked = 0; + for (int i = 0; i < 100; i++) { + if (!read_halts[i]) + continue; + if (read_halts[i]->has_data) { + return 0; + } + blocked = 1; + } + for (int i = 0; i < 100; i++) { + if (!write_halts[i]) + continue; + if (write_halts[i]->can_write) { + return 0; + } + blocked = 1; + } + for (int i = 0; i < 100; i++) { + if (!disconnect_halts[i]) + continue; + if (!disconnect_halts[i]->is_open) { + return 0; + } + blocked = 1; + } + return blocked; +} diff --git a/kernel/halts.h b/kernel/halts.h new file mode 100644 index 0000000..bd71673 --- /dev/null +++ b/kernel/halts.h @@ -0,0 +1,21 @@ +#ifndef HALTS_H +#define HALTS_H +#include +#include + +typedef struct { + uint8_t *ptr; + uint8_t active; +} halt_t; + +int create_read_fdhalt(vfs_fd_t *fd); +int create_read_inode_halt(vfs_inode_t *inode); +void unset_read_fdhalt(int i); +int create_write_fdhalt(vfs_fd_t *fd); +int create_write_inode_halt(vfs_inode_t *inode); +void unset_write_fdhalt(int i); +int create_disconnect_fdhalt(vfs_fd_t *fd); +void unset_disconnect_fdhalt(int i); +int isset_fdhalt(vfs_inode_t *read_halts[], vfs_inode_t *write_halts[], + vfs_inode_t *disconnect_halts[]); +#endif diff --git a/kernel/hashmap/hashmap.c b/kernel/hashmap/hashmap.c new file mode 100644 index 0000000..2eeef98 --- /dev/null +++ b/kernel/hashmap/hashmap.c @@ -0,0 +1,212 @@ +// +// Copyright (C) 2022 by Anton Kling +// +// SPDX-License-Identifier: BSD-2-Clause +// +/* + * HashMap + * ------- + * This hashmap works by creating a array of linked lists and associating + * the "key" with a specific entry in the array. This is done through a + * hash. Once the linked list is found it goes through it until it finds + * a entry that has the "key" provided. + * + * Changing the hashing function + * ----------------------------- + * The default hashing function in this library is a custom made + * one that can be found in hash.c. But it should be possible to use any + * other hashing algorithm should you want to as long as it uses these + * types: + * uint32_t hash_function(uint8_t*, size_t) + * + * The hashing algorithm can be changed via changing the "hash_function" + * pointer in the HashMap structure. + * + * Important to note that the hashing function shall not be changed + * after having added entries to the hashmap as the key to linked list + * pairing will change. + */ +#include "hashmap.h" + +#include +#include +#include +#include + +#define CONSTANT 0x031b5515 + +uint32_t mix(uint32_t x) { + x ^= CONSTANT; + x ^= (x << 13); + x ^= (x >> 7); + x ^= (x << 17); + return x; +} + +uint32_t hash(const uint8_t *data, size_t len) { + uint32_t hash = 0; + for (; len;) { + uint32_t value = 0; + uint8_t read_len = (sizeof(uint32_t) < len) ? sizeof(uint32_t) : len; + memcpy(&value, data, read_len); + hash ^= mix(value); + data += read_len; + len -= read_len; + } + return hash; +} + +char *copy_c_string(const char *str) { + char *ret_string; + size_t len = strlen(str); + ret_string = kmalloc(len + 1); + if (!ret_string) + return NULL; + memcpy(ret_string, str, len); + ret_string[len] = '\0'; + return ret_string; +} + +uint32_t limit_hash(HashMap *m, uint32_t hash) { return hash % m->size; } + +void free_linkedlist_entry(LinkedList *entry) { + if (entry->key_allocated) { + // If the key is allocated by the hashmap library then it owns the + // key and can safley discard the const qualifier and override its + // contents + kfree((char *)entry->key); + } + kfree(entry); +} + +LinkedList *get_linkedlist_entry(LinkedList *list, const char *key, + LinkedList **prev) { + if (prev) + *prev = NULL; + for (; list; list = list->next) { + const char *str1 = key; + const char *str2 = list->key; + for (; *str1 && *str2; str1++, str2++) + if (*str1 != *str2) + break; + if (*str1 == *str2) + return list; + if (prev) + prev = &list; + } + return NULL; +} + +void *get_linkedlist_value(LinkedList *list, const char *key) { + LinkedList *entry = get_linkedlist_entry(list, key, NULL); + if (!entry) + return NULL; + return entry->value; +} + +uint32_t find_index(HashMap *m, const char *key) { + return limit_hash(m, m->hash_function((uint8_t *)key, strlen(key))); +} + +int hashmap_add_entry(HashMap *m, const char *key, void *value, + void (*upon_deletion)(const char *, void *), + int do_not_allocate_key) { + // Create the entry + LinkedList *entry = kmalloc(sizeof(LinkedList)); + if (!entry) + return 0; + + entry->key_allocated = !do_not_allocate_key; + if (do_not_allocate_key) { + entry->key = key; + } else { + if (!(entry->key = copy_c_string(key))) + return 0; + } + entry->value = value; + entry->next = NULL; + entry->upon_deletion = upon_deletion; + + // Add the new entry to the list. + uint32_t index = find_index(m, key); + LinkedList **list_pointer = &m->entries[index]; + for (; *list_pointer;) + list_pointer = &(*list_pointer)->next; + + *list_pointer = entry; + m->num_entries++; + return 1; +} + +void *hashmap_get_entry(HashMap *m, const char *key) { + uint32_t index = find_index(m, key); + if (!m->entries[index]) + return NULL; + return get_linkedlist_value(m->entries[index], key); +} + +int hashmap_delete_entry(HashMap *m, const char *key) { + LinkedList *list = m->entries[find_index(m, key)]; + if (!list) + return 0; + LinkedList **prev = NULL; + LinkedList *entry = get_linkedlist_entry(list, key, prev); + if (!entry) + return 0; + if (!prev) + prev = &m->entries[find_index(m, key)]; + + if (entry->upon_deletion) + entry->upon_deletion(entry->key, entry->value); + + LinkedList *next = entry->next; + free_linkedlist_entry(entry); + if (*prev != entry) + (*prev)->next = next; + else + *prev = NULL; + + // Redo the delete process incase there are multiple + // entires that have the same key. + hashmap_delete_entry(m, key); + m->num_entries--; + return 1; +} + +void hashmap_free(HashMap *m) { + for (int i = 0; i < m->size; i++) { + if (!m->entries[i]) + continue; + LinkedList *list = m->entries[i]; + for (; list;) { + if (list->upon_deletion) + list->upon_deletion(list->key, list->value); + LinkedList *old = list; + list = list->next; + free_linkedlist_entry(old); + } + } + kfree(m->entries); + kfree(m); +} + +HashMap *hashmap_create(size_t size) { + HashMap *m = kmalloc(sizeof(HashMap)); + if (!m) + return NULL; + + m->size = size; + m->num_entries = 0; + + // Create a array of pointers to linkedlists but don't create them + // yet. + m->entries = kcalloc(size, sizeof(LinkedList **)); + if (!m->entries) + return NULL; + + for (size_t i = 0; i < m->size; i++) + m->entries[i] = NULL; + + m->hash_function = hash; + return m; +} diff --git a/kernel/hashmap/hashmap.h b/kernel/hashmap/hashmap.h new file mode 100644 index 0000000..40f146a --- /dev/null +++ b/kernel/hashmap/hashmap.h @@ -0,0 +1,39 @@ +// +// Copyright (C) 2022 by Anton Kling +// +// SPDX-License-Identifier: BSD-2-Clause +// +#ifndef HASHMAP_H +#define HASHMAP_H +#include +#include + +typedef struct LinkedList { + const char *key; + int key_allocated; + void *value; + void (*upon_deletion)(const char *, void *); + struct LinkedList *next; +} LinkedList; + +typedef struct HashMap { + LinkedList **entries; + size_t size; + size_t num_entries; + uint32_t (*hash_function)(const uint8_t *data, size_t len); +} HashMap; + +HashMap *hashmap_create(size_t size); +void hashmap_free(HashMap *m); + +// hashmap_add_entry() +// ------------------- +// This function adds a entry to the hashmap. The "key" passed to the +// hashmap will be allocated by default unless (do_not_allocate_key) is +// set to 1. +int hashmap_add_entry(HashMap *m, const char *key, void *value, + void (*upon_deletion)(const char *, void *), + int do_not_allocate_key); +void *hashmap_get_entry(HashMap *m, const char *key); +int hashmap_delete_entry(HashMap *m, const char *key); +#endif diff --git a/kernel/includes/defs.h b/kernel/includes/defs.h new file mode 100644 index 0000000..3a373b3 --- /dev/null +++ b/kernel/includes/defs.h @@ -0,0 +1,5 @@ +#ifndef DEFS_H +#define DEFS_H +#define BYTE unsigned char +#define BYTEPTR BYTE* +#endif diff --git a/kernel/includes/math.h b/kernel/includes/math.h new file mode 100644 index 0000000..19fc595 --- /dev/null +++ b/kernel/includes/math.h @@ -0,0 +1,2 @@ +int min(int a, int b); +int max(int a, int b); diff --git a/kernel/includes/mmu.h b/kernel/includes/mmu.h new file mode 100644 index 0000000..1df337d --- /dev/null +++ b/kernel/includes/mmu.h @@ -0,0 +1,61 @@ +#ifndef PAGING_H +#define PAGING_H +#include "kmalloc.h" +#include + +typedef uint8_t mmu_flags; + +#define MMU_FLAG_RW (1 << 0) +#define MMU_FLAG_KERNEL (1 << 1) + +void *next_page(void *a); +void *align_page(void *a); + +typedef struct Page { + uint32_t present : 1; + uint32_t rw : 1; + uint32_t user : 1; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t unused : 7; + uint32_t frame : 20; +} __attribute__((packed)) Page; + +typedef struct PageTable { + Page pages[1024]; +} __attribute__((packed)) PageTable; + +typedef struct PageDirectory { + PageTable *tables[1024]; + uint32_t physical_tables[1024]; + uint32_t physical_address; +} PageDirectory; + +int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags, PageDirectory *pd); +void mmu_allocate_shared_kernel_region(void *rc, size_t n); +void *mmu_find_unallocated_virtual_range(void *addr, size_t length); +void mmu_remove_virtual_physical_address_mapping(void *ptr, size_t length); +void mmu_free_address_range(void *ptr, size_t length); +void mmu_map_directories(void *dst, PageDirectory *d, void *src, + PageDirectory *s, size_t length); +uint32_t mmu_get_number_of_allocated_frames(void); +void *mmu_map_frames(void *ptr, size_t s); +void mmu_map_physical(void *dst, PageDirectory *d, void *physical, + size_t length); +void mmu_free_pages(void *a, uint32_t n); + +void flush_tlb(void); +void paging_init(void); +PageDirectory *get_active_pagedirectory(void); +void move_stack(uint32_t new_stack_address, uint32_t size); +void switch_page_directory(PageDirectory *directory); +void *allocate_frame(Page *page, int rw, int is_kernel); +PageDirectory *clone_directory(PageDirectory *original); +void *virtual_to_physical(void *address, PageDirectory *directory); +void *is_valid_userpointer(const void *const p, size_t s); +void *is_valid_user_c_string(const char *ptr, size_t *size); +void *ksbrk(size_t s); + +Page *get_page(void *ptr, PageDirectory *directory, int create_new_page, + int set_user); +#endif diff --git a/kernel/includes/signal.h b/kernel/includes/signal.h new file mode 100644 index 0000000..3de9998 --- /dev/null +++ b/kernel/includes/signal.h @@ -0,0 +1,46 @@ +#ifndef SIGNAL_H +#define SIGNAL_H +#include +#define SIGHUP 0 +#define SIGINT 1 +#define SIGWINCH 2 +#define SIGQUIT 3 +#define SIG_IGN 4 +typedef int pid_t; +typedef int uid_t; +typedef int sigset_t; + +union sigval { + int sival_int; // Integer signal value. + void *sival_ptr; // Pointer signal value. +}; + +struct siginfo { + int si_signo; // Signal number. + int si_code; // Signal code. + int si_errno; // If non-zero, an errno value associated with + // this signal, as described in . + pid_t si_pid; // Sending process ID. + uid_t si_uid; // Real user ID of sending process. + void *si_addr; // Address of faulting instruction. + int si_status; // Exit value or signal. + long si_band; // Band event for SIGPOLL. + union sigval si_value; // Signal value. +}; + +typedef struct siginfo siginfo_t; + +int kill(pid_t pid, int sig); + +struct sigaction { + void (*sa_handler)(int); // Pointer to a signal-catching function or one of + // the macros SIG_IGN or SIG_DFL. + sigset_t sa_mask; // Additional set of signals to be blocked during execution + // of signal-catching function. + int sa_flags; // Special flags to affect behavior of signal. + void (*sa_sigaction)(int, siginfo_t *, + void *); // Pointer to a signal-catching function. +}; + +int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); +#endif // SIGNAL_H diff --git a/kernel/includes/sys/types.h b/kernel/includes/sys/types.h new file mode 100644 index 0000000..1ccbf63 --- /dev/null +++ b/kernel/includes/sys/types.h @@ -0,0 +1,2 @@ +typedef int time_t; +typedef int pid_t; diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c new file mode 100644 index 0000000..8c0f70c --- /dev/null +++ b/kernel/init/kernel.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) +#error "You are not using a cross-compiler." +#endif + +#if !defined(__i386__) +#error "This OS needs to be compiled with a ix86-elf compiler" +#endif + +uint32_t inital_esp; +uintptr_t data_end; + +void kernel_main(uint32_t kernel_end, unsigned long magic, unsigned long addr, + uint32_t inital_stack) { + data_end = kernel_end; + inital_esp = inital_stack; + + asm("cli"); + kprintf("If you see this then the serial driver works :D.\n"); + assert(magic == MULTIBOOT_BOOTLOADER_MAGIC); + + paging_init(); + klog("Paging Initalized", LOG_SUCCESS); + multiboot_info_t *mb = + mmu_map_frames((multiboot_info_t *)addr, sizeof(multiboot_info_t)); + + gdt_init(); + klog("GDT Initalized", LOG_SUCCESS); + + idt_init(); + klog("IDT Initalized", LOG_SUCCESS); + + syscalls_init(); + klog("Syscalls Initalized", LOG_SUCCESS); + + pit_install(); + set_pit_count(2000); + klog("PIT driver installed", LOG_SUCCESS); + + ata_init(); + klog("ATA Initalized", LOG_SUCCESS); + + tasking_init(); + klog("Tasking Initalized", LOG_SUCCESS); + + install_mouse(); + klog("PS2 Mouse driver installed", LOG_SUCCESS); + + install_keyboard(); + klog("PS2 Keyboard driver installed", LOG_SUCCESS); + + vfs_mount("/", ext2_mount()); + vfs_mount("/dev", devfs_mount()); + add_stdout(); + add_serial(); + add_random_devices(); + shm_init(); + + setup_random(); + + add_keyboard(); + add_mouse(); + rtl8139_init(); + + display_driver_init(mb); + add_vbe_device(); + int pid; + if (0 == (pid = fork())) { + char *argv[] = {"/init", NULL}; + if (0 == exec("/init", argv)) { + kprintf("exec() failed\n"); + } + } + for (;;) + ; +} diff --git a/kernel/isodir/boot/grub/grub.cfg b/kernel/isodir/boot/grub/grub.cfg new file mode 100644 index 0000000..b2f8404 --- /dev/null +++ b/kernel/isodir/boot/grub/grub.cfg @@ -0,0 +1,3 @@ +menuentry "myos" { + multiboot /boot/myos.bin +} diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c new file mode 100644 index 0000000..34c466d --- /dev/null +++ b/kernel/kmalloc.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#define NEW_ALLOC_SIZE 0x30000 + +#define IS_FREE (1 << 0) +#define IS_FINAL (1 << 1) + +typedef struct MallocHeader { + uint64_t magic; + uint32_t size; + uint8_t flags; + struct MallocHeader *n; +} MallocHeader; + +uint64_t delta_page(uint64_t a) { return 0x1000 - (a % 0x1000); } + +MallocHeader *head = NULL; +MallocHeader *final = NULL; +uint32_t total_heap_size = 0; + +int init_heap(void) { + head = (MallocHeader *)ksbrk(NEW_ALLOC_SIZE); + total_heap_size += NEW_ALLOC_SIZE - sizeof(MallocHeader); + head->magic = 0xdde51ab9410268b1; + head->size = NEW_ALLOC_SIZE - sizeof(MallocHeader); + head->flags = IS_FREE | IS_FINAL; + head->n = NULL; + final = head; + return 1; +} + +int add_heap_memory(size_t min_desired) { + min_desired += sizeof(MallocHeader) + 0x1000; + size_t allocation_size = max(min_desired, NEW_ALLOC_SIZE); + allocation_size += delta_page(allocation_size); + void *p; + if ((void *)(-1) == (p = (void *)ksbrk(allocation_size))) { + return 0; + } + total_heap_size += allocation_size - sizeof(MallocHeader); + void *e = final; + e = (void *)((uint32_t)e + final->size); + if (p == e) { + final->size += allocation_size - sizeof(MallocHeader); + return 1; + } + MallocHeader *new_entry = p; + new_entry->size = allocation_size - sizeof(MallocHeader); + new_entry->flags = IS_FREE | IS_FINAL; + new_entry->n = NULL; + new_entry->magic = 0xdde51ab9410268b1; + final->n = new_entry; + final = new_entry; + return 1; +} + +MallocHeader *next_header(MallocHeader *a) { + assert(a->magic == 0xdde51ab9410268b1); + if (a->n) { + assert(a->n->magic == 0xdde51ab9410268b1); + return a->n; + } + return NULL; +} + +MallocHeader *next_close_header(MallocHeader *a) { + if (!a) { + kprintf("next close header fail\n"); + for (;;) + ; + } + if (a->flags & IS_FINAL) + return NULL; + return next_header(a); +} + +MallocHeader *find_free_entry(uint32_t s) { + // A new header is required as well as the newly allocated chunk + s += sizeof(MallocHeader); + if (!head) + init_heap(); + MallocHeader *p = head; + for (; p; p = next_header(p)) { + assert(p->magic == 0xdde51ab9410268b1); + if (!(p->flags & IS_FREE)) + continue; + uint64_t required_size = s; + if (p->size < required_size) + continue; + return p; + } + return NULL; +} + +void merge_headers(MallocHeader *b) { + if (!(b->flags & IS_FREE)) + return; + + MallocHeader *n = next_close_header(b); + if (!n) + return; + + if (!(n->flags & IS_FREE)) + return; + + b->size += n->size; + b->flags |= n->flags & IS_FINAL; + b->n = n->n; + if (n == final) + final = b; +} + +void *kmalloc(size_t s) { + size_t n = s; + MallocHeader *free_entry = find_free_entry(s); + if (!free_entry) { + if (!add_heap_memory(s)) { + klog("Ran out of memory.", LOG_ERROR); + assert(0); + return NULL; + } + return kmalloc(s); + } + + void *rc = (void *)(free_entry + 1); + + // Create a new header + MallocHeader *new_entry = (MallocHeader *)((uintptr_t)rc + n); + new_entry->flags = free_entry->flags; + new_entry->n = free_entry->n; + new_entry->size = free_entry->size - n - sizeof(MallocHeader); + new_entry->magic = 0xdde51ab9410268b1; + + if (free_entry == final) + final = new_entry; + merge_headers(new_entry); + + // Modify the free entry + free_entry->size = n; + free_entry->flags = 0; + free_entry->n = new_entry; + free_entry->magic = 0xdde51ab9410268b1; + return rc; +} + +#define HEAP 0x00E00000 +#define PHYS 0x403000 + +void *latest = NULL; +uint64_t left = 0; + +void *kmalloc_eternal_physical_align(size_t s, void **physical) { + void *return_address = ksbrk(s); + if (physical) { + if (0 == get_active_pagedirectory()) + *physical = + (void *)((uintptr_t)return_address - (0xC0000000 + PHYS) + HEAP); + else + *physical = (void *)virtual_to_physical(return_address, 0); + } + memset(return_address, 0, 0x1000); + return return_address; +} + +void *kmalloc_eternal_align(size_t s) { + return kmalloc_eternal_physical_align(s, NULL); +} + +void *kmalloc_eternal(size_t s) { return kmalloc_eternal_align(s); } + +size_t get_mem_size(void *ptr) { + if (!ptr) + return 0; + return ((MallocHeader *)((uintptr_t)ptr - sizeof(MallocHeader)))->size; +} + +void *krealloc(void *ptr, size_t size) { + void *rc = kmalloc(size); + if (!rc) + return NULL; + if (!ptr) + return rc; + size_t l = get_mem_size(ptr); + size_t to_copy = min(l, size); + memcpy(rc, ptr, to_copy); + // kfree(ptr); + return rc; +} + +// This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX +// if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void *kreallocarray(void *ptr, size_t nmemb, size_t size) { + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && + SIZE_MAX / nmemb < size) { + return NULL; + } + + return krealloc(ptr, nmemb * size); +} + +void *kallocarray(size_t nmemb, size_t size) { + return kreallocarray(NULL, nmemb, size); +} + +void *kcalloc(size_t nelem, size_t elsize) { + void *rc = kallocarray(nelem, elsize); + if (!rc) + return NULL; + memset(rc, 0, nelem * elsize); + return rc; +} + +void kfree(void *p) { + /* +if (!p) +return; +// FIXME: This assumes that p is at the start of a allocated area. +// Could this be avoided in a simple way? +MallocHeader *h = (MallocHeader *)((uintptr_t)p - sizeof(MallocHeader)); +assert(h->magic == 0xdde51ab9410268b1); +if (h->flags & IS_FREE) +return; + +h->flags |= IS_FREE; +merge_headers(h);*/ +} diff --git a/kernel/kmalloc.h b/kernel/kmalloc.h new file mode 100644 index 0000000..69e0de3 --- /dev/null +++ b/kernel/kmalloc.h @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include + +void kmalloc_allocate_heap(void); + +void *kmalloc_eternal(size_t size); +void *kmalloc_eternal_align(size_t size); +void *kmalloc_eternal_physical(size_t size, void **physical); +void *kmalloc_eternal_physical_align(size_t size, void **physical); + +void *kmalloc(size_t s); +void *kmalloc_align(size_t s); +void *krealloc(void *ptr, size_t size); +void *kreallocarray(void *ptr, size_t nmemb, size_t size); +void *kallocarray(size_t nmemb, size_t size); +void *kcalloc(size_t nelem, size_t elsize); +void kfree(void *p); +int init_heap(void); diff --git a/kernel/ksbrk.c b/kernel/ksbrk.c new file mode 100644 index 0000000..755a4ed --- /dev/null +++ b/kernel/ksbrk.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +/* +extern uintptr_t data_end; +extern PageDirectory *kernel_directory; + +#define HEAP 0x00E00000 +#define PHYS 0x403000 +#define PAGE_SIZE ((uintptr_t)0x1000) +void *ksbrk(size_t s) { + uintptr_t rc = (uintptr_t)align_page((void *)data_end); + data_end += s; + data_end = (uintptr_t)align_page((void *)data_end); + + if (!get_active_pagedirectory()) { + // If there is no active pagedirectory we + // just assume that the memory is + // already mapped. + return (void *)rc; + } + mmu_allocate_shared_kernel_region((void *)rc, (data_end - (uintptr_t)rc)); + assert(((uintptr_t)rc % PAGE_SIZE) == 0); + memset((void *)rc, 0xFF, s); + return (void *)rc; +} + +void *ksbrk_physical(size_t s, void **physical) { + void *r = ksbrk(s); + if (physical) { + // if (0 == get_active_pagedirectory()) + // *physical = (void *)((uintptr_t)r - (0xC0000000 + PHYS) + HEAP); + // else + *physical = (void *)virtual_to_physical(r, 0); + } + return r; +}*/ diff --git a/kernel/ksbrk.h b/kernel/ksbrk.h new file mode 100644 index 0000000..34987dc --- /dev/null +++ b/kernel/ksbrk.h @@ -0,0 +1,8 @@ +#ifndef KSBRK_H +#define KSBRK_H +#include +#include + +void* ksbrk(size_t s); +void *ksbrk_physical(size_t s, void **physical); +#endif diff --git a/kernel/kubsan.c b/kernel/kubsan.c new file mode 100644 index 0000000..c81b3fc --- /dev/null +++ b/kernel/kubsan.c @@ -0,0 +1,58 @@ +#include +#include +#include + +void ubsan_log(const char *cause, struct source_location source) { + kprintf("%s: %s : %d\n", cause, source.file_name, source.line); + dump_backtrace(5); + asm("cli"); + asm volatile("1: jmp 1b"); + asm("hlt"); + for (;;) + ; +} + +void __ubsan_handle_shift_out_of_bounds(struct ShiftOutOfBoundsData *data, + unsigned long lhs, unsigned long rhs) { + (void)lhs; + (void)rhs; + ubsan_log("handle_shift_out_of_bounds", data->location); +} + +void __ubsan_handle_add_overflow(struct OverflowData *data, unsigned long lhs, + unsigned long rhs) { + (void)lhs; + (void)rhs; + ubsan_log("handle_add_overflow", data->location); +} + +void __ubsan_handle_sub_overflow(struct OverflowData *data, unsigned long lhs, + unsigned long rhs) { + (void)lhs; + (void)rhs; + ubsan_log("handle_sub_overflow", data->location); +} + +void __ubsan_handle_mul_overflow(struct OverflowData *data, unsigned long lhs, + unsigned long rhs) { + (void)lhs; + (void)rhs; + ubsan_log("handle_mul_overflow", data->location); +} + +void __ubsan_handle_out_of_bounds(struct OutOfBoundsData *data, void *index) { + (void)index; + ubsan_log("handle_out_of_bounds", data->location); +} + +void __ubsan_handle_pointer_overflow(struct OutOfBoundsData *data, + void *index) { + (void)index; + ubsan_log("handle_pointer_overflow", data->location); +} + +void __ubsan_handle_vla_bound_not_positive(struct OutOfBoundsData *data, + void *index) { + (void)index; + ubsan_log("handle_vla_bound_not_positive", data->location); +} diff --git a/kernel/kubsan.h b/kernel/kubsan.h new file mode 100644 index 0000000..dac5407 --- /dev/null +++ b/kernel/kubsan.h @@ -0,0 +1,79 @@ +#include + +enum { type_kind_int = 0, type_kind_float = 1, type_unknown = 0xffff }; + +struct type_descriptor { + uint16_t type_kind; + uint16_t type_info; + char type_name[1]; +}; + +struct source_location { + const char *file_name; + union { + unsigned long reported; + struct { + uint32_t line; + uint32_t column; + }; + }; +}; + +struct OverflowData { + struct source_location location; + struct type_descriptor *type; +}; + +struct type_mismatch_data { + struct source_location location; + struct type_descriptor *type; + unsigned long alignment; + unsigned char type_check_kind; +}; + +struct type_mismatch_data_v1 { + struct source_location location; + struct type_descriptor *type; + unsigned char log_alignment; + unsigned char type_check_kind; +}; + +struct type_mismatch_data_common { + struct source_location *location; + struct type_descriptor *type; + unsigned long alignment; + unsigned char type_check_kind; +}; + +struct nonnull_arg_data { + struct source_location location; + struct source_location attr_location; + int arg_index; +}; + +struct OutOfBoundsData { + struct source_location location; + struct type_descriptor *array_type; + struct type_descriptor *index_type; +}; + +struct ShiftOutOfBoundsData { + struct source_location location; + struct type_descriptor *lhs_type; + struct type_descriptor *rhs_type; +}; + +struct unreachable_data { + struct source_location location; +}; + +struct invalid_value_data { + struct source_location location; + struct type_descriptor *type; +}; + +struct alignment_assumption_data { + struct source_location location; + struct source_location assumption_location; + struct type_descriptor *type; +}; diff --git a/kernel/libc/exit/assert.c b/kernel/libc/exit/assert.c new file mode 100644 index 0000000..b48773a --- /dev/null +++ b/kernel/libc/exit/assert.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +void aFailed(char *f, int l) { + kprintf("Assert failed\n"); + kprintf("%s : %d\n", f, l); + dump_backtrace(10); + for (;;) + ; +} diff --git a/kernel/libc/include/assert.h b/kernel/libc/include/assert.h new file mode 100644 index 0000000..90a0be4 --- /dev/null +++ b/kernel/libc/include/assert.h @@ -0,0 +1,19 @@ +#include +#include + +#define assert(expr) \ + { \ + if (!(expr)) \ + aFailed(__FILE__, __LINE__); \ + } + +#define ASSERT_BUT_FIXME_PROPOGATE(expr) \ + { \ + if (!(expr)) \ + kprintf("Performing assert that should have been a propogated error."); \ + assert(expr); \ + } + +void aFailed(char *f, int l); +#define ASSERT_NOT_REACHED \ + { assert(0) } diff --git a/kernel/libc/include/errno.h b/kernel/libc/include/errno.h new file mode 100644 index 0000000..1ad1004 --- /dev/null +++ b/kernel/libc/include/errno.h @@ -0,0 +1,85 @@ +#ifndef ERRNO_H +#define ERRNO_H +// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html +#define E2BIG 1 // Argument list too long. +#define EACCES 2 // Permission denied. +#define EADDRINUSE 3 // Address in use. +#define EADDRNOTAVAIL 4 // Address not available. +#define EAFNOSUPPORT 5 // Address family not supported. +#define EAGAIN 6 // Resource unavailable, try again. +#define EALREADY 7 // Connection already in progress. +#define EBADF 8 // Bad file descriptor. +#define EBADMSG 9 // Bad message. +#define EBUSY 10 // Device or resource busy. +#define ECANCELED 11 // Operation canceled. +#define ECHILD 12 // No child processes. +#define ECONNABORTED 13 // Connection aborted. +#define ECONNREFUSED 14 // Connection refused. +#define ECONNRESET 15 // Connection reset. +#define EDEADLK 16 // Resource deadlock would occur. +#define EDESTADDRREQ 17 // Destination address required. +#define EDOM 18 // Mathematics argument out of domain of function. +#define EDQUOT 19 // Reserved. +#define EEXIST 20 // File exists. +#define EFAULT 21 // Bad address. +#define EFBIG 22 // File too large. +#define EHOSTUNREACH 23 // Host is unreachable. +#define EIDRM 24 // Identifier removed. +#define EILSEQ 25 // Illegal byte sequence. +#define EINPROGRESS 26 // Operation in progress. +#define EINTR 27 // Interrupted function. +#define EINVAL 28 // Invalid argument. +#define EIO 29 // I/O error. +#define EISCONN 30 // Socket is connected. +#define EISDIR 31 // Is a directory. +#define ELOOP 32 // Too many levels of symbolic links. +#define EMFILE 33 // File descriptor value too large. +#define EMLINK 34 // Too many links. +#define EMSGSIZE 35 // Message too large. +#define EMULTIHOP 36 // Reserved. +#define ENAMETOOLONG 37 // Filename too long. +#define ENETDOWN 38 // Network is down. +#define ENETRESET 39 // Connection aborted by network. +#define ENETUNREACH 40 // Network unreachable. +#define ENFILE 41 // Too many files open in system. +#define ENOBUFS 42 // No buffer space available. +#define ENODATA 43 // No message is available on the STREAM head read queue. +#define ENODEV 44 // No such device. +#define ENOENT 45 // No such file or directory. +#define ENOEXEC 46 // Executable file format error. +#define ENOLCK 47 // No locks available. +#define ENOLINK 48 // Reserved. +#define ENOMEM 49 // Not enough space. +#define ENOMSG 50 // No message of the desired type. +#define ENOPROTOOPT 51 // Protocol not available. +#define ENOSPC 52 // No space left on device. +#define ENOSR 53 // No STREAM resources. +#define ENOSTR 54 // Not a STREAM. +#define ENOSYS 55 // Functionality not supported. +#define ENOTCONN 56 // The socket is not connected. +#define ENOTDIR 57 // Not a directory or a symbolic link to a directory. +#define ENOTEMPTY 58 // Directory not empty. +#define ENOTRECOVERABLE 59 // State not recoverable. +#define ENOTSOCK 60 // Not a socket. +#define ENOTSUP 61 // Not supported (may be the same value as. +#define ENOTTY 62 // Inappropriate I/O control operation. +#define ENXIO 63 // No such device or address. +#define EOPNOTSUPP ENOTSUP // Operation not supported on socket. +#define EOVERFLOW 65 // Value too large to be stored in data type. +#define EOWNERDEAD 66 // Previous owner died. +#define EPERM 67 // Operation not permitted. +#define EPIPE 68 // Broken pipe. +#define EPROTO 69 // Protocol error. +#define EPROTONOSUPPORT 70 // Protocol not supported. +#define EPROTOTYPE 71 // Protocol wrong type for socket. +#define ERANGE 72 // Result too large. +#define EROFS 73 // Read-only file system. +#define ESPIPE 74 // Invalid seek. +#define ESRCH 75 // No such process. +#define ESTALE 76 // Reserved. +#define ETIME 77 // Stream ioctl() timeout. +#define ETIMEDOUT 78 // Connection timed out. +#define ETXTBSY 79 // Text file busy. +#define EWOULDBLOCK EAGAIN // Operation would block. +#define EXDEV 81 // Cross-device link. +#endif diff --git a/kernel/libc/include/limits.h b/kernel/libc/include/limits.h new file mode 100644 index 0000000..05022ec --- /dev/null +++ b/kernel/libc/include/limits.h @@ -0,0 +1 @@ +#define PATH_MAX 256 diff --git a/kernel/libc/include/stdio.h b/kernel/libc/include/stdio.h new file mode 100644 index 0000000..f2bbb32 --- /dev/null +++ b/kernel/libc/include/stdio.h @@ -0,0 +1,9 @@ +#ifndef STDIO_H +#define STDIO_H + +void putc(const char c); +int puts(char *str); +void delete_characther(void); +int kprintf(const char *format, ...); + +#endif diff --git a/kernel/libc/include/stdlib.h b/kernel/libc/include/stdlib.h new file mode 100644 index 0000000..e69de29 diff --git a/kernel/libc/include/string.h b/kernel/libc/include/string.h new file mode 100644 index 0000000..7cee4b2 --- /dev/null +++ b/kernel/libc/include/string.h @@ -0,0 +1,19 @@ +#ifndef STRING_H +#define STRING_H +#include +#include + +unsigned long strlen(const char *s); +void *memcpy(void *dest, const void *src, uint32_t n); +void *memset(void *dst, const unsigned char c, uint32_t n); +int memcmp(const void *s1, const void *s2, uint32_t n); +char *strcpy(char *d, const char *s); +int strcmp(const char *s1, const char *s2); +int isequal(const char *s1, const char *s2); +int isequal_n(const char *s1, const char *s2, uint32_t n); +char *copy_and_allocate_string(const char *s); +char *copy_and_allocate_user_string(const char *s); +char *strncpy(char *dest, const char *src, size_t n); +size_t strlcpy(char *dst, const char *src, size_t dsize); +char *strcat(char *s1, const char *s2); +#endif diff --git a/kernel/libc/include/time.h b/kernel/libc/include/time.h new file mode 100644 index 0000000..4e356d1 --- /dev/null +++ b/kernel/libc/include/time.h @@ -0,0 +1,6 @@ +#include + +struct timespec { + time_t tv_sec; // Seconds. + long tv_nsec; // Nanoseconds. +}; diff --git a/kernel/libc/include/types.h b/kernel/libc/include/types.h new file mode 100644 index 0000000..ffcf281 --- /dev/null +++ b/kernel/libc/include/types.h @@ -0,0 +1,27 @@ +#ifndef TYPES_H +#define TYPES_H +typedef unsigned int ino_t; + +typedef int mode_t; + +typedef int nlink_t; +typedef int uid_t; +typedef int gid_t; +typedef int id_t; + +typedef int blkcnt_t; +typedef int off_t; + +typedef int dev_t; +typedef unsigned int fsblkcnt_t; +typedef unsigned int fsfilcnt_t; +typedef unsigned int ino_t; +//typedef unsigned int size_t; + +typedef int blksize_t; +typedef int pid_t; +typedef int ssize_t; + +//typedef int clock_t; +typedef int time_t; +#endif diff --git a/kernel/libc/stdio/print.c b/kernel/libc/stdio/print.c new file mode 100644 index 0000000..8174983 --- /dev/null +++ b/kernel/libc/stdio/print.c @@ -0,0 +1,97 @@ +#include "../../drivers/serial.h" +#include "../include/assert.h" +#include "../include/stdio.h" +#include + +#define TAB_SIZE 8 + +const char HEX_SET[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + +inline void putc(const char c) { write_serial(c); } + +int kprint_hex(uint64_t num) { + int c = 2; + + if (num == 0) { + putc('0'); + c++; + return c; + } + + char str[16] = {0}; + int i = 0; + for (; num != 0 && i < 16; i++, num /= 16) + str[i] = HEX_SET[(num % 16)]; + + c += i; + for (i--; i >= 0; i--) + putc(str[i]); + + return c; +} + +int kprint_int(int num) { + int c = 0; + if (0 == num) { + putc('0'); + c++; + return c; + } + char str[10]; + int i = 0; + for (; num != 0 && i < 10; i++, num /= 10) + str[i] = (num % 10) + '0'; + + c += i; + for (i--; i >= 0; i--) + putc(str[i]); + return c; +} + +int kprintf(const char *format, ...) { + int c = 0; + va_list list; + va_start(list, format); + + const char *s = format; + for (; *s; s++) { + if ('%' != *s) { + putc(*s); + c++; + continue; + } + + char flag = *(s + 1); + if ('\0' == flag) + break; + + switch (flag) { + case 'c': + putc((char)va_arg(list, int)); + c++; + break; + case 'd': + c += kprint_int(va_arg(list, int)); + break; + case 's': + for (char *string = va_arg(list, char *); *string; putc(*string++), c++) + ; + break; + case 'x': + c += kprint_hex(va_arg(list, const uint32_t)); + break; + case '%': + putc('%'); + c++; + break; + default: + ASSERT_NOT_REACHED; + break; + } + s++; + } + return c; +} + +int puts(char *str) { return kprintf("%s\n", str); } diff --git a/kernel/libc/string/copy.c b/kernel/libc/string/copy.c new file mode 100644 index 0000000..277c808 --- /dev/null +++ b/kernel/libc/string/copy.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +char *copy_and_allocate_string(const char *s) { + size_t l = strlen(s); + char *r = kmalloc(l + 1); + if (!r) + return NULL; + return strncpy(r, s, l); +} + +char *copy_and_allocate_user_string(const char *s) { + size_t len; + if (!is_valid_user_c_string(s, &len)) + return NULL; + size_t real_len = strlen(s); + assert(real_len == len); + len = real_len; + char *r = kmalloc(len + 1); + if (!r) + return NULL; + strlcpy(r, s, len); + return r; +} diff --git a/kernel/libc/string/isequal.c b/kernel/libc/string/isequal.c new file mode 100644 index 0000000..cdbd3cc --- /dev/null +++ b/kernel/libc/string/isequal.c @@ -0,0 +1,15 @@ +#include "../include/string.h" + +int isequal(const char *s1, const char *s2) { + for(;*s1;s1++,s2++) + if(*s1 != *s2) + return 0; + return 1; +} + +int isequal_n(const char *s1, const char *s2, uint32_t n) { + for(;*s1 && n;s1++,s2++,n--) + if(*s1 != *s2) + return 0; + return 1; +} diff --git a/kernel/libc/string/memcmp.c b/kernel/libc/string/memcmp.c new file mode 100644 index 0000000..72c680a --- /dev/null +++ b/kernel/libc/string/memcmp.c @@ -0,0 +1,12 @@ +#include "../include/string.h" + +int memcmp(const void *s1, const void *s2, uint32_t n) +{ + int return_value = 0; + + for(uint32_t i = 0;i < n;i++) + if(((unsigned char *)(s1))[i] != ((unsigned char *)(s2))[i]) + return_value++; + + return return_value; +} diff --git a/kernel/libc/string/memcpy.c b/kernel/libc/string/memcpy.c new file mode 100644 index 0000000..5c04407 --- /dev/null +++ b/kernel/libc/string/memcpy.c @@ -0,0 +1,20 @@ +#include "../include/string.h" + +void * +memcpy(void *dest, const void *src, uint32_t n) { + unsigned char *d = dest; + const unsigned char *s = src; + + for (; n >= 8; n -= 8, d += 8, s += 8) + *(uint64_t *)d = *(uint64_t *)s; + + for (; n >= 4; n -= 4, d += 4, s += 4) + *(uint32_t *)d = *(uint32_t *)s; + + for (; n >= 2; n -= 2, d += 2, s += 2) + *(uint16_t *)d = *(uint16_t *)s; + + for (; n; n--) + *d++ = *s++; + return dest; +} diff --git a/kernel/libc/string/memset.c b/kernel/libc/string/memset.c new file mode 100644 index 0000000..a446eb4 --- /dev/null +++ b/kernel/libc/string/memset.c @@ -0,0 +1,9 @@ +#include + +void *memset(void *dst, const unsigned char c, uint32_t n) { + uintptr_t d = (uintptr_t)dst; + for (uint32_t i = 0; i < n; i++, d++) + *(unsigned char *)d = c; + + return (void *)d; +} diff --git a/kernel/libc/string/strcat.c b/kernel/libc/string/strcat.c new file mode 100644 index 0000000..78a9ec6 --- /dev/null +++ b/kernel/libc/string/strcat.c @@ -0,0 +1,6 @@ +#include + +char *strcat(char *s1, const char *s2) { + strcpy(s1 + strlen(s1), s2); + return s1; +} diff --git a/kernel/libc/string/strcmp.c b/kernel/libc/string/strcmp.c new file mode 100644 index 0000000..d7039e2 --- /dev/null +++ b/kernel/libc/string/strcmp.c @@ -0,0 +1,8 @@ +#include "../include/string.h" + +int strcmp(const char *s1, const char *s2) +{ + for(;*s1 == *s2 && *s1; s1++, s2++) + ; + return *s1 - *s2; +} diff --git a/kernel/libc/string/strcpy.c b/kernel/libc/string/strcpy.c new file mode 100644 index 0000000..fa1e336 --- /dev/null +++ b/kernel/libc/string/strcpy.c @@ -0,0 +1,8 @@ +#include + +char *strcpy(char *d, const char *s) { + char *s1 = d; + for (; (*d++ = *s++);) + ; + return s1; +} diff --git a/kernel/libc/string/strlcpy.c b/kernel/libc/string/strlcpy.c new file mode 100644 index 0000000..43d0e58 --- /dev/null +++ b/kernel/libc/string/strlcpy.c @@ -0,0 +1,21 @@ +#include +#include + +// Copy string src to buffer dst of size dsize. At most dsize-1 +// chars will be copied. Always NUL terminates (unless dsize == 0). +// Returns strlen(src); if retval >= dsize, truncation occurred. +size_t strlcpy(char *dst, const char *src, size_t dsize) { + size_t n = dsize; + const char *osrc = src; + for (; n; n--) { + if ((*dst++ = *src++) == '\0') + break; + } + if (n == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) + ; + } + return src - osrc - 1; +} diff --git a/kernel/libc/string/strlen.c b/kernel/libc/string/strlen.c new file mode 100644 index 0000000..4346383 --- /dev/null +++ b/kernel/libc/string/strlen.c @@ -0,0 +1,8 @@ +#include "../include/string.h" + +unsigned long strlen(const char *s) +{ + const char * tmp = s; + for(;*tmp++;); + return (tmp - s)-1; +} diff --git a/kernel/libc/string/strncpy.c b/kernel/libc/string/strncpy.c new file mode 100644 index 0000000..a886895 --- /dev/null +++ b/kernel/libc/string/strncpy.c @@ -0,0 +1,11 @@ +#include +#include + +// FIXME: Something is weird with this function +char *strncpy(char *dest, const char *src, size_t n) { + char *r = dest; + for (; n && (*dest = *src); n--, src++, dest++) + ; + *dest = '\0'; + return r; +} diff --git a/kernel/linker.ld b/kernel/linker.ld new file mode 100644 index 0000000..59b150d --- /dev/null +++ b/kernel/linker.ld @@ -0,0 +1,41 @@ +ENTRY (_start) + +SECTIONS +{ + . = 0x00100000; + /* The kernel will live at 3GB + 1MB in the virtual address space, */ + /* which will be mapped to 1MB in the physical address space. */ + /* Note that we page-align the sections. */ + + _kernel_start = .; + .multiboot.data : { + *(.multiboot.data) + } + + .multiboot.text : { + *(.multiboot.text) + } + + . += 0xC0000000; + /* Add a symbol that indicates the start address of the kernel. */ + .text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000) + { + *(.text) + } + .rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000) + { + *(.rodata) + } + .data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000) + { + *(.data) + } + .bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000) + { + *(COMMON) + *(.bss) + *(.bootstrap_stack) + } + /* Add a symbol that indicates the end address of the kernel. */ + _kernel_end = .; +} diff --git a/kernel/log.c b/kernel/log.c new file mode 100644 index 0000000..56d38e8 --- /dev/null +++ b/kernel/log.c @@ -0,0 +1,40 @@ +#include "log.h" +#include + +struct stackframe { + struct stackframe *ebp; + uint32_t eip; +}; + +void dump_backtrace(uint32_t max_frames) { + struct stackframe *stk; + asm("mov %%ebp,%0" : "=r"(stk)::); + kprintf("Stack trace:\n"); + for (uint32_t frame = 0; stk && frame < max_frames; ++frame) { + kprintf(" 0x%x\n", stk->eip); + stk = stk->ebp; + } + if (get_current_task()) { + kprintf(" PID: %x\n", get_current_task()->pid); + } +} + +void klog(char *str, int code) { + switch (code) { + case LOG_NOTE: + kprintf("[NOTE] "); + break; + case LOG_WARN: + kprintf("[WARN] "); + break; + case LOG_ERROR: + kprintf("[ERROR] "); + break; + default: + case LOG_SUCCESS: + kprintf("[SUCCESS] "); + break; + } + + puts(str); +} diff --git a/kernel/log.h b/kernel/log.h new file mode 100644 index 0000000..fe499bc --- /dev/null +++ b/kernel/log.h @@ -0,0 +1,10 @@ +#include +#include + +#define LOG_NOTE 3 +#define LOG_WARN 2 +#define LOG_ERROR 1 +#define LOG_SUCCESS 0 + +void klog(char *str, int code); +void dump_backtrace(uint32_t max_frames); diff --git a/kernel/math.c b/kernel/math.c new file mode 100644 index 0000000..2d5e30c --- /dev/null +++ b/kernel/math.c @@ -0,0 +1,3 @@ +#include +int min(int a, int b) { return ((a) > (b) ? b : a); } +int max(int a, int b) { return (a > b) ? a : b; } diff --git a/kernel/mount/cat b/kernel/mount/cat new file mode 120000 index 0000000..a24e907 --- /dev/null +++ b/kernel/mount/cat @@ -0,0 +1 @@ +./minibox \ No newline at end of file diff --git a/kernel/mount/init b/kernel/mount/init new file mode 120000 index 0000000..a24e907 --- /dev/null +++ b/kernel/mount/init @@ -0,0 +1 @@ +./minibox \ No newline at end of file diff --git a/kernel/mount/pid1 b/kernel/mount/pid1 new file mode 100755 index 0000000..773d54c Binary files /dev/null and b/kernel/mount/pid1 differ diff --git a/kernel/mount/program b/kernel/mount/program new file mode 100755 index 0000000..c93d7ba Binary files /dev/null and b/kernel/mount/program differ diff --git a/kernel/mount/sh b/kernel/mount/sh new file mode 100755 index 0000000..c05684c Binary files /dev/null and b/kernel/mount/sh differ diff --git a/kernel/multiboot.h b/kernel/multiboot.h new file mode 100644 index 0000000..ecbb6a0 --- /dev/null +++ b/kernel/multiboot.h @@ -0,0 +1,243 @@ +#include +#ifndef MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 +#define MULTIBOOT_HEADER_ALIGN 4 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* Flags set in the ’flags’ member of the multiboot header. */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* Flags to be set in the ’flags’ member of the multiboot info structure. */ + +/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MULTIBOOT_INFO_VBE_INFO 0x00000800 +#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 + +#ifndef ASM_FILE + +typedef uint8_t multiboot_uint8_t; +typedef uint16_t multiboot_uint16_t; +typedef uint32_t multiboot_uint32_t; +typedef uint64_t multiboot_uint64_t; + +struct multiboot_header { + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table { + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table { + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; +}; +typedef struct multiboot_elf_section_header_table + multiboot_elf_section_header_table_t; + +struct multiboot_info { + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + union { + struct { + multiboot_uint32_t framebuffer_palette_addr; + multiboot_uint16_t framebuffer_palette_num_colors; + }; + struct { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_color { + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + +struct multiboot_mmap_entry { + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list { + /* the memory used goes from bytes ’mod_start’ to ’mod_end-1’ inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +/* APM BIOS info. */ +struct multiboot_apm_info { + multiboot_uint16_t version; + multiboot_uint16_t cseg; + multiboot_uint32_t offset; + multiboot_uint16_t cseg_16; + multiboot_uint16_t dseg; + multiboot_uint16_t flags; + multiboot_uint16_t cseg_len; + multiboot_uint16_t cseg_16_len; + multiboot_uint16_t dseg_len; +}; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/kernel/network/arp.c b/kernel/network/arp.c new file mode 100644 index 0000000..de6d898 --- /dev/null +++ b/kernel/network/arp.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include +#include + +struct ARP_DATA { + uint16_t htype; // Hardware type + uint16_t ptype; // Protocol type + uint8_t hlen; // Hardware address length (Ethernet = 6) + uint8_t plen; // Protocol address length (IPv4 = 4) + uint16_t opcode; // ARP Operation Code + uint8_t srchw[6]; // Source hardware address - hlen bytes (see above) + uint8_t srcpr[4]; // Source protocol address - plen bytes (see above). + // If IPv4 can just be a "u32" type. + uint8_t dsthw[6]; // Destination hardware address - hlen bytes (see above) + uint8_t dstpr[4]; // Destination protocol address - plen bytes (see + // above). If IPv4 can just be a "u32" type. +}; + +struct ARP_TABLE_ENTRY { + uint8_t is_used; + uint8_t mac[6]; + uint8_t ip[4]; +}; + +struct ARP_TABLE_ENTRY arp_table[10] = {0}; + +// FIXME: This is hardcoded, don't do this. +uint8_t ip_address[4] = {10, 0, 2, 15}; + +struct ARP_TABLE_ENTRY *find_arp_entry_to_use(void) { + // This does not need to find a "free" entry as a ARP table is + // just a cache, it just has to pick a entry efficently. + for (int i = 0; i < 10; i++) { + if (!arp_table[i].is_used) { + return &arp_table[i]; + } + } + return &arp_table[0]; +} + +void print_mac(const char *str, uint8_t *mac) { + kprintf("%s: ", str); + for (int i = 0; i < 6; i++) { + kprintf("%x", mac[i]); + if (5 != i) + kprintf(":"); + } + kprintf("\n"); +} + +void print_ip(const char *str, const uint8_t *ip) { + kprintf("%s: ", str); + for (int i = 0; i < 4; i++) { + kprintf("%d", ip[i]); + if (3 != i) + kprintf("."); + } + kprintf("\n"); +} + +void send_arp_request(const uint8_t ip[4]) { + struct ARP_DATA data; + data.htype = htons(1); + data.ptype = htons(0x0800); + + data.hlen = 6; + data.plen = 4; + + data.opcode = htons(0x0001); + get_mac_address(data.srchw); + memcpy(data.srcpr, ip_address, sizeof(uint8_t[4])); + + memset(data.dsthw, 0, sizeof(uint8_t[6])); + memcpy(data.dstpr, ip, sizeof(uint8_t[4])); + + uint8_t broadcast[6]; + memset(broadcast, 0xFF, sizeof(broadcast)); + send_ethernet_packet(broadcast, 0x0806, (uint8_t *)&data, sizeof(data)); +} + +int get_mac_from_ip(const uint8_t ip[4], uint8_t mac[6]) { + print_ip("ARP GETTING MAC FROM IP: ", ip); + for (int i = 0; i < 10; i++) { + if (0 != memcmp(arp_table[i].ip, ip, sizeof(uint8_t[4]))) + continue; + memcpy(mac, arp_table[i].mac, sizeof(uint8_t[6])); + return 1; + } + klog("ARP cache miss", LOG_NOTE); + asm("sti"); + send_arp_request(ip); + // TODO: Maybe wait a bit? + for (int i = 0; i < 10; i++) { + if (0 != memcmp(arp_table[i].ip, ip, sizeof(uint8_t[4]))) + continue; + memcpy(mac, arp_table[i].mac, sizeof(uint8_t[6])); + return 1; + } + assert(0); + return 0; +} + +void handle_arp(const uint8_t *payload) { + struct ARP_DATA *data = (struct ARP_DATA *)payload; + + // Assert that communication is over ethernet + assert(1 == ntohs(data->htype)); + // Assert that request uses IP + assert(0x0800 == ntohs(data->ptype)); + + assert(6 == data->hlen); + assert(4 == data->plen); + // Assert it is a request + if (0x0001 /*arp_request*/ == ntohs(data->opcode)) { + print_mac("srchw: ", data->srchw); + print_ip("srcpr: ", data->srcpr); + + print_mac("dsthw: ", data->dsthw); + print_ip("dstpr: ", data->dstpr); + + assert(0 == memcmp(data->dstpr, ip_address, sizeof(uint8_t[4]))); + + // Now we have to construct a ARP response + struct ARP_DATA response; + response.htype = htons(1); + response.ptype = htons(0x0800); + response.opcode = htons(0x00002); + response.hlen = 6; + response.plen = 4; + get_mac_address(response.srchw); + memcpy(response.srcpr, ip_address, sizeof(uint8_t[4])); + + memcpy(response.dsthw, data->srchw, sizeof(uint8_t[6])); + memcpy(response.dstpr, data->srcpr, sizeof(uint8_t[4])); + + send_ethernet_packet(data->srchw, 0x0806, (uint8_t *)&response, + sizeof(response)); + } else if (0x0002 /*arp_response*/ == ntohs(data->opcode)) { + // Find a entry to fill + struct ARP_TABLE_ENTRY *entry = find_arp_entry_to_use(); + entry->is_used = 1; + memcpy(entry->mac, data->srchw, sizeof(uint8_t[6])); + memcpy(entry->ip, data->srcpr, sizeof(uint8_t[4])); + print_ip("Added ip: ", entry->ip); + } else { + kprintf("GOT A ARP REQEUST WITH TYPE: %x\n", ntohs(data->opcode)); + assert(0); + } +} diff --git a/kernel/network/arp.h b/kernel/network/arp.h new file mode 100644 index 0000000..c2beb94 --- /dev/null +++ b/kernel/network/arp.h @@ -0,0 +1,4 @@ +#include + +int get_mac_from_ip(const uint8_t ip[4], uint8_t mac[6]); +void handle_arp(const uint8_t *payload); diff --git a/kernel/network/bytes.c b/kernel/network/bytes.c new file mode 100644 index 0000000..94afa73 --- /dev/null +++ b/kernel/network/bytes.c @@ -0,0 +1,10 @@ +#include + +uint16_t ntohs(uint16_t net) { return (net >> 8) | (net << 8); } + +uint16_t htons(uint16_t net) { return (net >> 8) | (net << 8); } + +uint32_t htonl(uint32_t net) { + return (((net & 0x000000FF) << 24) | ((net & 0x0000FF00) << 8) | + ((net & 0x00FF0000) >> 8) | ((net & 0xFF000000) >> 24)); +} diff --git a/kernel/network/bytes.h b/kernel/network/bytes.h new file mode 100644 index 0000000..c291589 --- /dev/null +++ b/kernel/network/bytes.h @@ -0,0 +1,5 @@ +#include + +uint16_t ntohs(uint16_t net); +uint16_t htons(uint16_t net); +uint32_t htonl(uint32_t net); diff --git a/kernel/network/ethernet.c b/kernel/network/ethernet.c new file mode 100644 index 0000000..e97ccbd --- /dev/null +++ b/kernel/network/ethernet.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct ETHERNET_HEADER { + uint8_t mac_dst[6]; + uint8_t mac_src[6]; + uint16_t type; +}; + +uint32_t crc32(const char *buf, size_t len) { + static uint32_t table[256]; + static int have_table = 0; + uint32_t rem; + uint8_t octet; + int i, j; + const char *p, *q; + + if (have_table == 0) { + for (i = 0; i < 256; i++) { + rem = i; + for (j = 0; j < 8; j++) { + if (rem & 1) { + rem >>= 1; + rem ^= 0xedb88320; + } else + rem >>= 1; + } + table[i] = rem; + } + have_table = 1; + } + + uint32_t crc = 0xFFFFFFFF; + q = buf + len; + for (p = buf; p < q; p++) { + octet = *p; + crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet]; + } + return ~crc; +} + +void handle_ethernet(const uint8_t *packet, uint64_t packet_length) { + struct ETHERNET_HEADER *eth_header = (struct ETHERNET_HEADER *)packet; + packet += sizeof(struct ETHERNET_HEADER); + const uint8_t *payload = packet; + packet += packet_length - sizeof(struct ETHERNET_HEADER); + uint32_t crc = *((uint32_t *)packet - 1); + kprintf("PACKET crc: %x\n", crc); + kprintf("OUR OWN CALCULATED crc: %x\n", + crc32((const char *)eth_header, (packet_length - 4))); + + uint16_t type = ntohs(eth_header->type); + switch (type) { + case 0x0806: + handle_arp(payload); + break; + case 0x0800: + handle_ipv4(payload, packet_length - sizeof(struct ETHERNET_HEADER) - 4); + break; + default: + kprintf("Can't handle ethernet type\n"); + break; + } +} + +void send_ethernet_packet(uint8_t mac_dst[6], uint16_t type, uint8_t *payload, + uint64_t payload_length) { + // FIXME: Janky allocation, do this better + uint64_t buffer_size = + sizeof(struct ETHERNET_HEADER) + payload_length + sizeof(uint32_t); + uint8_t *buffer = kmalloc(buffer_size); + uint8_t *buffer_start = buffer; + struct ETHERNET_HEADER *eth_header = (struct ETHERNET_HEADER *)buffer; + buffer += sizeof(struct ETHERNET_HEADER); + memcpy(buffer, payload, payload_length); + buffer += payload_length; + + memcpy(eth_header->mac_dst, mac_dst, sizeof(uint8_t[6])); + get_mac_address(eth_header->mac_src); + eth_header->type = htons(type); + *(uint32_t *)(buffer) = + htonl(crc32((const char *)buffer_start, buffer_size - 4)); + + assert(rtl8139_send_data(buffer_start, buffer_size)); + kfree(buffer_start); + kprintf("sent data\n"); +} diff --git a/kernel/network/ethernet.h b/kernel/network/ethernet.h new file mode 100644 index 0000000..0fdcee3 --- /dev/null +++ b/kernel/network/ethernet.h @@ -0,0 +1,5 @@ +#include + +void handle_ethernet(const uint8_t *packet, uint64_t packet_length); +void send_ethernet_packet(uint8_t mac_dst[6], uint16_t type, uint8_t *payload, + uint64_t payload_length); diff --git a/kernel/network/ipv4.c b/kernel/network/ipv4.c new file mode 100644 index 0000000..099aa0d --- /dev/null +++ b/kernel/network/ipv4.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +uint16_t ip_checksum(void *vdata, size_t length) { + // Cast the data pointer to one that can be indexed. + char *data = (char *)vdata; + + // Initialise the accumulator. + uint32_t acc = 0xffff; + + // Handle complete 16-bit blocks. + for (size_t i = 0; i + 1 < length; i += 2) { + uint16_t word; + memcpy(&word, data + i, 2); + acc += ntohs(word); + if (acc > 0xffff) { + acc -= 0xffff; + } + } + + // Handle any partial block at the end of the data. + if (length & 1) { + uint16_t word = 0; + memcpy(&word, data + length - 1, 1); + acc += ntohs(word); + if (acc > 0xffff) { + acc -= 0xffff; + } + } + + // Return the checksum in network byte order. + return htons(~acc); +} + +extern uint8_t ip_address[4]; +void send_ipv4_packet(uint32_t ip, uint8_t protocol, const uint8_t *payload, + uint16_t length) { + uint8_t header[20] = {0}; + header[0] = (4 /*version*/ << 4) | (5 /*IHL*/); + *((uint16_t *)(header + 2)) = htons(length + 20); + header[8 /*TTL*/] = 0xF8; + header[9] = protocol; + + memcpy(header + 12 /*src_ip*/, ip_address, sizeof(uint8_t[4])); + memcpy(header + 16, &ip, sizeof(uint8_t[4])); + + *((uint16_t *)(header + 10 /*checksum*/)) = ip_checksum(header, 20); + uint16_t packet_length = length + 20; + uint8_t *packet = kmalloc(packet_length); + memcpy(packet, header, 20); + memcpy(packet + 20, payload, length); + + uint8_t mac[6]; + uint8_t ip_copy[4]; // TODO: Do I need to do this? + memcpy(ip_copy, &ip, sizeof(uint8_t[4])); + get_mac_from_ip(ip_copy, mac); + send_ethernet_packet(mac, 0x0800, packet, packet_length); + kfree(packet); +} + +void handle_ipv4(const uint8_t *payload, uint32_t packet_length) { + assert(packet_length > 4); + + uint16_t saved_checksum = *(uint16_t *)(payload + 10); + *(uint16_t *)(payload + 10) = 0; + uint16_t calc_checksum = ip_checksum((uint8_t *)payload, 20); + *(uint16_t *)(payload + 10) = saved_checksum; + assert(calc_checksum == saved_checksum); + + uint8_t version = (*payload & 0xF0) >> 4; + uint8_t IHL = (*payload & 0xF); + kprintf("version: %x\n", version); + assert(4 == version); + assert(5 == IHL); + uint16_t ipv4_total_length = ntohs(*(uint16_t *)(payload + 2)); + assert(ipv4_total_length >= 20); + // Make sure the ipv4 header is not trying to get uninitalized memory + assert(ipv4_total_length <= packet_length); + + uint8_t src_ip[4]; + memcpy(src_ip, payload + 12, sizeof(uint8_t[4])); + + uint8_t protocol = *(payload + 9); + switch (protocol) { + case 0x11: + handle_udp(src_ip, payload + 20, ipv4_total_length - 20); + break; + default: + kprintf("Protocol given in IPv4 header not handeld: %x\n", protocol); + break; + } +} diff --git a/kernel/network/ipv4.h b/kernel/network/ipv4.h new file mode 100644 index 0000000..f578202 --- /dev/null +++ b/kernel/network/ipv4.h @@ -0,0 +1,5 @@ +#include + +void handle_ipv4(const uint8_t *payload, uint32_t packet_length); +void send_ipv4_packet(uint32_t ip, uint8_t protocol, const uint8_t *payload, + uint16_t length); diff --git a/kernel/network/udp.c b/kernel/network/udp.c new file mode 100644 index 0000000..23411da --- /dev/null +++ b/kernel/network/udp.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include + +void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst, + const uint8_t *payload, uint16_t payload_length) { + uint16_t header[4] = {0}; + header[0] = src->sin_port; + header[1] = dst->sin_port; + header[2] = htons(payload_length + 8); + + uint16_t packet_length = sizeof(header) + payload_length; + uint8_t *packet = kmalloc(packet_length); + memcpy(packet, header, sizeof(header)); + memcpy(packet + sizeof(header), payload, payload_length); + send_ipv4_packet(dst->sin_addr.s_addr, 0x11, packet, packet_length); + kfree(packet); +} + +void handle_udp(uint8_t src_ip[4], const uint8_t *payload, + uint32_t packet_length) { + assert(packet_length >= 8); + // n_.* means network format(big endian) + // h_.* means host format((probably) little endian) + uint16_t n_source_port = *(uint16_t *)payload; + uint16_t h_source_port = ntohs(n_source_port); + (void)h_source_port; + uint16_t h_dst_port = ntohs(*(uint16_t *)(payload + 2)); + uint16_t h_length = ntohs(*(uint16_t *)(payload + 4)); + assert(h_length == packet_length); + uint16_t data_length = h_length - 8; + const uint8_t *data = payload + 8; + + // Find the open port + OPEN_INET_SOCKET *in_s = find_open_udp_port(htons(h_dst_port)); + assert(in_s); + SOCKET *s = in_s->s; + vfs_fd_t *fifo_file = s->ptr_socket_fd; + + // Write the sockaddr struct such that it can later be + // given to userland if asked. + struct sockaddr_in /*{ + sa_family_t sin_family; + union { + uint32_t s_addr; + } sin_addr; + uint16_t sin_port; + }*/ in; + in.sin_family = AF_INET; + memcpy(&in.sin_addr.s_addr, src_ip, sizeof(uint32_t)); + in.sin_port = n_source_port; + socklen_t sock_length = sizeof(struct sockaddr_in); + + raw_vfs_pwrite(fifo_file, &sock_length, sizeof(sock_length), 0); + raw_vfs_pwrite(fifo_file, &in, sizeof(in), 0); + + // Write the UDP payload length(not including header) + raw_vfs_pwrite(fifo_file, &data_length, sizeof(uint16_t), 0); + + // Write the UDP payload + raw_vfs_pwrite(fifo_file, (char *)data, data_length, 0); +} diff --git a/kernel/network/udp.h b/kernel/network/udp.h new file mode 100644 index 0000000..c30b8c8 --- /dev/null +++ b/kernel/network/udp.h @@ -0,0 +1,7 @@ +#include +#include + +void handle_udp(uint8_t src_ip[4], const uint8_t *payload, + uint32_t packet_length); +void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst, + const uint8_t *payload, uint16_t payload_length); diff --git a/kernel/poll.c b/kernel/poll.c new file mode 100644 index 0000000..5e02723 --- /dev/null +++ b/kernel/poll.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +int poll(struct pollfd *fds, size_t nfds, int timeout) { + (void)timeout; + int read_locks[nfds]; + int write_locks[nfds]; + int disconnect_locks[nfds]; + for (size_t i = 0; i < nfds; i++) { + if (fds[i].fd < 0) + continue; + vfs_fd_t *f = get_vfs_fd(fds[i].fd); + if (fds[i].events & POLLIN) + read_locks[i] = create_read_fdhalt(f); + if (fds[i].events & POLLOUT) + write_locks[i] = create_write_fdhalt(f); + if (fds[i].events & POLLHUP) + disconnect_locks[i] = create_disconnect_fdhalt(f); + } + + switch_task(); + + for (size_t i = 0; i < nfds; i++) { + if (fds[i].fd < 0) + continue; + if (fds[i].events & POLLIN) + unset_read_fdhalt(read_locks[i]); + if (fds[i].events & POLLOUT) + unset_write_fdhalt(write_locks[i]); + if (fds[i].events & POLLHUP) + unset_disconnect_fdhalt(disconnect_locks[i]); + } + for (size_t i = 0; i < nfds; i++) { + if (0 > fds[i].fd) { + fds[i].revents = 0; + continue; + } + vfs_fd_t *f = get_vfs_fd(fds[i].fd); + if (!f) { + if (fds[i].events & POLLHUP) + fds[i].revents |= POLLHUP; + } else { + if (f->inode->has_data && fds[i].events & POLLIN) + fds[i].revents |= POLLIN; + if (f->inode->can_write && fds[i].events & POLLOUT) + fds[i].revents |= POLLOUT; + if (!(f->inode->is_open) && fds[i].events & POLLHUP) + fds[i].revents |= POLLHUP; + } + } + return 0; +} diff --git a/kernel/poll.h b/kernel/poll.h new file mode 100644 index 0000000..19698dd --- /dev/null +++ b/kernel/poll.h @@ -0,0 +1,15 @@ +#include +#include + +#define POLLIN (1 << 0) +#define POLLPRI (1 << 1) +#define POLLOUT (1 << 2) +#define POLLHUP (1 << 3) + +struct pollfd { + int fd; + short events; + short revents; +}; + +int poll(struct pollfd *fds, size_t nfds, int timeout); diff --git a/kernel/process.s b/kernel/process.s new file mode 100644 index 0000000..24e1869 --- /dev/null +++ b/kernel/process.s @@ -0,0 +1,33 @@ +.intel_syntax noprefix +.global copy_page_physical +.global loop_m +copy_page_physical: + push ebx + pushf + + cli + + mov ebx, [esp+12] + mov ecx, [esp+16] + + mov edx, cr0 + and edx, 0x7fffffff + mov cr0, edx + + mov edx, 1024 + +.loop: + mov eax, [ebx] + mov [ecx], eax + add ebx, 4 + add ecx, 4 + dec edx + jnz .loop + + mov edx, cr0 + or edx, 0x80000000 + mov cr0, edx + + popf + pop ebx + ret diff --git a/kernel/random.c b/kernel/random.c new file mode 100644 index 0000000..0e1b760 --- /dev/null +++ b/kernel/random.c @@ -0,0 +1,142 @@ +// FIXME: This is mostlikely incredibly inefficent and insecure. +#include +#include +#include +#include +#include +#include +#include + +#define HASH_CTX SHA1_CTX +#define HASH_LEN SHA1_LEN + +uint32_t internal_chacha_block[16] = { + // Constant ascii values of "expand 32-byte k" + 0x61707865, + 0x3320646e, + 0x79622d32, + 0x6b206574, + // The unique key + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + // Block counter + 0x00000000, + // Nonce + 0x00000000, + 0x00000000, +}; + +void mix_chacha(void) { + uint8_t rand_data[BLOCK_SIZE]; + get_random((BYTEPTR)rand_data, BLOCK_SIZE); + memcpy(internal_chacha_block + KEY, rand_data, KEY_SIZE); + memcpy(internal_chacha_block + NONCE, rand_data + KEY_SIZE, NONCE_SIZE); + internal_chacha_block[COUNT] = 0; +} + +void get_random(BYTEPTR buffer, uint64_t len) { + uint8_t rand_data[BLOCK_SIZE]; + for (; len > 0;) { + if (COUNT_MAX - 1 == internal_chacha_block[COUNT]) { + // The current block has used up all the 2^32 counts. If the + // key and/or the nonce are not changed and the count + // overflows back to zero then the random values would + // repeate. This is of course not desiered behaviour. The + // solution is to create a new nonce and key using the + // already established chacha block. + internal_chacha_block[COUNT]++; + mix_chacha(); + } + uint32_t read_len = (BLOCK_SIZE < len) ? (BLOCK_SIZE) : len; + chacha_block((uint32_t *)rand_data, internal_chacha_block); + internal_chacha_block[COUNT]++; + memcpy(buffer, rand_data, read_len); + buffer += read_len; + len -= read_len; + } +} + +HASH_CTX hash_pool; +uint32_t hash_pool_size = 0; + +void add_hash_pool(void) { + uint8_t new_chacha_key[KEY_SIZE]; + get_random(new_chacha_key, KEY_SIZE); + + uint8_t hash_buffer[HASH_LEN]; + SHA1_Final(&hash_pool, hash_buffer); + for (size_t i = 0; i < HASH_LEN; i++) + new_chacha_key[i % KEY_SIZE] ^= hash_buffer[i]; + + SHA1_Init(&hash_pool); + SHA1_Update(&hash_pool, hash_buffer, HASH_LEN); + + uint8_t block[BLOCK_SIZE]; + get_random(block, BLOCK_SIZE); + SHA1_Update(&hash_pool, block, BLOCK_SIZE); + + memcpy(internal_chacha_block + KEY, new_chacha_key, KEY_SIZE); + + mix_chacha(); +} + +void add_entropy(uint8_t *buffer, size_t size) { + SHA1_Update(&hash_pool, buffer, size); + hash_pool_size += size; + if (hash_pool_size >= HASH_LEN * 2) + add_hash_pool(); +} + +void setup_random(void) { + SHA1_Init(&hash_pool); + + BYTE seed[1024]; + int rand_fd = vfs_open("/etc/seed", O_RDWR, 0); + if (0 > rand_fd) { + klog("/etc/seed not found", LOG_WARN); + return; + } + + size_t offset = 0; + for (int rc; (rc = vfs_pread(rand_fd, seed, 1024, offset)); offset += rc) { + if (0 > rc) { + klog("/etc/seed read error", LOG_WARN); + break; + } + add_entropy(seed, rc); + } + add_hash_pool(); + + // Update the /etc/seed file to ensure we get a new state upon next + // boot. + get_random(seed, 1024); + vfs_pwrite(rand_fd, seed, 1024, 0); + vfs_close(rand_fd); +} + +int random_write(BYTEPTR buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + (void)offset; + (void)fd; + add_entropy(buffer, len); + return len; // add_entropy() never fails to recieve (len) amount of data. +} + +int random_read(BYTEPTR buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + (void)offset; + (void)fd; + get_random(buffer, len); + return len; // get_random() never fails to give "len" amount of data. +} + +void add_random_devices(void) { + devfs_add_file("/random", random_read, random_write, NULL, 1, 1, + FS_TYPE_CHAR_DEVICE); + devfs_add_file("/urandom", random_read, random_write, NULL, 1, 1, + FS_TYPE_CHAR_DEVICE); +} diff --git a/kernel/random.h b/kernel/random.h new file mode 100644 index 0000000..437927f --- /dev/null +++ b/kernel/random.h @@ -0,0 +1,7 @@ +#include +#include +#include + +void setup_random(void); +void add_random_devices(void); +void get_random(uint8_t* buffer, uint64_t len); diff --git a/kernel/read_eip.s b/kernel/read_eip.s new file mode 100644 index 0000000..6041db0 --- /dev/null +++ b/kernel/read_eip.s @@ -0,0 +1,5 @@ +.intel_syntax noprefix +.global read_eip +read_eip: + pop eax + jmp eax diff --git a/kernel/scalls/accept.c b/kernel/scalls/accept.c new file mode 100644 index 0000000..3c3f5ad --- /dev/null +++ b/kernel/scalls/accept.c @@ -0,0 +1,5 @@ +#include "accept.h" + +int syscall_accept(SYS_ACCEPT_PARAMS *args) { + return accept(args->socket, args->address, args->address_len); +} diff --git a/kernel/scalls/accept.h b/kernel/scalls/accept.h new file mode 100644 index 0000000..d022999 --- /dev/null +++ b/kernel/scalls/accept.h @@ -0,0 +1,9 @@ +#include "../socket.h" + +typedef struct SYS_ACCEPT_PARAMS { + int socket; + struct sockaddr *address; + socklen_t *address_len; +} __attribute__((packed)) SYS_ACCEPT_PARAMS; + +int syscall_accept(SYS_ACCEPT_PARAMS *args); diff --git a/kernel/scalls/bind.c b/kernel/scalls/bind.c new file mode 100644 index 0000000..76e36ab --- /dev/null +++ b/kernel/scalls/bind.c @@ -0,0 +1,5 @@ +#include "bind.h" + +int syscall_bind(SYS_BIND_PARAMS *args) { + return bind(args->sockfd, args->addr, args->addrlen); +} diff --git a/kernel/scalls/bind.h b/kernel/scalls/bind.h new file mode 100644 index 0000000..5661ad0 --- /dev/null +++ b/kernel/scalls/bind.h @@ -0,0 +1,9 @@ +#include "../socket.h" + +typedef struct SYS_BIND_PARAMS { + int sockfd; + const struct sockaddr *addr; + socklen_t addrlen; +} __attribute__((packed)) SYS_BIND_PARAMS; + +int syscall_bind(SYS_BIND_PARAMS *args); diff --git a/kernel/scalls/clock_gettime.c b/kernel/scalls/clock_gettime.c new file mode 100644 index 0000000..632ea08 --- /dev/null +++ b/kernel/scalls/clock_gettime.c @@ -0,0 +1,10 @@ +#include + +int syscall_clock_gettime(SYS_CLOCK_GETTIME_PARAMS *args) { + // FIXME: Actually implement this + if (args->ts) { + args->ts->tv_sec = 0; + args->ts->tv_nsec = 0; + } + return 0; +} diff --git a/kernel/scalls/clock_gettime.h b/kernel/scalls/clock_gettime.h new file mode 100644 index 0000000..145aa24 --- /dev/null +++ b/kernel/scalls/clock_gettime.h @@ -0,0 +1,8 @@ +#include + +typedef struct SYS_CLOCK_GETTIME_PARAMS { + clockid_t clk; + struct timespec *ts; +} __attribute__((packed)) SYS_CLOCK_GETTIME_PARAMS; + +int syscall_clock_gettime(SYS_CLOCK_GETTIME_PARAMS *args); diff --git a/kernel/scalls/ftruncate.c b/kernel/scalls/ftruncate.c new file mode 100644 index 0000000..6bc1170 --- /dev/null +++ b/kernel/scalls/ftruncate.c @@ -0,0 +1,6 @@ +#include +#include + +int syscall_ftruncate(int fd, size_t length) { + return vfs_ftruncate(fd, length); +} diff --git a/kernel/scalls/ftruncate.h b/kernel/scalls/ftruncate.h new file mode 100644 index 0000000..9213e85 --- /dev/null +++ b/kernel/scalls/ftruncate.h @@ -0,0 +1,2 @@ +#include +int syscall_ftruncate(int fd, size_t length); diff --git a/kernel/scalls/kill.c b/kernel/scalls/kill.c new file mode 100644 index 0000000..d5b7445 --- /dev/null +++ b/kernel/scalls/kill.c @@ -0,0 +1,5 @@ +#include +#include +#include + +int syscall_kill(pid_t pid, int sig) {return kill(pid, sig);} diff --git a/kernel/scalls/kill.h b/kernel/scalls/kill.h new file mode 100644 index 0000000..acf5f30 --- /dev/null +++ b/kernel/scalls/kill.h @@ -0,0 +1,2 @@ +#include +int syscall_kill(pid_t pid, int sig); diff --git a/kernel/scalls/mkdir.c b/kernel/scalls/mkdir.c new file mode 100644 index 0000000..43f2424 --- /dev/null +++ b/kernel/scalls/mkdir.c @@ -0,0 +1,5 @@ +#include + +int syscall_mkdir(const char *path, int mode) { + return vfs_mkdir(path, mode); +} diff --git a/kernel/scalls/mkdir.h b/kernel/scalls/mkdir.h new file mode 100644 index 0000000..0bf0043 --- /dev/null +++ b/kernel/scalls/mkdir.h @@ -0,0 +1,2 @@ +#include +int syscall_mkdir(const char *path, int mode); diff --git a/kernel/scalls/mmap.c b/kernel/scalls/mmap.c new file mode 100644 index 0000000..83fff6a --- /dev/null +++ b/kernel/scalls/mmap.c @@ -0,0 +1,7 @@ +#include +#include + +void *syscall_mmap(SYS_MMAP_PARAMS *args) { + return mmap(args->addr, args->length, args->prot, args->flags, args->fd, + args->offset); +} diff --git a/kernel/scalls/mmap.h b/kernel/scalls/mmap.h new file mode 100644 index 0000000..f5e121e --- /dev/null +++ b/kernel/scalls/mmap.h @@ -0,0 +1,13 @@ +#include +#include + +typedef struct SYS_MMAP_PARAMS { + void *addr; + size_t length; + int prot; + int flags; + int fd; + size_t offset; +} __attribute__((packed)) SYS_MMAP_PARAMS; + +void *syscall_mmap(SYS_MMAP_PARAMS *args); diff --git a/kernel/scalls/msleep.c b/kernel/scalls/msleep.c new file mode 100644 index 0000000..0120f08 --- /dev/null +++ b/kernel/scalls/msleep.c @@ -0,0 +1,9 @@ +#include +#include +#include +#include + +void syscall_msleep(uint32_t ms) { + get_current_task()->sleep_until = pit_num_ms() + ms; + switch_task(); +} diff --git a/kernel/scalls/msleep.h b/kernel/scalls/msleep.h new file mode 100644 index 0000000..71bf269 --- /dev/null +++ b/kernel/scalls/msleep.h @@ -0,0 +1,5 @@ +#ifndef MSLEEP_H +#define MSLEEP_H +#include +void syscall_msleep(uint32_t ms); +#endif diff --git a/kernel/scalls/ppoll.c b/kernel/scalls/ppoll.c new file mode 100644 index 0000000..8feb35c --- /dev/null +++ b/kernel/scalls/ppoll.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +int syscall_poll(SYS_POLL_PARAMS *args) { + struct pollfd *fds = args->fds; + size_t nfds = args->nfds; + int timeout = args->timeout; + return poll(fds, nfds, timeout); +} diff --git a/kernel/scalls/ppoll.h b/kernel/scalls/ppoll.h new file mode 100644 index 0000000..13700b5 --- /dev/null +++ b/kernel/scalls/ppoll.h @@ -0,0 +1,9 @@ +#include + +typedef struct SYS_POLL_PARAMS { + struct pollfd *fds; + size_t nfds; + int timeout; +} __attribute__((packed)) SYS_POLL_PARAMS; + +int syscall_poll(SYS_POLL_PARAMS *args); diff --git a/kernel/scalls/recvfrom.c b/kernel/scalls/recvfrom.c new file mode 100644 index 0000000..1770fa1 --- /dev/null +++ b/kernel/scalls/recvfrom.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +size_t syscall_recvfrom( + int socket, void *buffer, size_t length, int flags, + struct two_args + *extra_args /*struct sockaddr *address, socklen_t *address_len*/) { + + struct sockaddr *address = (struct sockaddr *)extra_args->a; + socklen_t *address_len = (socklen_t *)extra_args->b; + kprintf("address: %x\n", address); + kprintf("address_len: %x\n", address_len); + + if (flags & MSG_WAITALL) { + struct pollfd fds[1]; + fds[0].fd = socket; + fds[0].events = POLLIN; + poll(fds, 1, 0); + } + + uint16_t data_length; + socklen_t tmp_socklen; + vfs_pread(socket, &tmp_socklen, sizeof(socklen_t), 0); + if (address_len) + *address_len = tmp_socklen; + if (address) { + vfs_pread(socket, address, tmp_socklen, 0); + } else { + // We still have to throwaway the data. + char devnull[100]; + for (; tmp_socklen;) { + int rc = vfs_pread(socket, devnull, min(tmp_socklen, 100), 0); + assert(rc >= 0); + tmp_socklen -= rc; + } + } + + vfs_pread(socket, &data_length, sizeof(data_length), 0); + // If it is reading less than the packet length that could cause + // problems as the next read will not be put at a new header. Luckily + // it seems as if other UNIX systems can discard the rest of the + // packet if not read. + + // Read in the data requested + int read_len = min(length, data_length); + int rc = vfs_pread(socket, buffer, read_len, 0); + // Discard the rest of the packet + int rest = data_length - read_len; + char devnull[100]; + for (; rest;) { + int rc = vfs_pread(socket, devnull, 100, 0); + assert(rc >= 0); + rest -= rc; + } + return rc; +} diff --git a/kernel/scalls/recvfrom.h b/kernel/scalls/recvfrom.h new file mode 100644 index 0000000..d81a1e0 --- /dev/null +++ b/kernel/scalls/recvfrom.h @@ -0,0 +1,11 @@ +#include + +struct two_args { + uint32_t a; + uint32_t b; +}; + +size_t syscall_recvfrom( + int socket, void *buffer, size_t length, int flags, + struct two_args + *extra_args /*struct sockaddr *address, socklen_t *address_len*/); diff --git a/kernel/scalls/sendto.c b/kernel/scalls/sendto.c new file mode 100644 index 0000000..48c4020 --- /dev/null +++ b/kernel/scalls/sendto.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +size_t syscall_sendto(int socket, const void *message, size_t length, + int flags, struct t_two_args *extra_args /* + const struct sockaddr *dest_addr, + socklen_t dest_len*/) { + const struct sockaddr *dest_addr = (const struct sockaddr *)extra_args->a; + socklen_t dest_len = (socklen_t)extra_args->b; + (void)dest_len; + vfs_fd_t *fd = get_vfs_fd(socket); + assert(fd); + SOCKET *s = (SOCKET *)fd->inode->internal_object; + OPEN_INET_SOCKET *inet = s->child; + assert(inet); + struct sockaddr_in in; + in.sin_addr.s_addr = inet->address; + in.sin_port = inet->port; + send_udp_packet(&in, (const struct sockaddr_in *)dest_addr, message, length); + return length; // FIXME: This is probably not true. +} diff --git a/kernel/scalls/sendto.h b/kernel/scalls/sendto.h new file mode 100644 index 0000000..0f852de --- /dev/null +++ b/kernel/scalls/sendto.h @@ -0,0 +1,11 @@ +#include +#include + +struct t_two_args { + uint32_t a; + uint32_t b; +}; +size_t syscall_sendto(int socket, const void *message, size_t length, + int flags, struct t_two_args *extra_args /* + const struct sockaddr *dest_addr, + socklen_t dest_len*/); diff --git a/kernel/scalls/shm.c b/kernel/scalls/shm.c new file mode 100644 index 0000000..979084a --- /dev/null +++ b/kernel/scalls/shm.c @@ -0,0 +1,6 @@ +#include "shm.h" +#include "../fs/shm.h" + +int syscall_shm_open(SYS_SHM_OPEN_PARAMS *args) { + return shm_open(args->name, args->oflag, args->mode); +} diff --git a/kernel/scalls/shm.h b/kernel/scalls/shm.h new file mode 100644 index 0000000..80e4366 --- /dev/null +++ b/kernel/scalls/shm.h @@ -0,0 +1,14 @@ +#ifndef SYS_SHM_H +#define SYS_SHM_H +#include +#include +typedef int mode_t; + +typedef struct SYS_SHM_OPEN_PARAMS { + const char *name; + int oflag; + mode_t mode; +} __attribute__((packed)) SYS_SHM_OPEN_PARAMS; + +int syscall_shm_open(SYS_SHM_OPEN_PARAMS *args); +#endif diff --git a/kernel/scalls/socket.c b/kernel/scalls/socket.c new file mode 100644 index 0000000..594c745 --- /dev/null +++ b/kernel/scalls/socket.c @@ -0,0 +1,5 @@ +#include "socket.h" + +int syscall_socket(SYS_SOCKET_PARAMS *args) { + return socket(args->domain, args->type, args->protocol); +} diff --git a/kernel/scalls/socket.h b/kernel/scalls/socket.h new file mode 100644 index 0000000..6540b0f --- /dev/null +++ b/kernel/scalls/socket.h @@ -0,0 +1,9 @@ +#include "../socket.h" + +typedef struct SYS_SOCKET_PARAMS { + int domain; + int type; + int protocol; +} __attribute__((packed)) SYS_SOCKET_PARAMS; + +int syscall_socket(SYS_SOCKET_PARAMS *args); diff --git a/kernel/scalls/stat.c b/kernel/scalls/stat.c new file mode 100644 index 0000000..0850151 --- /dev/null +++ b/kernel/scalls/stat.c @@ -0,0 +1,13 @@ +#include +#include +#include + +int syscall_stat(SYS_STAT_PARAMS *args) { + const char *pathname = copy_and_allocate_user_string(args->pathname); + struct stat *statbuf = args->statbuf; + vfs_inode_t *i = vfs_internal_open(pathname); + if (!i) + return -ENOENT; + statbuf->st_size = i->file_size; + return 0; +} diff --git a/kernel/scalls/stat.h b/kernel/scalls/stat.h new file mode 100644 index 0000000..78e8c45 --- /dev/null +++ b/kernel/scalls/stat.h @@ -0,0 +1,33 @@ +#include +#include + +typedef struct SYS_STAT_PARAMS { + const char *pathname; + struct stat *statbuf; +} __attribute__((packed)) SYS_STAT_PARAMS; + +struct stat { + dev_t st_dev; // Device ID of device containing file. + ino_t st_ino; // File serial number. + mode_t st_mode; // Mode of file (see below). + nlink_t st_nlink; // Number of hard links to the file. + uid_t st_uid; // User ID of file. + gid_t st_gid; // Group ID of file. + dev_t st_rdev; // Device ID (if file is character or block special). + off_t st_size; // For regular files, the file size in bytes. + // For symbolic links, the length in bytes of the + // pathname contained in the symbolic link. + // For a shared memory object, the length in bytes. + // For a typed memory object, the length in bytes. + // For other file types, the use of this field is + // unspecified. + struct timespec st_atim; // Last data access timestamp. + struct timespec st_mtim; // Last data modification timestamp. + struct timespec st_ctim; // Last file status change timestamp. + blksize_t st_blksize; // A file system-specific preferred I/O block size + // for this object. In some file system types, this + // may vary from file to file. + blkcnt_t st_blocks; // Number of blocks allocated for this object. +}; + +int syscall_stat(SYS_STAT_PARAMS *args); diff --git a/kernel/scalls/uptime.c b/kernel/scalls/uptime.c new file mode 100644 index 0000000..866c7e5 --- /dev/null +++ b/kernel/scalls/uptime.c @@ -0,0 +1,4 @@ +#include +#include + +uint32_t syscall_uptime(void) { return (uint32_t)pit_num_ms(); } diff --git a/kernel/scalls/uptime.h b/kernel/scalls/uptime.h new file mode 100644 index 0000000..2b5b0c9 --- /dev/null +++ b/kernel/scalls/uptime.h @@ -0,0 +1,2 @@ +#include +uint32_t syscall_uptime(void); diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c new file mode 100644 index 0000000..a6ace7d --- /dev/null +++ b/kernel/sched/scheduler.c @@ -0,0 +1,449 @@ +#include +#include +#include +#include +#include +#include +#include + +#define STACK_LOCATION ((void *)0x90000000) +#define STACK_SIZE 0x80000 +#define HEAP_SIZE 0x400000 +#define HEAP_LOCATION (STACK_LOCATION - STACK_SIZE - HEAP_SIZE) + +process_t *ready_queue; +process_t *current_task = NULL; +uint32_t next_pid = 0; + +extern uint32_t read_eip(void); + +process_t *get_current_task(void) { return current_task; } + +void set_signal_handler(int sig, void (*handler)(int)) { + if (sig >= 20 || sig < 0) + return; + if (9 == sig) + return; + current_task->signal_handlers[sig] = handler; +} + +process_t *create_process(process_t *p) { + process_t *r; + r = ksbrk(sizeof(process_t)); + r->dead = 0; + r->pid = next_pid++; + r->esp = r->ebp = 0; + r->eip = 0; + r->sleep_until = 0; + if (!p) { + assert(1 == next_pid); + strncpy(r->program_name, "[kernel]", sizeof(current_task->program_name)); + } else + strncpy(r->program_name, "[Not yet named]", + sizeof(current_task->program_name)); + + r->cr3 = (p) ? clone_directory(get_active_pagedirectory()) + : get_active_pagedirectory(); + r->next = 0; + r->incoming_signal = 0; + r->parent = p; + r->child = NULL; + r->halt_list = NULL; + + mmu_allocate_region((void *)(0x80000000 - 0x1000), 0x1000, MMU_FLAG_RW, + r->cr3); + r->signal_handler_stack = 0x80000000; + + strcpy(r->current_working_directory, "/"); + r->data_segment_end = (p) ? p->data_segment_end : NULL; + memset((void *)r->halts, 0, 2 * sizeof(uint32_t)); + for (int i = 0; i < 100; i++) { + if (p) { + r->file_descriptors[i] = p->file_descriptors[i]; + if (r->file_descriptors[i]) { + r->file_descriptors[i]->reference_count++; + } + } + if (i < 20) + r->signal_handlers[i] = NULL; + r->read_halt_inode[i] = NULL; + r->write_halt_inode[i] = NULL; + r->disconnect_halt_inode[i] = NULL; + r->maps[i] = NULL; + } + return r; +} + +int get_free_fd(process_t *p, int allocate) { + if (!p) + p = (process_t *)current_task; + int i; + for (i = 0; i < 100; i++) + if (!p->file_descriptors[i]) + break; + if (p->file_descriptors[i]) + return -1; + if (allocate) { + vfs_fd_t *fd = p->file_descriptors[i] = kmalloc(sizeof(vfs_fd_t)); + fd->inode = kmalloc(sizeof(vfs_inode_t)); + } + return i; +} + +void tasking_init(void) { current_task = ready_queue = create_process(NULL); } + +int i = 0; +void __attribute__((optimize("O0"))) free_process(void) { + kprintf("Exiting process: %s\n", get_current_task()->program_name); + // free_process() will purge all contents such as allocated frames + // out of the current process. This will be called by exit() and + // exec*(). + + // Do a special free for shared memory which avoids labeling + // underlying frames as "unused". + for (int i = 0; i < 100; i++) { + vfs_close(i); + if (!current_task->maps[i]) + continue; + MemoryMap *m = current_task->maps[i]; + mmu_remove_virtual_physical_address_mapping(m->u_address, m->length); + } + + // NOTE: Kernel stuff begins at 0x90000000 + mmu_free_address_range((void *)0x1000, 0x90000000); +} + +void exit(int status) { + assert(current_task->pid != 1); + if (current_task->parent) { + current_task->parent->halts[WAIT_CHILD_HALT] = 0; + current_task->parent->child_rc = status; + } + process_t *new_task = current_task; + for (; new_task == current_task;) { + if (!new_task->next) + new_task = ready_queue; + new_task = new_task->next; + } + + free_process(); + // Remove current_task from list + for (process_t *tmp = ready_queue; tmp;) { + if (tmp == current_task) // current_task is ready_queue(TODO: + // Figure out whether this could even + // happen) + { + ready_queue = current_task->next; + break; + } + if (tmp->next == current_task) { + tmp->next = tmp->next->next; + break; + } + tmp = tmp->next; + } + current_task->dead = 1; + // This function will enable interrupts + switch_task(); +} + +uint32_t setup_stack(uint32_t stack_pointer, int argc, char **argv) { + mmu_allocate_region(STACK_LOCATION - STACK_SIZE, STACK_SIZE, MMU_FLAG_RW, + NULL); + flush_tlb(); + + uint32_t ptr = stack_pointer; + + char *argv_ptrs[argc + 1]; + for (int i = 0; i < argc; i++) { + char *s = argv[i]; + size_t l = strlen(s); + ptr -= l + 1; + char *b = (char *)ptr; + memcpy(b, s, l); + b[l] = '\0'; + argv_ptrs[i] = b; + } + + char **ptrs[argc + 1]; + for (int i = argc; i >= 0; i--) { + ptr -= sizeof(char *); + ptrs[i] = (char **)ptr; + if (i != argc) { + *(ptrs[i]) = argv_ptrs[i]; + } else { + *(ptrs[i]) = NULL; + } + } + + char *s = (char *)ptr; + ptr -= sizeof(char **); + *(char ***)ptr = (char **)s; + + ptr -= sizeof(int); + *(int *)ptr = argc; + return ptr; +} + +int exec(const char *filename, char **argv) { + // exec() will "takeover" the process by loading the file specified in + // filename into memory, change from ring 0 to ring 3 and jump to the + // files entry point as decided by the ELF header of the file. + int argc = 0; + for (; argv[argc];) { + argc++; + } + + uint32_t end_of_code; + void *entry = load_elf_file(filename, &end_of_code); + if (!entry) { + return 0; + } + + strncpy(current_task->program_name, filename, + sizeof(current_task->program_name)); + + current_task->data_segment_end = align_page((void *)end_of_code); + + uint32_t ptr = setup_stack(0x90000000, argc, argv); + + jump_usermode((void (*)())(entry), ptr); + ASSERT_NOT_REACHED; + return 0; +} + +int __attribute__((optimize("O0"))) fork(void) { + process_t *parent_task = (process_t *)current_task; + + process_t *new_task = create_process(parent_task); + + process_t *tmp_task = (process_t *)ready_queue; + for (; tmp_task->next;) + tmp_task = tmp_task->next; + + tmp_task->next = new_task; + + uint32_t eip = read_eip(); + + if (current_task != parent_task) { + return 0; + } + + new_task->child_rc = -1; + new_task->parent = current_task; + current_task->child = new_task; + + new_task->eip = eip; + asm("\ + mov %%esp, %0;\ + mov %%ebp, %1;" + : "=r"(new_task->esp), "=r"(new_task->ebp)); + asm("sti"); + return new_task->pid; +} + +int is_halted(process_t *process) { + for (int i = 0; i < 2; i++) + if (process->halts[i]) + return 1; + + if (isset_fdhalt(process->read_halt_inode, process->write_halt_inode, + process->disconnect_halt_inode)) { + return 1; + } + return 0; +} + +extern PageDirectory *active_directory; + +process_t *next_task(process_t *c) { + for (;;) { + c = c->next; + if (!c) + c = ready_queue; + if (c->incoming_signal) + break; + if (c->sleep_until > pit_num_ms()) + continue; + if (is_halted(c) || c->dead) + continue; + break; + } + return c; +} + +int task_save_state(void) { + asm("mov %%esp, %0" : "=r"(current_task->esp)); + asm("mov %%ebp, %0" : "=r"(current_task->ebp)); + + uint32_t eip = read_eip(); + + if (0x1 == eip) { + // Should the returned value from read_eip be equal to one it + // means that we have just switched over to this task after we + // saved the state(since the switch_task() function changes the + // eax register to 1). + return 0; + } + + current_task->eip = eip; + return 1; +} + +int kill(pid_t pid, int sig) { + process_t *p = current_task; + p = p->next; + if (!p) + p = ready_queue; + for (; p->pid != pid;) { + if (p == current_task) + break; + p = p->next; + if (!p) + p = ready_queue; + } + if (p->pid != pid) + return -ESRCH; + p->incoming_signal = sig; + return 0; +} + +void jump_signal_handler(void *func, uint32_t esp); +void switch_task() { + if (!current_task) + return; + + if (0 == task_save_state()) { + return; + } + + current_task = next_task((process_t *)current_task); + + active_directory = current_task->cr3; + + if (current_task->incoming_signal) { + uint8_t sig = current_task->incoming_signal; + current_task->incoming_signal = 0; + asm("mov %0, %%cr3" ::"r"(current_task->cr3->physical_address)); + + void *handler = current_task->signal_handlers[sig]; + if (9 == sig) { + klog("Task recieved SIGKILL", LOG_NOTE); + exit(0); + } + if (!handler) { + klog("Task recieved unhandeled signal. Killing process.", LOG_WARN); + exit(1); + } + jump_signal_handler(handler, current_task->signal_handler_stack); + } else { + asm(" \ + mov %0, %%esp; \ + mov %1, %%ebp; \ + mov %2, %%ecx; \ + mov %3, %%cr3; \ + mov $0x1, %%eax; \ + jmp *%%ecx" ::"r"(current_task->esp), + "r"(current_task->ebp), "r"(current_task->eip), + "r"(current_task->cr3->physical_address)); + } +} + +MemoryMap **get_free_map(void) { + for (int i = 0; i < 100; i++) + if (!(current_task->maps[i])) + return &(current_task->maps[i]); + assert(0); + return NULL; +} + +void *get_free_virtual_memory(size_t length) { + void *n = + (void *)((uintptr_t)(get_current_task()->data_segment_end) + length); + + void *rc = get_current_task()->data_segment_end; + get_current_task()->data_segment_end = align_page(n); + return rc; +} + +void *allocate_virtual_user_memory(size_t length, int prot, int flags) { + (void)prot; + (void)flags; + void *rc = get_free_virtual_memory(length); + if ((void *)-1 == rc) + return (void *)-1; + + mmu_allocate_region(rc, length, MMU_FLAG_RW, NULL); + return rc; +} + +void *user_kernel_mapping(void *kernel_addr, size_t length) { + void *rc = get_free_virtual_memory(length); + if ((void *)-1 == rc) + return (void *)-1; + + mmu_map_directories(rc, NULL, kernel_addr, NULL, length); + return rc; +} + +void *create_physical_mapping(void **physical_addresses, size_t length) { + void *rc = get_free_virtual_memory(length); + if ((void *)-1 == rc) + return (void *)-1; + int n = (uintptr_t)align_page((void *)length) / 0x1000; + for (int i = 0; i < n; i++) { + mmu_map_physical(rc + (i * 0x1000), NULL, physical_addresses[i], 0x1000); + } + return rc; +} + +void *mmap(void *addr, size_t length, int prot, int flags, int fd, + size_t offset) { + (void)addr; + if (0 == length) { + kprintf("EINVAL\n"); + return (void *)-EINVAL; + } + + MemoryMap **ptr = get_free_map(); + if (!ptr) { + klog("mmap(): No free memory map.", LOG_WARN); + return (void *)-1; + } + *ptr = kmalloc(sizeof(MemoryMap)); + MemoryMap *free_map = *ptr; + + if (fd == -1) { + void *rc = allocate_virtual_user_memory(length, prot, flags); + if ((void *)-1 == rc) { + kprintf("ENOMEM\n"); + return (void *)-ENOMEM; + } + free_map->u_address = rc; + free_map->k_address = NULL; + free_map->length = length; + free_map->fd = -1; + return rc; + } + + vfs_vm_object_t *vmobject = vfs_get_vm_object(fd, length, offset); + if (!vmobject) { + kprintf("ENODEV\n"); + return (void *)-ENODEV; + } + + if (vmobject->size < length) { + kprintf("EOVERFLOW\n"); + return (void *)-EOVERFLOW; // TODO: Check if this is the correct + // code. + } + + if (length > vmobject->size) + length = vmobject->size; + void *rc = create_physical_mapping(vmobject->object, length); + free_map->u_address = rc; + free_map->k_address = NULL; + free_map->length = length; + free_map->fd = fd; + return rc; +} diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h new file mode 100644 index 0000000..fc92ff3 --- /dev/null +++ b/kernel/sched/scheduler.h @@ -0,0 +1,65 @@ +#ifndef SCHEDULER_H +#define SCHEDULER_H +#include +#include +#include +#include +#include + +#define MAX_PATH 256 +#define KEYBOARD_HALT 0 +#define WAIT_CHILD_HALT 1 + +int fork(void); +int exec(const char *filename, char **argv); +void switch_task(); +void tasking_init(void); +void exit(int status); + +void *mmap(void *addr, size_t length, int prot, int flags, int fd, + size_t offset); +int munmap(void *addr, size_t length); +int msync(void *addr, size_t length, int flags); +int kill(pid_t pid, int sig); +void set_signal_handler(int sig, void (*handler)(int)); + +typedef struct { + void *u_address; + void *k_address; + uint32_t length; + int fd; +} MemoryMap; + +typedef struct Process process_t; + +struct Process { + uint32_t pid; + char program_name[100]; + char current_working_directory[MAX_PATH]; + uint32_t eip, esp, ebp; + uint8_t incoming_signal; + uint32_t signal_handler_stack; + void *signal_handlers[20]; + PageDirectory *cr3; + vfs_fd_t *file_descriptors[100]; + vfs_inode_t *read_halt_inode[100]; + vfs_inode_t *write_halt_inode[100]; + vfs_inode_t *disconnect_halt_inode[100]; + uint32_t halts[2]; + struct Halt *halt_list; + void *data_segment_end; + process_t *next; + process_t *parent; + // TODO: Create a linkedlist of childs so that the parent process + // can do stuff such as reap zombies and get status. + process_t *child; + MemoryMap *maps[100]; + uint32_t sleep_until; + int child_rc; + int dead; +}; + +process_t *get_current_task(void); +int get_free_fd(process_t *p, int allocate); +void free_process(void); +#endif diff --git a/kernel/signal.s b/kernel/signal.s new file mode 100644 index 0000000..38604a4 --- /dev/null +++ b/kernel/signal.s @@ -0,0 +1,18 @@ +.intel_syntax noprefix +.global jump_signal_handler +jump_signal_handler: + mov ebx, [esp+8] + mov ecx, [esp+4] + mov ax, (4 * 8) | 3 # ring 3 data with bottom 2 bits set for ring 3 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax # SS is handled by iret + + mov eax, ebx + push (4 * 8) | 3 # data selector + push eax + pushf + push (3 * 8) | 3 + push ecx + iret diff --git a/kernel/socket.c b/kernel/socket.c new file mode 100644 index 0000000..0519c65 --- /dev/null +++ b/kernel/socket.c @@ -0,0 +1,180 @@ +#include +#include +#include +#include +#include +#include +#include + +// FIXME: Make these more dynamic +OPEN_UNIX_SOCKET *un_sockets[100] = {0}; +OPEN_INET_SOCKET *inet_sockets[100] = {0}; + +OPEN_INET_SOCKET *find_open_udp_port(uint16_t port) { + for (int i = 0; i < 100; i++) { + if (!inet_sockets[i]) + continue; + if (inet_sockets[i]->port == port) + return inet_sockets[i]; + } + return NULL; +} + +int uds_open(const char *path) { + // FIXME: This is super ugly + + // Find the socket that path belongs to + SOCKET *s = NULL; + for (int i = 0; i < 100; i++) { + if (!un_sockets[i]) + continue; + const char *p = path; + const char *e = p; + for (; *e; e++) + ; + for (; e != p && *e != '/'; e--) + ; + if (0 == strcmp(e, un_sockets[i]->path)) { + s = un_sockets[i]->s; + break; + } + } + if (!s) { + return -1; + } + + // Create a pipe + int fd[2]; + dual_pipe(fd); + + char c = 'i'; + fifo_object_write((uint8_t *)&c, 1, 0, s->fifo_file); + s->ptr_socket_fd->inode->has_data = 1; + + s->incoming_fd = get_current_task()->file_descriptors[fd[1]]; + // vfs_close(fd[1]); + return fd[0]; +} + +int accept(int socket, struct sockaddr *address, socklen_t *address_len) { + (void)address; + (void)address_len; + vfs_inode_t *inode = get_current_task()->file_descriptors[socket]->inode; + SOCKET *s = (SOCKET *)inode->internal_object; + + if (NULL == s->incoming_fd) { + // Wait until we have gotten a connection + struct pollfd fds[1]; + fds[0].fd = socket; + fds[0].events = POLLIN; + fds[0].revents = 0; + poll(fds, 1, 0); + } + + int n = 0; + for (; get_current_task()->file_descriptors[n]; n++) + ; + get_current_task()->file_descriptors[n] = s->incoming_fd; + get_current_task()->file_descriptors[n]->reference_count++; + s->incoming_fd = NULL; + // for (char c; 0 < vfs_pread(s->fifo_fd, &c, 1, 0);) + // ; + inode->has_data = 0; + // s->ptr_fifo_fd->inode->has_data = 0; + + return n; +} + +int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + (void)addrlen; + vfs_fd_t *fd = get_vfs_fd(sockfd); + if (!fd) + return -EBADF; + vfs_inode_t *inode = fd->inode; + if (!inode) + return -EBADF; + SOCKET *s = (SOCKET *)inode->internal_object; + if (AF_UNIX == s->domain) { + struct sockaddr_un *un = (struct sockaddr_un *)addr; + size_t path_len = strlen(un->sun_path); + s->path = kmalloc(path_len + 1); + memcpy(s->path, un->sun_path, path_len); + s->path[path_len] = '\0'; + + OPEN_UNIX_SOCKET *us; + int i = 0; + for (; i < 100; i++) + if (!un_sockets[i]) + break; + + us = un_sockets[i] = kmalloc(sizeof(OPEN_UNIX_SOCKET)); + + us->path = s->path; + us->s = s; + s->child = us; + devfs_add_file(us->path, NULL, NULL, NULL, 1, 1, FS_TYPE_UNIX_SOCKET); + return 0; + } + if (AF_INET == s->domain) { + struct sockaddr_in *in = (struct sockaddr_in *)addr; + assert(in->sin_family == AF_INET); // FIXME: Figure out error value + OPEN_INET_SOCKET *inet; + int i = 0; + for (; i < 100; i++) + if (!inet_sockets[i]) + break; + + inet = inet_sockets[i] = kmalloc(sizeof(OPEN_INET_SOCKET)); + inet->address = in->sin_addr.s_addr; + inet->port = in->sin_port; + inet->s = s; + s->child = inet; + return 0; + } + return 0; +} + +int socket_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + SOCKET *s = (SOCKET *)fd->inode->internal_object; + FIFO_FILE *file = s->fifo_file; + int rc = fifo_object_write(buffer, 0, len, file); + fd->inode->has_data = file->has_data; + return rc; +} + +int socket_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { + SOCKET *s = (SOCKET *)fd->inode->internal_object; + FIFO_FILE *file = s->fifo_file; + int rc = fifo_object_read(buffer, 0, len, file); + fd->inode->has_data = file->has_data; + return rc; +} + +void socket_close(vfs_fd_t *fd) { fd->inode->is_open = 0; } + +int socket(int domain, int type, int protocol) { + if (!(AF_UNIX == domain || AF_INET == domain)) + return -EINVAL; + + SOCKET *new_socket = kmalloc_eternal(sizeof(SOCKET)); + vfs_inode_t *inode = vfs_create_inode( + 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, 0 /*has_data*/, 1 /*can_write*/, + 1 /*is_open*/, new_socket /*internal_object*/, 0 /*file_size*/, + NULL /*open*/, NULL /*create_file*/, socket_read, socket_write, + socket_close, NULL /*create_directory*/, NULL /*get_vm_object*/, + NULL /*truncate*/); + + vfs_fd_t *fd; + int n = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, inode, &fd); + + new_socket->domain = domain; + new_socket->type = type; + new_socket->protocol = protocol; + new_socket->path = NULL; + new_socket->incoming_fd = NULL; + + new_socket->fifo_file = create_fifo_object(); + + new_socket->ptr_socket_fd = fd; + return n; +} diff --git a/kernel/socket.h b/kernel/socket.h new file mode 100644 index 0000000..bb278c1 --- /dev/null +++ b/kernel/socket.h @@ -0,0 +1,72 @@ +#ifndef SOCKET_H +#define SOCKET_H +#include +#include +#include +#include + +#define AF_UNIX 0 +#define AF_INET 1 +#define AF_LOCAL AF_UNIX + +#define SOCK_DGRAM 0 + +#define INADDR_ANY 0 + +#define MSG_WAITALL 1 + +typedef struct { + vfs_fd_t *ptr_socket_fd; + FIFO_FILE *fifo_file; + + int domain; + int type; + int protocol; + void *child; + + // UNIX socket + char *path; + vfs_fd_t *incoming_fd; +} SOCKET; + +typedef struct { + char *path; + SOCKET *s; +} OPEN_UNIX_SOCKET; + +typedef struct { + uint32_t address; + uint16_t port; + SOCKET *s; +} OPEN_INET_SOCKET; + +typedef uint32_t in_addr_t; +typedef uint16_t in_port_t; +typedef unsigned int sa_family_t; +typedef int socklen_t; + +struct sockaddr { + sa_family_t sa_family; /* Address family */ + char *sa_data; /* Socket address */ +}; + +struct sockaddr_in { + sa_family_t sin_family; + union { + uint32_t s_addr; + uint8_t a[4]; + } sin_addr; + uint16_t sin_port; +}; + +struct sockaddr_un { + sa_family_t sun_family; /* Address family */ + char *sun_path; /* Socket pathname */ +}; + +OPEN_INET_SOCKET *find_open_udp_port(uint16_t port); +int uds_open(const char *path); +int socket(int domain, int type, int protocol); +int accept(int socket, struct sockaddr *address, socklen_t *address_len); +int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +#endif diff --git a/kernel/time.h b/kernel/time.h new file mode 100644 index 0000000..2d4eef6 --- /dev/null +++ b/kernel/time.h @@ -0,0 +1,10 @@ +#ifndef TIME_H +#define TIME_H +#include + +typedef int clockid_t; +struct timespec { + time_t tv_sec; // Seconds. + long tv_nsec; // Nanoseconds. +}; +#endif diff --git a/kmalloc.c b/kmalloc.c deleted file mode 100644 index 34c466d..0000000 --- a/kmalloc.c +++ /dev/null @@ -1,230 +0,0 @@ -#include -#include -#include -#include -#define NEW_ALLOC_SIZE 0x30000 - -#define IS_FREE (1 << 0) -#define IS_FINAL (1 << 1) - -typedef struct MallocHeader { - uint64_t magic; - uint32_t size; - uint8_t flags; - struct MallocHeader *n; -} MallocHeader; - -uint64_t delta_page(uint64_t a) { return 0x1000 - (a % 0x1000); } - -MallocHeader *head = NULL; -MallocHeader *final = NULL; -uint32_t total_heap_size = 0; - -int init_heap(void) { - head = (MallocHeader *)ksbrk(NEW_ALLOC_SIZE); - total_heap_size += NEW_ALLOC_SIZE - sizeof(MallocHeader); - head->magic = 0xdde51ab9410268b1; - head->size = NEW_ALLOC_SIZE - sizeof(MallocHeader); - head->flags = IS_FREE | IS_FINAL; - head->n = NULL; - final = head; - return 1; -} - -int add_heap_memory(size_t min_desired) { - min_desired += sizeof(MallocHeader) + 0x1000; - size_t allocation_size = max(min_desired, NEW_ALLOC_SIZE); - allocation_size += delta_page(allocation_size); - void *p; - if ((void *)(-1) == (p = (void *)ksbrk(allocation_size))) { - return 0; - } - total_heap_size += allocation_size - sizeof(MallocHeader); - void *e = final; - e = (void *)((uint32_t)e + final->size); - if (p == e) { - final->size += allocation_size - sizeof(MallocHeader); - return 1; - } - MallocHeader *new_entry = p; - new_entry->size = allocation_size - sizeof(MallocHeader); - new_entry->flags = IS_FREE | IS_FINAL; - new_entry->n = NULL; - new_entry->magic = 0xdde51ab9410268b1; - final->n = new_entry; - final = new_entry; - return 1; -} - -MallocHeader *next_header(MallocHeader *a) { - assert(a->magic == 0xdde51ab9410268b1); - if (a->n) { - assert(a->n->magic == 0xdde51ab9410268b1); - return a->n; - } - return NULL; -} - -MallocHeader *next_close_header(MallocHeader *a) { - if (!a) { - kprintf("next close header fail\n"); - for (;;) - ; - } - if (a->flags & IS_FINAL) - return NULL; - return next_header(a); -} - -MallocHeader *find_free_entry(uint32_t s) { - // A new header is required as well as the newly allocated chunk - s += sizeof(MallocHeader); - if (!head) - init_heap(); - MallocHeader *p = head; - for (; p; p = next_header(p)) { - assert(p->magic == 0xdde51ab9410268b1); - if (!(p->flags & IS_FREE)) - continue; - uint64_t required_size = s; - if (p->size < required_size) - continue; - return p; - } - return NULL; -} - -void merge_headers(MallocHeader *b) { - if (!(b->flags & IS_FREE)) - return; - - MallocHeader *n = next_close_header(b); - if (!n) - return; - - if (!(n->flags & IS_FREE)) - return; - - b->size += n->size; - b->flags |= n->flags & IS_FINAL; - b->n = n->n; - if (n == final) - final = b; -} - -void *kmalloc(size_t s) { - size_t n = s; - MallocHeader *free_entry = find_free_entry(s); - if (!free_entry) { - if (!add_heap_memory(s)) { - klog("Ran out of memory.", LOG_ERROR); - assert(0); - return NULL; - } - return kmalloc(s); - } - - void *rc = (void *)(free_entry + 1); - - // Create a new header - MallocHeader *new_entry = (MallocHeader *)((uintptr_t)rc + n); - new_entry->flags = free_entry->flags; - new_entry->n = free_entry->n; - new_entry->size = free_entry->size - n - sizeof(MallocHeader); - new_entry->magic = 0xdde51ab9410268b1; - - if (free_entry == final) - final = new_entry; - merge_headers(new_entry); - - // Modify the free entry - free_entry->size = n; - free_entry->flags = 0; - free_entry->n = new_entry; - free_entry->magic = 0xdde51ab9410268b1; - return rc; -} - -#define HEAP 0x00E00000 -#define PHYS 0x403000 - -void *latest = NULL; -uint64_t left = 0; - -void *kmalloc_eternal_physical_align(size_t s, void **physical) { - void *return_address = ksbrk(s); - if (physical) { - if (0 == get_active_pagedirectory()) - *physical = - (void *)((uintptr_t)return_address - (0xC0000000 + PHYS) + HEAP); - else - *physical = (void *)virtual_to_physical(return_address, 0); - } - memset(return_address, 0, 0x1000); - return return_address; -} - -void *kmalloc_eternal_align(size_t s) { - return kmalloc_eternal_physical_align(s, NULL); -} - -void *kmalloc_eternal(size_t s) { return kmalloc_eternal_align(s); } - -size_t get_mem_size(void *ptr) { - if (!ptr) - return 0; - return ((MallocHeader *)((uintptr_t)ptr - sizeof(MallocHeader)))->size; -} - -void *krealloc(void *ptr, size_t size) { - void *rc = kmalloc(size); - if (!rc) - return NULL; - if (!ptr) - return rc; - size_t l = get_mem_size(ptr); - size_t to_copy = min(l, size); - memcpy(rc, ptr, to_copy); - // kfree(ptr); - return rc; -} - -// This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX -// if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW -#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) - -void *kreallocarray(void *ptr, size_t nmemb, size_t size) { - if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && - SIZE_MAX / nmemb < size) { - return NULL; - } - - return krealloc(ptr, nmemb * size); -} - -void *kallocarray(size_t nmemb, size_t size) { - return kreallocarray(NULL, nmemb, size); -} - -void *kcalloc(size_t nelem, size_t elsize) { - void *rc = kallocarray(nelem, elsize); - if (!rc) - return NULL; - memset(rc, 0, nelem * elsize); - return rc; -} - -void kfree(void *p) { - /* -if (!p) -return; -// FIXME: This assumes that p is at the start of a allocated area. -// Could this be avoided in a simple way? -MallocHeader *h = (MallocHeader *)((uintptr_t)p - sizeof(MallocHeader)); -assert(h->magic == 0xdde51ab9410268b1); -if (h->flags & IS_FREE) -return; - -h->flags |= IS_FREE; -merge_headers(h);*/ -} diff --git a/kmalloc.h b/kmalloc.h deleted file mode 100644 index 69e0de3..0000000 --- a/kmalloc.h +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include -#include -#include - -void kmalloc_allocate_heap(void); - -void *kmalloc_eternal(size_t size); -void *kmalloc_eternal_align(size_t size); -void *kmalloc_eternal_physical(size_t size, void **physical); -void *kmalloc_eternal_physical_align(size_t size, void **physical); - -void *kmalloc(size_t s); -void *kmalloc_align(size_t s); -void *krealloc(void *ptr, size_t size); -void *kreallocarray(void *ptr, size_t nmemb, size_t size); -void *kallocarray(size_t nmemb, size_t size); -void *kcalloc(size_t nelem, size_t elsize); -void kfree(void *p); -int init_heap(void); diff --git a/ksbrk.c b/ksbrk.c deleted file mode 100644 index 755a4ed..0000000 --- a/ksbrk.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include -#include -#include - -/* -extern uintptr_t data_end; -extern PageDirectory *kernel_directory; - -#define HEAP 0x00E00000 -#define PHYS 0x403000 -#define PAGE_SIZE ((uintptr_t)0x1000) -void *ksbrk(size_t s) { - uintptr_t rc = (uintptr_t)align_page((void *)data_end); - data_end += s; - data_end = (uintptr_t)align_page((void *)data_end); - - if (!get_active_pagedirectory()) { - // If there is no active pagedirectory we - // just assume that the memory is - // already mapped. - return (void *)rc; - } - mmu_allocate_shared_kernel_region((void *)rc, (data_end - (uintptr_t)rc)); - assert(((uintptr_t)rc % PAGE_SIZE) == 0); - memset((void *)rc, 0xFF, s); - return (void *)rc; -} - -void *ksbrk_physical(size_t s, void **physical) { - void *r = ksbrk(s); - if (physical) { - // if (0 == get_active_pagedirectory()) - // *physical = (void *)((uintptr_t)r - (0xC0000000 + PHYS) + HEAP); - // else - *physical = (void *)virtual_to_physical(r, 0); - } - return r; -}*/ diff --git a/ksbrk.h b/ksbrk.h deleted file mode 100644 index 34987dc..0000000 --- a/ksbrk.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef KSBRK_H -#define KSBRK_H -#include -#include - -void* ksbrk(size_t s); -void *ksbrk_physical(size_t s, void **physical); -#endif diff --git a/kubsan.c b/kubsan.c deleted file mode 100644 index c81b3fc..0000000 --- a/kubsan.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -void ubsan_log(const char *cause, struct source_location source) { - kprintf("%s: %s : %d\n", cause, source.file_name, source.line); - dump_backtrace(5); - asm("cli"); - asm volatile("1: jmp 1b"); - asm("hlt"); - for (;;) - ; -} - -void __ubsan_handle_shift_out_of_bounds(struct ShiftOutOfBoundsData *data, - unsigned long lhs, unsigned long rhs) { - (void)lhs; - (void)rhs; - ubsan_log("handle_shift_out_of_bounds", data->location); -} - -void __ubsan_handle_add_overflow(struct OverflowData *data, unsigned long lhs, - unsigned long rhs) { - (void)lhs; - (void)rhs; - ubsan_log("handle_add_overflow", data->location); -} - -void __ubsan_handle_sub_overflow(struct OverflowData *data, unsigned long lhs, - unsigned long rhs) { - (void)lhs; - (void)rhs; - ubsan_log("handle_sub_overflow", data->location); -} - -void __ubsan_handle_mul_overflow(struct OverflowData *data, unsigned long lhs, - unsigned long rhs) { - (void)lhs; - (void)rhs; - ubsan_log("handle_mul_overflow", data->location); -} - -void __ubsan_handle_out_of_bounds(struct OutOfBoundsData *data, void *index) { - (void)index; - ubsan_log("handle_out_of_bounds", data->location); -} - -void __ubsan_handle_pointer_overflow(struct OutOfBoundsData *data, - void *index) { - (void)index; - ubsan_log("handle_pointer_overflow", data->location); -} - -void __ubsan_handle_vla_bound_not_positive(struct OutOfBoundsData *data, - void *index) { - (void)index; - ubsan_log("handle_vla_bound_not_positive", data->location); -} diff --git a/kubsan.h b/kubsan.h deleted file mode 100644 index dac5407..0000000 --- a/kubsan.h +++ /dev/null @@ -1,79 +0,0 @@ -#include - -enum { type_kind_int = 0, type_kind_float = 1, type_unknown = 0xffff }; - -struct type_descriptor { - uint16_t type_kind; - uint16_t type_info; - char type_name[1]; -}; - -struct source_location { - const char *file_name; - union { - unsigned long reported; - struct { - uint32_t line; - uint32_t column; - }; - }; -}; - -struct OverflowData { - struct source_location location; - struct type_descriptor *type; -}; - -struct type_mismatch_data { - struct source_location location; - struct type_descriptor *type; - unsigned long alignment; - unsigned char type_check_kind; -}; - -struct type_mismatch_data_v1 { - struct source_location location; - struct type_descriptor *type; - unsigned char log_alignment; - unsigned char type_check_kind; -}; - -struct type_mismatch_data_common { - struct source_location *location; - struct type_descriptor *type; - unsigned long alignment; - unsigned char type_check_kind; -}; - -struct nonnull_arg_data { - struct source_location location; - struct source_location attr_location; - int arg_index; -}; - -struct OutOfBoundsData { - struct source_location location; - struct type_descriptor *array_type; - struct type_descriptor *index_type; -}; - -struct ShiftOutOfBoundsData { - struct source_location location; - struct type_descriptor *lhs_type; - struct type_descriptor *rhs_type; -}; - -struct unreachable_data { - struct source_location location; -}; - -struct invalid_value_data { - struct source_location location; - struct type_descriptor *type; -}; - -struct alignment_assumption_data { - struct source_location location; - struct source_location assumption_location; - struct type_descriptor *type; -}; diff --git a/libc/exit/assert.c b/libc/exit/assert.c deleted file mode 100644 index b48773a..0000000 --- a/libc/exit/assert.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include -#include - -void aFailed(char *f, int l) { - kprintf("Assert failed\n"); - kprintf("%s : %d\n", f, l); - dump_backtrace(10); - for (;;) - ; -} diff --git a/libc/include/assert.h b/libc/include/assert.h deleted file mode 100644 index 90a0be4..0000000 --- a/libc/include/assert.h +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include - -#define assert(expr) \ - { \ - if (!(expr)) \ - aFailed(__FILE__, __LINE__); \ - } - -#define ASSERT_BUT_FIXME_PROPOGATE(expr) \ - { \ - if (!(expr)) \ - kprintf("Performing assert that should have been a propogated error."); \ - assert(expr); \ - } - -void aFailed(char *f, int l); -#define ASSERT_NOT_REACHED \ - { assert(0) } diff --git a/libc/include/errno.h b/libc/include/errno.h deleted file mode 100644 index 1ad1004..0000000 --- a/libc/include/errno.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef ERRNO_H -#define ERRNO_H -// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html -#define E2BIG 1 // Argument list too long. -#define EACCES 2 // Permission denied. -#define EADDRINUSE 3 // Address in use. -#define EADDRNOTAVAIL 4 // Address not available. -#define EAFNOSUPPORT 5 // Address family not supported. -#define EAGAIN 6 // Resource unavailable, try again. -#define EALREADY 7 // Connection already in progress. -#define EBADF 8 // Bad file descriptor. -#define EBADMSG 9 // Bad message. -#define EBUSY 10 // Device or resource busy. -#define ECANCELED 11 // Operation canceled. -#define ECHILD 12 // No child processes. -#define ECONNABORTED 13 // Connection aborted. -#define ECONNREFUSED 14 // Connection refused. -#define ECONNRESET 15 // Connection reset. -#define EDEADLK 16 // Resource deadlock would occur. -#define EDESTADDRREQ 17 // Destination address required. -#define EDOM 18 // Mathematics argument out of domain of function. -#define EDQUOT 19 // Reserved. -#define EEXIST 20 // File exists. -#define EFAULT 21 // Bad address. -#define EFBIG 22 // File too large. -#define EHOSTUNREACH 23 // Host is unreachable. -#define EIDRM 24 // Identifier removed. -#define EILSEQ 25 // Illegal byte sequence. -#define EINPROGRESS 26 // Operation in progress. -#define EINTR 27 // Interrupted function. -#define EINVAL 28 // Invalid argument. -#define EIO 29 // I/O error. -#define EISCONN 30 // Socket is connected. -#define EISDIR 31 // Is a directory. -#define ELOOP 32 // Too many levels of symbolic links. -#define EMFILE 33 // File descriptor value too large. -#define EMLINK 34 // Too many links. -#define EMSGSIZE 35 // Message too large. -#define EMULTIHOP 36 // Reserved. -#define ENAMETOOLONG 37 // Filename too long. -#define ENETDOWN 38 // Network is down. -#define ENETRESET 39 // Connection aborted by network. -#define ENETUNREACH 40 // Network unreachable. -#define ENFILE 41 // Too many files open in system. -#define ENOBUFS 42 // No buffer space available. -#define ENODATA 43 // No message is available on the STREAM head read queue. -#define ENODEV 44 // No such device. -#define ENOENT 45 // No such file or directory. -#define ENOEXEC 46 // Executable file format error. -#define ENOLCK 47 // No locks available. -#define ENOLINK 48 // Reserved. -#define ENOMEM 49 // Not enough space. -#define ENOMSG 50 // No message of the desired type. -#define ENOPROTOOPT 51 // Protocol not available. -#define ENOSPC 52 // No space left on device. -#define ENOSR 53 // No STREAM resources. -#define ENOSTR 54 // Not a STREAM. -#define ENOSYS 55 // Functionality not supported. -#define ENOTCONN 56 // The socket is not connected. -#define ENOTDIR 57 // Not a directory or a symbolic link to a directory. -#define ENOTEMPTY 58 // Directory not empty. -#define ENOTRECOVERABLE 59 // State not recoverable. -#define ENOTSOCK 60 // Not a socket. -#define ENOTSUP 61 // Not supported (may be the same value as. -#define ENOTTY 62 // Inappropriate I/O control operation. -#define ENXIO 63 // No such device or address. -#define EOPNOTSUPP ENOTSUP // Operation not supported on socket. -#define EOVERFLOW 65 // Value too large to be stored in data type. -#define EOWNERDEAD 66 // Previous owner died. -#define EPERM 67 // Operation not permitted. -#define EPIPE 68 // Broken pipe. -#define EPROTO 69 // Protocol error. -#define EPROTONOSUPPORT 70 // Protocol not supported. -#define EPROTOTYPE 71 // Protocol wrong type for socket. -#define ERANGE 72 // Result too large. -#define EROFS 73 // Read-only file system. -#define ESPIPE 74 // Invalid seek. -#define ESRCH 75 // No such process. -#define ESTALE 76 // Reserved. -#define ETIME 77 // Stream ioctl() timeout. -#define ETIMEDOUT 78 // Connection timed out. -#define ETXTBSY 79 // Text file busy. -#define EWOULDBLOCK EAGAIN // Operation would block. -#define EXDEV 81 // Cross-device link. -#endif diff --git a/libc/include/limits.h b/libc/include/limits.h deleted file mode 100644 index 05022ec..0000000 --- a/libc/include/limits.h +++ /dev/null @@ -1 +0,0 @@ -#define PATH_MAX 256 diff --git a/libc/include/stdio.h b/libc/include/stdio.h deleted file mode 100644 index f2bbb32..0000000 --- a/libc/include/stdio.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef STDIO_H -#define STDIO_H - -void putc(const char c); -int puts(char *str); -void delete_characther(void); -int kprintf(const char *format, ...); - -#endif diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h deleted file mode 100644 index e69de29..0000000 diff --git a/libc/include/string.h b/libc/include/string.h deleted file mode 100644 index 7cee4b2..0000000 --- a/libc/include/string.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef STRING_H -#define STRING_H -#include -#include - -unsigned long strlen(const char *s); -void *memcpy(void *dest, const void *src, uint32_t n); -void *memset(void *dst, const unsigned char c, uint32_t n); -int memcmp(const void *s1, const void *s2, uint32_t n); -char *strcpy(char *d, const char *s); -int strcmp(const char *s1, const char *s2); -int isequal(const char *s1, const char *s2); -int isequal_n(const char *s1, const char *s2, uint32_t n); -char *copy_and_allocate_string(const char *s); -char *copy_and_allocate_user_string(const char *s); -char *strncpy(char *dest, const char *src, size_t n); -size_t strlcpy(char *dst, const char *src, size_t dsize); -char *strcat(char *s1, const char *s2); -#endif diff --git a/libc/include/time.h b/libc/include/time.h deleted file mode 100644 index 4e356d1..0000000 --- a/libc/include/time.h +++ /dev/null @@ -1,6 +0,0 @@ -#include - -struct timespec { - time_t tv_sec; // Seconds. - long tv_nsec; // Nanoseconds. -}; diff --git a/libc/include/types.h b/libc/include/types.h deleted file mode 100644 index ffcf281..0000000 --- a/libc/include/types.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TYPES_H -#define TYPES_H -typedef unsigned int ino_t; - -typedef int mode_t; - -typedef int nlink_t; -typedef int uid_t; -typedef int gid_t; -typedef int id_t; - -typedef int blkcnt_t; -typedef int off_t; - -typedef int dev_t; -typedef unsigned int fsblkcnt_t; -typedef unsigned int fsfilcnt_t; -typedef unsigned int ino_t; -//typedef unsigned int size_t; - -typedef int blksize_t; -typedef int pid_t; -typedef int ssize_t; - -//typedef int clock_t; -typedef int time_t; -#endif diff --git a/libc/stdio/print.c b/libc/stdio/print.c deleted file mode 100644 index 8174983..0000000 --- a/libc/stdio/print.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "../../drivers/serial.h" -#include "../include/assert.h" -#include "../include/stdio.h" -#include - -#define TAB_SIZE 8 - -const char HEX_SET[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - -inline void putc(const char c) { write_serial(c); } - -int kprint_hex(uint64_t num) { - int c = 2; - - if (num == 0) { - putc('0'); - c++; - return c; - } - - char str[16] = {0}; - int i = 0; - for (; num != 0 && i < 16; i++, num /= 16) - str[i] = HEX_SET[(num % 16)]; - - c += i; - for (i--; i >= 0; i--) - putc(str[i]); - - return c; -} - -int kprint_int(int num) { - int c = 0; - if (0 == num) { - putc('0'); - c++; - return c; - } - char str[10]; - int i = 0; - for (; num != 0 && i < 10; i++, num /= 10) - str[i] = (num % 10) + '0'; - - c += i; - for (i--; i >= 0; i--) - putc(str[i]); - return c; -} - -int kprintf(const char *format, ...) { - int c = 0; - va_list list; - va_start(list, format); - - const char *s = format; - for (; *s; s++) { - if ('%' != *s) { - putc(*s); - c++; - continue; - } - - char flag = *(s + 1); - if ('\0' == flag) - break; - - switch (flag) { - case 'c': - putc((char)va_arg(list, int)); - c++; - break; - case 'd': - c += kprint_int(va_arg(list, int)); - break; - case 's': - for (char *string = va_arg(list, char *); *string; putc(*string++), c++) - ; - break; - case 'x': - c += kprint_hex(va_arg(list, const uint32_t)); - break; - case '%': - putc('%'); - c++; - break; - default: - ASSERT_NOT_REACHED; - break; - } - s++; - } - return c; -} - -int puts(char *str) { return kprintf("%s\n", str); } diff --git a/libc/string/copy.c b/libc/string/copy.c deleted file mode 100644 index 277c808..0000000 --- a/libc/string/copy.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include -#include - -char *copy_and_allocate_string(const char *s) { - size_t l = strlen(s); - char *r = kmalloc(l + 1); - if (!r) - return NULL; - return strncpy(r, s, l); -} - -char *copy_and_allocate_user_string(const char *s) { - size_t len; - if (!is_valid_user_c_string(s, &len)) - return NULL; - size_t real_len = strlen(s); - assert(real_len == len); - len = real_len; - char *r = kmalloc(len + 1); - if (!r) - return NULL; - strlcpy(r, s, len); - return r; -} diff --git a/libc/string/isequal.c b/libc/string/isequal.c deleted file mode 100644 index cdbd3cc..0000000 --- a/libc/string/isequal.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "../include/string.h" - -int isequal(const char *s1, const char *s2) { - for(;*s1;s1++,s2++) - if(*s1 != *s2) - return 0; - return 1; -} - -int isequal_n(const char *s1, const char *s2, uint32_t n) { - for(;*s1 && n;s1++,s2++,n--) - if(*s1 != *s2) - return 0; - return 1; -} diff --git a/libc/string/memcmp.c b/libc/string/memcmp.c deleted file mode 100644 index 72c680a..0000000 --- a/libc/string/memcmp.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "../include/string.h" - -int memcmp(const void *s1, const void *s2, uint32_t n) -{ - int return_value = 0; - - for(uint32_t i = 0;i < n;i++) - if(((unsigned char *)(s1))[i] != ((unsigned char *)(s2))[i]) - return_value++; - - return return_value; -} diff --git a/libc/string/memcpy.c b/libc/string/memcpy.c deleted file mode 100644 index 5c04407..0000000 --- a/libc/string/memcpy.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "../include/string.h" - -void * -memcpy(void *dest, const void *src, uint32_t n) { - unsigned char *d = dest; - const unsigned char *s = src; - - for (; n >= 8; n -= 8, d += 8, s += 8) - *(uint64_t *)d = *(uint64_t *)s; - - for (; n >= 4; n -= 4, d += 4, s += 4) - *(uint32_t *)d = *(uint32_t *)s; - - for (; n >= 2; n -= 2, d += 2, s += 2) - *(uint16_t *)d = *(uint16_t *)s; - - for (; n; n--) - *d++ = *s++; - return dest; -} diff --git a/libc/string/memset.c b/libc/string/memset.c deleted file mode 100644 index a446eb4..0000000 --- a/libc/string/memset.c +++ /dev/null @@ -1,9 +0,0 @@ -#include - -void *memset(void *dst, const unsigned char c, uint32_t n) { - uintptr_t d = (uintptr_t)dst; - for (uint32_t i = 0; i < n; i++, d++) - *(unsigned char *)d = c; - - return (void *)d; -} diff --git a/libc/string/strcat.c b/libc/string/strcat.c deleted file mode 100644 index 78a9ec6..0000000 --- a/libc/string/strcat.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -char *strcat(char *s1, const char *s2) { - strcpy(s1 + strlen(s1), s2); - return s1; -} diff --git a/libc/string/strcmp.c b/libc/string/strcmp.c deleted file mode 100644 index d7039e2..0000000 --- a/libc/string/strcmp.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "../include/string.h" - -int strcmp(const char *s1, const char *s2) -{ - for(;*s1 == *s2 && *s1; s1++, s2++) - ; - return *s1 - *s2; -} diff --git a/libc/string/strcpy.c b/libc/string/strcpy.c deleted file mode 100644 index fa1e336..0000000 --- a/libc/string/strcpy.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -char *strcpy(char *d, const char *s) { - char *s1 = d; - for (; (*d++ = *s++);) - ; - return s1; -} diff --git a/libc/string/strlcpy.c b/libc/string/strlcpy.c deleted file mode 100644 index 43d0e58..0000000 --- a/libc/string/strlcpy.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include - -// Copy string src to buffer dst of size dsize. At most dsize-1 -// chars will be copied. Always NUL terminates (unless dsize == 0). -// Returns strlen(src); if retval >= dsize, truncation occurred. -size_t strlcpy(char *dst, const char *src, size_t dsize) { - size_t n = dsize; - const char *osrc = src; - for (; n; n--) { - if ((*dst++ = *src++) == '\0') - break; - } - if (n == 0) { - if (dsize != 0) - *dst = '\0'; /* NUL-terminate dst */ - while (*src++) - ; - } - return src - osrc - 1; -} diff --git a/libc/string/strlen.c b/libc/string/strlen.c deleted file mode 100644 index 4346383..0000000 --- a/libc/string/strlen.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "../include/string.h" - -unsigned long strlen(const char *s) -{ - const char * tmp = s; - for(;*tmp++;); - return (tmp - s)-1; -} diff --git a/libc/string/strncpy.c b/libc/string/strncpy.c deleted file mode 100644 index a886895..0000000 --- a/libc/string/strncpy.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -// FIXME: Something is weird with this function -char *strncpy(char *dest, const char *src, size_t n) { - char *r = dest; - for (; n && (*dest = *src); n--, src++, dest++) - ; - *dest = '\0'; - return r; -} diff --git a/linker.ld b/linker.ld deleted file mode 100644 index 59b150d..0000000 --- a/linker.ld +++ /dev/null @@ -1,41 +0,0 @@ -ENTRY (_start) - -SECTIONS -{ - . = 0x00100000; - /* The kernel will live at 3GB + 1MB in the virtual address space, */ - /* which will be mapped to 1MB in the physical address space. */ - /* Note that we page-align the sections. */ - - _kernel_start = .; - .multiboot.data : { - *(.multiboot.data) - } - - .multiboot.text : { - *(.multiboot.text) - } - - . += 0xC0000000; - /* Add a symbol that indicates the start address of the kernel. */ - .text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000) - { - *(.text) - } - .rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000) - { - *(.rodata) - } - .data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000) - { - *(.data) - } - .bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000) - { - *(COMMON) - *(.bss) - *(.bootstrap_stack) - } - /* Add a symbol that indicates the end address of the kernel. */ - _kernel_end = .; -} diff --git a/log.c b/log.c deleted file mode 100644 index 56d38e8..0000000 --- a/log.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "log.h" -#include - -struct stackframe { - struct stackframe *ebp; - uint32_t eip; -}; - -void dump_backtrace(uint32_t max_frames) { - struct stackframe *stk; - asm("mov %%ebp,%0" : "=r"(stk)::); - kprintf("Stack trace:\n"); - for (uint32_t frame = 0; stk && frame < max_frames; ++frame) { - kprintf(" 0x%x\n", stk->eip); - stk = stk->ebp; - } - if (get_current_task()) { - kprintf(" PID: %x\n", get_current_task()->pid); - } -} - -void klog(char *str, int code) { - switch (code) { - case LOG_NOTE: - kprintf("[NOTE] "); - break; - case LOG_WARN: - kprintf("[WARN] "); - break; - case LOG_ERROR: - kprintf("[ERROR] "); - break; - default: - case LOG_SUCCESS: - kprintf("[SUCCESS] "); - break; - } - - puts(str); -} diff --git a/log.h b/log.h deleted file mode 100644 index fe499bc..0000000 --- a/log.h +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -#define LOG_NOTE 3 -#define LOG_WARN 2 -#define LOG_ERROR 1 -#define LOG_SUCCESS 0 - -void klog(char *str, int code); -void dump_backtrace(uint32_t max_frames); diff --git a/math.c b/math.c deleted file mode 100644 index 2d5e30c..0000000 --- a/math.c +++ /dev/null @@ -1,3 +0,0 @@ -#include -int min(int a, int b) { return ((a) > (b) ? b : a); } -int max(int a, int b) { return (a > b) ? a : b; } diff --git a/mount/cat b/mount/cat deleted file mode 120000 index a24e907..0000000 --- a/mount/cat +++ /dev/null @@ -1 +0,0 @@ -./minibox \ No newline at end of file diff --git a/mount/init b/mount/init deleted file mode 120000 index a24e907..0000000 --- a/mount/init +++ /dev/null @@ -1 +0,0 @@ -./minibox \ No newline at end of file diff --git a/mount/pid1 b/mount/pid1 deleted file mode 100755 index 773d54c..0000000 Binary files a/mount/pid1 and /dev/null differ diff --git a/mount/program b/mount/program deleted file mode 100755 index c93d7ba..0000000 Binary files a/mount/program and /dev/null differ diff --git a/mount/sh b/mount/sh deleted file mode 100755 index c05684c..0000000 Binary files a/mount/sh and /dev/null differ diff --git a/multiboot.h b/multiboot.h deleted file mode 100644 index ecbb6a0..0000000 --- a/multiboot.h +++ /dev/null @@ -1,243 +0,0 @@ -#include -#ifndef MULTIBOOT_HEADER -#define MULTIBOOT_HEADER 1 - -/* How many bytes from the start of the file we search for the header. */ -#define MULTIBOOT_SEARCH 8192 -#define MULTIBOOT_HEADER_ALIGN 4 - -/* The magic field should contain this. */ -#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 - -/* This should be in %eax. */ -#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 - -/* Alignment of multiboot modules. */ -#define MULTIBOOT_MOD_ALIGN 0x00001000 - -/* Alignment of the multiboot info structure. */ -#define MULTIBOOT_INFO_ALIGN 0x00000004 - -/* Flags set in the ’flags’ member of the multiboot header. */ - -/* Align all boot modules on i386 page (4KB) boundaries. */ -#define MULTIBOOT_PAGE_ALIGN 0x00000001 - -/* Must pass memory information to OS. */ -#define MULTIBOOT_MEMORY_INFO 0x00000002 - -/* Must pass video information to OS. */ -#define MULTIBOOT_VIDEO_MODE 0x00000004 - -/* This flag indicates the use of the address fields in the header. */ -#define MULTIBOOT_AOUT_KLUDGE 0x00010000 - -/* Flags to be set in the ’flags’ member of the multiboot info structure. */ - -/* is there basic lower/upper memory information? */ -#define MULTIBOOT_INFO_MEMORY 0x00000001 -/* is there a boot device set? */ -#define MULTIBOOT_INFO_BOOTDEV 0x00000002 -/* is the command-line defined? */ -#define MULTIBOOT_INFO_CMDLINE 0x00000004 -/* are there modules to do something with? */ -#define MULTIBOOT_INFO_MODS 0x00000008 - -/* These next two are mutually exclusive */ - -/* is there a symbol table loaded? */ -#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 -/* is there an ELF section header table? */ -#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 - -/* is there a full memory map? */ -#define MULTIBOOT_INFO_MEM_MAP 0x00000040 - -/* Is there drive info? */ -#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 - -/* Is there a config table? */ -#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 - -/* Is there a boot loader name? */ -#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 - -/* Is there a APM table? */ -#define MULTIBOOT_INFO_APM_TABLE 0x00000400 - -/* Is there video information? */ -#define MULTIBOOT_INFO_VBE_INFO 0x00000800 -#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 - -#ifndef ASM_FILE - -typedef uint8_t multiboot_uint8_t; -typedef uint16_t multiboot_uint16_t; -typedef uint32_t multiboot_uint32_t; -typedef uint64_t multiboot_uint64_t; - -struct multiboot_header { - /* Must be MULTIBOOT_MAGIC - see above. */ - multiboot_uint32_t magic; - - /* Feature flags. */ - multiboot_uint32_t flags; - - /* The above fields plus this one must equal 0 mod 2^32. */ - multiboot_uint32_t checksum; - - /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ - multiboot_uint32_t header_addr; - multiboot_uint32_t load_addr; - multiboot_uint32_t load_end_addr; - multiboot_uint32_t bss_end_addr; - multiboot_uint32_t entry_addr; - - /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ - multiboot_uint32_t mode_type; - multiboot_uint32_t width; - multiboot_uint32_t height; - multiboot_uint32_t depth; -}; - -/* The symbol table for a.out. */ -struct multiboot_aout_symbol_table { - multiboot_uint32_t tabsize; - multiboot_uint32_t strsize; - multiboot_uint32_t addr; - multiboot_uint32_t reserved; -}; -typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; - -/* The section header table for ELF. */ -struct multiboot_elf_section_header_table { - multiboot_uint32_t num; - multiboot_uint32_t size; - multiboot_uint32_t addr; - multiboot_uint32_t shndx; -}; -typedef struct multiboot_elf_section_header_table - multiboot_elf_section_header_table_t; - -struct multiboot_info { - /* Multiboot info version number */ - multiboot_uint32_t flags; - - /* Available memory from BIOS */ - multiboot_uint32_t mem_lower; - multiboot_uint32_t mem_upper; - - /* "root" partition */ - multiboot_uint32_t boot_device; - - /* Kernel command line */ - multiboot_uint32_t cmdline; - - /* Boot-Module list */ - multiboot_uint32_t mods_count; - multiboot_uint32_t mods_addr; - - union { - multiboot_aout_symbol_table_t aout_sym; - multiboot_elf_section_header_table_t elf_sec; - } u; - - /* Memory Mapping buffer */ - multiboot_uint32_t mmap_length; - multiboot_uint32_t mmap_addr; - - /* Drive Info buffer */ - multiboot_uint32_t drives_length; - multiboot_uint32_t drives_addr; - - /* ROM configuration table */ - multiboot_uint32_t config_table; - - /* Boot Loader Name */ - multiboot_uint32_t boot_loader_name; - - /* APM table */ - multiboot_uint32_t apm_table; - - /* Video */ - multiboot_uint32_t vbe_control_info; - multiboot_uint32_t vbe_mode_info; - multiboot_uint16_t vbe_mode; - multiboot_uint16_t vbe_interface_seg; - multiboot_uint16_t vbe_interface_off; - multiboot_uint16_t vbe_interface_len; - - multiboot_uint64_t framebuffer_addr; - multiboot_uint32_t framebuffer_pitch; - multiboot_uint32_t framebuffer_width; - multiboot_uint32_t framebuffer_height; - multiboot_uint8_t framebuffer_bpp; -#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 -#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 -#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 - multiboot_uint8_t framebuffer_type; - union { - struct { - multiboot_uint32_t framebuffer_palette_addr; - multiboot_uint16_t framebuffer_palette_num_colors; - }; - struct { - multiboot_uint8_t framebuffer_red_field_position; - multiboot_uint8_t framebuffer_red_mask_size; - multiboot_uint8_t framebuffer_green_field_position; - multiboot_uint8_t framebuffer_green_mask_size; - multiboot_uint8_t framebuffer_blue_field_position; - multiboot_uint8_t framebuffer_blue_mask_size; - }; - }; -}; -typedef struct multiboot_info multiboot_info_t; - -struct multiboot_color { - multiboot_uint8_t red; - multiboot_uint8_t green; - multiboot_uint8_t blue; -}; - -struct multiboot_mmap_entry { - multiboot_uint32_t size; - multiboot_uint64_t addr; - multiboot_uint64_t len; -#define MULTIBOOT_MEMORY_AVAILABLE 1 -#define MULTIBOOT_MEMORY_RESERVED 2 -#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 -#define MULTIBOOT_MEMORY_NVS 4 -#define MULTIBOOT_MEMORY_BADRAM 5 - multiboot_uint32_t type; -} __attribute__((packed)); -typedef struct multiboot_mmap_entry multiboot_memory_map_t; - -struct multiboot_mod_list { - /* the memory used goes from bytes ’mod_start’ to ’mod_end-1’ inclusive */ - multiboot_uint32_t mod_start; - multiboot_uint32_t mod_end; - - /* Module command line */ - multiboot_uint32_t cmdline; - - /* padding to take it to 16 bytes (must be zero) */ - multiboot_uint32_t pad; -}; -typedef struct multiboot_mod_list multiboot_module_t; - -/* APM BIOS info. */ -struct multiboot_apm_info { - multiboot_uint16_t version; - multiboot_uint16_t cseg; - multiboot_uint32_t offset; - multiboot_uint16_t cseg_16; - multiboot_uint16_t dseg; - multiboot_uint16_t flags; - multiboot_uint16_t cseg_len; - multiboot_uint16_t cseg_16_len; - multiboot_uint16_t dseg_len; -}; - -#endif /* ! ASM_FILE */ - -#endif /* ! MULTIBOOT_HEADER */ diff --git a/network/arp.c b/network/arp.c deleted file mode 100644 index de6d898..0000000 --- a/network/arp.c +++ /dev/null @@ -1,153 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -struct ARP_DATA { - uint16_t htype; // Hardware type - uint16_t ptype; // Protocol type - uint8_t hlen; // Hardware address length (Ethernet = 6) - uint8_t plen; // Protocol address length (IPv4 = 4) - uint16_t opcode; // ARP Operation Code - uint8_t srchw[6]; // Source hardware address - hlen bytes (see above) - uint8_t srcpr[4]; // Source protocol address - plen bytes (see above). - // If IPv4 can just be a "u32" type. - uint8_t dsthw[6]; // Destination hardware address - hlen bytes (see above) - uint8_t dstpr[4]; // Destination protocol address - plen bytes (see - // above). If IPv4 can just be a "u32" type. -}; - -struct ARP_TABLE_ENTRY { - uint8_t is_used; - uint8_t mac[6]; - uint8_t ip[4]; -}; - -struct ARP_TABLE_ENTRY arp_table[10] = {0}; - -// FIXME: This is hardcoded, don't do this. -uint8_t ip_address[4] = {10, 0, 2, 15}; - -struct ARP_TABLE_ENTRY *find_arp_entry_to_use(void) { - // This does not need to find a "free" entry as a ARP table is - // just a cache, it just has to pick a entry efficently. - for (int i = 0; i < 10; i++) { - if (!arp_table[i].is_used) { - return &arp_table[i]; - } - } - return &arp_table[0]; -} - -void print_mac(const char *str, uint8_t *mac) { - kprintf("%s: ", str); - for (int i = 0; i < 6; i++) { - kprintf("%x", mac[i]); - if (5 != i) - kprintf(":"); - } - kprintf("\n"); -} - -void print_ip(const char *str, const uint8_t *ip) { - kprintf("%s: ", str); - for (int i = 0; i < 4; i++) { - kprintf("%d", ip[i]); - if (3 != i) - kprintf("."); - } - kprintf("\n"); -} - -void send_arp_request(const uint8_t ip[4]) { - struct ARP_DATA data; - data.htype = htons(1); - data.ptype = htons(0x0800); - - data.hlen = 6; - data.plen = 4; - - data.opcode = htons(0x0001); - get_mac_address(data.srchw); - memcpy(data.srcpr, ip_address, sizeof(uint8_t[4])); - - memset(data.dsthw, 0, sizeof(uint8_t[6])); - memcpy(data.dstpr, ip, sizeof(uint8_t[4])); - - uint8_t broadcast[6]; - memset(broadcast, 0xFF, sizeof(broadcast)); - send_ethernet_packet(broadcast, 0x0806, (uint8_t *)&data, sizeof(data)); -} - -int get_mac_from_ip(const uint8_t ip[4], uint8_t mac[6]) { - print_ip("ARP GETTING MAC FROM IP: ", ip); - for (int i = 0; i < 10; i++) { - if (0 != memcmp(arp_table[i].ip, ip, sizeof(uint8_t[4]))) - continue; - memcpy(mac, arp_table[i].mac, sizeof(uint8_t[6])); - return 1; - } - klog("ARP cache miss", LOG_NOTE); - asm("sti"); - send_arp_request(ip); - // TODO: Maybe wait a bit? - for (int i = 0; i < 10; i++) { - if (0 != memcmp(arp_table[i].ip, ip, sizeof(uint8_t[4]))) - continue; - memcpy(mac, arp_table[i].mac, sizeof(uint8_t[6])); - return 1; - } - assert(0); - return 0; -} - -void handle_arp(const uint8_t *payload) { - struct ARP_DATA *data = (struct ARP_DATA *)payload; - - // Assert that communication is over ethernet - assert(1 == ntohs(data->htype)); - // Assert that request uses IP - assert(0x0800 == ntohs(data->ptype)); - - assert(6 == data->hlen); - assert(4 == data->plen); - // Assert it is a request - if (0x0001 /*arp_request*/ == ntohs(data->opcode)) { - print_mac("srchw: ", data->srchw); - print_ip("srcpr: ", data->srcpr); - - print_mac("dsthw: ", data->dsthw); - print_ip("dstpr: ", data->dstpr); - - assert(0 == memcmp(data->dstpr, ip_address, sizeof(uint8_t[4]))); - - // Now we have to construct a ARP response - struct ARP_DATA response; - response.htype = htons(1); - response.ptype = htons(0x0800); - response.opcode = htons(0x00002); - response.hlen = 6; - response.plen = 4; - get_mac_address(response.srchw); - memcpy(response.srcpr, ip_address, sizeof(uint8_t[4])); - - memcpy(response.dsthw, data->srchw, sizeof(uint8_t[6])); - memcpy(response.dstpr, data->srcpr, sizeof(uint8_t[4])); - - send_ethernet_packet(data->srchw, 0x0806, (uint8_t *)&response, - sizeof(response)); - } else if (0x0002 /*arp_response*/ == ntohs(data->opcode)) { - // Find a entry to fill - struct ARP_TABLE_ENTRY *entry = find_arp_entry_to_use(); - entry->is_used = 1; - memcpy(entry->mac, data->srchw, sizeof(uint8_t[6])); - memcpy(entry->ip, data->srcpr, sizeof(uint8_t[4])); - print_ip("Added ip: ", entry->ip); - } else { - kprintf("GOT A ARP REQEUST WITH TYPE: %x\n", ntohs(data->opcode)); - assert(0); - } -} diff --git a/network/arp.h b/network/arp.h deleted file mode 100644 index c2beb94..0000000 --- a/network/arp.h +++ /dev/null @@ -1,4 +0,0 @@ -#include - -int get_mac_from_ip(const uint8_t ip[4], uint8_t mac[6]); -void handle_arp(const uint8_t *payload); diff --git a/network/bytes.c b/network/bytes.c deleted file mode 100644 index 94afa73..0000000 --- a/network/bytes.c +++ /dev/null @@ -1,10 +0,0 @@ -#include - -uint16_t ntohs(uint16_t net) { return (net >> 8) | (net << 8); } - -uint16_t htons(uint16_t net) { return (net >> 8) | (net << 8); } - -uint32_t htonl(uint32_t net) { - return (((net & 0x000000FF) << 24) | ((net & 0x0000FF00) << 8) | - ((net & 0x00FF0000) >> 8) | ((net & 0xFF000000) >> 24)); -} diff --git a/network/bytes.h b/network/bytes.h deleted file mode 100644 index c291589..0000000 --- a/network/bytes.h +++ /dev/null @@ -1,5 +0,0 @@ -#include - -uint16_t ntohs(uint16_t net); -uint16_t htons(uint16_t net); -uint32_t htonl(uint32_t net); diff --git a/network/ethernet.c b/network/ethernet.c deleted file mode 100644 index e97ccbd..0000000 --- a/network/ethernet.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -struct ETHERNET_HEADER { - uint8_t mac_dst[6]; - uint8_t mac_src[6]; - uint16_t type; -}; - -uint32_t crc32(const char *buf, size_t len) { - static uint32_t table[256]; - static int have_table = 0; - uint32_t rem; - uint8_t octet; - int i, j; - const char *p, *q; - - if (have_table == 0) { - for (i = 0; i < 256; i++) { - rem = i; - for (j = 0; j < 8; j++) { - if (rem & 1) { - rem >>= 1; - rem ^= 0xedb88320; - } else - rem >>= 1; - } - table[i] = rem; - } - have_table = 1; - } - - uint32_t crc = 0xFFFFFFFF; - q = buf + len; - for (p = buf; p < q; p++) { - octet = *p; - crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet]; - } - return ~crc; -} - -void handle_ethernet(const uint8_t *packet, uint64_t packet_length) { - struct ETHERNET_HEADER *eth_header = (struct ETHERNET_HEADER *)packet; - packet += sizeof(struct ETHERNET_HEADER); - const uint8_t *payload = packet; - packet += packet_length - sizeof(struct ETHERNET_HEADER); - uint32_t crc = *((uint32_t *)packet - 1); - kprintf("PACKET crc: %x\n", crc); - kprintf("OUR OWN CALCULATED crc: %x\n", - crc32((const char *)eth_header, (packet_length - 4))); - - uint16_t type = ntohs(eth_header->type); - switch (type) { - case 0x0806: - handle_arp(payload); - break; - case 0x0800: - handle_ipv4(payload, packet_length - sizeof(struct ETHERNET_HEADER) - 4); - break; - default: - kprintf("Can't handle ethernet type\n"); - break; - } -} - -void send_ethernet_packet(uint8_t mac_dst[6], uint16_t type, uint8_t *payload, - uint64_t payload_length) { - // FIXME: Janky allocation, do this better - uint64_t buffer_size = - sizeof(struct ETHERNET_HEADER) + payload_length + sizeof(uint32_t); - uint8_t *buffer = kmalloc(buffer_size); - uint8_t *buffer_start = buffer; - struct ETHERNET_HEADER *eth_header = (struct ETHERNET_HEADER *)buffer; - buffer += sizeof(struct ETHERNET_HEADER); - memcpy(buffer, payload, payload_length); - buffer += payload_length; - - memcpy(eth_header->mac_dst, mac_dst, sizeof(uint8_t[6])); - get_mac_address(eth_header->mac_src); - eth_header->type = htons(type); - *(uint32_t *)(buffer) = - htonl(crc32((const char *)buffer_start, buffer_size - 4)); - - assert(rtl8139_send_data(buffer_start, buffer_size)); - kfree(buffer_start); - kprintf("sent data\n"); -} diff --git a/network/ethernet.h b/network/ethernet.h deleted file mode 100644 index 0fdcee3..0000000 --- a/network/ethernet.h +++ /dev/null @@ -1,5 +0,0 @@ -#include - -void handle_ethernet(const uint8_t *packet, uint64_t packet_length); -void send_ethernet_packet(uint8_t mac_dst[6], uint16_t type, uint8_t *payload, - uint64_t payload_length); diff --git a/network/ipv4.c b/network/ipv4.c deleted file mode 100644 index 099aa0d..0000000 --- a/network/ipv4.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -uint16_t ip_checksum(void *vdata, size_t length) { - // Cast the data pointer to one that can be indexed. - char *data = (char *)vdata; - - // Initialise the accumulator. - uint32_t acc = 0xffff; - - // Handle complete 16-bit blocks. - for (size_t i = 0; i + 1 < length; i += 2) { - uint16_t word; - memcpy(&word, data + i, 2); - acc += ntohs(word); - if (acc > 0xffff) { - acc -= 0xffff; - } - } - - // Handle any partial block at the end of the data. - if (length & 1) { - uint16_t word = 0; - memcpy(&word, data + length - 1, 1); - acc += ntohs(word); - if (acc > 0xffff) { - acc -= 0xffff; - } - } - - // Return the checksum in network byte order. - return htons(~acc); -} - -extern uint8_t ip_address[4]; -void send_ipv4_packet(uint32_t ip, uint8_t protocol, const uint8_t *payload, - uint16_t length) { - uint8_t header[20] = {0}; - header[0] = (4 /*version*/ << 4) | (5 /*IHL*/); - *((uint16_t *)(header + 2)) = htons(length + 20); - header[8 /*TTL*/] = 0xF8; - header[9] = protocol; - - memcpy(header + 12 /*src_ip*/, ip_address, sizeof(uint8_t[4])); - memcpy(header + 16, &ip, sizeof(uint8_t[4])); - - *((uint16_t *)(header + 10 /*checksum*/)) = ip_checksum(header, 20); - uint16_t packet_length = length + 20; - uint8_t *packet = kmalloc(packet_length); - memcpy(packet, header, 20); - memcpy(packet + 20, payload, length); - - uint8_t mac[6]; - uint8_t ip_copy[4]; // TODO: Do I need to do this? - memcpy(ip_copy, &ip, sizeof(uint8_t[4])); - get_mac_from_ip(ip_copy, mac); - send_ethernet_packet(mac, 0x0800, packet, packet_length); - kfree(packet); -} - -void handle_ipv4(const uint8_t *payload, uint32_t packet_length) { - assert(packet_length > 4); - - uint16_t saved_checksum = *(uint16_t *)(payload + 10); - *(uint16_t *)(payload + 10) = 0; - uint16_t calc_checksum = ip_checksum((uint8_t *)payload, 20); - *(uint16_t *)(payload + 10) = saved_checksum; - assert(calc_checksum == saved_checksum); - - uint8_t version = (*payload & 0xF0) >> 4; - uint8_t IHL = (*payload & 0xF); - kprintf("version: %x\n", version); - assert(4 == version); - assert(5 == IHL); - uint16_t ipv4_total_length = ntohs(*(uint16_t *)(payload + 2)); - assert(ipv4_total_length >= 20); - // Make sure the ipv4 header is not trying to get uninitalized memory - assert(ipv4_total_length <= packet_length); - - uint8_t src_ip[4]; - memcpy(src_ip, payload + 12, sizeof(uint8_t[4])); - - uint8_t protocol = *(payload + 9); - switch (protocol) { - case 0x11: - handle_udp(src_ip, payload + 20, ipv4_total_length - 20); - break; - default: - kprintf("Protocol given in IPv4 header not handeld: %x\n", protocol); - break; - } -} diff --git a/network/ipv4.h b/network/ipv4.h deleted file mode 100644 index f578202..0000000 --- a/network/ipv4.h +++ /dev/null @@ -1,5 +0,0 @@ -#include - -void handle_ipv4(const uint8_t *payload, uint32_t packet_length); -void send_ipv4_packet(uint32_t ip, uint8_t protocol, const uint8_t *payload, - uint16_t length); diff --git a/network/udp.c b/network/udp.c deleted file mode 100644 index 23411da..0000000 --- a/network/udp.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include -#include -#include -#include - -void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst, - const uint8_t *payload, uint16_t payload_length) { - uint16_t header[4] = {0}; - header[0] = src->sin_port; - header[1] = dst->sin_port; - header[2] = htons(payload_length + 8); - - uint16_t packet_length = sizeof(header) + payload_length; - uint8_t *packet = kmalloc(packet_length); - memcpy(packet, header, sizeof(header)); - memcpy(packet + sizeof(header), payload, payload_length); - send_ipv4_packet(dst->sin_addr.s_addr, 0x11, packet, packet_length); - kfree(packet); -} - -void handle_udp(uint8_t src_ip[4], const uint8_t *payload, - uint32_t packet_length) { - assert(packet_length >= 8); - // n_.* means network format(big endian) - // h_.* means host format((probably) little endian) - uint16_t n_source_port = *(uint16_t *)payload; - uint16_t h_source_port = ntohs(n_source_port); - (void)h_source_port; - uint16_t h_dst_port = ntohs(*(uint16_t *)(payload + 2)); - uint16_t h_length = ntohs(*(uint16_t *)(payload + 4)); - assert(h_length == packet_length); - uint16_t data_length = h_length - 8; - const uint8_t *data = payload + 8; - - // Find the open port - OPEN_INET_SOCKET *in_s = find_open_udp_port(htons(h_dst_port)); - assert(in_s); - SOCKET *s = in_s->s; - vfs_fd_t *fifo_file = s->ptr_socket_fd; - - // Write the sockaddr struct such that it can later be - // given to userland if asked. - struct sockaddr_in /*{ - sa_family_t sin_family; - union { - uint32_t s_addr; - } sin_addr; - uint16_t sin_port; - }*/ in; - in.sin_family = AF_INET; - memcpy(&in.sin_addr.s_addr, src_ip, sizeof(uint32_t)); - in.sin_port = n_source_port; - socklen_t sock_length = sizeof(struct sockaddr_in); - - raw_vfs_pwrite(fifo_file, &sock_length, sizeof(sock_length), 0); - raw_vfs_pwrite(fifo_file, &in, sizeof(in), 0); - - // Write the UDP payload length(not including header) - raw_vfs_pwrite(fifo_file, &data_length, sizeof(uint16_t), 0); - - // Write the UDP payload - raw_vfs_pwrite(fifo_file, (char *)data, data_length, 0); -} diff --git a/network/udp.h b/network/udp.h deleted file mode 100644 index c30b8c8..0000000 --- a/network/udp.h +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -void handle_udp(uint8_t src_ip[4], const uint8_t *payload, - uint32_t packet_length); -void send_udp_packet(struct sockaddr_in *src, const struct sockaddr_in *dst, - const uint8_t *payload, uint16_t payload_length); diff --git a/poll.c b/poll.c deleted file mode 100644 index 5e02723..0000000 --- a/poll.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include - -int poll(struct pollfd *fds, size_t nfds, int timeout) { - (void)timeout; - int read_locks[nfds]; - int write_locks[nfds]; - int disconnect_locks[nfds]; - for (size_t i = 0; i < nfds; i++) { - if (fds[i].fd < 0) - continue; - vfs_fd_t *f = get_vfs_fd(fds[i].fd); - if (fds[i].events & POLLIN) - read_locks[i] = create_read_fdhalt(f); - if (fds[i].events & POLLOUT) - write_locks[i] = create_write_fdhalt(f); - if (fds[i].events & POLLHUP) - disconnect_locks[i] = create_disconnect_fdhalt(f); - } - - switch_task(); - - for (size_t i = 0; i < nfds; i++) { - if (fds[i].fd < 0) - continue; - if (fds[i].events & POLLIN) - unset_read_fdhalt(read_locks[i]); - if (fds[i].events & POLLOUT) - unset_write_fdhalt(write_locks[i]); - if (fds[i].events & POLLHUP) - unset_disconnect_fdhalt(disconnect_locks[i]); - } - for (size_t i = 0; i < nfds; i++) { - if (0 > fds[i].fd) { - fds[i].revents = 0; - continue; - } - vfs_fd_t *f = get_vfs_fd(fds[i].fd); - if (!f) { - if (fds[i].events & POLLHUP) - fds[i].revents |= POLLHUP; - } else { - if (f->inode->has_data && fds[i].events & POLLIN) - fds[i].revents |= POLLIN; - if (f->inode->can_write && fds[i].events & POLLOUT) - fds[i].revents |= POLLOUT; - if (!(f->inode->is_open) && fds[i].events & POLLHUP) - fds[i].revents |= POLLHUP; - } - } - return 0; -} diff --git a/poll.h b/poll.h deleted file mode 100644 index 19698dd..0000000 --- a/poll.h +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -#define POLLIN (1 << 0) -#define POLLPRI (1 << 1) -#define POLLOUT (1 << 2) -#define POLLHUP (1 << 3) - -struct pollfd { - int fd; - short events; - short revents; -}; - -int poll(struct pollfd *fds, size_t nfds, int timeout); diff --git a/process.s b/process.s deleted file mode 100644 index 24e1869..0000000 --- a/process.s +++ /dev/null @@ -1,33 +0,0 @@ -.intel_syntax noprefix -.global copy_page_physical -.global loop_m -copy_page_physical: - push ebx - pushf - - cli - - mov ebx, [esp+12] - mov ecx, [esp+16] - - mov edx, cr0 - and edx, 0x7fffffff - mov cr0, edx - - mov edx, 1024 - -.loop: - mov eax, [ebx] - mov [ecx], eax - add ebx, 4 - add ecx, 4 - dec edx - jnz .loop - - mov edx, cr0 - or edx, 0x80000000 - mov cr0, edx - - popf - pop ebx - ret diff --git a/random.c b/random.c deleted file mode 100644 index 0e1b760..0000000 --- a/random.c +++ /dev/null @@ -1,142 +0,0 @@ -// FIXME: This is mostlikely incredibly inefficent and insecure. -#include -#include -#include -#include -#include -#include -#include - -#define HASH_CTX SHA1_CTX -#define HASH_LEN SHA1_LEN - -uint32_t internal_chacha_block[16] = { - // Constant ascii values of "expand 32-byte k" - 0x61707865, - 0x3320646e, - 0x79622d32, - 0x6b206574, - // The unique key - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - // Block counter - 0x00000000, - // Nonce - 0x00000000, - 0x00000000, -}; - -void mix_chacha(void) { - uint8_t rand_data[BLOCK_SIZE]; - get_random((BYTEPTR)rand_data, BLOCK_SIZE); - memcpy(internal_chacha_block + KEY, rand_data, KEY_SIZE); - memcpy(internal_chacha_block + NONCE, rand_data + KEY_SIZE, NONCE_SIZE); - internal_chacha_block[COUNT] = 0; -} - -void get_random(BYTEPTR buffer, uint64_t len) { - uint8_t rand_data[BLOCK_SIZE]; - for (; len > 0;) { - if (COUNT_MAX - 1 == internal_chacha_block[COUNT]) { - // The current block has used up all the 2^32 counts. If the - // key and/or the nonce are not changed and the count - // overflows back to zero then the random values would - // repeate. This is of course not desiered behaviour. The - // solution is to create a new nonce and key using the - // already established chacha block. - internal_chacha_block[COUNT]++; - mix_chacha(); - } - uint32_t read_len = (BLOCK_SIZE < len) ? (BLOCK_SIZE) : len; - chacha_block((uint32_t *)rand_data, internal_chacha_block); - internal_chacha_block[COUNT]++; - memcpy(buffer, rand_data, read_len); - buffer += read_len; - len -= read_len; - } -} - -HASH_CTX hash_pool; -uint32_t hash_pool_size = 0; - -void add_hash_pool(void) { - uint8_t new_chacha_key[KEY_SIZE]; - get_random(new_chacha_key, KEY_SIZE); - - uint8_t hash_buffer[HASH_LEN]; - SHA1_Final(&hash_pool, hash_buffer); - for (size_t i = 0; i < HASH_LEN; i++) - new_chacha_key[i % KEY_SIZE] ^= hash_buffer[i]; - - SHA1_Init(&hash_pool); - SHA1_Update(&hash_pool, hash_buffer, HASH_LEN); - - uint8_t block[BLOCK_SIZE]; - get_random(block, BLOCK_SIZE); - SHA1_Update(&hash_pool, block, BLOCK_SIZE); - - memcpy(internal_chacha_block + KEY, new_chacha_key, KEY_SIZE); - - mix_chacha(); -} - -void add_entropy(uint8_t *buffer, size_t size) { - SHA1_Update(&hash_pool, buffer, size); - hash_pool_size += size; - if (hash_pool_size >= HASH_LEN * 2) - add_hash_pool(); -} - -void setup_random(void) { - SHA1_Init(&hash_pool); - - BYTE seed[1024]; - int rand_fd = vfs_open("/etc/seed", O_RDWR, 0); - if (0 > rand_fd) { - klog("/etc/seed not found", LOG_WARN); - return; - } - - size_t offset = 0; - for (int rc; (rc = vfs_pread(rand_fd, seed, 1024, offset)); offset += rc) { - if (0 > rc) { - klog("/etc/seed read error", LOG_WARN); - break; - } - add_entropy(seed, rc); - } - add_hash_pool(); - - // Update the /etc/seed file to ensure we get a new state upon next - // boot. - get_random(seed, 1024); - vfs_pwrite(rand_fd, seed, 1024, 0); - vfs_close(rand_fd); -} - -int random_write(BYTEPTR buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - (void)offset; - (void)fd; - add_entropy(buffer, len); - return len; // add_entropy() never fails to recieve (len) amount of data. -} - -int random_read(BYTEPTR buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - (void)offset; - (void)fd; - get_random(buffer, len); - return len; // get_random() never fails to give "len" amount of data. -} - -void add_random_devices(void) { - devfs_add_file("/random", random_read, random_write, NULL, 1, 1, - FS_TYPE_CHAR_DEVICE); - devfs_add_file("/urandom", random_read, random_write, NULL, 1, 1, - FS_TYPE_CHAR_DEVICE); -} diff --git a/random.h b/random.h deleted file mode 100644 index 437927f..0000000 --- a/random.h +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include -#include - -void setup_random(void); -void add_random_devices(void); -void get_random(uint8_t* buffer, uint64_t len); diff --git a/read_eip.s b/read_eip.s deleted file mode 100644 index 6041db0..0000000 --- a/read_eip.s +++ /dev/null @@ -1,5 +0,0 @@ -.intel_syntax noprefix -.global read_eip -read_eip: - pop eax - jmp eax diff --git a/scalls/accept.c b/scalls/accept.c deleted file mode 100644 index 3c3f5ad..0000000 --- a/scalls/accept.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "accept.h" - -int syscall_accept(SYS_ACCEPT_PARAMS *args) { - return accept(args->socket, args->address, args->address_len); -} diff --git a/scalls/accept.h b/scalls/accept.h deleted file mode 100644 index d022999..0000000 --- a/scalls/accept.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "../socket.h" - -typedef struct SYS_ACCEPT_PARAMS { - int socket; - struct sockaddr *address; - socklen_t *address_len; -} __attribute__((packed)) SYS_ACCEPT_PARAMS; - -int syscall_accept(SYS_ACCEPT_PARAMS *args); diff --git a/scalls/bind.c b/scalls/bind.c deleted file mode 100644 index 76e36ab..0000000 --- a/scalls/bind.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "bind.h" - -int syscall_bind(SYS_BIND_PARAMS *args) { - return bind(args->sockfd, args->addr, args->addrlen); -} diff --git a/scalls/bind.h b/scalls/bind.h deleted file mode 100644 index 5661ad0..0000000 --- a/scalls/bind.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "../socket.h" - -typedef struct SYS_BIND_PARAMS { - int sockfd; - const struct sockaddr *addr; - socklen_t addrlen; -} __attribute__((packed)) SYS_BIND_PARAMS; - -int syscall_bind(SYS_BIND_PARAMS *args); diff --git a/scalls/clock_gettime.c b/scalls/clock_gettime.c deleted file mode 100644 index 632ea08..0000000 --- a/scalls/clock_gettime.c +++ /dev/null @@ -1,10 +0,0 @@ -#include - -int syscall_clock_gettime(SYS_CLOCK_GETTIME_PARAMS *args) { - // FIXME: Actually implement this - if (args->ts) { - args->ts->tv_sec = 0; - args->ts->tv_nsec = 0; - } - return 0; -} diff --git a/scalls/clock_gettime.h b/scalls/clock_gettime.h deleted file mode 100644 index 145aa24..0000000 --- a/scalls/clock_gettime.h +++ /dev/null @@ -1,8 +0,0 @@ -#include - -typedef struct SYS_CLOCK_GETTIME_PARAMS { - clockid_t clk; - struct timespec *ts; -} __attribute__((packed)) SYS_CLOCK_GETTIME_PARAMS; - -int syscall_clock_gettime(SYS_CLOCK_GETTIME_PARAMS *args); diff --git a/scalls/ftruncate.c b/scalls/ftruncate.c deleted file mode 100644 index 6bc1170..0000000 --- a/scalls/ftruncate.c +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include - -int syscall_ftruncate(int fd, size_t length) { - return vfs_ftruncate(fd, length); -} diff --git a/scalls/ftruncate.h b/scalls/ftruncate.h deleted file mode 100644 index 9213e85..0000000 --- a/scalls/ftruncate.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -int syscall_ftruncate(int fd, size_t length); diff --git a/scalls/mkdir.c b/scalls/mkdir.c deleted file mode 100644 index 43f2424..0000000 --- a/scalls/mkdir.c +++ /dev/null @@ -1,5 +0,0 @@ -#include - -int syscall_mkdir(const char *path, int mode) { - return vfs_mkdir(path, mode); -} diff --git a/scalls/mkdir.h b/scalls/mkdir.h deleted file mode 100644 index 0bf0043..0000000 --- a/scalls/mkdir.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -int syscall_mkdir(const char *path, int mode); diff --git a/scalls/mmap.c b/scalls/mmap.c deleted file mode 100644 index 83fff6a..0000000 --- a/scalls/mmap.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -void *syscall_mmap(SYS_MMAP_PARAMS *args) { - return mmap(args->addr, args->length, args->prot, args->flags, args->fd, - args->offset); -} diff --git a/scalls/mmap.h b/scalls/mmap.h deleted file mode 100644 index f5e121e..0000000 --- a/scalls/mmap.h +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include - -typedef struct SYS_MMAP_PARAMS { - void *addr; - size_t length; - int prot; - int flags; - int fd; - size_t offset; -} __attribute__((packed)) SYS_MMAP_PARAMS; - -void *syscall_mmap(SYS_MMAP_PARAMS *args); diff --git a/scalls/msleep.c b/scalls/msleep.c deleted file mode 100644 index 0120f08..0000000 --- a/scalls/msleep.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include -#include - -void syscall_msleep(uint32_t ms) { - get_current_task()->sleep_until = pit_num_ms() + ms; - switch_task(); -} diff --git a/scalls/msleep.h b/scalls/msleep.h deleted file mode 100644 index 71bf269..0000000 --- a/scalls/msleep.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef MSLEEP_H -#define MSLEEP_H -#include -void syscall_msleep(uint32_t ms); -#endif diff --git a/scalls/ppoll.c b/scalls/ppoll.c deleted file mode 100644 index 8feb35c..0000000 --- a/scalls/ppoll.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include -#include -#include - -int syscall_poll(SYS_POLL_PARAMS *args) { - struct pollfd *fds = args->fds; - size_t nfds = args->nfds; - int timeout = args->timeout; - return poll(fds, nfds, timeout); -} diff --git a/scalls/ppoll.h b/scalls/ppoll.h deleted file mode 100644 index 13700b5..0000000 --- a/scalls/ppoll.h +++ /dev/null @@ -1,9 +0,0 @@ -#include - -typedef struct SYS_POLL_PARAMS { - struct pollfd *fds; - size_t nfds; - int timeout; -} __attribute__((packed)) SYS_POLL_PARAMS; - -int syscall_poll(SYS_POLL_PARAMS *args); diff --git a/scalls/recvfrom.c b/scalls/recvfrom.c deleted file mode 100644 index 1770fa1..0000000 --- a/scalls/recvfrom.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include -#include -#include - -size_t syscall_recvfrom( - int socket, void *buffer, size_t length, int flags, - struct two_args - *extra_args /*struct sockaddr *address, socklen_t *address_len*/) { - - struct sockaddr *address = (struct sockaddr *)extra_args->a; - socklen_t *address_len = (socklen_t *)extra_args->b; - kprintf("address: %x\n", address); - kprintf("address_len: %x\n", address_len); - - if (flags & MSG_WAITALL) { - struct pollfd fds[1]; - fds[0].fd = socket; - fds[0].events = POLLIN; - poll(fds, 1, 0); - } - - uint16_t data_length; - socklen_t tmp_socklen; - vfs_pread(socket, &tmp_socklen, sizeof(socklen_t), 0); - if (address_len) - *address_len = tmp_socklen; - if (address) { - vfs_pread(socket, address, tmp_socklen, 0); - } else { - // We still have to throwaway the data. - char devnull[100]; - for (; tmp_socklen;) { - int rc = vfs_pread(socket, devnull, min(tmp_socklen, 100), 0); - assert(rc >= 0); - tmp_socklen -= rc; - } - } - - vfs_pread(socket, &data_length, sizeof(data_length), 0); - // If it is reading less than the packet length that could cause - // problems as the next read will not be put at a new header. Luckily - // it seems as if other UNIX systems can discard the rest of the - // packet if not read. - - // Read in the data requested - int read_len = min(length, data_length); - int rc = vfs_pread(socket, buffer, read_len, 0); - // Discard the rest of the packet - int rest = data_length - read_len; - char devnull[100]; - for (; rest;) { - int rc = vfs_pread(socket, devnull, 100, 0); - assert(rc >= 0); - rest -= rc; - } - return rc; -} diff --git a/scalls/recvfrom.h b/scalls/recvfrom.h deleted file mode 100644 index d81a1e0..0000000 --- a/scalls/recvfrom.h +++ /dev/null @@ -1,11 +0,0 @@ -#include - -struct two_args { - uint32_t a; - uint32_t b; -}; - -size_t syscall_recvfrom( - int socket, void *buffer, size_t length, int flags, - struct two_args - *extra_args /*struct sockaddr *address, socklen_t *address_len*/); diff --git a/scalls/sendto.c b/scalls/sendto.c deleted file mode 100644 index 48c4020..0000000 --- a/scalls/sendto.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include - -size_t syscall_sendto(int socket, const void *message, size_t length, - int flags, struct t_two_args *extra_args /* - const struct sockaddr *dest_addr, - socklen_t dest_len*/) { - const struct sockaddr *dest_addr = (const struct sockaddr *)extra_args->a; - socklen_t dest_len = (socklen_t)extra_args->b; - (void)dest_len; - vfs_fd_t *fd = get_vfs_fd(socket); - assert(fd); - SOCKET *s = (SOCKET *)fd->inode->internal_object; - OPEN_INET_SOCKET *inet = s->child; - assert(inet); - struct sockaddr_in in; - in.sin_addr.s_addr = inet->address; - in.sin_port = inet->port; - send_udp_packet(&in, (const struct sockaddr_in *)dest_addr, message, length); - return length; // FIXME: This is probably not true. -} diff --git a/scalls/sendto.h b/scalls/sendto.h deleted file mode 100644 index 0f852de..0000000 --- a/scalls/sendto.h +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -struct t_two_args { - uint32_t a; - uint32_t b; -}; -size_t syscall_sendto(int socket, const void *message, size_t length, - int flags, struct t_two_args *extra_args /* - const struct sockaddr *dest_addr, - socklen_t dest_len*/); diff --git a/scalls/shm.c b/scalls/shm.c deleted file mode 100644 index 979084a..0000000 --- a/scalls/shm.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "shm.h" -#include "../fs/shm.h" - -int syscall_shm_open(SYS_SHM_OPEN_PARAMS *args) { - return shm_open(args->name, args->oflag, args->mode); -} diff --git a/scalls/shm.h b/scalls/shm.h deleted file mode 100644 index 80e4366..0000000 --- a/scalls/shm.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SYS_SHM_H -#define SYS_SHM_H -#include -#include -typedef int mode_t; - -typedef struct SYS_SHM_OPEN_PARAMS { - const char *name; - int oflag; - mode_t mode; -} __attribute__((packed)) SYS_SHM_OPEN_PARAMS; - -int syscall_shm_open(SYS_SHM_OPEN_PARAMS *args); -#endif diff --git a/scalls/socket.c b/scalls/socket.c deleted file mode 100644 index 594c745..0000000 --- a/scalls/socket.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "socket.h" - -int syscall_socket(SYS_SOCKET_PARAMS *args) { - return socket(args->domain, args->type, args->protocol); -} diff --git a/scalls/socket.h b/scalls/socket.h deleted file mode 100644 index 6540b0f..0000000 --- a/scalls/socket.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "../socket.h" - -typedef struct SYS_SOCKET_PARAMS { - int domain; - int type; - int protocol; -} __attribute__((packed)) SYS_SOCKET_PARAMS; - -int syscall_socket(SYS_SOCKET_PARAMS *args); diff --git a/scalls/stat.c b/scalls/stat.c deleted file mode 100644 index 0850151..0000000 --- a/scalls/stat.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include -#include - -int syscall_stat(SYS_STAT_PARAMS *args) { - const char *pathname = copy_and_allocate_user_string(args->pathname); - struct stat *statbuf = args->statbuf; - vfs_inode_t *i = vfs_internal_open(pathname); - if (!i) - return -ENOENT; - statbuf->st_size = i->file_size; - return 0; -} diff --git a/scalls/stat.h b/scalls/stat.h deleted file mode 100644 index 78e8c45..0000000 --- a/scalls/stat.h +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include - -typedef struct SYS_STAT_PARAMS { - const char *pathname; - struct stat *statbuf; -} __attribute__((packed)) SYS_STAT_PARAMS; - -struct stat { - dev_t st_dev; // Device ID of device containing file. - ino_t st_ino; // File serial number. - mode_t st_mode; // Mode of file (see below). - nlink_t st_nlink; // Number of hard links to the file. - uid_t st_uid; // User ID of file. - gid_t st_gid; // Group ID of file. - dev_t st_rdev; // Device ID (if file is character or block special). - off_t st_size; // For regular files, the file size in bytes. - // For symbolic links, the length in bytes of the - // pathname contained in the symbolic link. - // For a shared memory object, the length in bytes. - // For a typed memory object, the length in bytes. - // For other file types, the use of this field is - // unspecified. - struct timespec st_atim; // Last data access timestamp. - struct timespec st_mtim; // Last data modification timestamp. - struct timespec st_ctim; // Last file status change timestamp. - blksize_t st_blksize; // A file system-specific preferred I/O block size - // for this object. In some file system types, this - // may vary from file to file. - blkcnt_t st_blocks; // Number of blocks allocated for this object. -}; - -int syscall_stat(SYS_STAT_PARAMS *args); diff --git a/scalls/uptime.c b/scalls/uptime.c deleted file mode 100644 index 866c7e5..0000000 --- a/scalls/uptime.c +++ /dev/null @@ -1,4 +0,0 @@ -#include -#include - -uint32_t syscall_uptime(void) { return (uint32_t)pit_num_ms(); } diff --git a/scalls/uptime.h b/scalls/uptime.h deleted file mode 100644 index 2b5b0c9..0000000 --- a/scalls/uptime.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -uint32_t syscall_uptime(void); diff --git a/sched/scheduler.c b/sched/scheduler.c deleted file mode 100644 index a6ace7d..0000000 --- a/sched/scheduler.c +++ /dev/null @@ -1,449 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define STACK_LOCATION ((void *)0x90000000) -#define STACK_SIZE 0x80000 -#define HEAP_SIZE 0x400000 -#define HEAP_LOCATION (STACK_LOCATION - STACK_SIZE - HEAP_SIZE) - -process_t *ready_queue; -process_t *current_task = NULL; -uint32_t next_pid = 0; - -extern uint32_t read_eip(void); - -process_t *get_current_task(void) { return current_task; } - -void set_signal_handler(int sig, void (*handler)(int)) { - if (sig >= 20 || sig < 0) - return; - if (9 == sig) - return; - current_task->signal_handlers[sig] = handler; -} - -process_t *create_process(process_t *p) { - process_t *r; - r = ksbrk(sizeof(process_t)); - r->dead = 0; - r->pid = next_pid++; - r->esp = r->ebp = 0; - r->eip = 0; - r->sleep_until = 0; - if (!p) { - assert(1 == next_pid); - strncpy(r->program_name, "[kernel]", sizeof(current_task->program_name)); - } else - strncpy(r->program_name, "[Not yet named]", - sizeof(current_task->program_name)); - - r->cr3 = (p) ? clone_directory(get_active_pagedirectory()) - : get_active_pagedirectory(); - r->next = 0; - r->incoming_signal = 0; - r->parent = p; - r->child = NULL; - r->halt_list = NULL; - - mmu_allocate_region((void *)(0x80000000 - 0x1000), 0x1000, MMU_FLAG_RW, - r->cr3); - r->signal_handler_stack = 0x80000000; - - strcpy(r->current_working_directory, "/"); - r->data_segment_end = (p) ? p->data_segment_end : NULL; - memset((void *)r->halts, 0, 2 * sizeof(uint32_t)); - for (int i = 0; i < 100; i++) { - if (p) { - r->file_descriptors[i] = p->file_descriptors[i]; - if (r->file_descriptors[i]) { - r->file_descriptors[i]->reference_count++; - } - } - if (i < 20) - r->signal_handlers[i] = NULL; - r->read_halt_inode[i] = NULL; - r->write_halt_inode[i] = NULL; - r->disconnect_halt_inode[i] = NULL; - r->maps[i] = NULL; - } - return r; -} - -int get_free_fd(process_t *p, int allocate) { - if (!p) - p = (process_t *)current_task; - int i; - for (i = 0; i < 100; i++) - if (!p->file_descriptors[i]) - break; - if (p->file_descriptors[i]) - return -1; - if (allocate) { - vfs_fd_t *fd = p->file_descriptors[i] = kmalloc(sizeof(vfs_fd_t)); - fd->inode = kmalloc(sizeof(vfs_inode_t)); - } - return i; -} - -void tasking_init(void) { current_task = ready_queue = create_process(NULL); } - -int i = 0; -void __attribute__((optimize("O0"))) free_process(void) { - kprintf("Exiting process: %s\n", get_current_task()->program_name); - // free_process() will purge all contents such as allocated frames - // out of the current process. This will be called by exit() and - // exec*(). - - // Do a special free for shared memory which avoids labeling - // underlying frames as "unused". - for (int i = 0; i < 100; i++) { - vfs_close(i); - if (!current_task->maps[i]) - continue; - MemoryMap *m = current_task->maps[i]; - mmu_remove_virtual_physical_address_mapping(m->u_address, m->length); - } - - // NOTE: Kernel stuff begins at 0x90000000 - mmu_free_address_range((void *)0x1000, 0x90000000); -} - -void exit(int status) { - assert(current_task->pid != 1); - if (current_task->parent) { - current_task->parent->halts[WAIT_CHILD_HALT] = 0; - current_task->parent->child_rc = status; - } - process_t *new_task = current_task; - for (; new_task == current_task;) { - if (!new_task->next) - new_task = ready_queue; - new_task = new_task->next; - } - - free_process(); - // Remove current_task from list - for (process_t *tmp = ready_queue; tmp;) { - if (tmp == current_task) // current_task is ready_queue(TODO: - // Figure out whether this could even - // happen) - { - ready_queue = current_task->next; - break; - } - if (tmp->next == current_task) { - tmp->next = tmp->next->next; - break; - } - tmp = tmp->next; - } - current_task->dead = 1; - // This function will enable interrupts - switch_task(); -} - -uint32_t setup_stack(uint32_t stack_pointer, int argc, char **argv) { - mmu_allocate_region(STACK_LOCATION - STACK_SIZE, STACK_SIZE, MMU_FLAG_RW, - NULL); - flush_tlb(); - - uint32_t ptr = stack_pointer; - - char *argv_ptrs[argc + 1]; - for (int i = 0; i < argc; i++) { - char *s = argv[i]; - size_t l = strlen(s); - ptr -= l + 1; - char *b = (char *)ptr; - memcpy(b, s, l); - b[l] = '\0'; - argv_ptrs[i] = b; - } - - char **ptrs[argc + 1]; - for (int i = argc; i >= 0; i--) { - ptr -= sizeof(char *); - ptrs[i] = (char **)ptr; - if (i != argc) { - *(ptrs[i]) = argv_ptrs[i]; - } else { - *(ptrs[i]) = NULL; - } - } - - char *s = (char *)ptr; - ptr -= sizeof(char **); - *(char ***)ptr = (char **)s; - - ptr -= sizeof(int); - *(int *)ptr = argc; - return ptr; -} - -int exec(const char *filename, char **argv) { - // exec() will "takeover" the process by loading the file specified in - // filename into memory, change from ring 0 to ring 3 and jump to the - // files entry point as decided by the ELF header of the file. - int argc = 0; - for (; argv[argc];) { - argc++; - } - - uint32_t end_of_code; - void *entry = load_elf_file(filename, &end_of_code); - if (!entry) { - return 0; - } - - strncpy(current_task->program_name, filename, - sizeof(current_task->program_name)); - - current_task->data_segment_end = align_page((void *)end_of_code); - - uint32_t ptr = setup_stack(0x90000000, argc, argv); - - jump_usermode((void (*)())(entry), ptr); - ASSERT_NOT_REACHED; - return 0; -} - -int __attribute__((optimize("O0"))) fork(void) { - process_t *parent_task = (process_t *)current_task; - - process_t *new_task = create_process(parent_task); - - process_t *tmp_task = (process_t *)ready_queue; - for (; tmp_task->next;) - tmp_task = tmp_task->next; - - tmp_task->next = new_task; - - uint32_t eip = read_eip(); - - if (current_task != parent_task) { - return 0; - } - - new_task->child_rc = -1; - new_task->parent = current_task; - current_task->child = new_task; - - new_task->eip = eip; - asm("\ - mov %%esp, %0;\ - mov %%ebp, %1;" - : "=r"(new_task->esp), "=r"(new_task->ebp)); - asm("sti"); - return new_task->pid; -} - -int is_halted(process_t *process) { - for (int i = 0; i < 2; i++) - if (process->halts[i]) - return 1; - - if (isset_fdhalt(process->read_halt_inode, process->write_halt_inode, - process->disconnect_halt_inode)) { - return 1; - } - return 0; -} - -extern PageDirectory *active_directory; - -process_t *next_task(process_t *c) { - for (;;) { - c = c->next; - if (!c) - c = ready_queue; - if (c->incoming_signal) - break; - if (c->sleep_until > pit_num_ms()) - continue; - if (is_halted(c) || c->dead) - continue; - break; - } - return c; -} - -int task_save_state(void) { - asm("mov %%esp, %0" : "=r"(current_task->esp)); - asm("mov %%ebp, %0" : "=r"(current_task->ebp)); - - uint32_t eip = read_eip(); - - if (0x1 == eip) { - // Should the returned value from read_eip be equal to one it - // means that we have just switched over to this task after we - // saved the state(since the switch_task() function changes the - // eax register to 1). - return 0; - } - - current_task->eip = eip; - return 1; -} - -int kill(pid_t pid, int sig) { - process_t *p = current_task; - p = p->next; - if (!p) - p = ready_queue; - for (; p->pid != pid;) { - if (p == current_task) - break; - p = p->next; - if (!p) - p = ready_queue; - } - if (p->pid != pid) - return -ESRCH; - p->incoming_signal = sig; - return 0; -} - -void jump_signal_handler(void *func, uint32_t esp); -void switch_task() { - if (!current_task) - return; - - if (0 == task_save_state()) { - return; - } - - current_task = next_task((process_t *)current_task); - - active_directory = current_task->cr3; - - if (current_task->incoming_signal) { - uint8_t sig = current_task->incoming_signal; - current_task->incoming_signal = 0; - asm("mov %0, %%cr3" ::"r"(current_task->cr3->physical_address)); - - void *handler = current_task->signal_handlers[sig]; - if (9 == sig) { - klog("Task recieved SIGKILL", LOG_NOTE); - exit(0); - } - if (!handler) { - klog("Task recieved unhandeled signal. Killing process.", LOG_WARN); - exit(1); - } - jump_signal_handler(handler, current_task->signal_handler_stack); - } else { - asm(" \ - mov %0, %%esp; \ - mov %1, %%ebp; \ - mov %2, %%ecx; \ - mov %3, %%cr3; \ - mov $0x1, %%eax; \ - jmp *%%ecx" ::"r"(current_task->esp), - "r"(current_task->ebp), "r"(current_task->eip), - "r"(current_task->cr3->physical_address)); - } -} - -MemoryMap **get_free_map(void) { - for (int i = 0; i < 100; i++) - if (!(current_task->maps[i])) - return &(current_task->maps[i]); - assert(0); - return NULL; -} - -void *get_free_virtual_memory(size_t length) { - void *n = - (void *)((uintptr_t)(get_current_task()->data_segment_end) + length); - - void *rc = get_current_task()->data_segment_end; - get_current_task()->data_segment_end = align_page(n); - return rc; -} - -void *allocate_virtual_user_memory(size_t length, int prot, int flags) { - (void)prot; - (void)flags; - void *rc = get_free_virtual_memory(length); - if ((void *)-1 == rc) - return (void *)-1; - - mmu_allocate_region(rc, length, MMU_FLAG_RW, NULL); - return rc; -} - -void *user_kernel_mapping(void *kernel_addr, size_t length) { - void *rc = get_free_virtual_memory(length); - if ((void *)-1 == rc) - return (void *)-1; - - mmu_map_directories(rc, NULL, kernel_addr, NULL, length); - return rc; -} - -void *create_physical_mapping(void **physical_addresses, size_t length) { - void *rc = get_free_virtual_memory(length); - if ((void *)-1 == rc) - return (void *)-1; - int n = (uintptr_t)align_page((void *)length) / 0x1000; - for (int i = 0; i < n; i++) { - mmu_map_physical(rc + (i * 0x1000), NULL, physical_addresses[i], 0x1000); - } - return rc; -} - -void *mmap(void *addr, size_t length, int prot, int flags, int fd, - size_t offset) { - (void)addr; - if (0 == length) { - kprintf("EINVAL\n"); - return (void *)-EINVAL; - } - - MemoryMap **ptr = get_free_map(); - if (!ptr) { - klog("mmap(): No free memory map.", LOG_WARN); - return (void *)-1; - } - *ptr = kmalloc(sizeof(MemoryMap)); - MemoryMap *free_map = *ptr; - - if (fd == -1) { - void *rc = allocate_virtual_user_memory(length, prot, flags); - if ((void *)-1 == rc) { - kprintf("ENOMEM\n"); - return (void *)-ENOMEM; - } - free_map->u_address = rc; - free_map->k_address = NULL; - free_map->length = length; - free_map->fd = -1; - return rc; - } - - vfs_vm_object_t *vmobject = vfs_get_vm_object(fd, length, offset); - if (!vmobject) { - kprintf("ENODEV\n"); - return (void *)-ENODEV; - } - - if (vmobject->size < length) { - kprintf("EOVERFLOW\n"); - return (void *)-EOVERFLOW; // TODO: Check if this is the correct - // code. - } - - if (length > vmobject->size) - length = vmobject->size; - void *rc = create_physical_mapping(vmobject->object, length); - free_map->u_address = rc; - free_map->k_address = NULL; - free_map->length = length; - free_map->fd = fd; - return rc; -} diff --git a/sched/scheduler.h b/sched/scheduler.h deleted file mode 100644 index fc92ff3..0000000 --- a/sched/scheduler.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef SCHEDULER_H -#define SCHEDULER_H -#include -#include -#include -#include -#include - -#define MAX_PATH 256 -#define KEYBOARD_HALT 0 -#define WAIT_CHILD_HALT 1 - -int fork(void); -int exec(const char *filename, char **argv); -void switch_task(); -void tasking_init(void); -void exit(int status); - -void *mmap(void *addr, size_t length, int prot, int flags, int fd, - size_t offset); -int munmap(void *addr, size_t length); -int msync(void *addr, size_t length, int flags); -int kill(pid_t pid, int sig); -void set_signal_handler(int sig, void (*handler)(int)); - -typedef struct { - void *u_address; - void *k_address; - uint32_t length; - int fd; -} MemoryMap; - -typedef struct Process process_t; - -struct Process { - uint32_t pid; - char program_name[100]; - char current_working_directory[MAX_PATH]; - uint32_t eip, esp, ebp; - uint8_t incoming_signal; - uint32_t signal_handler_stack; - void *signal_handlers[20]; - PageDirectory *cr3; - vfs_fd_t *file_descriptors[100]; - vfs_inode_t *read_halt_inode[100]; - vfs_inode_t *write_halt_inode[100]; - vfs_inode_t *disconnect_halt_inode[100]; - uint32_t halts[2]; - struct Halt *halt_list; - void *data_segment_end; - process_t *next; - process_t *parent; - // TODO: Create a linkedlist of childs so that the parent process - // can do stuff such as reap zombies and get status. - process_t *child; - MemoryMap *maps[100]; - uint32_t sleep_until; - int child_rc; - int dead; -}; - -process_t *get_current_task(void); -int get_free_fd(process_t *p, int allocate); -void free_process(void); -#endif diff --git a/socket.c b/socket.c deleted file mode 100644 index 0519c65..0000000 --- a/socket.c +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -// FIXME: Make these more dynamic -OPEN_UNIX_SOCKET *un_sockets[100] = {0}; -OPEN_INET_SOCKET *inet_sockets[100] = {0}; - -OPEN_INET_SOCKET *find_open_udp_port(uint16_t port) { - for (int i = 0; i < 100; i++) { - if (!inet_sockets[i]) - continue; - if (inet_sockets[i]->port == port) - return inet_sockets[i]; - } - return NULL; -} - -int uds_open(const char *path) { - // FIXME: This is super ugly - - // Find the socket that path belongs to - SOCKET *s = NULL; - for (int i = 0; i < 100; i++) { - if (!un_sockets[i]) - continue; - const char *p = path; - const char *e = p; - for (; *e; e++) - ; - for (; e != p && *e != '/'; e--) - ; - if (0 == strcmp(e, un_sockets[i]->path)) { - s = un_sockets[i]->s; - break; - } - } - if (!s) { - return -1; - } - - // Create a pipe - int fd[2]; - dual_pipe(fd); - - char c = 'i'; - fifo_object_write((uint8_t *)&c, 1, 0, s->fifo_file); - s->ptr_socket_fd->inode->has_data = 1; - - s->incoming_fd = get_current_task()->file_descriptors[fd[1]]; - // vfs_close(fd[1]); - return fd[0]; -} - -int accept(int socket, struct sockaddr *address, socklen_t *address_len) { - (void)address; - (void)address_len; - vfs_inode_t *inode = get_current_task()->file_descriptors[socket]->inode; - SOCKET *s = (SOCKET *)inode->internal_object; - - if (NULL == s->incoming_fd) { - // Wait until we have gotten a connection - struct pollfd fds[1]; - fds[0].fd = socket; - fds[0].events = POLLIN; - fds[0].revents = 0; - poll(fds, 1, 0); - } - - int n = 0; - for (; get_current_task()->file_descriptors[n]; n++) - ; - get_current_task()->file_descriptors[n] = s->incoming_fd; - get_current_task()->file_descriptors[n]->reference_count++; - s->incoming_fd = NULL; - // for (char c; 0 < vfs_pread(s->fifo_fd, &c, 1, 0);) - // ; - inode->has_data = 0; - // s->ptr_fifo_fd->inode->has_data = 0; - - return n; -} - -int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - (void)addrlen; - vfs_fd_t *fd = get_vfs_fd(sockfd); - if (!fd) - return -EBADF; - vfs_inode_t *inode = fd->inode; - if (!inode) - return -EBADF; - SOCKET *s = (SOCKET *)inode->internal_object; - if (AF_UNIX == s->domain) { - struct sockaddr_un *un = (struct sockaddr_un *)addr; - size_t path_len = strlen(un->sun_path); - s->path = kmalloc(path_len + 1); - memcpy(s->path, un->sun_path, path_len); - s->path[path_len] = '\0'; - - OPEN_UNIX_SOCKET *us; - int i = 0; - for (; i < 100; i++) - if (!un_sockets[i]) - break; - - us = un_sockets[i] = kmalloc(sizeof(OPEN_UNIX_SOCKET)); - - us->path = s->path; - us->s = s; - s->child = us; - devfs_add_file(us->path, NULL, NULL, NULL, 1, 1, FS_TYPE_UNIX_SOCKET); - return 0; - } - if (AF_INET == s->domain) { - struct sockaddr_in *in = (struct sockaddr_in *)addr; - assert(in->sin_family == AF_INET); // FIXME: Figure out error value - OPEN_INET_SOCKET *inet; - int i = 0; - for (; i < 100; i++) - if (!inet_sockets[i]) - break; - - inet = inet_sockets[i] = kmalloc(sizeof(OPEN_INET_SOCKET)); - inet->address = in->sin_addr.s_addr; - inet->port = in->sin_port; - inet->s = s; - s->child = inet; - return 0; - } - return 0; -} - -int socket_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - SOCKET *s = (SOCKET *)fd->inode->internal_object; - FIFO_FILE *file = s->fifo_file; - int rc = fifo_object_write(buffer, 0, len, file); - fd->inode->has_data = file->has_data; - return rc; -} - -int socket_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) { - SOCKET *s = (SOCKET *)fd->inode->internal_object; - FIFO_FILE *file = s->fifo_file; - int rc = fifo_object_read(buffer, 0, len, file); - fd->inode->has_data = file->has_data; - return rc; -} - -void socket_close(vfs_fd_t *fd) { fd->inode->is_open = 0; } - -int socket(int domain, int type, int protocol) { - if (!(AF_UNIX == domain || AF_INET == domain)) - return -EINVAL; - - SOCKET *new_socket = kmalloc_eternal(sizeof(SOCKET)); - vfs_inode_t *inode = vfs_create_inode( - 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, 0 /*has_data*/, 1 /*can_write*/, - 1 /*is_open*/, new_socket /*internal_object*/, 0 /*file_size*/, - NULL /*open*/, NULL /*create_file*/, socket_read, socket_write, - socket_close, NULL /*create_directory*/, NULL /*get_vm_object*/, - NULL /*truncate*/); - - vfs_fd_t *fd; - int n = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, inode, &fd); - - new_socket->domain = domain; - new_socket->type = type; - new_socket->protocol = protocol; - new_socket->path = NULL; - new_socket->incoming_fd = NULL; - - new_socket->fifo_file = create_fifo_object(); - - new_socket->ptr_socket_fd = fd; - return n; -} diff --git a/socket.h b/socket.h deleted file mode 100644 index bb278c1..0000000 --- a/socket.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef SOCKET_H -#define SOCKET_H -#include -#include -#include -#include - -#define AF_UNIX 0 -#define AF_INET 1 -#define AF_LOCAL AF_UNIX - -#define SOCK_DGRAM 0 - -#define INADDR_ANY 0 - -#define MSG_WAITALL 1 - -typedef struct { - vfs_fd_t *ptr_socket_fd; - FIFO_FILE *fifo_file; - - int domain; - int type; - int protocol; - void *child; - - // UNIX socket - char *path; - vfs_fd_t *incoming_fd; -} SOCKET; - -typedef struct { - char *path; - SOCKET *s; -} OPEN_UNIX_SOCKET; - -typedef struct { - uint32_t address; - uint16_t port; - SOCKET *s; -} OPEN_INET_SOCKET; - -typedef uint32_t in_addr_t; -typedef uint16_t in_port_t; -typedef unsigned int sa_family_t; -typedef int socklen_t; - -struct sockaddr { - sa_family_t sa_family; /* Address family */ - char *sa_data; /* Socket address */ -}; - -struct sockaddr_in { - sa_family_t sin_family; - union { - uint32_t s_addr; - uint8_t a[4]; - } sin_addr; - uint16_t sin_port; -}; - -struct sockaddr_un { - sa_family_t sun_family; /* Address family */ - char *sun_path; /* Socket pathname */ -}; - -OPEN_INET_SOCKET *find_open_udp_port(uint16_t port); -int uds_open(const char *path); -int socket(int domain, int type, int protocol); -int accept(int socket, struct sockaddr *address, socklen_t *address_len); -int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); -#endif diff --git a/time.h b/time.h deleted file mode 100644 index 2d4eef6..0000000 --- a/time.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef TIME_H -#define TIME_H -#include - -typedef int clockid_t; -struct timespec { - time_t tv_sec; // Seconds. - long tv_nsec; // Nanoseconds. -}; -#endif -- cgit v1.2.3