From 1a9fd27a31b297a7b6cbb8d5bbaa0e321c76d39a Mon Sep 17 00:00:00 2001 From: alexvoste Date: Thu, 7 May 2026 02:22:25 +0300 Subject: [PATCH] push --- .gitignore | 10 + LICENSE | 674 +++++ README.md | 85 + TODO | 23 + build | Bin 0 -> 87584 bytes builder/Makefile | 15 + builder/build.c | 2496 +++++++++++++++++++ kernel/include/acpi/acpi.h | 199 ++ kernel/include/apic/apic.h | 113 + kernel/include/drivers/ata.h | 77 + kernel/include/drivers/blkdev.h | 38 + kernel/include/drivers/disk.h | 11 + kernel/include/drivers/partition.h | 52 + kernel/include/drivers/ps2.h | 91 + kernel/include/drivers/timer.h | 17 + kernel/include/elf/elf.h | 118 + kernel/include/fs/devfs.h | 9 + kernel/include/fs/ext2.h | 161 ++ kernel/include/fs/fat32.h | 146 ++ kernel/include/fs/initramfs.h | 9 + kernel/include/fs/ramfs.h | 11 + kernel/include/fs/vfs.h | 181 ++ kernel/include/gdt/gdt.h | 78 + kernel/include/graphics/fb/fb.h | 58 + kernel/include/interrupts/idt.h | 47 + kernel/include/interrupts/interrupts.h | 77 + kernel/include/interrupts/irq.h | 31 + kernel/include/interrupts/isr.h | 81 + kernel/include/io/ports.h | 40 + kernel/include/io/serial.h | 51 + kernel/include/memory/paging.h | 44 + kernel/include/memory/pmm.h | 89 + kernel/include/memory/vmm.h | 41 + kernel/include/panic/panic.h | 19 + kernel/include/sched/capabilities.h | 49 + kernel/include/sched/sched.h | 183 ++ kernel/include/sched/spinlock.h | 44 + kernel/include/smp/percpu.h | 55 + kernel/include/smp/smp.h | 60 + kernel/include/sse/fpu.h | 17 + kernel/include/sse/sse.h | 31 + kernel/include/syscall/errno.h | 66 + kernel/include/syscall/syscall.h | 12 + kernel/include/syscall/syscall_nums.h | 142 ++ kernel/src/acpi/acpi.c | 397 +++ kernel/src/apic/apic.c | 212 ++ kernel/src/apic/ioapic.c | 79 + kernel/src/apic/lapic.c | 207 ++ kernel/src/drivers/ata.c | 371 +++ kernel/src/drivers/blkdev.c | 95 + kernel/src/drivers/disk.c | 164 ++ kernel/src/drivers/partition.c | 204 ++ kernel/src/drivers/ps2.c | 505 ++++ kernel/src/drivers/timer.c | 145 ++ kernel/src/elf/elf.c | 374 +++ kernel/src/font.psf | Bin 0 -> 9975 bytes kernel/src/fs/devfs.c | 352 +++ kernel/src/fs/ext2.c | 935 +++++++ kernel/src/fs/fat32.c | 1198 +++++++++ kernel/src/fs/initramfs.c | 311 +++ kernel/src/fs/ramfs.c | 283 +++ kernel/src/fs/vfs.c | 617 +++++ kernel/src/gdt/gdt.c | 41 + kernel/src/gdt/gdt_asm.asm | 28 + kernel/src/graphics/fb/fb.c | 136 + kernel/src/interrupts/idt.c | 79 + kernel/src/interrupts/interrupt_trap.asm | 133 + kernel/src/interrupts/interrupts.c | 32 + kernel/src/interrupts/irq/irq.c | 82 + kernel/src/interrupts/isr/isr.c | 271 ++ kernel/src/io/serial.c | 826 ++++++ kernel/src/kernel.c | 300 +++ kernel/src/memory/paging.c | 320 +++ kernel/src/memory/pmm.c | 614 +++++ kernel/src/memory/vmm.c | 402 +++ kernel/src/panic/panic.c | 211 ++ kernel/src/sched/sched.c | 669 +++++ kernel/src/sched/sched_asm.asm | 157 ++ kernel/src/smp/percpu.c | 88 + kernel/src/smp/smp.c | 327 +++ kernel/src/sse/fpu.c | 96 + kernel/src/sse/sse.c | 238 ++ kernel/src/syscall/disk_syscalls.c | 431 ++++ kernel/src/syscall/syscall.c | 1313 ++++++++++ kernel/src/syscall/syscall_asm.asm | 145 ++ libc/include/ctype.h | 19 + libc/include/math.h | 62 + libc/include/stdio.h | 44 + libc/include/stdlib.h | 30 + libc/include/string.h | 45 + libc/src/ctype/isalnum.c | 7 + libc/src/ctype/isalpha.c | 6 + libc/src/ctype/isblank.c | 5 + libc/src/ctype/iscntrl.c | 8 + libc/src/ctype/isdigit.c | 5 + libc/src/ctype/isgraph.c | 5 + libc/src/ctype/islower.c | 5 + libc/src/ctype/isprint.c | 5 + libc/src/ctype/ispunct.c | 8 + libc/src/ctype/isspace.c | 6 + libc/src/ctype/isupper.c | 5 + libc/src/ctype/isxdigit.c | 7 + libc/src/ctype/tolower.c | 8 + libc/src/ctype/toupper.c | 8 + libc/src/math/abs.c | 5 + libc/src/math/fabs.c | 12 + libc/src/math/isinf.c | 14 + libc/src/math/isnan.c | 14 + libc/src/math/pow.c | 37 + libc/src/math/pow10.c | 17 + libc/src/stdio/getchar.c | 6 + libc/src/stdio/printf.c | 9 + libc/src/stdio/putchar.c | 360 +++ libc/src/stdio/puts.c | 27 + libc/src/stdio/scanf.c | 246 ++ libc/src/stdio/screen.c | 38 + libc/src/stdio/snprintf.c | 381 +++ libc/src/stdlib/aligned_alloc.c | 14 + libc/src/stdlib/aligned_free.c | 8 + libc/src/stdlib/calloc.c | 11 + libc/src/stdlib/free.c | 6 + libc/src/stdlib/itoa.c | 41 + libc/src/stdlib/malloc.c | 7 + libc/src/stdlib/realloc.c | 7 + libc/src/stdlib/strtoll.c | 40 + libc/src/stdlib/strtoull.c | 36 + libc/src/string/memchr.c | 12 + libc/src/string/memcmp.c | 14 + libc/src/string/memcpy.c | 12 + libc/src/string/memmove.c | 18 + libc/src/string/memset.c | 11 + libc/src/string/memset_explicit.c | 7 + libc/src/string/rawmemchr.c | 11 + libc/src/string/strcat.c | 17 + libc/src/string/strchr.c | 16 + libc/src/string/strcmp.c | 13 + libc/src/string/strcpy.c | 7 + libc/src/string/strcspn.c | 11 + libc/src/string/strdup.c | 9 + libc/src/string/strlen.c | 11 + libc/src/string/strncat.c | 9 + libc/src/string/strncmp.c | 18 + libc/src/string/strncpy.c | 11 + libc/src/string/strnlen.c | 7 + libc/src/string/strpbrk.c | 11 + libc/src/string/strrchr.c | 9 + libc/src/string/strspn.c | 24 + libc/src/string/strstr.c | 17 + libc/src/string/strtok.c | 22 + libc/src/string/strtol.c | 39 + libc/src/string/strtoul.c | 37 + usr/apps/cal.c | 179 ++ usr/apps/calc.c | 206 ++ usr/apps/date.c | 98 + usr/apps/execve_target.c | 15 + usr/apps/fetch.c | 93 + usr/apps/hello.c | 10 + usr/apps/neo.c | 908 +++++++ usr/apps/shell.c | 975 ++++++++ usr/apps/test_execve.c | 91 + usr/apps/test_files.c | 164 ++ usr/apps/test_mem.c | 78 + usr/apps/test_pipe.c | 82 + usr/apps/test_process.c | 48 + usr/apps/uptime.c | 22 + usr/installer/install-on-disk.c | 592 +++++ usr/lib/libcervus/compat.c | 349 +++ usr/lib/libcervus/crt0.asm | 41 + usr/lib/libcervus/ctype/ctype.c | 16 + usr/lib/libcervus/dirent/dirent.c | 59 + usr/lib/libcervus/libcervus.c | 461 ++++ usr/lib/libcervus/math/abs.c | 5 + usr/lib/libcervus/math/fabs.c | 12 + usr/lib/libcervus/math/isinf.c | 14 + usr/lib/libcervus/math/isnan.c | 14 + usr/lib/libcervus/math/pow.c | 37 + usr/lib/libcervus/math/pow10.c | 17 + usr/lib/libcervus/memory/memory.c | 219 ++ usr/lib/libcervus/setjmp.asm | 38 + usr/lib/libcervus/signal/signal.c | 39 + usr/lib/libcervus/stdio/scanf.c | 252 ++ usr/lib/libcervus/stdio/stdio.c | 430 ++++ usr/lib/libcervus/stdlib/stdlib.c | 138 + usr/lib/libcervus/stdlib/strtod.c | 170 ++ usr/lib/libcervus/string/string.c | 296 +++ usr/lib/libcervus/time/time.c | 205 ++ usr/sysroot/usr/include/assert.h | 16 + usr/sysroot/usr/include/cervus_util.h | 162 ++ usr/sysroot/usr/include/ctype.h | 19 + usr/sysroot/usr/include/dirent.h | 30 + usr/sysroot/usr/include/errno.h | 45 + usr/sysroot/usr/include/fcntl.h | 27 + usr/sysroot/usr/include/inttypes.h | 76 + usr/sysroot/usr/include/limits.h | 30 + usr/sysroot/usr/include/math.h | 77 + usr/sysroot/usr/include/setjmp.h | 13 + usr/sysroot/usr/include/signal.h | 169 ++ usr/sysroot/usr/include/stdarg.h | 11 + usr/sysroot/usr/include/stdbool.h | 9 + usr/sysroot/usr/include/stddef.h | 15 + usr/sysroot/usr/include/stdint.h | 48 + usr/sysroot/usr/include/stdio.h | 66 + usr/sysroot/usr/include/stdlib.h | 76 + usr/sysroot/usr/include/string.h | 36 + usr/sysroot/usr/include/sys/cervus.h | 140 ++ usr/sysroot/usr/include/sys/ioctl.h | 29 + usr/sysroot/usr/include/sys/mman.h | 24 + usr/sysroot/usr/include/sys/stat.h | 50 + usr/sysroot/usr/include/sys/syscall.h | 98 + usr/sysroot/usr/include/sys/time.h | 19 + usr/sysroot/usr/include/sys/types.h | 18 + usr/sysroot/usr/include/sys/ucontext.h | 67 + usr/sysroot/usr/include/sys/utsname.h | 16 + usr/sysroot/usr/include/sys/wait.h | 19 + usr/sysroot/usr/include/termios.h | 58 + usr/sysroot/usr/include/time.h | 47 + usr/sysroot/usr/include/unistd.h | 68 + usr/sysroot/usr/share/cervus/README.sysroot | 1 + wallpapers/cervus1024x768.png | Bin 0 -> 160768 bytes wallpapers/cervus1280x720.png | Bin 0 -> 146122 bytes wallpapers/cervus1280x800.png | Bin 0 -> 199710 bytes wallpapers/cervus1366x768.png | Bin 0 -> 164159 bytes wallpapers/cervus1600x900.png | Bin 0 -> 221083 bytes wallpapers/cervus1920x1080.png | Bin 0 -> 309794 bytes wallpapers/cervus800x600.png | Bin 0 -> 102242 bytes wallpapers/cervus_logo.jpg | Bin 0 -> 41577 bytes 226 files changed, 29188 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 TODO create mode 100755 build create mode 100644 builder/Makefile create mode 100644 builder/build.c create mode 100644 kernel/include/acpi/acpi.h create mode 100644 kernel/include/apic/apic.h create mode 100644 kernel/include/drivers/ata.h create mode 100644 kernel/include/drivers/blkdev.h create mode 100644 kernel/include/drivers/disk.h create mode 100644 kernel/include/drivers/partition.h create mode 100644 kernel/include/drivers/ps2.h create mode 100644 kernel/include/drivers/timer.h create mode 100644 kernel/include/elf/elf.h create mode 100644 kernel/include/fs/devfs.h create mode 100644 kernel/include/fs/ext2.h create mode 100644 kernel/include/fs/fat32.h create mode 100644 kernel/include/fs/initramfs.h create mode 100644 kernel/include/fs/ramfs.h create mode 100644 kernel/include/fs/vfs.h create mode 100644 kernel/include/gdt/gdt.h create mode 100644 kernel/include/graphics/fb/fb.h create mode 100644 kernel/include/interrupts/idt.h create mode 100644 kernel/include/interrupts/interrupts.h create mode 100644 kernel/include/interrupts/irq.h create mode 100644 kernel/include/interrupts/isr.h create mode 100644 kernel/include/io/ports.h create mode 100644 kernel/include/io/serial.h create mode 100644 kernel/include/memory/paging.h create mode 100644 kernel/include/memory/pmm.h create mode 100644 kernel/include/memory/vmm.h create mode 100644 kernel/include/panic/panic.h create mode 100644 kernel/include/sched/capabilities.h create mode 100644 kernel/include/sched/sched.h create mode 100644 kernel/include/sched/spinlock.h create mode 100644 kernel/include/smp/percpu.h create mode 100644 kernel/include/smp/smp.h create mode 100644 kernel/include/sse/fpu.h create mode 100644 kernel/include/sse/sse.h create mode 100644 kernel/include/syscall/errno.h create mode 100644 kernel/include/syscall/syscall.h create mode 100644 kernel/include/syscall/syscall_nums.h create mode 100644 kernel/src/acpi/acpi.c create mode 100644 kernel/src/apic/apic.c create mode 100644 kernel/src/apic/ioapic.c create mode 100644 kernel/src/apic/lapic.c create mode 100644 kernel/src/drivers/ata.c create mode 100644 kernel/src/drivers/blkdev.c create mode 100644 kernel/src/drivers/disk.c create mode 100644 kernel/src/drivers/partition.c create mode 100644 kernel/src/drivers/ps2.c create mode 100644 kernel/src/drivers/timer.c create mode 100644 kernel/src/elf/elf.c create mode 100644 kernel/src/font.psf create mode 100644 kernel/src/fs/devfs.c create mode 100644 kernel/src/fs/ext2.c create mode 100644 kernel/src/fs/fat32.c create mode 100644 kernel/src/fs/initramfs.c create mode 100644 kernel/src/fs/ramfs.c create mode 100644 kernel/src/fs/vfs.c create mode 100644 kernel/src/gdt/gdt.c create mode 100644 kernel/src/gdt/gdt_asm.asm create mode 100644 kernel/src/graphics/fb/fb.c create mode 100644 kernel/src/interrupts/idt.c create mode 100644 kernel/src/interrupts/interrupt_trap.asm create mode 100644 kernel/src/interrupts/interrupts.c create mode 100644 kernel/src/interrupts/irq/irq.c create mode 100644 kernel/src/interrupts/isr/isr.c create mode 100644 kernel/src/io/serial.c create mode 100644 kernel/src/kernel.c create mode 100644 kernel/src/memory/paging.c create mode 100644 kernel/src/memory/pmm.c create mode 100644 kernel/src/memory/vmm.c create mode 100644 kernel/src/panic/panic.c create mode 100644 kernel/src/sched/sched.c create mode 100644 kernel/src/sched/sched_asm.asm create mode 100644 kernel/src/smp/percpu.c create mode 100644 kernel/src/smp/smp.c create mode 100644 kernel/src/sse/fpu.c create mode 100644 kernel/src/sse/sse.c create mode 100644 kernel/src/syscall/disk_syscalls.c create mode 100644 kernel/src/syscall/syscall.c create mode 100644 kernel/src/syscall/syscall_asm.asm create mode 100644 libc/include/ctype.h create mode 100644 libc/include/math.h create mode 100644 libc/include/stdio.h create mode 100644 libc/include/stdlib.h create mode 100644 libc/include/string.h create mode 100644 libc/src/ctype/isalnum.c create mode 100644 libc/src/ctype/isalpha.c create mode 100644 libc/src/ctype/isblank.c create mode 100644 libc/src/ctype/iscntrl.c create mode 100644 libc/src/ctype/isdigit.c create mode 100644 libc/src/ctype/isgraph.c create mode 100644 libc/src/ctype/islower.c create mode 100644 libc/src/ctype/isprint.c create mode 100644 libc/src/ctype/ispunct.c create mode 100644 libc/src/ctype/isspace.c create mode 100644 libc/src/ctype/isupper.c create mode 100644 libc/src/ctype/isxdigit.c create mode 100644 libc/src/ctype/tolower.c create mode 100644 libc/src/ctype/toupper.c create mode 100644 libc/src/math/abs.c create mode 100644 libc/src/math/fabs.c create mode 100644 libc/src/math/isinf.c create mode 100644 libc/src/math/isnan.c create mode 100644 libc/src/math/pow.c create mode 100644 libc/src/math/pow10.c create mode 100644 libc/src/stdio/getchar.c create mode 100644 libc/src/stdio/printf.c create mode 100644 libc/src/stdio/putchar.c create mode 100644 libc/src/stdio/puts.c create mode 100644 libc/src/stdio/scanf.c create mode 100644 libc/src/stdio/screen.c create mode 100644 libc/src/stdio/snprintf.c create mode 100644 libc/src/stdlib/aligned_alloc.c create mode 100644 libc/src/stdlib/aligned_free.c create mode 100644 libc/src/stdlib/calloc.c create mode 100644 libc/src/stdlib/free.c create mode 100644 libc/src/stdlib/itoa.c create mode 100644 libc/src/stdlib/malloc.c create mode 100644 libc/src/stdlib/realloc.c create mode 100644 libc/src/stdlib/strtoll.c create mode 100644 libc/src/stdlib/strtoull.c create mode 100644 libc/src/string/memchr.c create mode 100644 libc/src/string/memcmp.c create mode 100644 libc/src/string/memcpy.c create mode 100644 libc/src/string/memmove.c create mode 100644 libc/src/string/memset.c create mode 100644 libc/src/string/memset_explicit.c create mode 100644 libc/src/string/rawmemchr.c create mode 100644 libc/src/string/strcat.c create mode 100644 libc/src/string/strchr.c create mode 100644 libc/src/string/strcmp.c create mode 100644 libc/src/string/strcpy.c create mode 100644 libc/src/string/strcspn.c create mode 100644 libc/src/string/strdup.c create mode 100644 libc/src/string/strlen.c create mode 100644 libc/src/string/strncat.c create mode 100644 libc/src/string/strncmp.c create mode 100644 libc/src/string/strncpy.c create mode 100644 libc/src/string/strnlen.c create mode 100644 libc/src/string/strpbrk.c create mode 100644 libc/src/string/strrchr.c create mode 100644 libc/src/string/strspn.c create mode 100644 libc/src/string/strstr.c create mode 100644 libc/src/string/strtok.c create mode 100644 libc/src/string/strtol.c create mode 100644 libc/src/string/strtoul.c create mode 100644 usr/apps/cal.c create mode 100644 usr/apps/calc.c create mode 100644 usr/apps/date.c create mode 100644 usr/apps/execve_target.c create mode 100644 usr/apps/fetch.c create mode 100644 usr/apps/hello.c create mode 100644 usr/apps/neo.c create mode 100644 usr/apps/shell.c create mode 100644 usr/apps/test_execve.c create mode 100644 usr/apps/test_files.c create mode 100644 usr/apps/test_mem.c create mode 100644 usr/apps/test_pipe.c create mode 100644 usr/apps/test_process.c create mode 100644 usr/apps/uptime.c create mode 100644 usr/installer/install-on-disk.c create mode 100644 usr/lib/libcervus/compat.c create mode 100644 usr/lib/libcervus/crt0.asm create mode 100644 usr/lib/libcervus/ctype/ctype.c create mode 100644 usr/lib/libcervus/dirent/dirent.c create mode 100644 usr/lib/libcervus/libcervus.c create mode 100644 usr/lib/libcervus/math/abs.c create mode 100644 usr/lib/libcervus/math/fabs.c create mode 100644 usr/lib/libcervus/math/isinf.c create mode 100644 usr/lib/libcervus/math/isnan.c create mode 100644 usr/lib/libcervus/math/pow.c create mode 100644 usr/lib/libcervus/math/pow10.c create mode 100644 usr/lib/libcervus/memory/memory.c create mode 100644 usr/lib/libcervus/setjmp.asm create mode 100644 usr/lib/libcervus/signal/signal.c create mode 100644 usr/lib/libcervus/stdio/scanf.c create mode 100644 usr/lib/libcervus/stdio/stdio.c create mode 100644 usr/lib/libcervus/stdlib/stdlib.c create mode 100644 usr/lib/libcervus/stdlib/strtod.c create mode 100644 usr/lib/libcervus/string/string.c create mode 100644 usr/lib/libcervus/time/time.c create mode 100644 usr/sysroot/usr/include/assert.h create mode 100644 usr/sysroot/usr/include/cervus_util.h create mode 100644 usr/sysroot/usr/include/ctype.h create mode 100644 usr/sysroot/usr/include/dirent.h create mode 100644 usr/sysroot/usr/include/errno.h create mode 100644 usr/sysroot/usr/include/fcntl.h create mode 100644 usr/sysroot/usr/include/inttypes.h create mode 100644 usr/sysroot/usr/include/limits.h create mode 100644 usr/sysroot/usr/include/math.h create mode 100644 usr/sysroot/usr/include/setjmp.h create mode 100644 usr/sysroot/usr/include/signal.h create mode 100644 usr/sysroot/usr/include/stdarg.h create mode 100644 usr/sysroot/usr/include/stdbool.h create mode 100644 usr/sysroot/usr/include/stddef.h create mode 100644 usr/sysroot/usr/include/stdint.h create mode 100644 usr/sysroot/usr/include/stdio.h create mode 100644 usr/sysroot/usr/include/stdlib.h create mode 100644 usr/sysroot/usr/include/string.h create mode 100644 usr/sysroot/usr/include/sys/cervus.h create mode 100644 usr/sysroot/usr/include/sys/ioctl.h create mode 100644 usr/sysroot/usr/include/sys/mman.h create mode 100644 usr/sysroot/usr/include/sys/stat.h create mode 100644 usr/sysroot/usr/include/sys/syscall.h create mode 100644 usr/sysroot/usr/include/sys/time.h create mode 100644 usr/sysroot/usr/include/sys/types.h create mode 100644 usr/sysroot/usr/include/sys/ucontext.h create mode 100644 usr/sysroot/usr/include/sys/utsname.h create mode 100644 usr/sysroot/usr/include/sys/wait.h create mode 100644 usr/sysroot/usr/include/termios.h create mode 100644 usr/sysroot/usr/include/time.h create mode 100644 usr/sysroot/usr/include/unistd.h create mode 100644 usr/sysroot/usr/share/cervus/README.sysroot create mode 100644 wallpapers/cervus1024x768.png create mode 100644 wallpapers/cervus1280x720.png create mode 100644 wallpapers/cervus1280x800.png create mode 100644 wallpapers/cervus1366x768.png create mode 100644 wallpapers/cervus1600x900.png create mode 100644 wallpapers/cervus1920x1080.png create mode 100644 wallpapers/cervus800x600.png create mode 100644 wallpapers/cervus_logo.jpg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..646648d --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +demo_iso/ +limine/ +limine-tools/ +limine.conf +OS-TREE.txt +.vscode/ +linker-scripts/ +bin/ +obj/ +iso_root/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b5780c0 --- /dev/null +++ b/README.md @@ -0,0 +1,85 @@ +

+ Cervus OS Logo +

+ + +# Cervus x86_64 Operating System + +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![Platform: x86_64](https://img.shields.io/badge/Platform-x86_64-lightgrey.svg)](https://en.wikipedia.org/wiki/X86-64) +[![Stage: Alpha](https://img.shields.io/badge/Stage-Alpha-orange.svg)]() + +**Cervus** - This is a modern 64-bit operating system written for the x86_64 architecture. It is currently under development. + +--- + +## Technical Features + +Cervus is currently in the active development phase. The kernel implements core low-level primitives required for a stable execution environment: + +### Core Architecture +- *Boot Protocol:* Utilizes the [Limine](https://github.com/limine-bootloader/limine) bootloader (Barebone profile). +- *Memory Management:* + - *PMM:* Bitmap-based Physical Memory Manager. + - *VMM:* Virtual Memory Management with 4-level paging support. +- *CPU Initialization:* Custom GDT (Global Descriptor Table) and IDT (Interrupt Descriptor Table) implementation. +- *Acceleration:* Native support for *SIMD* instructions (SSE/AVX) with proper state saving. + +## Roadmap & Progress + +| Component | Status | Description | +| :--- | :---: | :--- | +| *Bootloader* | Done | Limine Integration | +| *Graphics/PSF* | Done | Framebuffer & Text Rendering | +| *Memory (PMM/VMM)* | Done | Physical & Virtual Memory Management | +| *Interrupts (IDT)* | Done | Handling exceptions and IRQs | +| *ACPI* | Done(without rebooting) | Table parsing & SDT discovery | +| *APIC / IOAPIC* | Done | Advanced Interrupt Controllers | +| *Timers (HPET/APIC)* | Done | High Precision Event Timers | +| *SMP* | Done | Multicore Initialization | +| *Scheduler* | Done/In parallel development | Preemptive Multitasking | +| *Userspace* | In parallel development | Syscalls & Ring 3 execution | + +--- + +## Build Environment + +### Prerequisites + +To build Cervus, you need a cross-compilation toolchain and the following utilities: + +* *Compiler:* `x86_64-elf-gcc` +* *Assemblers:* `nasm` +* *Emulation:* `qemu-system-x86_64` +* *ISO Tools:* `xorriso`, `mtools` + +### Compiling and Running + +*1. Clone the repository:* + +```bash +bash +git clone https://github.com/VeoQeo/Cervus.git +cd Cervus +``` + +*2. Compile and launch in QEMU:* +```bash +./build run +``` + +*3. Deploy to hardware (Flash Drive):* +**WARNING: This will overwrite data on the target device.** +```bash +sudo ./build flash +``` + +## Contributing + +Cervus is an open-source research project. Contributions regarding bug fixes, hardware support, or documentation are welcome. Please feel free to open an Issue or submit a Pull Request. + +## License + +This project is licensed under the *GPL-3.0 License*. See the [LICENSE](LICENSE) file for details. + +--- diff --git a/TODO b/TODO new file mode 100644 index 0000000..7d0ccb8 --- /dev/null +++ b/TODO @@ -0,0 +1,23 @@ +- [x] **Bootloader**: Limine Barebone +- [x] **Графика**: Базовая поддержка фреймбуфера +- [x] **Шрифты**: Поддержка PSF шрифтов +- [x] **Порты ввода-вывода**: Базовые операции с портами +- [x] **Последовательный порт**: Отладочный вывод через COM1 +- [x] **Минимальная libc**: Базовая стандартная библиотека C +- [x] **GDT**: Глобальная таблица дескрипторов +- [x] **IDT**: Таблица дескрипторов прерываний +- [x] **SIMD**: Поддержка инструкций SSE/AVX +- [x] **PMM**: Менеджер физической памяти +- [x] **VMM**: Менеджер виртуальной памяти +- [x] **PAGING** +- [x] **ACPI**: Парсинг таблиц ACPI +- [x] **APIC**: Расширенный программируемый контроллер прерываний +- [x] **IOAPIC**: Контроллер прерываний ввода-вывода +- [x] **LAPIC**: Локальный APIC +- [x] **HPET**: Таймер высокой точности +- [x] **APIC-TIMER**: Таймер на основе APIC +- [x] **SMP**: Симметричная многопроцессорность +- [x] **Multitasking**: Многозадачность и планировщик +- [x] **Syscalls**: Системные вызовы +- [x] **Userspace**: Пространство пользователя +- [x_x(help me)] **Веселье начинается**: Дальнейшее развитие \ No newline at end of file diff --git a/build b/build new file mode 100755 index 0000000000000000000000000000000000000000..c9e52384447a85ce8c9ba2815c958b1152873409 GIT binary patch literal 87584 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMAGE_NAME "Cervus" +#define VERSION "v0.0.2" +#define QEMUFLAGS "-m 8G -smp 8 -cpu qemu64,+fsgsbase -display gtk,grab-on-hover=on " \ + "-drive file=cervus_disk.img,format=raw,if=ide,index=0,media=disk " + +#define LIMINE_CONF_PATH "/boot/limine/limine.conf" +#define LIMINE_CONF_BACKUP "/boot/limine/limine.conf.cervus-backup" +#define CERVUS_BOOT_DIR "/boot/cervus" +#define CERVUS_MARKER "# --- CERVUS OS ENTRY ---" + +#define WALLPAPER_SRC "wallpapers/cervus1280x720.png" +#define WALLPAPER_DST "boot():/boot/wallpapers/cervus.png" + +#define APPS_DIR "usr/apps" +#define BIN_APPS_DIR "usr/bin" +#define INSTALLER_DIR "usr/installer" +#define SYSROOT_DIR "usr/sysroot" +#define SYSROOT_INC "usr/sysroot/usr/include" +#define SYSROOT_LIB "usr/sysroot/usr/lib" +#define LIBCERVUS_DIR "usr/lib/libcervus" +#define SHELL_SRC "usr/apps/shell.c" +#define SHELL_ELF "usr/apps/shell.elf" +#define INSTALLER_SRC "usr/installer/install-on-disk.c" +#define INSTALLER_ELF "usr/installer/install-on-disk.elf" + +#define INITRAMFS_TAR "initramfs.tar" +#define INITRAMFS_ROOTFS "rootfs" + +#define BIGPATH (PATH_MAX * 2) + +#define SHORTPATH 512 + +static void path_join2(char *dst, size_t dst_size, const char *a, const char *b) { + if (dst_size == 0) return; + size_t la = strlen(a); + size_t lb = strlen(b); + if (la >= dst_size) la = dst_size - 1; + memcpy(dst, a, la); + size_t off = la; + if (off + 1 < dst_size) dst[off++] = '/'; + if (lb > dst_size - off - 1) lb = dst_size - off - 1; + memcpy(dst + off, b, lb); + dst[off + lb] = '\0'; +} + +#define COLOR_RESET "\033[0m" +#define COLOR_RED "\033[91m" +#define COLOR_GREEN "\033[92m" +#define COLOR_YELLOW "\033[93m" +#define COLOR_BLUE "\033[94m" +#define COLOR_MAGENTA "\033[95m" +#define COLOR_CYAN "\033[96m" +#define COLOR_BOLD "\033[1m" + +const char *DIRS_TO_CLEAN[] = { + "bin", "obj", "iso_root", "limine", "kernel/linker-scripts", + "demo_iso", "limine-tools", "edk2-ovmf", + INITRAMFS_ROOTFS, + NULL +}; +const char *FILES_TO_CLEAN[] = { + "Cervus.iso", "Cervus.hdd", + "kernel/.deps-obtained", + "limine.conf", + "OS-TREE.txt", "log.txt", + SHELL_ELF, INSTALLER_ELF, + SYSROOT_LIB "/libcervus.a", + SYSROOT_LIB "/crt0.o", + SYSROOT_DIR "/usr/bin/tcc", + SYSROOT_LIB "/tcc/libtcc1.a", + INITRAMFS_TAR, + "cervus_disk.img", + NULL +}; + +const char *SSE_FILES[] = { + "sse.c", "fpu.c", "fabs.c", "pow.c", "pow10.c", + "serial.c", "snprintf.c", "printf.c", NULL +}; + +struct Dependency { + const char *name; + const char *url; + const char *commit; +}; + +struct Dependency DEPENDENCIES[] = { + {"freestnd-c-hdrs", "https://codeberg.org/OSDev/freestnd-c-hdrs-0bsd.git", "5df91dd7062ad0c54f5ffd86193bb9f008677631"}, + {"cc-runtime", "https://codeberg.org/OSDev/cc-runtime.git", "dae79833b57a01b9fd3e359ee31def69f5ae899b"}, + {"limine-protocol", "https://codeberg.org/Limine/limine-protocol.git", "c4616df2572d77c60020bdefa617dd9bdcc6566a"}, + {NULL, NULL, NULL} +}; + +bool ARG_NO_CLEAN = false; +bool ARG_TREE = false; +bool ARG_STRUCTURE_ONLY = false; +bool ARG_NO_INITRAMFS = false; +bool ARG_RESET_HW_CONF = false; +bool ARG_RESET_DISK = false; +bool ARG_LIVE = false; + +char **TREE_FILES = NULL; +int TREE_FILES_COUNT = 0; +int TREE_FILES_CAP = 0; + +void print_color(const char *color, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + printf("%s", color); + vprintf(fmt, args); + printf("%s\n", COLOR_RESET); + va_end(args); +} + +void add_tree_file(const char *filename) { + if (TREE_FILES_COUNT >= TREE_FILES_CAP) { + TREE_FILES_CAP = (TREE_FILES_CAP == 0) ? 8 : TREE_FILES_CAP * 2; + TREE_FILES = realloc(TREE_FILES, TREE_FILES_CAP * sizeof(char *)); + } + TREE_FILES[TREE_FILES_COUNT++] = strdup(filename); +} + +bool should_print_content(const char *filename) { + if (TREE_FILES_COUNT == 0) return true; + for (int i = 0; i < TREE_FILES_COUNT; i++) + if (strcmp(filename, TREE_FILES[i]) == 0) return true; + return false; +} + +int cmd_run(bool verbose, const char *fmt, ...) { + char cmd[8192]; + va_list args; + va_start(args, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, args); + va_end(args); + if (verbose) print_color(COLOR_BLUE, "Running: %s", cmd); + int ret = system(cmd); + return (ret != 0) ? WEXITSTATUS(ret) : 0; +} + +void ensure_dir(const char *path) { + char tmp[1024]; + snprintf(tmp, sizeof(tmp), "mkdir -p %s", path); + int r = system(tmp); + (void)r; +} + +bool file_exists(const char *path) { + return access(path, F_OK) == 0; +} + +time_t get_mtime(const char *path) { + struct stat attr; + if (stat(path, &attr) == 0) return attr.st_mtime; + return 0; +} + +void rm_rf(const char *path) { + if (file_exists(path)) { + print_color(COLOR_BLUE, "Removing %s", path); + cmd_run(false, "rm -rf %s", path); + } +} + +bool setup_dependencies(void) { + print_color(COLOR_GREEN, "Checking dependencies..."); + ensure_dir("limine-tools"); + + for (int i = 0; DEPENDENCIES[i].name != NULL; i++) { + char path[PATH_MAX]; + snprintf(path, sizeof(path), "limine-tools/%s", DEPENDENCIES[i].name); + + if (!file_exists(path)) { + print_color(COLOR_YELLOW, "Missing %s, setting up...", DEPENDENCIES[i].name); + if (cmd_run(true, "git clone %s %s", DEPENDENCIES[i].url, path) != 0) return false; + char gc[PATH_MAX + 128]; + snprintf(gc, sizeof(gc), + "git -C %s -c advice.detachedHead=false checkout %s", + path, DEPENDENCIES[i].commit); + if (system(gc) != 0) return false; + } + } + return true; +} + +static bool extract_limine_hdd_bin(void) { + const char *src = "limine/limine-bios-hdd.h"; + const char *dst = "limine/limine-bios-hdd.bin"; + + if (file_exists(dst) && file_exists(src) && get_mtime(src) <= get_mtime(dst)) { + return true; + } + if (!file_exists(src)) { + print_color(COLOR_RED, "limine-bios-hdd.h not found in limine/"); + return false; + } + + FILE *in = fopen(src, "r"); + if (!in) { + print_color(COLOR_RED, "cannot open %s", src); + return false; + } + FILE *out = fopen(dst, "wb"); + if (!out) { + fclose(in); + print_color(COLOR_RED, "cannot create %s", dst); + return false; + } + + char line[4096]; + size_t total = 0; + while (fgets(line, sizeof(line), in)) { + char *p = line; + while (*p) { + if (p[0] == '0' && p[1] == 'x') { + unsigned v = 0; + p += 2; + if (sscanf(p, "%2x", &v) == 1) { + unsigned char b = (unsigned char)v; + fwrite(&b, 1, 1, out); + total++; + p += 2; + } else { + p++; + } + } else { + p++; + } + } + } + fclose(in); + fclose(out); + print_color(COLOR_GREEN, "Extracted limine-bios-hdd.bin (%zu bytes)", total); + return true; +} + +bool build_limine(void) { + if (file_exists("limine/limine")) { + print_color(COLOR_GREEN, "Limine already built"); + extract_limine_hdd_bin(); + return true; + } + print_color(COLOR_GREEN, "Building Limine..."); + if (file_exists("limine")) rm_rf("limine"); + if (cmd_run(true, "git clone https://codeberg.org/Limine/Limine.git limine " + "--branch=v11.2.1-binary --depth=1") != 0) return false; + if (cmd_run(true, "make -C limine") != 0) return false; + if (!extract_limine_hdd_bin()) return false; + return true; +} + +void ensure_linker_script(void) { + ensure_dir("kernel/linker-scripts"); + const char *lds_path = "kernel/linker-scripts/x86_64.lds"; + if (file_exists(lds_path)) return; + + const char *script = +"OUTPUT_FORMAT(elf64-x86-64)\n" +"ENTRY(kernel_main)\n" +"PHDRS {\n" +" limine_requests PT_LOAD;\n" +" text PT_LOAD;\n" +" rodata PT_LOAD;\n" +" data PT_LOAD;\n" +"}\n" +"SECTIONS {\n" +" . = 0xffffffff80000000;\n" +" .limine_requests : {\n" +" KEEP(*(.limine_requests_start))\n" +" KEEP(*(.limine_requests))\n" +" KEEP(*(.limine_requests_end))\n" +" } :limine_requests\n" +" . = ALIGN(CONSTANT(MAXPAGESIZE));\n" +" .text : {\n" +" __start_isr_handlers = .;\n" +" KEEP(*(.isr_handlers))\n" +" __stop_isr_handlers = .;\n" +" __start_irq_handlers = .;\n" +" KEEP(*(.irq_handlers))\n" +" __stop_irq_handlers = .;\n" +" *(.text .text.*)\n" +" } :text\n" +" . = ALIGN(CONSTANT(MAXPAGESIZE));\n" +" .rodata : { *(.rodata .rodata.*) } :rodata\n" +" .note.gnu.build-id : { *(.note.gnu.build-id) } :rodata\n" +" . = ALIGN(CONSTANT(MAXPAGESIZE));\n" +" .data : {\n" +" *(.data .data.*)\n" +" . = ALIGN(4096);\n" +" __percpu_start = .;\n" +" KEEP(*(.percpu .percpu.*))\n" +" . = ALIGN(4096);\n" +" __percpu_end = .;\n" +" } :data\n" +" .bss : { *(.bss .bss.*) *(COMMON) } :data\n" +" /DISCARD/ : { *(.eh_frame*) *(.note .note.*) }\n" +"}\n"; + + FILE *f = fopen(lds_path, "w"); + if (!f) return; + fprintf(f, "%s", script); + fclose(f); + print_color(COLOR_GREEN, "x86_64.lds created"); +} + +typedef struct { + char src[512]; + char elf[512]; + char name[256]; +} app_entry_t; + +#define MAX_APPS 64 +static app_entry_t g_apps[MAX_APPS]; +static int g_naps = 0; + +static int scan_apps(void) { + g_naps = 0; + DIR *d = opendir(APPS_DIR); + if (!d) { + print_color(COLOR_RED, "[apps] Cannot open directory '%s'", APPS_DIR); + return 0; + } + struct dirent *de; + while ((de = readdir(d)) != NULL && g_naps < MAX_APPS) { + const char *nm = de->d_name; + size_t nlen = strlen(nm); + if (nlen < 3) continue; + if (nm[0] == '.') continue; + if (strcmp(nm + nlen - 2, ".c") != 0) continue; + + app_entry_t *e = &g_apps[g_naps]; + snprintf(e->src, sizeof(e->src), "%s/%s", APPS_DIR, nm); + snprintf(e->elf, sizeof(e->elf), "%s/%.*s.elf", APPS_DIR, (int)(nlen-2), nm); + snprintf(e->name, sizeof(e->name), "%.*s", (int)(nlen-2), nm); + g_naps++; + } + closedir(d); + for (int i = 1; i < g_naps; i++) { + app_entry_t tmp = g_apps[i]; int j = i-1; + while (j >= 0 && strcmp(g_apps[j].name, tmp.name) > 0) { + g_apps[j+1] = g_apps[j]; j--; + } + g_apps[j+1] = tmp; + } + return g_naps; +} + +static bool build_one_app(const app_entry_t *e) { + if (file_exists(e->elf) && get_mtime(e->src) <= get_mtime(e->elf)) { + print_color(COLOR_GREEN, "[ELF] %s is up to date", e->elf); + return true; + } + print_color(COLOR_CYAN, "[ELF] Compiling %s -> %s", e->src, e->elf); + + int ret = cmd_run(false, + "gcc -ffreestanding -nostdlib -static -fno-stack-protector" + " -fno-pie -fno-pic" + " -mno-sse -mno-sse2 -mno-mmx -mno-avx -mno-avx2" + " -mno-red-zone" + " -O0 -g" + " -nostdinc -isystem " SYSROOT_INC + " -Wl,-Ttext-segment=0x401000" + " -o %s %s " SYSROOT_LIB "/crt0.o " SYSROOT_LIB "/libcervus.a", + e->elf, e->src); + if (ret != 0) { + print_color(COLOR_RED, "[ELF] Failed to compile %s", e->src); + return false; + } + print_color(COLOR_GREEN, "[ELF] %s built successfully", e->elf); + return true; +} + +bool build_all_apps(void) { + scan_apps(); + if (g_naps == 0) { + print_color(COLOR_YELLOW, "[apps] No .c files found in '%s'", APPS_DIR); + return true; + } + print_color(COLOR_CYAN, "[apps] Found %d app(s) in '%s'", g_naps, APPS_DIR); + for (int i = 0; i < g_naps; i++) { + if (!build_one_app(&g_apps[i])) return false; + } + return true; +} + +void clean_apps_elfs(void) { + DIR *d = opendir(APPS_DIR); + if (!d) return; + struct dirent *de; + while ((de = readdir(d)) != NULL) { + const char *nm = de->d_name; + size_t nlen = strlen(nm); + if (nlen < 5) continue; + if (strcmp(nm + nlen - 4, ".elf") != 0) continue; + char path[512]; + snprintf(path, sizeof(path), "%s/%s", APPS_DIR, nm); + remove(path); + print_color(COLOR_YELLOW, "[clean] removed %s", path); + } + closedir(d); +} + +static app_entry_t g_bin_apps[MAX_APPS]; +static int g_nbin = 0; + +static int scan_bin_apps(void) { + g_nbin = 0; + DIR *d = opendir(BIN_APPS_DIR); + if (!d) { + print_color(COLOR_YELLOW, "[bin] No '%s' directory found, skipping", BIN_APPS_DIR); + return 0; + } + struct dirent *de; + while ((de = readdir(d)) != NULL && g_nbin < MAX_APPS) { + const char *nm = de->d_name; + size_t nlen = strlen(nm); + if (nlen < 3) continue; + if (nm[0] == '.') continue; + if (strcmp(nm + nlen - 2, ".c") != 0) continue; + + app_entry_t *e = &g_bin_apps[g_nbin]; + snprintf(e->src, sizeof(e->src), "%s/%s", BIN_APPS_DIR, nm); + snprintf(e->elf, sizeof(e->elf), "%s/%.*s.elf", BIN_APPS_DIR, (int)(nlen-2), nm); + snprintf(e->name, sizeof(e->name), "%.*s", (int)(nlen-2), nm); + g_nbin++; + } + closedir(d); + for (int i = 1; i < g_nbin; i++) { + app_entry_t tmp = g_bin_apps[i]; int j = i-1; + while (j >= 0 && strcmp(g_bin_apps[j].name, tmp.name) > 0) { + g_bin_apps[j+1] = g_bin_apps[j]; j--; + } + g_bin_apps[j+1] = tmp; + } + return g_nbin; +} + +static bool build_one_bin_app(const app_entry_t *e) { + if (file_exists(e->elf) && get_mtime(e->src) <= get_mtime(e->elf)) { + print_color(COLOR_GREEN, "[bin] %s is up to date", e->elf); + return true; + } + print_color(COLOR_CYAN, "[bin] Compiling %s -> %s", e->src, e->elf); + + int ret = cmd_run(false, + "gcc -ffreestanding -nostdlib -static -fno-stack-protector" + " -fno-pie -fno-pic" + " -mno-sse -mno-sse2 -mno-mmx -mno-avx -mno-avx2" + " -mno-red-zone" + " -O0 -g" + " -nostdinc -isystem " SYSROOT_INC + " -Wl,-Ttext-segment=0x401000" + " -o %s %s " SYSROOT_LIB "/crt0.o " SYSROOT_LIB "/libcervus.a", + e->elf, e->src); + if (ret != 0) { + print_color(COLOR_RED, "[bin] Failed to compile %s", e->src); + return false; + } + print_color(COLOR_GREEN, "[bin] %s built successfully", e->elf); + return true; +} + +bool build_all_bin_apps(void) { + scan_bin_apps(); + if (g_nbin == 0) { + print_color(COLOR_YELLOW, "[bin] No .c files found in '%s'", BIN_APPS_DIR); + return true; + } + print_color(COLOR_CYAN, "[bin] Found %d program(s) in '%s'", g_nbin, BIN_APPS_DIR); + for (int i = 0; i < g_nbin; i++) { + if (!build_one_bin_app(&g_bin_apps[i])) return false; + } + return true; +} + +void clean_bin_elfs(void) { + DIR *d = opendir(BIN_APPS_DIR); + if (!d) return; + struct dirent *de; + while ((de = readdir(d)) != NULL) { + const char *nm = de->d_name; + size_t nlen = strlen(nm); + if (nlen < 5) continue; + if (strcmp(nm + nlen - 4, ".elf") != 0) continue; + char path[512]; + snprintf(path, sizeof(path), "%s/%s", BIN_APPS_DIR, nm); + remove(path); + print_color(COLOR_YELLOW, "[clean] removed %s", path); + } + closedir(d); +} + +#define LCV_CFLAGS_INT "-ffreestanding -nostdlib -static -fno-stack-protector " \ + "-mno-sse -mno-sse2 -mno-mmx -mno-avx -mno-avx2 " \ + "-mno-red-zone -fno-pie -fno-pic " \ + "-O0 -g -Wall -Wextra" + +#define LCV_CFLAGS_FLT "-ffreestanding -nostdlib -static -fno-stack-protector " \ + "-mno-red-zone -fno-pie -fno-pic " \ + "-O0 -g -Wall -Wextra" + +typedef struct { + const char *src; + const char *obj; + int is_float; +} libcervus_unit_t; + +static const libcervus_unit_t LCV_UNITS[] = { + { "libcervus.c", "libcervus.o", 0 }, + { "compat.c", "compat.o", 0 }, + { "ctype/ctype.c", "ctype/ctype.o", 0 }, + { "string/string.c", "string/string.o", 0 }, + { "memory/memory.c", "memory/memory.o", 0 }, + { "stdlib/stdlib.c", "stdlib/stdlib.o", 0 }, + { "stdlib/strtod.c", "stdlib/strtod.o", 1 }, + { "stdio/stdio.c", "stdio/stdio.o", 1 }, + { "stdio/scanf.c", "stdio/scanf.o", 1 }, + { "time/time.c", "time/time.o", 0 }, + { "signal/signal.c", "signal/signal.o", 0 }, + { "dirent/dirent.c", "dirent/dirent.o", 0 }, + { "math/abs.c", "math/abs.o", 0 }, + { "math/fabs.c", "math/fabs.o", 1 }, + { "math/isinf.c", "math/isinf.o", 0 }, + { "math/isnan.c", "math/isnan.o", 0 }, + { "math/pow.c", "math/pow.o", 1 }, + { "math/pow10.c", "math/pow10.o", 1 }, + { NULL, NULL, 0 } +}; + +static long get_mtime_safe(const char *p) { + struct stat st; + if (stat(p, &st) != 0) return 0; + return (long)st.st_mtime; +} + +static bool need_rebuild(const char *src, const char *obj) { + if (!file_exists(obj)) return true; + return get_mtime_safe(src) > get_mtime_safe(obj); +} + +bool build_libcervus(void) { + if (cmd_run(false, "command -v nasm >/dev/null 2>&1") != 0) { + print_color(COLOR_RED, + "[libcervus] 'nasm' is required to build crt0.o/setjmp.o. Install: " + "apt install nasm | dnf install nasm | pacman -S nasm"); + return false; + } + if (cmd_run(false, "command -v ar >/dev/null 2>&1") != 0) { + print_color(COLOR_RED, "[libcervus] 'ar' (binutils) is required"); + return false; + } + + print_color(COLOR_CYAN, "[libcervus] Building libcervus.a and crt0.o (native)..."); + + char incdir[BIGPATH]; + char libdir[BIGPATH]; + char cwd_buf[PATH_MAX]; + if (!getcwd(cwd_buf, sizeof(cwd_buf))) { + print_color(COLOR_RED, "[libcervus] getcwd failed"); + return false; + } + path_join2(incdir, sizeof(incdir), cwd_buf, SYSROOT_INC); + path_join2(libdir, sizeof(libdir), cwd_buf, SYSROOT_LIB); + + int rc = chdir(LIBCERVUS_DIR); + if (rc != 0) { + print_color(COLOR_RED, "[libcervus] cannot chdir to %s", LIBCERVUS_DIR); + return false; + } + + bool any_changed = false; + int built = 0; + int skipped = 0; + + for (int i = 0; LCV_UNITS[i].src; i++) { + const libcervus_unit_t *u = &LCV_UNITS[i]; + if (!need_rebuild(u->src, u->obj)) { skipped++; continue; } + const char *cflags = u->is_float ? LCV_CFLAGS_FLT : LCV_CFLAGS_INT; + if (cmd_run(false, "gcc %s -nostdinc -isystem %s -c -o %s %s", + cflags, incdir, u->obj, u->src) != 0) { + print_color(COLOR_RED, "[libcervus] failed to compile %s", u->src); + (void)!chdir(cwd_buf); + return false; + } + any_changed = true; + built++; + } + + if (need_rebuild("setjmp.asm", "setjmp.o")) { + if (cmd_run(false, "nasm -f elf64 -o setjmp.o setjmp.asm") != 0) { + print_color(COLOR_RED, "[libcervus] nasm failed on setjmp.asm"); + (void)!chdir(cwd_buf); return false; + } + any_changed = true; built++; + } else skipped++; + + if (need_rebuild("crt0.asm", "crt0.o")) { + if (cmd_run(false, "nasm -f elf64 -o crt0.o crt0.asm") != 0) { + print_color(COLOR_RED, "[libcervus] nasm failed on crt0.asm"); + (void)!chdir(cwd_buf); return false; + } + any_changed = true; built++; + } else skipped++; + + bool need_ar = any_changed || !file_exists("libcervus.a"); + if (need_ar) { + char ar_cmd[8192]; + size_t pos = 0; + pos += snprintf(ar_cmd + pos, sizeof(ar_cmd) - pos, "ar rcs libcervus.a"); + for (int i = 0; LCV_UNITS[i].src; i++) { + pos += snprintf(ar_cmd + pos, sizeof(ar_cmd) - pos, " %s", LCV_UNITS[i].obj); + } + pos += snprintf(ar_cmd + pos, sizeof(ar_cmd) - pos, " setjmp.o"); + if (cmd_run(false, "%s", ar_cmd) != 0) { + print_color(COLOR_RED, "[libcervus] ar failed"); + (void)!chdir(cwd_buf); return false; + } + } + + if (cmd_run(false, "mkdir -p %s", libdir) != 0 || + cmd_run(false, "cp libcervus.a %s/", libdir) != 0 || + cmd_run(false, "cp crt0.o %s/", libdir) != 0) + { + print_color(COLOR_RED, "[libcervus] install copy failed"); + (void)!chdir(cwd_buf); return false; + } + + (void)!chdir(cwd_buf); + print_color(COLOR_GREEN, "[libcervus] OK (compiled %d, skipped %d)", built, skipped); + return true; +} + +#define TCC_VERSION_STR "0.9.27" +#define TCC_TAR_FNAME "tcc-0.9.27.tar.bz2" +#define TCC_SRC_DIR "tcc-0.9.27" +#define TCC_DOWNLOAD_URL "https://download.savannah.gnu.org/releases/tinycc/tcc-0.9.27.tar.bz2" +#define TCC_DIR "usr/tcc" + +typedef struct { char *data; size_t len; size_t cap; } dstr_t; + +static void dstr_init(dstr_t *s) { s->data = NULL; s->len = 0; s->cap = 0; } +static void dstr_free(dstr_t *s) { free(s->data); s->data = NULL; s->len = s->cap = 0; } + +static bool dstr_reserve(dstr_t *s, size_t need) { + if (s->cap >= need) return true; + size_t nc = s->cap ? s->cap : 256; + while (nc < need) nc *= 2; + char *p = realloc(s->data, nc); + if (!p) return false; + s->data = p; s->cap = nc; + return true; +} + +static bool read_file_dstr(const char *path, dstr_t *out) { + FILE *f = fopen(path, "rb"); + if (!f) return false; + fseek(f, 0, SEEK_END); + long sz = ftell(f); + fseek(f, 0, SEEK_SET); + if (sz < 0) { fclose(f); return false; } + if (!dstr_reserve(out, (size_t)sz + 1)) { fclose(f); return false; } + if (sz > 0 && fread(out->data, 1, (size_t)sz, f) != (size_t)sz) { + fclose(f); return false; + } + out->len = (size_t)sz; + out->data[out->len] = '\0'; + fclose(f); + return true; +} + +static bool write_file_dstr(const char *path, const dstr_t *s) { + FILE *f = fopen(path, "wb"); + if (!f) return false; + if (s->len > 0 && fwrite(s->data, 1, s->len, f) != s->len) { fclose(f); return false; } + fclose(f); + return true; +} + +static bool dstr_replace_once(dstr_t *s, const char *old_s, const char *new_s) { + size_t old_n = strlen(old_s); + size_t new_n = strlen(new_s); + if (old_n == 0 || s->len < old_n) return false; + char *p = memmem(s->data, s->len, old_s, old_n); + if (!p) return false; + size_t off = (size_t)(p - s->data); + + if (new_n > old_n) { + if (!dstr_reserve(s, s->len + (new_n - old_n) + 1)) return false; + p = s->data + off; + } + + memmove(p + new_n, p + old_n, s->len - off - old_n + 1 ); + memcpy(p, new_s, new_n); + s->len += (new_n - old_n); + return true; +} + +static bool dstr_guard_line_with(dstr_t *s, const char *marker, const char *guard_macro) { + char *p = memmem(s->data, s->len, marker, strlen(marker)); + if (!p) return false; + + char *line_start = p; + while (line_start > s->data && line_start[-1] != '\n') line_start--; + + char *prev_line_start = line_start; + if (prev_line_start > s->data) prev_line_start--; + while (prev_line_start > s->data && prev_line_start[-1] != '\n') prev_line_start--; + + char needle[160]; + snprintf(needle, sizeof(needle), "#ifndef %s", guard_macro); + size_t pll = (size_t)(line_start - prev_line_start); + if (pll >= strlen(needle) && + memcmp(prev_line_start, needle, strlen(needle)) == 0) + { + return false; + } + + char *line_end = p; + while ((size_t)(line_end - s->data) < s->len && *line_end != '\n') line_end++; + if ((size_t)(line_end - s->data) < s->len && *line_end == '\n') line_end++; + + char prefix[160], suffix[16]; + snprintf(prefix, sizeof(prefix), "#ifndef %s\n", guard_macro); + snprintf(suffix, sizeof(suffix), "#endif\n"); + size_t ins_pre = strlen(prefix), ins_suf = strlen(suffix); + size_t off_start = (size_t)(line_start - s->data); + size_t off_end = (size_t)(line_end - s->data); + + if (!dstr_reserve(s, s->len + ins_pre + ins_suf + 1)) return false; + line_start = s->data + off_start; + line_end = s->data + off_end; + + memmove(line_end + ins_pre + ins_suf, line_end, s->len - off_end + 1); + + memcpy(line_end + ins_pre, suffix, ins_suf); + + memmove(line_start + ins_pre, line_start, off_end - off_start); + + memcpy(line_start, prefix, ins_pre); + s->len += ins_pre + ins_suf; + return true; +} + +static int dstr_guard_func_impls(dstr_t *s, const char *name, const char *guard_macro) { + int count = 0; + size_t cursor = 0; + size_t name_n = strlen(name); + + while (cursor + name_n < s->len) { + char *p = memmem(s->data + cursor, s->len - cursor, name, name_n); + if (!p) break; + size_t pos = (size_t)(p - s->data); + + size_t i = pos + name_n; + while (i < s->len && (s->data[i] == ' ' || s->data[i] == '\t')) i++; + if (i >= s->len || s->data[i] != '(') { + cursor = pos + 1; continue; + } + + size_t j = i; + while (j < s->len && s->data[j] != '{' && s->data[j] != ';') j++; + if (j >= s->len) break; + if (s->data[j] == ';') { cursor = pos + 1; continue; } + + int depth = 0; + size_t end = j; + for (; end < s->len; end++) { + if (s->data[end] == '{') depth++; + else if (s->data[end] == '}') { depth--; if (depth == 0) { end++; break; } } + } + if (depth != 0) break; + if (end < s->len && s->data[end] == '\n') end++; + + size_t line_start = pos; + while (line_start > 0 && s->data[line_start - 1] != '\n') line_start--; + + size_t look = line_start > 200 ? line_start - 200 : 0; + if (memmem(s->data + look, line_start - look, + guard_macro, strlen(guard_macro))) { + cursor = end; continue; + } + + char prefix[160], suffix[16]; + snprintf(prefix, sizeof(prefix), "#ifndef %s\n", guard_macro); + snprintf(suffix, sizeof(suffix), "#endif\n"); + size_t pre_n = strlen(prefix), suf_n = strlen(suffix); + if (!dstr_reserve(s, s->len + pre_n + suf_n + 1)) return count; + + memmove(s->data + end + pre_n + suf_n, + s->data + end, + s->len - end + 1); + memcpy(s->data + end + pre_n, suffix, suf_n); + memmove(s->data + line_start + pre_n, + s->data + line_start, + end - line_start); + memcpy(s->data + line_start, prefix, pre_n); + s->len += pre_n + suf_n; + count++; + cursor = end + pre_n + suf_n; + } + return count; +} + +static bool patch_file(const char *src_dir, const char *rel, + int (*editor)(dstr_t *)) { + char path[SHORTPATH]; + path_join2(path, sizeof(path), src_dir, rel); + dstr_t s; dstr_init(&s); + if (!read_file_dstr(path, &s)) { + print_color(COLOR_RED, "[tcc-patch] cannot read %s", path); + return false; + } + int changed = editor(&s); + if (changed > 0) { + if (!write_file_dstr(path, &s)) { + print_color(COLOR_RED, "[tcc-patch] cannot write %s", path); + dstr_free(&s); return false; + } + print_color(COLOR_GREEN, "[tcc-patch] %s: %d edit(s)", rel, changed); + } else { + print_color(COLOR_YELLOW, "[tcc-patch] %s: no changes (already patched?)", rel); + } + dstr_free(&s); + return true; +} + +static int edit_tcc_h(dstr_t *s) { + int changed = 0; + if (dstr_guard_line_with(s, "#include ", "TCC_NO_DLOPEN")) changed++; + + { + const char *needle = "#include "; + char *p = memmem(s->data, s->len, needle, strlen(needle)); + if (p && !memmem(s->data, s->len, + "#include ", + strlen("#include "))) { + const char *ins = "#include \n"; + size_t off = (size_t)(p - s->data); + size_t ins_n = strlen(ins); + if (!dstr_reserve(s, s->len + ins_n + 1)) return changed; + memmove(s->data + off + ins_n, s->data + off, s->len - off + 1); + memcpy(s->data + off, ins, ins_n); + s->len += ins_n; + changed++; + } + } + + if (dstr_guard_line_with(s, "enable bound checking code", "CONFIG_TCC_BCHECK")) changed++; + return changed; +} + +static int edit_libtcc_c(dstr_t *s) { + int changed = 0; + + if (dstr_replace_once(s, + "return dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);\n", + "(void)filename;\n return NULL;\n")) changed++; + if (dstr_replace_once(s, + "return dlopen(filename, RTLD_LOCAL | RTLD_LAZY);\n", + "(void)filename;\n return NULL;\n")) changed++; + if (dstr_replace_once(s, + "return dlsym(handle, sym);\n", + "(void)handle; (void)sym;\n return NULL;\n")) changed++; + if (dstr_replace_once(s, + "dlclose(handle);\n", + "(void)handle;\n")) changed++; + + if (!memmem(s->data, s->len, "Cervus: no ld.so", 16)) { + if (dstr_replace_once(s, + " s->alacarte_link = 1;", + " s->alacarte_link = 1;\n s->static_link = 1; /* Cervus: no ld.so */")) + changed++; + } + + if (dstr_replace_once(s, + " if (output_type != TCC_OUTPUT_DLL)\n" + " tcc_add_crt(s, \"crt1.o\");\n" + " tcc_add_crt(s, \"crti.o\");", + " if (output_type != TCC_OUTPUT_DLL)\n" + " tcc_add_crt(s, \"crt0.o\"); /* Cervus: only crt0 */")) + changed++; + return changed; +} + +static int edit_tccrun_c(dstr_t *s) { + int changed = 0; + + if (dstr_guard_line_with(s, "", "TCC_NO_BACKTRACE")) changed++; + + if (!memmem(s->data, s->len, "typedef void *ucontext_t;", + strlen("typedef void *ucontext_t;"))) + { + + size_t scan = s->len < 4096 ? s->len : 4096; + size_t last_inc_end = 0; + for (size_t i = 0; i < scan; ) { + if (s->data[i] == '#' && i + 8 <= s->len && + memcmp(s->data + i, "#include", 8) == 0) + { + + size_t e = i; + while (e < s->len && s->data[e] != '\n') e++; + if (e < s->len) e++; + last_inc_end = e; + i = e; continue; + } + i++; + } + if (last_inc_end > 0) { + const char *stub = "\n#ifdef TCC_NO_BACKTRACE\n" + "typedef void *ucontext_t;\n" + "#endif\n"; + size_t stub_n = strlen(stub); + if (dstr_reserve(s, s->len + stub_n + 1)) { + memmove(s->data + last_inc_end + stub_n, + s->data + last_inc_end, + s->len - last_inc_end + 1); + memcpy(s->data + last_inc_end, stub, stub_n); + s->len += stub_n; + changed++; + } + } + } + + if (dstr_guard_line_with(s, "set_exception_handler();", "TCC_NO_BACKTRACE")) changed++; + + const char *names[] = { "rt_error", "sig_error", + "set_exception_handler", "rt_get_caller_pc", NULL }; + for (int i = 0; names[i]; i++) { + int n = dstr_guard_func_impls(s, names[i], "TCC_NO_BACKTRACE"); + if (n > 0) changed++; + } + return changed; +} + +static int edit_tccelf_c(dstr_t *s) { + int changed = 0; + + if (!memmem(s->data, s->len, "Cervus: -lcervus", 16)) { + if (dstr_replace_once(s, + " if (!s1->nostdlib) {\n tcc_add_library_err(s1, \"c\");", + " if (!s1->nostdlib) {\n tcc_add_library_err(s1, \"cervus\"); /* Cervus: -lcervus */")) + changed++; + } + + if (dstr_replace_once(s, + " if (s1->output_type != TCC_OUTPUT_MEMORY)\n" + " tcc_add_crt(s1, \"crtn.o\");\n" + " }\n", + " /* Cervus: no crtn.o */\n }\n")) + changed++; + return changed; +} + +static bool write_tcc_config_h(const char *src_dir) { + char path[SHORTPATH]; + path_join2(path, sizeof(path), src_dir, "config.h"); + FILE *f = fopen(path, "w"); + if (!f) return false; + fputs( + "#ifndef _CONFIG_H\n" + "#define _CONFIG_H\n\n" + "#define TCC_VERSION \"" TCC_VERSION_STR "\"\n\n" + "#define CONFIG_TCC_SYSROOT \"\"\n" + "#define CONFIG_TCC_LIBPATHS \"/usr/lib\"\n" + "#define CONFIG_TCC_CRTPREFIX \"/usr/lib\"\n" + "#define CONFIG_TCC_ELFINTERP \"\"\n" + "#define CONFIG_TCCDIR \"/usr/lib/tcc\"\n\n" + "#define HOST_OS \"Cervus\"\n" + "#define HOST_ARCH \"x86_64\"\n\n" + "#define TCC_TARGET_X86_64 1\n\n" + "#define CONFIG_TCC_PREDEFS 1\n" + "#define CONFIG_TCC_STATIC 1\n\n" + "#define TCC_NO_DLOPEN 1\n" + "#define TCC_NO_BACKTRACE 1\n\n" + "#define CONFIG_TCC_BCHECK 0\n\n" + "#undef CONFIG_WIN32\n" + "#undef CONFIG_WIN64\n" + "#undef TCC_TARGET_PE\n\n" + "#endif /* _CONFIG_H */\n", + f); + fclose(f); + return true; +} + +static bool tcc_download(void) { + char tar_path[SHORTPATH]; + path_join2(tar_path, sizeof(tar_path), TCC_DIR, TCC_TAR_FNAME); + if (file_exists(tar_path)) return true; + print_color(COLOR_CYAN, "[tcc] Downloading %s...", TCC_TAR_FNAME); + if (cmd_run(false, "command -v wget >/dev/null 2>&1") == 0) { + if (cmd_run(true, "wget -q -O %s %s", tar_path, TCC_DOWNLOAD_URL) == 0 + && file_exists(tar_path)) return true; + } + if (cmd_run(false, "command -v curl >/dev/null 2>&1") == 0) { + if (cmd_run(true, "curl -fL -o %s %s", tar_path, TCC_DOWNLOAD_URL) == 0 + && file_exists(tar_path)) return true; + } + print_color(COLOR_RED, "[tcc] cannot download (need wget or curl)"); + return false; +} + +static bool tcc_extract_and_patch(void) { + char src_dir_full[SHORTPATH]; + path_join2(src_dir_full, sizeof(src_dir_full), TCC_DIR, TCC_SRC_DIR); + + if (!file_exists(src_dir_full)) { + print_color(COLOR_CYAN, "[tcc] Extracting %s...", TCC_TAR_FNAME); + if (cmd_run(true, "tar -xjf %s/%s -C %s", + TCC_DIR, TCC_TAR_FNAME, TCC_DIR) != 0) { + print_color(COLOR_RED, "[tcc] tar -xjf failed"); + return false; + } + } + + if (!write_tcc_config_h(src_dir_full)) { + print_color(COLOR_RED, "[tcc] cannot write config.h"); + return false; + } + + print_color(COLOR_CYAN, "[tcc] Applying Cervus patches (idempotent)..."); + if (!patch_file(src_dir_full, "tcc.h", edit_tcc_h)) return false; + if (!patch_file(src_dir_full, "libtcc.c", edit_libtcc_c)) return false; + if (!patch_file(src_dir_full, "tccrun.c", edit_tccrun_c)) return false; + if (!patch_file(src_dir_full, "tccelf.c", edit_tccelf_c)) return false; + return true; +} + +static bool tcc_build_and_install(void) { + char src_dir_full[SHORTPATH]; + path_join2(src_dir_full, sizeof(src_dir_full), TCC_DIR, TCC_SRC_DIR); + + char cwd_buf[PATH_MAX]; + if (!getcwd(cwd_buf, sizeof(cwd_buf))) { + print_color(COLOR_RED, "[tcc] getcwd failed"); + return false; + } + char incdir[BIGPATH], libdir[BIGPATH]; + path_join2(incdir, sizeof(incdir), cwd_buf, SYSROOT_INC); + path_join2(libdir, sizeof(libdir), cwd_buf, SYSROOT_LIB); + + char tcc_elf[SHORTPATH], libtcc1_a[SHORTPATH]; + path_join2(tcc_elf, sizeof(tcc_elf), TCC_DIR, "tcc.elf"); + path_join2(libtcc1_a, sizeof(libtcc1_a), TCC_DIR, "libtcc1.a"); + + char one_src[SHORTPATH]; + path_join2(one_src, sizeof(one_src), src_dir_full, "tcc.c"); + + char one_hdr[SHORTPATH], one_libtcc[SHORTPATH]; + path_join2(one_hdr, sizeof(one_hdr), src_dir_full, "tcc.h"); + path_join2(one_libtcc, sizeof(one_libtcc), src_dir_full, "libtcc.c"); + + long elf_t = get_mtime_safe(tcc_elf); + bool need_tcc = + !file_exists(tcc_elf) || + get_mtime_safe(one_src) > elf_t || + get_mtime_safe(one_hdr) > elf_t || + get_mtime_safe(one_libtcc) > elf_t; + + if (need_tcc) { + print_color(COLOR_CYAN, "[tcc] Building tcc.elf for Cervus (x86_64)..."); + char crt0[BIGPATH]; + path_join2(crt0, sizeof(crt0), libdir, "crt0.o"); + if (!file_exists(crt0)) { + print_color(COLOR_RED, "[tcc] %s missing (libcervus build failed?)", crt0); + return false; + } + int rc = cmd_run(true, + "gcc -ffreestanding -nostdlib -static -fno-stack-protector " + "-mno-red-zone -fno-pie -fno-pic -O2 -D__CERVUS__ " + "-nostdinc -isystem %s " + "-DTCC_TARGET_X86_64 -DONE_SOURCE=1 " + "-DCONFIG_TCC_PREDEFS=1 -DTCC_NO_DLOPEN=1 -DTCC_NO_BACKTRACE=1 " + "-DCONFIG_TCC_STATIC=1 " + "-I%s " + "-o %s %s/tcc.c %s " + "-nostdlib -static -L%s -lcervus", + incdir, src_dir_full, tcc_elf, src_dir_full, crt0, libdir); + if (rc != 0) { + print_color(COLOR_RED, "[tcc] tcc.elf build failed"); + return false; + } + } else { + print_color(COLOR_GREEN, "[tcc] tcc.elf up to date"); + } + + char l1_o[SHORTPATH], al_o[SHORTPATH], va_o[SHORTPATH]; + path_join2(l1_o, sizeof(l1_o), TCC_DIR, "libtcc1.o"); + path_join2(al_o, sizeof(al_o), TCC_DIR, "alloca86_64.o"); + path_join2(va_o, sizeof(va_o), TCC_DIR, "va_list.o"); + + bool need_libtcc1 = !file_exists(libtcc1_a); + if (need_libtcc1) { + print_color(COLOR_CYAN, "[tcc] Building libtcc1.a..."); + const char *l1_flags = + "-ffreestanding -nostdlib -fno-stack-protector " + "-mno-red-zone -fno-pie -fno-pic -O2 -D__CERVUS__ " + "-DTCC_TARGET_X86_64"; + + char src_path[SHORTPATH]; + char ar_cmd[2048]; + size_t arpos = (size_t)snprintf(ar_cmd, sizeof(ar_cmd), + "ar rcs %s", libtcc1_a); + + path_join2(src_path, sizeof(src_path), src_dir_full, "lib/libtcc1.c"); + if (!file_exists(src_path)) { + print_color(COLOR_RED, "[tcc] missing %s", src_path); + return false; + } + if (cmd_run(true, "gcc %s -c %s -o %s", l1_flags, src_path, l1_o) != 0) { + print_color(COLOR_RED, "[tcc] libtcc1.c compile failed"); return false; + } + arpos += (size_t)snprintf(ar_cmd + arpos, sizeof(ar_cmd) - arpos, " %s", l1_o); + + path_join2(src_path, sizeof(src_path), src_dir_full, "lib/alloca86_64.S"); + if (file_exists(src_path)) { + if (cmd_run(true, "gcc %s -c %s -o %s", l1_flags, src_path, al_o) != 0) { + print_color(COLOR_RED, "[tcc] alloca86_64.S compile failed"); return false; + } + arpos += (size_t)snprintf(ar_cmd + arpos, sizeof(ar_cmd) - arpos, " %s", al_o); + } + + path_join2(src_path, sizeof(src_path), src_dir_full, "lib/va_list.c"); + if (file_exists(src_path)) { + if (cmd_run(true, "gcc %s -c %s -o %s", l1_flags, src_path, va_o) != 0) { + print_color(COLOR_RED, "[tcc] va_list.c compile failed"); return false; + } + arpos += (size_t)snprintf(ar_cmd + arpos, sizeof(ar_cmd) - arpos, " %s", va_o); + } + + if (cmd_run(true, "%s", ar_cmd) != 0) { + print_color(COLOR_RED, "[tcc] ar failed"); return false; + } + } else { + print_color(COLOR_GREEN, "[tcc] libtcc1.a up to date"); + } + + print_color(COLOR_CYAN, "[tcc] Installing to sysroot..."); + if (cmd_run(false, "mkdir -p %s/usr/bin %s/usr/lib/tcc/include", + SYSROOT_DIR, SYSROOT_DIR) != 0) { + print_color(COLOR_RED, "[tcc] mkdir failed"); + return false; + } + if (cmd_run(false, "cp %s %s/usr/bin/tcc", tcc_elf, SYSROOT_DIR) != 0 || + cmd_run(false, "cp %s %s/usr/lib/tcc/libtcc1.a", libtcc1_a, SYSROOT_DIR) != 0 || + cmd_run(false, "cp %s/include/*.h %s/usr/lib/tcc/include/", + src_dir_full, SYSROOT_DIR) != 0) + { + print_color(COLOR_RED, "[tcc] install copy failed"); + return false; + } + + print_color(COLOR_GREEN, "[tcc] Installed to %s/usr/bin/tcc", SYSROOT_DIR); + return true; +} + +bool build_tcc(void) { + if (!tcc_download()) return false; + if (!tcc_extract_and_patch()) return false; + if (!tcc_build_and_install()) return false; + return true; +} + +void clean_tcc_build(bool deep) { + char tcc_elf[PATH_MAX], libtcc1_a[PATH_MAX]; + path_join2(tcc_elf, sizeof(tcc_elf), TCC_DIR, "tcc.elf"); + path_join2(libtcc1_a, sizeof(libtcc1_a), TCC_DIR, "libtcc1.a"); + + cmd_run(false, "rm -f %s/libtcc1.o %s/alloca86_64.o %s/va_list.o", + TCC_DIR, TCC_DIR, TCC_DIR); + if (file_exists(tcc_elf)) { remove(tcc_elf); print_color(COLOR_YELLOW, "[clean] removed %s", tcc_elf); } + if (file_exists(libtcc1_a)) { remove(libtcc1_a); print_color(COLOR_YELLOW, "[clean] removed %s", libtcc1_a); } + + cmd_run(false, "rm -f %s/usr/bin/tcc", SYSROOT_DIR); + cmd_run(false, "rm -rf %s/usr/lib/tcc", SYSROOT_DIR); + print_color(COLOR_YELLOW, "[clean] removed %s/usr/bin/tcc and %s/usr/lib/tcc/", + SYSROOT_DIR, SYSROOT_DIR); + + if (deep) { + char src_dir[SHORTPATH], tar_path[SHORTPATH]; + path_join2(src_dir, sizeof(src_dir), TCC_DIR, TCC_SRC_DIR); + path_join2(tar_path, sizeof(tar_path), TCC_DIR, TCC_TAR_FNAME); + if (file_exists(src_dir)) { rm_rf(src_dir); print_color(COLOR_YELLOW, "[clean] removed %s", src_dir); } + if (file_exists(tar_path)) { remove(tar_path); print_color(COLOR_YELLOW, "[clean] removed %s", tar_path); } + } +} + +void clean_libcervus_build(bool deep) { + char buf[PATH_MAX]; + for (int i = 0; LCV_UNITS[i].src; i++) { + path_join2(buf, sizeof(buf), LIBCERVUS_DIR, LCV_UNITS[i].obj); + if (file_exists(buf)) remove(buf); + } + path_join2(buf, sizeof(buf), LIBCERVUS_DIR, "setjmp.o"); + if (file_exists(buf)) remove(buf); + path_join2(buf, sizeof(buf), LIBCERVUS_DIR, "crt0.o"); + if (file_exists(buf)) remove(buf); + path_join2(buf, sizeof(buf), LIBCERVUS_DIR, "libcervus.a"); + if (file_exists(buf)) remove(buf); + + cmd_run(false, "rm -f %s/libcervus.a %s/crt0.o", SYSROOT_LIB, SYSROOT_LIB); + (void)deep; +} + +bool build_installer(void) { + DIR *d = opendir(INSTALLER_DIR); + if (!d) { + print_color(COLOR_YELLOW, + "[installer] directory '%s' not found, skipping", INSTALLER_DIR); + return true; + } + struct dirent *de; + int built = 0; + while ((de = readdir(d)) != NULL) { + const char *nm = de->d_name; + size_t nlen = strlen(nm); + if (nlen < 3 || nm[0] == '.') continue; + if (strcmp(nm + nlen - 2, ".c") != 0) continue; + app_entry_t e; + snprintf(e.src, sizeof(e.src), "%s/%s", INSTALLER_DIR, nm); + snprintf(e.elf, sizeof(e.elf), "%s/%.*s.elf", INSTALLER_DIR, (int)(nlen-2), nm); + snprintf(e.name, sizeof(e.name), "%.*s", (int)(nlen-2), nm); + if (!build_one_app(&e)) { closedir(d); return false; } + built++; + } + closedir(d); + if (built == 0) + print_color(COLOR_YELLOW, "[installer] no .c sources in '%s'", INSTALLER_DIR); + return true; +} + +bool build_initramfs(void) { + if (ARG_NO_INITRAMFS) { + print_color(COLOR_YELLOW, "[initramfs] skipped (--no-initramfs)"); + return true; + } + + if (!build_limine()) { + print_color(COLOR_YELLOW, "[initramfs] warning: limine not available yet, boot files will be incomplete"); + } + + bool tar_exists = file_exists(INITRAMFS_TAR); + bool any_newer = false; + if (!tar_exists) { + any_newer = true; + } else { + scan_apps(); + for (int i = 0; i < g_naps; i++) { + if (file_exists(g_apps[i].elf) && + get_mtime(g_apps[i].elf) > get_mtime(INITRAMFS_TAR)) { + any_newer = true; break; + } + } + if (!any_newer) { + scan_bin_apps(); + for (int i = 0; i < g_nbin; i++) { + if (file_exists(g_bin_apps[i].elf) && + get_mtime(g_bin_apps[i].elf) > get_mtime(INITRAMFS_TAR)) { + any_newer = true; break; + } + } + } + if (!any_newer && file_exists(SHELL_ELF) && + get_mtime(SHELL_ELF) > get_mtime(INITRAMFS_TAR)) { + any_newer = true; + } + if (!any_newer && file_exists(INSTALLER_ELF) && + get_mtime(INSTALLER_ELF) > get_mtime(INITRAMFS_TAR)) { + any_newer = true; + } + if (!any_newer && file_exists(SYSROOT_LIB "/libcervus.a") && + get_mtime(SYSROOT_LIB "/libcervus.a") > get_mtime(INITRAMFS_TAR)) { + any_newer = true; + } + } + if (tar_exists && !any_newer) { + print_color(COLOR_GREEN, "[initramfs] %s is up to date", INITRAMFS_TAR); + return true; + } + + print_color(COLOR_CYAN, "[initramfs] Building rootfs..."); + + const char *dirs[] = { + INITRAMFS_ROOTFS "/bin", + INITRAMFS_ROOTFS "/dev", + INITRAMFS_ROOTFS "/etc", + INITRAMFS_ROOTFS "/home", + INITRAMFS_ROOTFS "/tmp", + INITRAMFS_ROOTFS "/proc", + NULL + }; + for (int i = 0; dirs[i]; i++) ensure_dir(dirs[i]); + + FILE *passwd = fopen(INITRAMFS_ROOTFS "/etc/passwd", "w"); + if (passwd) { + fprintf(passwd, "root:x:0:0:root:/root:/bin/sh\n"); + fclose(passwd); + } + + FILE *hostname = fopen(INITRAMFS_ROOTFS "/etc/hostname", "w"); + if (hostname) { + fprintf(hostname, "cervus"); + fclose(hostname); + } + + FILE *motd = fopen(INITRAMFS_ROOTFS "/etc/motd", "w"); + if (motd) { + fprintf(motd, + "\n" + " $$$$$$\\ \n" + " $$ __$$\\ \n" + " $$ / \\__| $$$$$$\\ $$$$$$\\ $$\\ $$\\ $$\\ $$\\ $$$$$$$\\ \n" + " $$ | $$ __$$\\ $$ __$$\\\\$$\\ $$ |$$ | $$ |$$ _____|\n" + " $$ | $$$$$$$$ |$$ | \\__|\\$$\\$$ / $$ | $$ |\\$$$$$$\\ \n" + " $$ | $$\\ $$ ____|$$ | \\$$$ / $$ | $$ | \\____$$\\ \n" + " \\$$$$$$ |\\$$$$$$$\\ $$ | \\$ / \\$$$$$$ |$$$$$$$ |\n" + " \\______/ \\______||\\__| \\_/ \\______/ \\_______/\n" + "\n" + " Cervus OS " VERSION " (Alpha release)\n" + "\n" + " Type 'help' to see available commands.\n" + "\n" + " Your home directory is /mnt/home (persistent ext2 disk).\n" + " Files created in /mnt/ will survive reboots.\n" + " Files outside /mnt/ are in RAM and will be lost on reboot.\n" + "\n"); + fclose(motd); + } + + if (file_exists(SHELL_ELF)) { + if (cmd_run(false, "cp %s %s/bin/init", SHELL_ELF, INITRAMFS_ROOTFS) != 0) { + print_color(COLOR_RED, "[initramfs] Failed to copy shell.elf -> bin/init"); + return false; + } + cmd_run(false, "cp %s %s/bin/shell", SHELL_ELF, INITRAMFS_ROOTFS); + print_color(COLOR_GREEN, "[initramfs] shell.elf -> /bin/init + /bin/shell"); + } else { + print_color(COLOR_RED, "[initramfs] shell.elf not found - boot will drop to nothing!"); + FILE *stub = fopen(INITRAMFS_ROOTFS "/bin/.keep", "w"); + if (stub) fclose(stub); + } + + scan_bin_apps(); + print_color(COLOR_CYAN, "[initramfs] Copying %d bin program(s) -> rootfs/bin/", g_nbin); + for (int i = 0; i < g_nbin; i++) { + if (!file_exists(g_bin_apps[i].elf)) { + print_color(COLOR_YELLOW, "[initramfs] %s not built, skipping", g_bin_apps[i].src); + continue; + } + char dst[512]; + snprintf(dst, sizeof(dst), "%s/bin/%s", INITRAMFS_ROOTFS, g_bin_apps[i].name); + if (cmd_run(false, "cp %s %s", g_bin_apps[i].elf, dst) != 0) { + print_color(COLOR_RED, "[initramfs] Failed to copy %s", g_bin_apps[i].elf); + } else { + print_color(COLOR_GREEN, "[initramfs] %s -> rootfs/bin/%s", + g_bin_apps[i].elf, g_bin_apps[i].name); + } + } + + ensure_dir(INITRAMFS_ROOTFS "/apps"); + scan_apps(); + for (int i = 0; i < g_naps; i++) { + if (strcmp(g_apps[i].name, "shell") == 0) continue; + if (!file_exists(g_apps[i].elf)) continue; + char dst[512]; + snprintf(dst, sizeof(dst), "%s/apps/%s", INITRAMFS_ROOTFS, g_apps[i].name); + if (cmd_run(false, "cp %s %s", g_apps[i].elf, dst) != 0) { + print_color(COLOR_RED, "[initramfs] Failed to copy %s", g_apps[i].elf); + } else { + print_color(COLOR_GREEN, "[initramfs] %s -> rootfs/apps/%s", + g_apps[i].elf, g_apps[i].name); + } + } + + if (file_exists(INSTALLER_ELF)) { + char dst[512]; + snprintf(dst, sizeof(dst), "%s/bin/install-on-disk", INITRAMFS_ROOTFS); + if (cmd_run(false, "cp %s %s", INSTALLER_ELF, dst) == 0) + print_color(COLOR_GREEN, "[initramfs] %s -> rootfs/bin/install-on-disk", + INSTALLER_ELF); + else + print_color(COLOR_RED, "[initramfs] failed to copy installer"); + } + + if (file_exists(SYSROOT_DIR "/usr")) { + print_color(COLOR_CYAN, "[initramfs] Copying sysroot -> rootfs/usr..."); + ensure_dir(INITRAMFS_ROOTFS "/usr"); + if (cmd_run(false, "cp -r " SYSROOT_DIR "/usr/. %s/usr/", + INITRAMFS_ROOTFS) != 0) { + print_color(COLOR_RED, "[initramfs] Failed to copy sysroot"); + return false; + } + print_color(COLOR_GREEN, "[initramfs] sysroot installed into rootfs/usr/"); + } else { + print_color(COLOR_YELLOW, + "[initramfs] " SYSROOT_DIR "/usr not found - skipping sysroot " + "(did libcervus.a build fail?)"); + } + + FILE *readme = fopen(INITRAMFS_ROOTFS "/home/readme.txt", "w"); + if (readme) { + fprintf(readme, + "Cervus OS v0.0.2\n" + "================\n" + "\n" + "This is Cervus - an x86_64 OS written in C.\n" + "Bootloader: Limine | Filesystem: ext2\n" + "\n" + "Built-in shell commands:\n" + " help, cd, exit\n" + "\n" + "Programs in /bin (always available):\n" + " ls, cat, echo, pwd, clear, uname, meminfo, cpuinfo\n" + "\n" + "Programs in /apps (run from /apps dir):\n" + " hello, calc, cal, date, ps, uptime, find, stat,\n" + " hexdump, kill, wc, yes, sleep, ...\n" + "\n" + "Persistent storage:\n" + " /mnt/home - user home directory (ext2)\n" + " /mnt/usr - sysroot for libraries and headers\n" + " /mnt/tmp - temporary files (persistent)\n" + "\n" + "Source: https://github.com/VeoQeo/Cervus\n" + ); + fclose(readme); + print_color(COLOR_GREEN, "[initramfs] created /home/readme.txt"); + } + + FILE *welcome = fopen(INITRAMFS_ROOTFS "/home/welcome.txt", "w"); + if (welcome) { + fprintf(welcome, + "Welcome to Cervus Shell!\n" + "\n" + "Tips:\n" + " - Use arrow keys to move cursor within a command\n" + " - Use Up/Down to browse command history (max 20)\n" + " - Type 'ls' to list files, 'cat ' to read .txt files\n" + " - Binaries are in /bin and /apps\n" + ); + fclose(welcome); + print_color(COLOR_GREEN, "[initramfs] created /home/welcome.txt"); + } + + ensure_dir(INITRAMFS_ROOTFS "/boot"); + + struct { const char *src; const char *dst; bool required; } boot_items[] = { + { "bin/kernel", INITRAMFS_ROOTFS "/boot/kernel", true }, + { SHELL_ELF, INITRAMFS_ROOTFS "/boot/shell.elf", true }, + { "limine/limine-bios.sys", INITRAMFS_ROOTFS "/boot/limine-bios.sys", false }, + { "limine/limine-bios-hdd.bin", INITRAMFS_ROOTFS "/boot/limine-bios-hdd.bin", false }, + { "limine/BOOTX64.EFI", INITRAMFS_ROOTFS "/boot/BOOTX64.EFI", false }, + { "limine/BOOTIA32.EFI", INITRAMFS_ROOTFS "/boot/BOOTIA32.EFI", false }, + { WALLPAPER_SRC, INITRAMFS_ROOTFS "/boot/wallpaper.png", false }, + { NULL, NULL, false } + }; + for (int i = 0; boot_items[i].src; i++) { + if (!file_exists(boot_items[i].src)) { + if (boot_items[i].required) { + print_color(COLOR_RED, "[initramfs] missing required boot file: %s", boot_items[i].src); + return false; + } + print_color(COLOR_YELLOW, "[initramfs] skip (not built yet): %s", boot_items[i].src); + continue; + } + if (cmd_run(false, "cp %s %s", boot_items[i].src, boot_items[i].dst) != 0) { + print_color(COLOR_RED, "[initramfs] failed to copy %s", boot_items[i].src); + if (boot_items[i].required) return false; + } else { + print_color(COLOR_GREEN, "[initramfs] %s -> %s", + boot_items[i].src, boot_items[i].dst); + } + } + + print_color(COLOR_CYAN, "[initramfs] Packing %s...", INITRAMFS_TAR); + if (cmd_run(false, + "tar --format=ustar -cf %s -C %s .", + INITRAMFS_TAR, INITRAMFS_ROOTFS) != 0) { + print_color(COLOR_RED, "[initramfs] tar failed"); + return false; + } + + print_color(COLOR_GREEN, "[initramfs] Contents of %s:", INITRAMFS_TAR); + cmd_run(false, "tar -tvf %s", INITRAMFS_TAR); + + print_color(COLOR_GREEN, "[initramfs] %s built successfully", INITRAMFS_TAR); + return true; +} + +typedef struct { + char **paths; + int count; + int capacity; +} FileList; + +void file_list_add(FileList *list, const char *path) { + if (list->count >= list->capacity) { + list->capacity = list->capacity == 0 ? 16 : list->capacity * 2; + list->paths = realloc(list->paths, list->capacity * sizeof(char *)); + } + list->paths[list->count++] = strdup(path); +} + +void find_src_files(const char *root_dir, FileList *list) { + DIR *dir; + struct dirent *entry; + if (!(dir = opendir(root_dir))) return; + + while ((entry = readdir(dir)) != NULL) { + if (entry->d_type == DT_DIR) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 || + strcmp(entry->d_name, ".git") == 0) continue; + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/%s", root_dir, entry->d_name); + find_src_files(path, list); + } else { + const char *ext = strrchr(entry->d_name, '.'); + if (ext && (strcmp(ext, ".c") == 0 || strcmp(ext, ".asm") == 0 || + strcmp(ext, ".S") == 0 || strcmp(ext, ".psf") == 0)) { + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/%s", root_dir, entry->d_name); + file_list_add(list, path); + } + } + } + closedir(dir); +} + +bool is_sse_file(const char *filename) { + for (int i = 0; SSE_FILES[i] != NULL; i++) + if (strstr(filename, SSE_FILES[i]) != NULL) return true; + return false; +} + +bool compile_kernel(void) { + print_color(COLOR_GREEN, "Compiling kernel..."); + ensure_linker_script(); + if (!setup_dependencies()) return false; + + if (!build_libcervus()) return false; + if (!build_tcc()) return false; + + if (!build_all_apps()) return false; + if (!build_all_bin_apps()) return false; + + if (!build_installer()) return false; + + ensure_dir("bin"); + ensure_dir("obj/kernel"); + ensure_dir("obj/libc"); + + const char *base_cflags = + "-g -O2 -pipe -Wall -Wextra -std=gnu11 -nostdinc -ffreestanding " + "-fno-stack-protector -fno-stack-check -fno-lto -fno-PIC " + "-ffunction-sections -fdata-sections " + "-m64 -march=x86-64 -mabi=sysv -mcmodel=kernel " + "-mno-red-zone -mgeneral-regs-only -fcf-protection=none"; + + const char *sse_base_cflags = + "-g -O2 -pipe -Wall -Wextra -std=gnu11 -nostdinc -ffreestanding " + "-fno-stack-protector -fno-stack-check -fno-lto -fno-PIC " + "-ffunction-sections -fdata-sections " + "-m64 -march=x86-64 -mabi=sysv -mcmodel=kernel " + "-mno-red-zone -fcf-protection=none"; + + const char *core_cflags = "-mno-sse -mno-sse2 -mno-mmx -mno-3dnow"; + const char *sse_cflags = "-msse -msse2 -mfpmath=sse -mno-mmx -mno-3dnow"; + + char cppflags[2048]; + snprintf(cppflags, sizeof(cppflags), + "-I kernel/src" + " -I libc/include" + " -I limine-tools/limine-protocol/include" + " -isystem limine-tools/freestnd-c-hdrs/include" + " -MMD -MP"); + + FileList sources = {0}; + if (file_exists("kernel/src")) find_src_files("kernel/src", &sources); + if (file_exists("libc/src")) find_src_files("libc/src", &sources); + + FileList objects = {0}; + bool failed = false; + + for (int i = 0; i < sources.count; i++) { + char *src = sources.paths[i]; + + char category[16] = "other"; + if (strncmp(src, "kernel/", 7) == 0) strcpy(category, "kernel"); + else if (strncmp(src, "libc/", 5) == 0) strcpy(category, "libc"); + + char obj_path[PATH_MAX]; + char flat[PATH_MAX]; + strcpy(flat, src); + for (int j = 0; flat[j]; j++) + if (flat[j] == '/' || flat[j] == '.') flat[j] = '_'; + snprintf(obj_path, sizeof(obj_path), "obj/%s/%s.o", category, flat); + file_list_add(&objects, obj_path); + + if (file_exists(obj_path) && get_mtime(src) <= get_mtime(obj_path) + && get_mtime("builder/build.c") <= get_mtime(obj_path)) continue; + + const char *ext = strrchr(src, '.'); + + if (strcmp(ext, ".psf") == 0) { + print_color(COLOR_BLUE, "Converting binary: %s", src); + char tmp[PATH_MAX]; + snprintf(tmp, sizeof(tmp), "temp_%s", strrchr(src, '/') + 1); + cmd_run(false, "cp %s %s", src, tmp); + cmd_run(false, "objcopy -I binary -O elf64-x86-64 -B i386:x86-64 " + "--rename-section .data=.rodata,alloc,load,readonly,data,contents " + "%s %s", tmp, obj_path); + remove(tmp); + char stem[256]; + strcpy(stem, strrchr(src, '/') + 1); + *strrchr(stem, '.') = '\0'; + char rsym[1024]; + snprintf(rsym, sizeof(rsym), + "--redefine-sym _binary_temp_%s_psf_start=_binary_%s_psf_start " + "--redefine-sym _binary_temp_%s_psf_end=_binary_%s_psf_end " + "--redefine-sym _binary_temp_%s_psf_size=_binary_%s_psf_size", + stem, stem, stem, stem, stem, stem); + cmd_run(false, "objcopy %s %s", rsym, obj_path); + + } else if (strcmp(ext, ".asm") == 0) { + print_color(COLOR_CYAN, "[asm] %s", src); + if (cmd_run(false, "nasm -g -F dwarf -f elf64 %s -o %s", src, obj_path) != 0) + failed = true; + + } else { + bool sse = is_sse_file(src); + char flags[1024]; + snprintf(flags, sizeof(flags), "%s %s", + sse ? sse_base_cflags : base_cflags, + sse ? sse_cflags : core_cflags); + print_color(sse ? COLOR_MAGENTA : COLOR_CYAN, "[%s] %s", category, src); + if (cmd_run(false, "gcc %s %s -c %s -o %s", + flags, cppflags, src, obj_path) != 0) + failed = true; + } + } + + if (failed) return false; + + print_color(COLOR_BLUE, "Linking kernel..."); + char ld_cmd[65536]; + snprintf(ld_cmd, sizeof(ld_cmd), + "ld -m elf_x86_64 -nostdlib -static -z max-page-size=0x1000 " + "--gc-sections -T kernel/linker-scripts/x86_64.lds -o bin/kernel"); + for (int i = 0; i < objects.count; i++) { + strcat(ld_cmd, " "); + strcat(ld_cmd, objects.paths[i]); + } + if (system(ld_cmd) != 0) return false; + + print_color(COLOR_GREEN, "Kernel linked: bin/kernel"); + return true; +} + +bool create_iso(void) { + print_color(COLOR_GREEN, "Creating ISO..."); + if (!build_limine()) return false; + if (!file_exists("bin/kernel")) { + print_color(COLOR_RED, "bin/kernel not found!"); + return false; + } + + rm_rf("iso_root"); + ensure_dir("iso_root/boot/limine"); + ensure_dir("iso_root/boot/wallpapers"); + ensure_dir("iso_root/EFI/BOOT"); + ensure_dir("demo_iso"); + + if (file_exists(WALLPAPER_SRC)) { + cmd_run(false, "cp %s iso_root/boot/wallpapers/cervus.png", WALLPAPER_SRC); + print_color(COLOR_GREEN, "Wallpaper copied"); + } else { + print_color(COLOR_YELLOW, "Warning: wallpaper not found at %s", WALLPAPER_SRC); + } + + cmd_run(false, "cp bin/kernel iso_root/boot/kernel"); + + bool has_elf = file_exists(SHELL_ELF); + if (has_elf) { + cmd_run(false, "cp %s iso_root/boot/shell.elf", SHELL_ELF); + print_color(COLOR_GREEN, "[module 0] shell.elf -> iso_root/boot/shell.elf"); + } else { + print_color(COLOR_RED, "[module 0] shell.elf not found - boot will fail!"); + } + + bool has_initramfs = !ARG_NO_INITRAMFS && file_exists(INITRAMFS_TAR); + if (has_initramfs) { + cmd_run(false, "cp %s iso_root/boot/initramfs.tar", INITRAMFS_TAR); + print_color(COLOR_GREEN, "[module 1] initramfs.tar -> iso_root/boot/initramfs.tar"); + } else { + print_color(COLOR_YELLOW, "[module 1] initramfs.tar not found - booting without rootfs"); + } + + FILE *f = fopen("limine.conf", "w"); + if (!f) { print_color(COLOR_RED, "Cannot create limine.conf"); return false; } + + if (file_exists(WALLPAPER_SRC)) + fprintf(f, "wallpaper: %s\n", WALLPAPER_DST); + + fprintf(f, "timeout: 5\n\n"); + + fprintf(f, + "/%s %s (Install / Live)\n" + " protocol: limine\n" + " path: boot():/boot/kernel\n", + IMAGE_NAME, VERSION); + + if (has_elf) { + fprintf(f, + " module_path: boot():/boot/shell.elf\n" + " module_cmdline: init\n"); + } + if (has_initramfs) { + fprintf(f, + " module_path: boot():/boot/initramfs.tar\n" + " module_cmdline: initramfs\n"); + } + + fclose(f); + + print_color(COLOR_CYAN, "--- limine.conf ---"); + cmd_run(false, "cat limine.conf"); + print_color(COLOR_CYAN, "-------------------"); + + cmd_run(false, "cp limine.conf iso_root/boot/limine/"); + cmd_run(false, "cp limine/limine-bios.sys limine/limine-bios-cd.bin " + "limine/limine-uefi-cd.bin iso_root/boot/limine/"); + cmd_run(false, "cp limine/BOOTX64.EFI limine/BOOTIA32.EFI iso_root/EFI/BOOT/"); + + char timestamp[64]; + time_t t = time(NULL); + strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", localtime(&t)); + + char iso_name[PATH_MAX]; + snprintf(iso_name, sizeof(iso_name), + "demo_iso/%s.%s.%s.iso", IMAGE_NAME, VERSION, timestamp); + + char xorriso[PATH_MAX + 1024]; + snprintf(xorriso, sizeof(xorriso), + "xorriso -as mkisofs -R -r -J" + " -b boot/limine/limine-bios-cd.bin" + " -no-emul-boot -boot-load-size 4 -boot-info-table" + " -hfsplus -apm-block-size 2048" + " --efi-boot boot/limine/limine-uefi-cd.bin" + " -efi-boot-part --efi-boot-image --protective-msdos-label" + " iso_root -o %s", iso_name); + + if (cmd_run(true, xorriso) != 0) return false; + cmd_run(true, "./limine/limine bios-install %s", iso_name); + + char link[PATH_MAX]; + snprintf(link, sizeof(link), "demo_iso/%s.latest.iso", IMAGE_NAME); + unlink(link); + (void)!symlink(strrchr(iso_name, '/') + 1, link); + + rm_rf("iso_root"); + + print_color(COLOR_GREEN, "ISO ready: %s", iso_name); + return true; +} + +void check_sudo(void) { + if (geteuid() != 0) { + print_color(COLOR_RED, "This command requires root. Run with sudo."); + exit(1); + } +} + +void list_iso_files(FileList *list) { + DIR *dir = opendir("demo_iso"); + if (!dir) return; + struct dirent *e; + while ((e = readdir(dir)) != NULL) { + if (strstr(e->d_name, ".iso")) { + char path[PATH_MAX]; + snprintf(path, sizeof(path), "demo_iso/%s", e->d_name); + file_list_add(list, path); + } + } + closedir(dir); +} + +void list_usb_devices(FileList *list) { + DIR *dir = opendir("/sys/block"); + if (!dir) return; + struct dirent *e; + while ((e = readdir(dir)) != NULL) { + if (e->d_name[0] == '.') continue; + char path[PATH_MAX]; + snprintf(path, sizeof(path), "/sys/block/%s/removable", e->d_name); + FILE *f = fopen(path, "r"); + if (f) { + int removable = 0; + if (fscanf(f, "%d", &removable) == 1 && removable) { + char dev[PATH_MAX]; + snprintf(dev, sizeof(dev), "/dev/%s", e->d_name); + file_list_add(list, dev); + } + fclose(f); + } + } + closedir(dir); +} + +void flash_iso(void) { + check_sudo(); + FileList isos = {0}, devs = {0}; + list_iso_files(&isos); + if (isos.count == 0) { print_color(COLOR_RED, "No ISO found in demo_iso/"); return; } + + printf("\n%s--- SELECT ISO ---%s\n", COLOR_CYAN, COLOR_RESET); + for (int i = 0; i < isos.count; i++) printf("[%d] %s\n", i + 1, isos.paths[i]); + int ic; printf("Choice: "); + if (scanf("%d", &ic) < 1 || ic < 1 || ic > isos.count) return; + + list_usb_devices(&devs); + if (devs.count == 0) { print_color(COLOR_RED, "No removable USB devices found!"); return; } + + printf("\n%s--- SELECT DEVICE ---%s\n", COLOR_RED, COLOR_RESET); + for (int i = 0; i < devs.count; i++) { + char mpath[PATH_MAX], model[256] = "Unknown"; + snprintf(mpath, sizeof(mpath), "/sys/block/%s/device/model", devs.paths[i] + 5); + FILE *mf = fopen(mpath, "r"); + if (mf) { if (fgets(model, sizeof(model), mf)) model[strcspn(model, "\n")] = 0; fclose(mf); } + printf("[%d] %s (%s)\n", i + 1, devs.paths[i], model); + } + int dc; printf("Choice: "); + if (scanf("%d", &dc) < 1 || dc < 1 || dc > devs.count) return; + + printf("\n%sWARNING: ALL DATA ON %s WILL BE ERASED!%s\n", + COLOR_BOLD, devs.paths[dc - 1], COLOR_RESET); + printf("Type 'YES' to confirm: "); + char confirm[10]; + if (scanf("%9s", confirm) != 1) { printf("Aborted.\n"); return; } + if (strcmp(confirm, "YES") != 0) { printf("Aborted.\n"); return; } + + print_color(COLOR_YELLOW, "Flashing %s -> %s ...", isos.paths[ic - 1], devs.paths[dc - 1]); + cmd_run(true, "dd if=%s of=%s bs=4M status=progress oflag=sync", + isos.paths[ic - 1], devs.paths[dc - 1]); + print_color(COLOR_GREEN, "Done!"); +} + +bool is_unreadable_file(const char *filename) { + const char *skip_names[] = { "TODO", "LICENSE", "build", NULL }; + for (int i = 0; skip_names[i]; i++) + if (strcmp(filename, skip_names[i]) == 0) return true; + + const char *ext = strrchr(filename, '.'); + if (!ext) return false; + + const char *bin_exts[] = { + ".psf", ".jpg", ".png", ".jpeg", ".iso", ".hdd", ".img", + ".bin", ".elf", ".o", ".txt", ".md", ".gitignore", ".json", + ".tar", + NULL + }; + for (int i = 0; bin_exts[i]; i++) + if (strcasecmp(ext, bin_exts[i]) == 0) return true; + return false; +} + +void generate_tree_recursive(const char *base_dir, FILE *out, int level) { + struct dirent **namelist; + int n = scandir(base_dir, &namelist, NULL, alphasort); + if (n < 0) return; + + const char *skip_dirs[] = { + "wallpapers", "demo_iso", ".vscode", "builder", + INITRAMFS_ROOTFS, + NULL + }; + + for (int i = 0; i < n; i++) { + const char *name = namelist[i]->d_name; + + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0 || + strcmp(name, ".git") == 0 || strcmp(name, "obj") == 0 || + strcmp(name, "bin") == 0 || strcmp(name, "limine") == 0) { + free(namelist[i]); continue; + } + + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/%s", base_dir, name); + struct stat st; + stat(path, &st); + + if (S_ISDIR(st.st_mode)) { + bool skip = false; + for (int j = 0; skip_dirs[j]; j++) + if (strcmp(name, skip_dirs[j]) == 0) { skip = true; break; } + if (skip) { free(namelist[i]); continue; } + } + + if (!S_ISDIR(st.st_mode) && is_unreadable_file(name)) { + free(namelist[i]); continue; + } + + for (int j = 0; j < level; j++) fprintf(out, "| "); + + if (S_ISDIR(st.st_mode)) { + fprintf(out, "+-- %s/\n", name); + generate_tree_recursive(path, out, level + 1); + } else { + fprintf(out, "+-- %s (%ld bytes)\n", name, st.st_size); + if (!ARG_STRUCTURE_ONLY && should_print_content(name)) { + FILE *src = fopen(path, "r"); + if (src) { + char line[4096]; int ln = 1; + while (fgets(line, sizeof(line), src) && ln <= 5000) { + for (int j = 0; j <= level; j++) fprintf(out, "| "); + fprintf(out, "| %4d: %s", ln++, line); + } + fclose(src); + } + } + } + free(namelist[i]); + } + free(namelist); +} + +void do_generate_tree(void) { + FILE *f = fopen("OS-TREE.txt", "w"); + if (!f) return; + time_t t = time(NULL); + fprintf(f, "OS Tree - %s %s | %s", IMAGE_NAME, VERSION, ctime(&t)); + generate_tree_recursive(".", f, 0); + fclose(f); + print_color(COLOR_GREEN, "Tree generated to OS-TREE.txt"); +} + +static bool limine_conf_has_cervus(const char *path) { + FILE *f = fopen(path, "r"); + if (!f) return false; + char line[1024]; + while (fgets(line, sizeof(line), f)) { + if (strstr(line, CERVUS_MARKER)) { fclose(f); return true; } + } + fclose(f); + return false; +} + +static bool __attribute__((unused)) copy_file_raw(const char *src, const char *dst) { + FILE *in = fopen(src, "r"); + if (!in) return false; + FILE *out = fopen(dst, "w"); + if (!out) { fclose(in); return false; } + char buf[4096]; + size_t n; + while ((n = fread(buf, 1, sizeof(buf), in)) > 0) + fwrite(buf, 1, n, out); + fclose(in); + fclose(out); + return true; +} + +static bool ask_yes_no(const char *question) { + printf("%s%s [y/n]: %s", COLOR_YELLOW, question, COLOR_RESET); + fflush(stdout); + char buf[16]; + if (!fgets(buf, sizeof(buf), stdin)) return false; + return (buf[0] == 'y' || buf[0] == 'Y'); +} + +void reset_hardware_conf(void) { + check_sudo(); + + if (!file_exists(LIMINE_CONF_BACKUP)) { + print_color(COLOR_RED, "No backup found at %s", LIMINE_CONF_BACKUP); + print_color(COLOR_RED, "Nothing to restore. Was hardwaretest ever run?"); + return; + } + + print_color(COLOR_CYAN, "Restoring original Limine configuration..."); + + if (cmd_run(true, "cp %s %s", LIMINE_CONF_BACKUP, LIMINE_CONF_PATH) != 0) { + print_color(COLOR_RED, "Failed to restore %s", LIMINE_CONF_PATH); + return; + } + + print_color(COLOR_GREEN, "Original limine.conf restored from backup"); + + if (file_exists(CERVUS_BOOT_DIR)) { + print_color(COLOR_CYAN, "Removing %s ...", CERVUS_BOOT_DIR); + cmd_run(true, "rm -rf %s", CERVUS_BOOT_DIR); + } + + print_color(COLOR_GREEN, "Hardware configuration reset complete"); + print_color(COLOR_CYAN, "--- Current limine.conf ---"); + cmd_run(false, "cat %s", LIMINE_CONF_PATH); + print_color(COLOR_CYAN, "---------------------------"); + + if (ask_yes_no("Reboot now?")) { + print_color(COLOR_YELLOW, "Rebooting..."); + cmd_run(false, "reboot"); + } +} + +static void write_cervus_entries(FILE *f, bool has_elf, bool has_initramfs) { + if (file_exists(WALLPAPER_SRC)) + fprintf(f, "wallpaper: boot():/cervus/wallpaper.png\n"); + + fprintf(f, + "/%s %s (Install / Live)\n" + " protocol: limine\n" + " path: boot():/cervus/kernel\n", + IMAGE_NAME, VERSION); + if (has_elf) { + fprintf(f, + " module_path: boot():/cervus/shell.elf\n" + " module_cmdline: init\n"); + } + if (has_initramfs) { + fprintf(f, + " module_path: boot():/cervus/initramfs.tar\n" + " module_cmdline: initramfs\n"); + } + + fprintf(f, + "/%s %s (Installed - boot from disk)\n" + " protocol: limine\n" + " path: boot():/cervus/kernel\n", + IMAGE_NAME, VERSION); + if (has_elf) { + fprintf(f, + " module_path: boot():/cervus/shell.elf\n" + " module_cmdline: init\n"); + } +} + +void hardware_test(void) { + check_sudo(); + + if (!file_exists(LIMINE_CONF_PATH)) { + print_color(COLOR_RED, "Limine config not found at %s", LIMINE_CONF_PATH); + print_color(COLOR_RED, "Is Limine installed as your bootloader?"); + print_color(COLOR_YELLOW, "Expected path: %s", LIMINE_CONF_PATH); + print_color(COLOR_YELLOW, "Install Limine first: https://github.com/limine-bootloader/limine"); + return; + } + + print_color(COLOR_GREEN, "=== Cervus Hardware Test Setup ==="); + print_color(COLOR_CYAN, "Limine config found: %s", LIMINE_CONF_PATH); + + print_color(COLOR_CYAN, "Step 1: Building Cervus..."); + + if (!compile_kernel()) { + print_color(COLOR_RED, "Kernel compilation failed"); + return; + } + + if (!build_initramfs()) { + print_color(COLOR_RED, "initramfs build failed"); + return; + } + + if (!file_exists("bin/kernel")) { + print_color(COLOR_RED, "bin/kernel not found after build!"); + return; + } + + print_color(COLOR_CYAN, "Step 2: Checking Limine configuration..."); + + bool already_has_cervus = limine_conf_has_cervus(LIMINE_CONF_PATH); + + if (already_has_cervus) { + print_color(COLOR_GREEN, "Cervus entry already present in limine.conf"); + print_color(COLOR_CYAN, "Updating boot files only..."); + } else { + print_color(COLOR_CYAN, "No Cervus entry found, will add one"); + + if (!file_exists(LIMINE_CONF_BACKUP)) { + print_color(COLOR_YELLOW, "Step 2a: Backing up original limine.conf..."); + if (cmd_run(true, "cp %s %s", LIMINE_CONF_PATH, LIMINE_CONF_BACKUP) != 0) { + print_color(COLOR_RED, "Failed to backup limine.conf!"); + return; + } + print_color(COLOR_GREEN, "Backup saved: %s", LIMINE_CONF_BACKUP); + print_color(COLOR_YELLOW, "To restore later: ./build --resethardwareconf"); + } else { + print_color(COLOR_GREEN, "Backup already exists: %s", LIMINE_CONF_BACKUP); + } + } + + print_color(COLOR_CYAN, "Step 3: Copying Cervus files to /boot..."); + + cmd_run(true, "mkdir -p %s", CERVUS_BOOT_DIR); + + if (cmd_run(true, "cp bin/kernel %s/kernel", CERVUS_BOOT_DIR) != 0) { + print_color(COLOR_RED, "Failed to copy kernel"); + return; + } + print_color(COLOR_GREEN, " kernel -> %s/kernel", CERVUS_BOOT_DIR); + + bool has_elf = file_exists(SHELL_ELF); + if (has_elf) { + cmd_run(true, "cp %s %s/shell.elf", SHELL_ELF, CERVUS_BOOT_DIR); + print_color(COLOR_GREEN, " shell.elf -> %s/shell.elf", CERVUS_BOOT_DIR); + } + + bool has_initramfs = file_exists(INITRAMFS_TAR); + if (has_initramfs) { + cmd_run(true, "cp %s %s/initramfs.tar", INITRAMFS_TAR, CERVUS_BOOT_DIR); + print_color(COLOR_GREEN, " initramfs.tar -> %s/initramfs.tar", CERVUS_BOOT_DIR); + } + + if (file_exists(WALLPAPER_SRC)) { + cmd_run(true, "cp %s %s/wallpaper.png", WALLPAPER_SRC, CERVUS_BOOT_DIR); + print_color(COLOR_GREEN, " wallpaper -> %s/wallpaper.png", CERVUS_BOOT_DIR); + } + + if (!already_has_cervus) { + print_color(COLOR_CYAN, "Step 4: Adding Cervus entries to limine.conf..."); + + FILE *f = fopen(LIMINE_CONF_PATH, "a"); + if (!f) { + print_color(COLOR_RED, "Cannot open %s for writing", LIMINE_CONF_PATH); + return; + } + + fprintf(f, "\n%s\n", CERVUS_MARKER); + write_cervus_entries(f, has_elf, has_initramfs); + fprintf(f, "%s\n", "# --- END CERVUS ---"); + + fclose(f); + print_color(COLOR_GREEN, "Cervus boot entries added to limine.conf"); + } else { + print_color(COLOR_CYAN, "Step 4: Updating Cervus entries in limine.conf..."); + + FILE *orig = fopen(LIMINE_CONF_PATH, "r"); + if (!orig) { + print_color(COLOR_RED, "Cannot read %s", LIMINE_CONF_PATH); + return; + } + + char tmppath[PATH_MAX]; + snprintf(tmppath, sizeof(tmppath), "%s.tmp", LIMINE_CONF_PATH); + FILE *tmp = fopen(tmppath, "w"); + if (!tmp) { fclose(orig); print_color(COLOR_RED, "Cannot create temp file"); return; } + + char line[1024]; + bool in_cervus = false; + while (fgets(line, sizeof(line), orig)) { + if (strstr(line, CERVUS_MARKER)) { + in_cervus = true; + continue; + } + if (in_cervus && strstr(line, "# --- END CERVUS ---")) { + in_cervus = false; + continue; + } + if (!in_cervus) { + fputs(line, tmp); + } + } + fclose(orig); + + fprintf(tmp, "\n%s\n", CERVUS_MARKER); + write_cervus_entries(tmp, has_elf, has_initramfs); + fprintf(tmp, "%s\n", "# --- END CERVUS ---"); + fclose(tmp); + + cmd_run(false, "mv %s %s", tmppath, LIMINE_CONF_PATH); + print_color(COLOR_GREEN, "Cervus entries updated in limine.conf"); + } + + print_color(COLOR_GREEN, "\n=== Setup Complete ==="); + print_color(COLOR_CYAN, "--- Current limine.conf ---"); + cmd_run(false, "cat %s", LIMINE_CONF_PATH); + print_color(COLOR_CYAN, "---------------------------"); + + print_color(COLOR_GREEN, "\nCervus will appear in your Limine boot menu."); + print_color(COLOR_YELLOW, "First boot: select '%s %s (Install / Live)'", IMAGE_NAME, VERSION); + print_color(COLOR_YELLOW, "After install: select '%s %s (Installed - boot from disk)'", IMAGE_NAME, VERSION); + print_color(COLOR_YELLOW, "To restore original config: sudo ./build --resethardwareconf"); + + if (ask_yes_no("\nReboot now to test on real hardware?")) { + print_color(COLOR_YELLOW, "Rebooting..."); + cmd_run(false, "reboot"); + } else { + print_color(COLOR_GREEN, "OK. Reboot manually when ready."); + } +} + +static const char* find_ovmf(void) { + const char *ovmf_paths[] = { + "/usr/share/edk2/x64/OVMF.4m.fd", + "/usr/share/edk2/x64/OVMF_CODE.4m.fd", + "/usr/share/edk2/ovmf/OVMF.fd", + "/usr/share/edk2/ovmf/OVMF_CODE.fd", + "/usr/share/ovmf/x64/OVMF.fd", + "/usr/share/ovmf/x64/OVMF_CODE.fd", + "/usr/share/ovmf/OVMF.fd", + "/usr/share/OVMF/OVMF.fd", + "/usr/share/OVMF/OVMF_CODE.fd", + "/usr/share/qemu/OVMF.fd", + NULL + }; + for (int i = 0; ovmf_paths[i]; i++) { + if (file_exists(ovmf_paths[i])) return ovmf_paths[i]; + } + return NULL; +} + +static void print_help(void) { + printf("%sCervus OS build system%s\n\n", COLOR_BOLD, COLOR_RESET); + printf("Usage: ./build [command] [options]\n\n"); + printf("Commands:\n"); + printf(" run Build kernel + initramfs + ISO, then launch QEMU (BIOS, with disk)\n"); + printf(" run-uefi Build kernel + initramfs + ISO, then launch QEMU (UEFI, with disk)\n"); + printf(" run-installed Launch QEMU from cervus_disk.img only (BIOS, no ISO, real hardware sim)\n"); + printf(" run-installed-uefi Launch QEMU from cervus_disk.img only (UEFI, no ISO)\n"); + printf(" run-fresh Wipe disk and run installer from ISO again (BIOS)\n"); + printf(" run-fresh-uefi Wipe disk and run installer from ISO again (UEFI)\n"); + printf(" hardwaretest Build & install Cervus into Limine boot menu (requires sudo)\n"); + printf(" flash Flash latest ISO to USB device (requires sudo)\n"); + printf(" clean Remove all build artifacts\n"); + printf(" cleaniso Remove only ISO images in demo_iso/\n"); + printf(" gitclean Same as clean (for git commit prep)\n"); + printf(" help Show this message\n\n"); + printf("Subcomponent build (debug):\n"); + printf(" _libcervus Build only libcervus.a + crt0.o into sysroot\n"); + printf(" _tcc Build only TCC (and libcervus first) into sysroot\n\n"); + printf("Options:\n"); + printf(" --tree [files] Generate OS-TREE.txt (optional: only list files)\n"); + printf(" --structure-only Generate tree without file contents\n"); + printf(" --no-clean Keep obj/ and bin/ after run\n"); + printf(" --no-initramfs Skip initramfs.tar creation\n"); + printf(" --reset-disk Re-create empty disk image\n"); + printf(" --live Run without disk (Live Mode, BIOS only)\n"); + printf(" --resethardwareconf Restore original Limine config (requires sudo)\n\n"); + printf("Boot entries in Limine menu:\n"); + printf(" Install / Live - first boot, runs installer, uses initramfs\n"); + printf(" Installed - boot from disk - after install, no initramfs, uses ext2 disk\n\n"); + printf("Hardware test workflow:\n"); + printf(" sudo ./build hardwaretest # build, install to /boot, add boot entries\n"); + printf(" sudo ./build --resethardwareconf # restore original bootloader config\n\n"); + printf("UEFI Requirements:\n"); + printf(" Install OVMF: sudo apt install ovmf (Debian/Ubuntu) or equivalent\n\n"); + printf("Examples:\n"); + printf(" ./build run # normal boot with disk (BIOS)\n"); + printf(" ./build run-uefi # normal boot with disk (UEFI)\n"); + printf(" ./build run --live # boot without disk (Live Mode, BIOS)\n"); + printf(" ./build run-fresh-uefi # fresh disk, boot installer (UEFI)\n"); + printf(" ./build run --reset-disk # fresh disk (BIOS)\n"); + printf(" ./build run --tree\n"); + printf(" ./build --tree kernel.c vfs.c\n"); +} + +int main(int argc, char **argv) { + char *command = NULL; + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--tree") == 0) { + ARG_TREE = true; + int j = i + 1; + while (j < argc && argv[j][0] != '-') add_tree_file(argv[j++]); + i = j - 1; + } else if (strcmp(argv[i], "--structure-only") == 0) { + ARG_STRUCTURE_ONLY = true; + } else if (strcmp(argv[i], "--no-clean") == 0) { + ARG_NO_CLEAN = true; + } else if (strcmp(argv[i], "--no-initramfs") == 0) { + ARG_NO_INITRAMFS = true; + } else if (strcmp(argv[i], "--resethardwareconf") == 0) { + ARG_RESET_HW_CONF = true; + } else if (strcmp(argv[i], "--reset-disk") == 0) { + ARG_RESET_DISK = true; + } else if (strcmp(argv[i], "--live") == 0) { + ARG_LIVE = true; + } else if (argv[i][0] != '-') { + command = argv[i]; + } + } + + if (ARG_TREE && !command) { do_generate_tree(); return 0; } + + if (ARG_RESET_HW_CONF) { + reset_hardware_conf(); + return 0; + } + + if (!command || strcmp(command, "help") == 0) { + print_help(); + return 0; + } + + if (strcmp(command, "clean") == 0 || strcmp(command, "gitclean") == 0) { + for (int i = 0; DIRS_TO_CLEAN[i]; i++) rm_rf(DIRS_TO_CLEAN[i]); + clean_apps_elfs(); + clean_bin_elfs(); + for (int i = 0; FILES_TO_CLEAN[i]; i++) + if (file_exists(FILES_TO_CLEAN[i])) remove(FILES_TO_CLEAN[i]); + clean_libcervus_build(true); + clean_tcc_build(true); + cmd_run(false, "rm -f " INSTALLER_DIR "/*.elf 2>/dev/null"); + cmd_run(false, "rm -f temp_* 2>/dev/null"); + print_color(COLOR_GREEN, "Cleanup complete"); + return 0; + } + + if (strcmp(command, "cleaniso") == 0) { + rm_rf("demo_iso"); + ensure_dir("demo_iso"); + return 0; + } + + if (strcmp(command, "flash") == 0) { + flash_iso(); + return 0; + } + + if (strcmp(command, "hardwaretest") == 0) { + hardware_test(); + return 0; + } + + if (strcmp(command, "_libcervus") == 0) { + return build_libcervus() ? 0 : 1; + } + if (strcmp(command, "_tcc") == 0) { + if (!build_libcervus()) return 1; + return build_tcc() ? 0 : 1; + } + + if (strcmp(command, "run-installed-uefi") == 0) { + if (!file_exists("cervus_disk.img")) { + print_color(COLOR_RED, "cervus_disk.img not found. Run './build run' first."); + return 1; + } + const char *ovmf = find_ovmf(); + if (!ovmf) { + print_color(COLOR_RED, "OVMF not found. Install: sudo apt install ovmf"); + return 1; + } + print_color(COLOR_GREEN, "Starting QEMU with UEFI firmware from disk only..."); + print_color(COLOR_GREEN, "Using OVMF: %s", ovmf); + cmd_run(false, + "GDK_BACKEND=x11 qemu-system-x86_64 -machine pc" + " -bios %s" + " -drive file=cervus_disk.img,format=raw,if=ide" + " -serial stdio" + " -m 8G -smp 8 -cpu qemu64,+fsgsbase -display gtk,grab-on-hover=on" + " 2>&1 | tee log.txt", + ovmf); + return 0; + } + + if (strcmp(command, "run-installed") == 0) { + if (!file_exists("cervus_disk.img")) { + print_color(COLOR_RED, "cervus_disk.img not found. " + "Run './build run' first to build and install Cervus."); + return 1; + } + print_color(COLOR_CYAN, "Starting QEMU from disk only (no ISO, simulates real hardware)..."); + cmd_run(false, + "GDK_BACKEND=x11 qemu-system-x86_64 -machine pc" + " -drive file=cervus_disk.img,format=raw,if=ide" + " -serial stdio" + " -m 8G -smp 8 -cpu qemu64,+fsgsbase -display gtk,grab-on-hover=on" + " 2>&1 | tee log.txt"); + return 0; + } + + if (strcmp(command, "run-fresh") == 0) { + ARG_RESET_DISK = true; + command = "run"; + } + + if (strcmp(command, "run-fresh-uefi") == 0) { + ARG_RESET_DISK = true; + command = "run-uefi"; + } + + if (strcmp(command, "run") == 0 || strcmp(command, "run-uefi") == 0) { + bool use_uefi = (strcmp(command, "run-uefi") == 0); + + if (!compile_kernel()) { + print_color(COLOR_RED, "Kernel compilation failed"); + return 1; + } + + if (!build_initramfs()) { + print_color(COLOR_RED, "initramfs build failed"); + return 1; + } + + if (!create_iso()) { + print_color(COLOR_RED, "ISO creation failed"); + return 1; + } + + if (ARG_TREE) do_generate_tree(); + + char iso_path[PATH_MAX]; + snprintf(iso_path, sizeof(iso_path), "demo_iso/%s.latest.iso", IMAGE_NAME); + + if (use_uefi) { + const char *ovmf = find_ovmf(); + if (!ovmf) { + print_color(COLOR_RED, "OVMF not found. Install: sudo apt install ovmf"); + return 1; + } + print_color(COLOR_GREEN, "Using OVMF: %s", ovmf); + } + + if (ARG_LIVE && !use_uefi) { + print_color(COLOR_CYAN, "Starting QEMU in Live Mode (no disk, BIOS)..."); + cmd_run(false, + "GDK_BACKEND=x11 qemu-system-x86_64 -machine pc" + " -cdrom %s -boot d" + " -serial stdio" + " -m 8G -smp 8 -cpu qemu64,+fsgsbase -display gtk,grab-on-hover=on" + " 2>&1 | tee log.txt", + iso_path); + } else if (ARG_LIVE && use_uefi) { + print_color(COLOR_RED, "Live mode (--live) is not supported in UEFI mode yet"); + return 1; + } else { + if (!file_exists("cervus_disk.img") || ARG_RESET_DISK) { + if (ARG_RESET_DISK && file_exists("cervus_disk.img")) { + print_color(COLOR_YELLOW, "[disk] --reset-disk: removing old disk image"); + remove("cervus_disk.img"); + } + print_color(COLOR_CYAN, "Creating empty disk image (256MB)..."); + cmd_run(false, "dd if=/dev/zero of=cervus_disk.img bs=1M count=256 2>/dev/null"); + print_color(COLOR_GREEN, "Disk created (OS installer will format on first boot)"); + } else { + print_color(COLOR_GREEN, "Using existing cervus_disk.img (persistent data)"); + } + + if (use_uefi) { + const char *ovmf = find_ovmf(); + print_color(COLOR_GREEN, "Starting QEMU with UEFI firmware (IDE mode)..."); + cmd_run(false, + "GDK_BACKEND=x11 qemu-system-x86_64 -machine pc" + " -bios %s" + " -cdrom %s -boot d" + " -serial stdio" + " -m 8G -smp 8 -cpu qemu64,+fsgsbase -display gtk,grab-on-hover=on" + " -drive file=cervus_disk.img,format=raw,if=ide,index=0,media=disk" + " 2>&1 | tee log.txt", + ovmf, iso_path); + } else { + print_color(COLOR_GREEN, "Starting QEMU with BIOS..."); + cmd_run(false, + "GDK_BACKEND=x11 qemu-system-x86_64 -machine pc" + " -cdrom %s -boot d" + " -serial stdio" + " %s" + " 2>&1 | tee log.txt", + iso_path, QEMUFLAGS); + } + } + + if (!ARG_NO_CLEAN) { + print_color(COLOR_CYAN, "[post-run] Cleaning build artifacts..."); + rm_rf("obj"); + rm_rf("bin"); + rm_rf(INITRAMFS_ROOTFS); + if (file_exists(INITRAMFS_TAR)) { + remove(INITRAMFS_TAR); + print_color(COLOR_GREEN, "[post-run] removed %s", INITRAMFS_TAR); + } + clean_apps_elfs(); + clean_bin_elfs(); + clean_libcervus_build(false); + clean_tcc_build(false); + print_color(COLOR_GREEN, "[post-run] Done."); + } + return 0; + } + + print_color(COLOR_RED, "Unknown command: %s (try: ./build help)", command); + return 1; +} \ No newline at end of file diff --git a/kernel/include/acpi/acpi.h b/kernel/include/acpi/acpi.h new file mode 100644 index 0000000..cdf54c8 --- /dev/null +++ b/kernel/include/acpi/acpi.h @@ -0,0 +1,199 @@ +#ifndef ACPI_H +#define ACPI_H + +#include +#include +#include +#include + +typedef struct { + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oem_id[6]; + char oem_table_id[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; +} __attribute__((packed)) acpi_sdt_header_t; + +typedef struct { + char signature[8]; + uint8_t checksum; + char oem_id[6]; + uint8_t revision; + uint32_t rsdt_address; +} __attribute__((packed)) acpi_rsdp_t; + +typedef struct { + acpi_rsdp_t rsdp_v1; + uint32_t length; + uint64_t xsdt_address; + uint8_t extended_checksum; + uint8_t reserved[3]; +} __attribute__((packed)) acpi_rsdp2_t; + +typedef struct { + acpi_sdt_header_t header; + uint32_t sdt_pointers[]; +} __attribute__((packed)) acpi_rsdt_t; + +typedef struct { + acpi_sdt_header_t header; + uint64_t sdt_pointers[]; +} __attribute__((packed)) acpi_xsdt_t; + +typedef struct { + uint8_t address_space_id; + uint8_t register_bit_width; + uint8_t register_bit_offset; + uint8_t access_size; + uint64_t address; +} __attribute__((packed)) acpi_gas_t; + +typedef struct { + acpi_sdt_header_t header; + uint32_t firmware_ctrl; + uint32_t dsdt; + uint8_t reserved; + uint8_t preferred_power_management_profile; + uint16_t sci_interrupt; + uint32_t smi_command_port; + uint8_t acpi_enable; + uint8_t acpi_disable; + uint8_t s4bios_req; + uint8_t pstate_control; + uint32_t pm1a_event_block; + uint32_t pm1b_event_block; + uint32_t pm1a_control_block; + uint32_t pm1b_control_block; + uint32_t pm2_control_block; + uint32_t pm_timer_block; + uint32_t gpe0_block; + uint32_t gpe1_block; + uint8_t pm1_event_length; + uint8_t pm1_control_length; + uint8_t pm2_control_length; + uint8_t pm_timer_length; + uint8_t gpe0_length; + uint8_t gpe1_length; + uint8_t gpe1_base; + uint8_t cstate_control; + uint16_t worst_c2_latency; + uint16_t worst_c3_latency; + uint16_t flush_size; + uint16_t flush_stride; + uint8_t duty_offset; + uint8_t duty_width; + uint8_t day_alarm; + uint8_t month_alarm; + uint8_t century; + uint16_t boot_architecture_flags; + uint8_t reserved2; + uint32_t flags; + acpi_gas_t reset_reg; + uint8_t reset_value; + uint16_t arm_boot_architecture_flags; + uint8_t fadt_minor_version; + uint64_t x_firmware_ctrl; + uint64_t x_dsdt; + acpi_gas_t x_pm1a_event_block; + acpi_gas_t x_pm1b_event_block; + acpi_gas_t x_pm1a_control_block; + acpi_gas_t x_pm1b_control_block; + acpi_gas_t x_pm2_control_block; + acpi_gas_t x_pm_timer_block; + acpi_gas_t x_gpe0_block; + acpi_gas_t x_gpe1_block; +} __attribute__((packed)) acpi_fadt_t; + +typedef struct { + acpi_sdt_header_t header; + uint32_t local_apic_address; + uint32_t flags; + uint8_t entries[]; +} __attribute__((packed)) acpi_madt_t; + +#define MADT_ENTRY_LAPIC 0 +#define MADT_ENTRY_IOAPIC 1 +#define MADT_ENTRY_ISO 2 +#define MADT_ENTRY_NMI 4 +#define MADT_ENTRY_LAPIC_ADDR 5 +#define MADT_ENTRY_IOAPIC_MMIO 6 + +typedef struct { + uint8_t type; + uint8_t length; +} __attribute__((packed)) madt_entry_header_t; + +typedef struct { + madt_entry_header_t header; + uint8_t processor_id; + uint8_t apic_id; + uint32_t flags; +} __attribute__((packed)) madt_lapic_entry_t; + +typedef struct { + madt_entry_header_t header; + uint8_t ioapic_id; + uint8_t reserved; + uint32_t ioapic_address; + uint32_t global_system_interrupt_base; +} __attribute__((packed)) madt_ioapic_entry_t; + +typedef struct { + madt_entry_header_t header; + uint8_t bus; + uint8_t source; + uint32_t global_system_interrupt; + uint16_t flags; +} __attribute__((packed)) madt_iso_entry_t; + +typedef struct { + acpi_sdt_header_t header; + uint8_t hardware_rev_id; + uint8_t comparator_count : 5; + uint8_t counter_size : 1; + uint8_t reserved : 1; + uint8_t legacy_replacement : 1; + uint16_t pci_vendor_id; + uint8_t address_space_id; + uint8_t register_bit_width; + uint8_t register_bit_offset; + uint8_t reserved2; + uint64_t address; + uint8_t hpet_number; + uint16_t minimum_tick; + uint8_t page_protection; +} __attribute__((packed)) acpi_hpet_t; + +typedef struct { + acpi_sdt_header_t header; + uint64_t reserved; +} __attribute__((packed)) acpi_mcfg_t; + +typedef struct { + uint64_t base_address; + uint16_t pci_segment_group; + uint8_t start_pci_bus; + uint8_t end_pci_bus; + uint32_t reserved; +} __attribute__((packed)) mcfg_entry_t; + +typedef struct { + acpi_sdt_header_t header; + uint8_t definition_block[]; +} __attribute__((packed)) acpi_ssdt_t; + +void acpi_init(void); +bool acpi_is_available(void); +void* acpi_find_table(const char* signature, uint64_t index); +void acpi_print_tables(void); + +extern volatile struct limine_rsdp_request rsdp_request; + +void acpi_shutdown(void); +void acpi_reboot(void); + +#endif \ No newline at end of file diff --git a/kernel/include/apic/apic.h b/kernel/include/apic/apic.h new file mode 100644 index 0000000..6dc141a --- /dev/null +++ b/kernel/include/apic/apic.h @@ -0,0 +1,113 @@ +#ifndef APIC_H +#define APIC_H + +#include +#include +#include "../acpi/acpi.h" + +#define LAPIC_ID 0x0020 +#define LAPIC_VERSION 0x0030 +#define LAPIC_TPR 0x0080 +#define LAPIC_EOI 0x00B0 +#define LAPIC_SIVR 0x00F0 +#define LAPIC_ISR0 0x0100 +#define LAPIC_TIMER 0x0320 +#define LAPIC_THERMAL 0x0330 +#define LAPIC_PERFORMANCE 0x0340 +#define LAPIC_LINT0 0x0350 +#define LAPIC_LINT1 0x0360 +#define LAPIC_ERROR 0x0370 +#define LAPIC_TIMER_ICR 0x0380 +#define LAPIC_TIMER_CCR 0x0390 +#define LAPIC_TIMER_DCR 0x03E0 + +#define LAPIC_ENABLE (1 << 8) +#define LAPIC_SPURIOUS_VECTOR 0xFF + +#define LAPIC_TIMER_MASKED (1 << 16) +#define LAPIC_TIMER_PERIODIC (1 << 17) +#define LAPIC_TIMER_DIV1 0x0 +#define LAPIC_TIMER_DIV2 0x1 +#define LAPIC_TIMER_DIV4 0x2 +#define LAPIC_TIMER_DIV8 0x3 +#define LAPIC_TIMER_DIV16 0x4 +#define LAPIC_TIMER_DIV32 0x5 +#define LAPIC_TIMER_DIV64 0x6 +#define LAPIC_TIMER_DIV128 0x7 + +#define IOAPIC_ID 0x00 +#define IOAPIC_VERSION 0x01 +#define IOAPIC_ARB 0x02 +#define IOAPIC_REDIR_START 0x10 + +#define IOAPIC_INT_MASKED (1 << 16) +#define IOAPIC_TRIGGER_LEVEL (1 << 15) +#define IOAPIC_POLARITY_LOW (1 << 13) +#define IOAPIC_DELIVERY_FIXED 0x0 +#define IOAPIC_DELIVERY_NMI 0x4 + +#define HPET_CAPABILITIES 0x000 +#define HPET_PERIOD 0x004 +#define HPET_CONFIG 0x010 +#define HPET_INTERRUPT_STATUS 0x020 +#define HPET_MAIN_COUNTER 0x0F0 +#define HPET_TIMER0_CONFIG 0x100 +#define HPET_TIMER0_COMPARATOR 0x108 + +#define HPET_ENABLE_CNF (1ULL << 0) +#define HPET_LEGACY_CNF (1ULL << 1) + +#define HPET_TN_INT_ENABLE_CNF (1 << 2) +#define HPET_TN_INT_TYPE_CNF (1 << 3) +#define HPET_TN_PERIODIC_CNF (1 << 4) +#define HPET_TN_32BIT_CNF (1 << 8) +#define HPET_TN_FSB_ENABLE_CNF (1 << 14) +#define HPET_TN_FSB_INT_DEL_CNF (1 << 15) + +void apic_init(void); +bool apic_is_available(void); +bool hpet_is_available(void); +bool hpet_init(void); + +void lapic_write(uint32_t reg, uint32_t value); +uint32_t lapic_read(uint32_t reg); +void lapic_eoi(void); +void lapic_enable(void); +uint32_t lapic_get_id(void); +void lapic_timer_init(uint32_t vector, uint32_t count, bool periodic, uint8_t divisor); +void lapic_timer_stop(void); +uint32_t lapic_timer_get_current(void); +void lapic_send_ipi(uint32_t target_lapic_id, uint8_t vector); +void lapic_send_ipi_to_all_but_self(uint8_t vector); +void lapic_send_nmi_to_all_but_self(void); + +void ioapic_write(uintptr_t base, uint32_t reg, uint32_t value); +uint32_t ioapic_read(uintptr_t base, uint32_t reg); +uint32_t ioapic_get_max_redirects(uintptr_t base); +void ioapic_redirect_irq(uint8_t irq, uint8_t vector, uint32_t flags); +void ioapic_mask_irq(uint8_t irq); +void ioapic_unmask_irq(uint8_t irq); + +void apic_setup_irq(uint8_t irq, uint8_t vector, bool mask, uint32_t flags); +void apic_timer_calibrate(void); + +uint64_t hpet_read_counter(void); +uint64_t hpet_get_frequency(void); +uint64_t hpet_elapsed_ns(void); +void hpet_sleep_ns(uint64_t nanoseconds); +void hpet_sleep_us(uint64_t microseconds); +void hpet_sleep_ms(uint64_t milliseconds); + +extern uintptr_t lapic_base; +extern uintptr_t ioapic_base; +extern uintptr_t hpet_base; +extern uint32_t hpet_period; +extern uint64_t g_hpet_boot_counter; + +void ipi_reschedule_all(void); +void ipi_reschedule_cpu(uint32_t lapic_id); +void ipi_reschedule_single(uint32_t target_lapic_id); +void ipi_tlb_shootdown_broadcast(const uintptr_t* addrs, size_t count); +void ipi_tlb_shootdown_single(uint32_t target_lapic_id, uintptr_t addr); + +#endif \ No newline at end of file diff --git a/kernel/include/drivers/ata.h b/kernel/include/drivers/ata.h new file mode 100644 index 0000000..2ba906c --- /dev/null +++ b/kernel/include/drivers/ata.h @@ -0,0 +1,77 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include +#include + +#define ATA_PRIMARY_IO 0x1F0 +#define ATA_PRIMARY_CTRL 0x3F6 +#define ATA_SECONDARY_IO 0x170 +#define ATA_SECONDARY_CTRL 0x376 + +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT 0x02 +#define ATA_REG_LBA_LO 0x03 +#define ATA_REG_LBA_MID 0x04 +#define ATA_REG_LBA_HI 0x05 +#define ATA_REG_DRIVE 0x06 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_COMMAND 0x07 + +#define ATA_REG_ALT_STATUS 0x00 +#define ATA_REG_DEV_CTRL 0x00 + +#define ATA_SR_BSY 0x80 +#define ATA_SR_DRDY 0x40 +#define ATA_SR_DF 0x20 +#define ATA_SR_DSC 0x10 +#define ATA_SR_DRQ 0x08 +#define ATA_SR_CORR 0x04 +#define ATA_SR_IDX 0x02 +#define ATA_SR_ERR 0x01 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_IDENTIFY 0xEC +#define ATA_CMD_IDENTIFY_PACKET 0xA1 + +#define ATA_DRIVE_MASTER 0xA0 +#define ATA_DRIVE_SLAVE 0xB0 + +#define ATA_LBA_BIT 0x40 + +#define ATA_MAX_DRIVES 4 + +#define ATA_SECTOR_SIZE 512 + +typedef struct { + bool present; + bool is_atapi; + bool lba48; + uint16_t io_base; + uint16_t ctrl_base; + uint8_t drive_select; + uint8_t irq; + uint64_t sectors; + uint64_t size_bytes; + char model[41]; + char serial[21]; + char firmware[9]; + uint16_t identify[256]; +} ata_drive_t; + +void ata_init(void); +ata_drive_t *ata_get_drive(int index); +int ata_get_drive_count(void); +int ata_read_sectors(ata_drive_t *drive, uint64_t lba, uint32_t count, void *buffer); +int ata_write_sectors(ata_drive_t *drive, uint64_t lba, uint32_t count, const void *buffer); +int ata_flush(ata_drive_t *drive); + +#endif \ No newline at end of file diff --git a/kernel/include/drivers/blkdev.h b/kernel/include/drivers/blkdev.h new file mode 100644 index 0000000..9e08251 --- /dev/null +++ b/kernel/include/drivers/blkdev.h @@ -0,0 +1,38 @@ +#ifndef BLKDEV_H +#define BLKDEV_H + +#include +#include +#include + +#define BLKDEV_MAX 8 +#define BLKDEV_NAME_MAX 32 +#define BLKDEV_SECTOR_SIZE 512 + +typedef struct blkdev blkdev_t; + +typedef struct blkdev_ops { + int (*read_sectors) (blkdev_t *dev, uint64_t lba, uint32_t count, void *buf); + int (*write_sectors)(blkdev_t *dev, uint64_t lba, uint32_t count, const void *buf); + int (*flush) (blkdev_t *dev); +} blkdev_ops_t; + +struct blkdev { + char name[BLKDEV_NAME_MAX]; + bool present; + uint64_t sector_count; + uint64_t size_bytes; + uint32_t sector_size; + const blkdev_ops_t *ops; + void *priv; +}; + +int blkdev_register(blkdev_t *dev); +blkdev_t *blkdev_get_by_name(const char *name); +blkdev_t *blkdev_get(int index); +int blkdev_count(void); +void blkdev_init(void); +int blkdev_read(blkdev_t *dev, uint64_t offset, void *buf, size_t len); +int blkdev_write(blkdev_t *dev, uint64_t offset, const void *buf, size_t len); + +#endif \ No newline at end of file diff --git a/kernel/include/drivers/disk.h b/kernel/include/drivers/disk.h new file mode 100644 index 0000000..6b2a926 --- /dev/null +++ b/kernel/include/drivers/disk.h @@ -0,0 +1,11 @@ +#ifndef DISK_H +#define DISK_H + +#include "../drivers/blkdev.h" + +void disk_init(void); +int disk_mount(const char *devname, const char *path); +int disk_umount(const char *path); +int disk_format(const char *devname, const char *label); + +#endif \ No newline at end of file diff --git a/kernel/include/drivers/partition.h b/kernel/include/drivers/partition.h new file mode 100644 index 0000000..94213ee --- /dev/null +++ b/kernel/include/drivers/partition.h @@ -0,0 +1,52 @@ +#ifndef PARTITION_H +#define PARTITION_H + +#include +#include +#include "blkdev.h" + +#define MBR_SIGNATURE 0xAA55 +#define MBR_SIGNATURE_OFF 510 +#define MBR_PARTITION_OFF 446 +#define MBR_MAX_PARTITIONS 4 + +#define MBR_TYPE_EMPTY 0x00 +#define MBR_TYPE_FAT12 0x01 +#define MBR_TYPE_FAT16_S 0x04 +#define MBR_TYPE_EXTENDED 0x05 +#define MBR_TYPE_FAT16 0x06 +#define MBR_TYPE_FAT32_CHS 0x0B +#define MBR_TYPE_FAT32_LBA 0x0C +#define MBR_TYPE_FAT16_LBA 0x0E +#define MBR_TYPE_LINUX 0x83 +#define MBR_TYPE_ESP 0xEF + +typedef struct __attribute__((packed)) { + uint8_t boot_flag; + uint8_t chs_start[3]; + uint8_t type; + uint8_t chs_end[3]; + uint32_t lba_start; + uint32_t sector_count; +} mbr_partition_t; + +typedef struct __attribute__((packed)) { + uint8_t bootstrap[440]; + uint32_t disk_signature; + uint16_t reserved; + mbr_partition_t partitions[4]; + uint16_t signature; +} mbr_t; + +_Static_assert(sizeof(mbr_t) == 512, "mbr size must be 512"); + +int partition_scan(blkdev_t *disk); + +int partition_write_mbr(blkdev_t *disk, const mbr_partition_t parts[4], + uint32_t disk_signature); + +int partition_read_mbr(blkdev_t *disk, mbr_t *out); + +blkdev_t *partition_get(const char *name); + +#endif \ No newline at end of file diff --git a/kernel/include/drivers/ps2.h b/kernel/include/drivers/ps2.h new file mode 100644 index 0000000..13ad328 --- /dev/null +++ b/kernel/include/drivers/ps2.h @@ -0,0 +1,91 @@ +#ifndef PS2_H +#define PS2_H + +#include +#include +#include + +#define PS2_DATA_PORT 0x60 +#define PS2_STATUS_PORT 0x64 +#define PS2_CMD_PORT 0x64 + +#define PS2_STATUS_OUTPUT_FULL (1 << 0) +#define PS2_STATUS_INPUT_FULL (1 << 1) + +#define PS2_CMD_READ_CONFIG 0x20 +#define PS2_CMD_WRITE_CONFIG 0x60 +#define PS2_CMD_DISABLE_PORT2 0xA7 +#define PS2_CMD_ENABLE_PORT2 0xA8 +#define PS2_CMD_TEST_PORT2 0xA9 +#define PS2_CMD_SELF_TEST 0xAA +#define PS2_CMD_TEST_PORT1 0xAB +#define PS2_CMD_DISABLE_PORT1 0xAD +#define PS2_CMD_ENABLE_PORT1 0xAE +#define PS2_CMD_WRITE_PORT2 0xD4 + +#define PS2_CFG_PORT1_IRQ (1 << 0) +#define PS2_CFG_PORT2_IRQ (1 << 1) +#define PS2_CFG_PORT1_XLAT (1 << 6) + +#define PS2_KEY_RELEASE_BIT 0x80 + +#define SC_LSHIFT 0x2A +#define SC_RSHIFT 0x36 +#define SC_CAPS 0x3A +#define SC_LCTRL 0x1D +#define SC_LALT 0x38 +#define SC_ESCAPE 0x01 +#define SC_F1 0x3B +#define SC_F2 0x3C +#define SC_F3 0x3D +#define SC_F4 0x3E +#define SC_F5 0x3F +#define SC_F6 0x40 +#define SC_F7 0x41 +#define SC_F8 0x42 +#define SC_F9 0x43 +#define SC_F10 0x44 +#define SC_F11 0x57 +#define SC_F12 0x58 + +#define MOUSE_BTN_LEFT (1 << 0) +#define MOUSE_BTN_RIGHT (1 << 1) +#define MOUSE_BTN_MIDDLE (1 << 2) +#define MOUSE_X_SIGN (1 << 4) +#define MOUSE_Y_SIGN (1 << 5) +#define MOUSE_X_OVERFLOW (1 << 6) +#define MOUSE_Y_OVERFLOW (1 << 7) + +typedef enum { + MOUSE_SCROLL_NONE = 0, + MOUSE_SCROLL_UP, + MOUSE_SCROLL_DOWN, +} mouse_scroll_t; + +typedef struct { + int32_t x, y; + bool btn_left, btn_right, btn_middle; + mouse_scroll_t scroll; +} mouse_state_t; + +typedef struct { + bool shift, caps_lock, ctrl, alt; +} kb_state_t; + +#define KB_BUF_SIZE 64 + +typedef struct { + char buf[KB_BUF_SIZE]; + uint8_t head, tail; +} kb_buf_t; + +bool ps2_init(void); +const kb_state_t* ps2_kb_get_state(void); +const mouse_state_t* ps2_mouse_get_state(void); +bool kb_buf_empty(void); +char kb_buf_getc(void); +bool kb_buf_try_getc(char *out); +bool kb_buf_has_ctrlc(void); +void kb_buf_consume_ctrlc(void); + +#endif \ No newline at end of file diff --git a/kernel/include/drivers/timer.h b/kernel/include/drivers/timer.h new file mode 100644 index 0000000..681d59c --- /dev/null +++ b/kernel/include/drivers/timer.h @@ -0,0 +1,17 @@ +#ifndef TIMER_H +#define TIMER_H + +#include +#include + +bool timer_init(void); + +uint64_t timer_get_ticks(void); + +void timer_sleep_ms(uint64_t milliseconds); +void timer_sleep_us(uint64_t microseconds); +void timer_sleep_ns(uint64_t nanoseconds); + +extern volatile uint32_t g_ctrlc_pending; + +#endif \ No newline at end of file diff --git a/kernel/include/elf/elf.h b/kernel/include/elf/elf.h new file mode 100644 index 0000000..e034602 --- /dev/null +++ b/kernel/include/elf/elf.h @@ -0,0 +1,118 @@ +#ifndef ELF_H +#define ELF_H + +#include +#include +#include +#include "../memory/vmm.h" +#include "../memory/paging.h" + +#define ELF_MAGIC 0x464C457F + +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_NIDENT 16 + +#define ELFCLASS64 2 +#define ELFDATA2LSB 1 +#define EV_CURRENT 1 + +#define ET_EXEC 2 +#define ET_DYN 3 + +#define EM_X86_64 62 + +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_PHDR 6 +#define PT_TLS 7 + +#define PF_X (1 << 0) +#define PF_W (1 << 1) +#define PF_R (1 << 2) + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_NOBITS 8 + +typedef struct { + uint8_t e_ident[EI_NIDENT]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint64_t e_entry; + uint64_t e_phoff; + uint64_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} __attribute__((packed)) elf64_ehdr_t; + +typedef struct { + uint32_t p_type; + uint32_t p_flags; + uint64_t p_offset; + uint64_t p_vaddr; + uint64_t p_paddr; + uint64_t p_filesz; + uint64_t p_memsz; + uint64_t p_align; +} __attribute__((packed)) elf64_phdr_t; + +typedef struct { + uint32_t sh_name; + uint32_t sh_type; + uint64_t sh_flags; + uint64_t sh_addr; + uint64_t sh_offset; + uint64_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint64_t sh_addralign; + uint64_t sh_entsize; +} __attribute__((packed)) elf64_shdr_t; + +typedef enum { + ELF_OK = 0, + ELF_ERR_NULL, + ELF_ERR_TOO_SMALL, + ELF_ERR_BAD_MAGIC, + ELF_ERR_NOT_64, + ELF_ERR_NOT_LE, + ELF_ERR_BAD_VERSION, + ELF_ERR_NOT_EXEC, + ELF_ERR_WRONG_ARCH, + ELF_ERR_NO_LOAD, + ELF_ERR_MAP_FAIL, + ELF_ERR_NO_MEM, +} elf_error_t; + +typedef struct { + uintptr_t entry; + vmm_pagemap_t* pagemap; + uintptr_t load_base; + uintptr_t stack_top; + size_t stack_size; + elf_error_t error; + uintptr_t load_end; +} elf_load_result_t; + +elf_load_result_t elf_load(const void* data, size_t size, size_t stack_sz); + +void elf_unload(elf_load_result_t* result); + +const char* elf_strerror(elf_error_t err); + +#endif \ No newline at end of file diff --git a/kernel/include/fs/devfs.h b/kernel/include/fs/devfs.h new file mode 100644 index 0000000..45d9521 --- /dev/null +++ b/kernel/include/fs/devfs.h @@ -0,0 +1,9 @@ +#ifndef DEVFS_H +#define DEVFS_H + +#include "vfs.h" + +vnode_t *devfs_create_root(void); +void devfs_register(const char *name, vnode_t *node); + +#endif \ No newline at end of file diff --git a/kernel/include/fs/ext2.h b/kernel/include/fs/ext2.h new file mode 100644 index 0000000..a5fd312 --- /dev/null +++ b/kernel/include/fs/ext2.h @@ -0,0 +1,161 @@ +#ifndef EXT2_H +#define EXT2_H + +#include +#include +#include +#include "../drivers/blkdev.h" +#include "vfs.h" + +#define EXT2_SUPER_MAGIC 0xEF53 +#define EXT2_SUPER_OFFSET 1024 +#define EXT2_ROOT_INO 2 +#define EXT2_GOOD_OLD_REV 0 +#define EXT2_DYNAMIC_REV 1 +#define EXT2_VALID_FS 1 +#define EXT2_ERROR_FS 2 + +#define EXT2_S_IFSOCK 0xC000 +#define EXT2_S_IFLNK 0xA000 +#define EXT2_S_IFREG 0x8000 +#define EXT2_S_IFBLK 0x6000 +#define EXT2_S_IFDIR 0x4000 +#define EXT2_S_IFCHR 0x2000 +#define EXT2_S_IFIFO 0x1000 + +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_REG_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHRDEV 3 +#define EXT2_FT_BLKDEV 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 + +#define EXT2_NDIR_BLOCKS 12 +#define EXT2_IND_BLOCK 12 +#define EXT2_DIND_BLOCK 13 +#define EXT2_TIND_BLOCK 14 +#define EXT2_N_BLOCKS 15 +#define EXT2_NAME_LEN 255 + +typedef struct __attribute__((packed)) { + uint32_t s_inodes_count; + uint32_t s_blocks_count; + uint32_t s_r_blocks_count; + uint32_t s_free_blocks_count; + uint32_t s_free_inodes_count; + uint32_t s_first_data_block; + uint32_t s_log_block_size; + uint32_t s_log_frag_size; + uint32_t s_blocks_per_group; + uint32_t s_frags_per_group; + uint32_t s_inodes_per_group; + uint32_t s_mtime; + uint32_t s_wtime; + uint16_t s_mnt_count; + uint16_t s_max_mnt_count; + uint16_t s_magic; + uint16_t s_state; + uint16_t s_errors; + uint16_t s_minor_rev_level; + uint32_t s_lastcheck; + uint32_t s_checkinterval; + uint32_t s_creator_os; + uint32_t s_rev_level; + uint16_t s_def_resuid; + uint16_t s_def_resgid; + uint32_t s_first_ino; + uint16_t s_inode_size; + uint16_t s_block_group_nr; + uint32_t s_feature_compat; + uint32_t s_feature_incompat; + uint32_t s_feature_ro_compat; + uint8_t s_uuid[16]; + char s_volume_name[16]; + char s_last_mounted[64]; + uint32_t s_algo_bitmap; + uint8_t s_prealloc_blocks; + uint8_t s_prealloc_dir_blocks; + uint16_t s_padding1; + uint8_t s_journal_uuid[16]; + uint32_t s_journal_inum; + uint32_t s_journal_dev; + uint32_t s_last_orphan; + uint32_t s_hash_seed[4]; + uint8_t s_def_hash_version; + uint8_t s_reserved_pad[3]; + uint32_t s_default_mount_options; + uint32_t s_first_meta_bg; + uint8_t s_reserved[760]; +} ext2_superblock_t; + +_Static_assert(sizeof(ext2_superblock_t) == 1024, "ext2 superblock size"); + +typedef struct __attribute__((packed)) { + uint32_t bg_block_bitmap; + uint32_t bg_inode_bitmap; + uint32_t bg_inode_table; + uint16_t bg_free_blocks_count; + uint16_t bg_free_inodes_count; + uint16_t bg_used_dirs_count; + uint16_t bg_pad; + uint8_t bg_reserved[12]; +} ext2_group_desc_t; + +_Static_assert(sizeof(ext2_group_desc_t) == 32, "ext2 group desc size"); + +typedef struct __attribute__((packed)) { + uint16_t i_mode; + uint16_t i_uid; + uint32_t i_size; + uint32_t i_atime; + uint32_t i_ctime; + uint32_t i_mtime; + uint32_t i_dtime; + uint16_t i_gid; + uint16_t i_links_count; + uint32_t i_blocks; + uint32_t i_flags; + uint32_t i_osd1; + uint32_t i_block[EXT2_N_BLOCKS]; + uint32_t i_generation; + uint32_t i_file_acl; + uint32_t i_dir_acl; + uint32_t i_faddr; + uint8_t i_osd2[12]; +} ext2_inode_t; + +_Static_assert(sizeof(ext2_inode_t) == 128, "ext2 inode size"); + +typedef struct __attribute__((packed)) { + uint32_t inode; + uint16_t rec_len; + uint8_t name_len; + uint8_t file_type; + char name[EXT2_NAME_LEN]; +} ext2_dir_entry_t; + +typedef struct { + blkdev_t *dev; + ext2_superblock_t sb; + ext2_group_desc_t *gdt; + uint32_t block_size; + uint32_t groups_count; + uint32_t inodes_per_block; + uint32_t inode_size; + uint32_t ptrs_per_block; + bool dirty; +} ext2_t; + +typedef struct { + ext2_t *fs; + uint32_t ino; +} ext2_vdata_t; + +int ext2_format(blkdev_t *dev, const char *label); +vnode_t *ext2_mount(blkdev_t *dev); +void ext2_unmount(ext2_t *fs); +void ext2_sync(ext2_t *fs); + +#endif \ No newline at end of file diff --git a/kernel/include/fs/fat32.h b/kernel/include/fs/fat32.h new file mode 100644 index 0000000..e5ca24b --- /dev/null +++ b/kernel/include/fs/fat32.h @@ -0,0 +1,146 @@ +#ifndef FAT32_H +#define FAT32_H + +#include +#include +#include +#include "../drivers/blkdev.h" +#include "vfs.h" + +#define FAT32_SECTOR_SIZE 512 +#define FAT32_EOC 0x0FFFFFFF +#define FAT32_EOC_MIN 0x0FFFFFF8 +#define FAT32_FREE_CLUSTER 0x00000000 +#define FAT32_BAD_CLUSTER 0x0FFFFFF7 +#define FAT32_CLUSTER_MASK 0x0FFFFFFF + +#define FAT32_FSINFO_LEAD_SIG 0x41615252 +#define FAT32_FSINFO_STRUCT_SIG 0x61417272 +#define FAT32_FSINFO_TRAIL_SIG 0xAA550000 + +#define FAT_ATTR_READ_ONLY 0x01 +#define FAT_ATTR_HIDDEN 0x02 +#define FAT_ATTR_SYSTEM 0x04 +#define FAT_ATTR_VOLUME_ID 0x08 +#define FAT_ATTR_DIRECTORY 0x10 +#define FAT_ATTR_ARCHIVE 0x20 +#define FAT_ATTR_LONG_NAME 0x0F + +typedef struct __attribute__((packed)) { + uint8_t bs_jmp[3]; + uint8_t bs_oem[8]; + uint16_t bpb_bytes_per_sector; + uint8_t bpb_sectors_per_cluster; + uint16_t bpb_reserved_sectors; + uint8_t bpb_num_fats; + uint16_t bpb_root_entries; + uint16_t bpb_total_sectors_16; + uint8_t bpb_media; + uint16_t bpb_fat_size_16; + uint16_t bpb_sectors_per_track; + uint16_t bpb_num_heads; + uint32_t bpb_hidden_sectors; + uint32_t bpb_total_sectors_32; + uint32_t bpb_fat_size_32; + uint16_t bpb_ext_flags; + uint16_t bpb_fs_version; + uint32_t bpb_root_cluster; + uint16_t bpb_fs_info; + uint16_t bpb_backup_boot; + uint8_t bpb_reserved[12]; + uint8_t bs_drive_num; + uint8_t bs_reserved1; + uint8_t bs_boot_sig; + uint32_t bs_vol_id; + uint8_t bs_vol_label[11]; + uint8_t bs_fs_type[8]; + uint8_t bs_boot_code[420]; + uint16_t bs_signature; +} fat32_bpb_t; + +_Static_assert(sizeof(fat32_bpb_t) == 512, "fat32 bpb size"); + +typedef struct __attribute__((packed)) { + uint32_t lead_sig; + uint8_t reserved1[480]; + uint32_t struct_sig; + uint32_t free_count; + uint32_t next_free; + uint8_t reserved2[12]; + uint32_t trail_sig; +} fat32_fsinfo_t; + +_Static_assert(sizeof(fat32_fsinfo_t) == 512, "fat32 fsinfo size"); + +typedef struct __attribute__((packed)) { + uint8_t name[11]; + uint8_t attr; + uint8_t nt_reserved; + uint8_t create_time_tenth; + uint16_t create_time; + uint16_t create_date; + uint16_t access_date; + uint16_t cluster_hi; + uint16_t modify_time; + uint16_t modify_date; + uint16_t cluster_lo; + uint32_t file_size; +} fat32_dirent_t; + +_Static_assert(sizeof(fat32_dirent_t) == 32, "fat32 dirent size"); + +typedef struct __attribute__((packed)) { + uint8_t order; + uint8_t name1[10]; + uint8_t attr; + uint8_t type; + uint8_t checksum; + uint8_t name2[12]; + uint16_t cluster_lo; + uint8_t name3[4]; +} fat32_lfn_t; + +_Static_assert(sizeof(fat32_lfn_t) == 32, "fat32 lfn size"); + +typedef struct { + blkdev_t *dev; + uint32_t bytes_per_sector; + uint32_t sectors_per_cluster; + uint32_t bytes_per_cluster; + uint32_t reserved_sectors; + uint32_t num_fats; + uint32_t fat_size_sectors; + uint32_t total_sectors; + uint32_t root_cluster; + uint32_t first_fat_sector; + uint32_t first_data_sector; + uint32_t total_clusters; + uint32_t fsinfo_sector; + uint32_t next_free_hint; + uint32_t free_count; + bool dirty; + bool readonly; + uint8_t *shared_buf; +} fat32_t; + +typedef struct { + fat32_t *fs; + uint32_t first_cluster; + uint32_t dir_cluster; + uint32_t dir_entry_offset; + uint32_t file_size; + uint8_t attr; + + uint32_t cached_cluster; + uint32_t cached_index; + bool size_dirty; + + uint8_t *io_buf; +} fat32_vdata_t; + +int fat32_format(blkdev_t *dev, const char *label); +vnode_t *fat32_mount(blkdev_t *dev); +void fat32_unmount(fat32_t *fs); +int fat32_sync(fat32_t *fs); + +#endif \ No newline at end of file diff --git a/kernel/include/fs/initramfs.h b/kernel/include/fs/initramfs.h new file mode 100644 index 0000000..2bbd104 --- /dev/null +++ b/kernel/include/fs/initramfs.h @@ -0,0 +1,9 @@ +#ifndef INITRAMFS_H +#define INITRAMFS_H + +#include +#include + +int initramfs_mount(const void *data, size_t size); + +#endif \ No newline at end of file diff --git a/kernel/include/fs/ramfs.h b/kernel/include/fs/ramfs.h new file mode 100644 index 0000000..9624ac7 --- /dev/null +++ b/kernel/include/fs/ramfs.h @@ -0,0 +1,11 @@ +#ifndef RAMFS_H +#define RAMFS_H + +#include "vfs.h" + +#define RAMFS_MAX_CHILDREN 64 +#define RAMFS_MAX_FILE_SIZE (4 * 1024 * 1024) + +vnode_t *ramfs_create_root(void); + +#endif \ No newline at end of file diff --git a/kernel/include/fs/vfs.h b/kernel/include/fs/vfs.h new file mode 100644 index 0000000..422976f --- /dev/null +++ b/kernel/include/fs/vfs.h @@ -0,0 +1,181 @@ +#ifndef VFS_H +#define VFS_H + +#include +#include +#include +#include "../syscall/errno.h" + +#define VFS_MAX_PATH 512 +#define VFS_MAX_NAME 256 +#define VFS_MAX_MOUNTS 16 +#define VFS_MAX_OPEN_FILES 512 + +#define O_RDONLY 0x000 +#define O_WRONLY 0x001 +#define O_RDWR 0x002 +#define O_ACCMODE 0x003 +#define O_CREAT 0x040 +#define O_TRUNC 0x200 +#define O_APPEND 0x400 +#define O_DIRECTORY 0x10000 +#define O_NONBLOCK 0x800 + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +#define FD_CLOEXEC (1 << 0) +#define TASK_MAX_FDS 256 + +typedef enum { + VFS_NODE_FILE = 0, + VFS_NODE_DIR = 1, + VFS_NODE_CHARDEV = 2, + VFS_NODE_BLKDEV = 3, + VFS_NODE_SYMLINK = 4, + VFS_NODE_PIPE = 5, +} vnode_type_t; + +typedef struct { + uint64_t st_ino; + vnode_type_t st_type; + uint32_t st_mode; + uint32_t st_uid; + uint32_t st_gid; + uint64_t st_size; + uint64_t st_blocks; +} vfs_stat_t; + +typedef struct { + uint64_t d_ino; + uint8_t d_type; + char d_name[VFS_MAX_NAME]; +} vfs_dirent_t; + +typedef struct vnode vnode_t; +typedef struct vfs_mount vfs_mount_t; + +typedef struct vnode_ops { + int64_t (*read) (vnode_t *node, void *buf, size_t len, uint64_t offset); + int64_t (*write) (vnode_t *node, const void *buf, size_t len, uint64_t offset); + int (*truncate)(vnode_t *node, uint64_t new_size); + int (*lookup) (vnode_t *dir, const char *name, vnode_t **out); + int (*readdir) (vnode_t *dir, uint64_t index, vfs_dirent_t *out); + int (*mkdir) (vnode_t *dir, const char *name, uint32_t mode); + int (*create) (vnode_t *dir, const char *name, uint32_t mode, vnode_t **out); + int (*unlink) (vnode_t *dir, const char *name); + int (*rename) (vnode_t *src_dir, const char *src_name, + vnode_t *dst_dir, const char *dst_name); + int (*stat) (vnode_t *node, vfs_stat_t *out); + void (*ref) (vnode_t *node); + void (*unref) (vnode_t *node); + int64_t (*ioctl) (vnode_t *node, uint64_t req, void *arg); +} vnode_ops_t; + +struct vnode { + vnode_type_t type; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint64_t size; + uint64_t ino; + const vnode_ops_t *ops; + void *fs_data; + volatile int refcount; + vfs_mount_t *mounted; +}; + +struct vfs_mount { + char path[VFS_MAX_PATH]; + char device[32]; + char fstype[16]; + vnode_t *root; + bool used; + void *fs_priv; + void (*unmount)(void *fs_priv); + void (*sync)(void *fs_priv); +}; + +typedef struct { + vnode_t *vnode; + uint64_t offset; + int flags; + volatile int refcount; +} vfs_file_t; + +typedef struct { + vfs_file_t *file; + int fd_flags; +} fd_entry_t; + +typedef struct fd_table fd_table_t; + +struct fd_table { + fd_entry_t entries[TASK_MAX_FDS]; +}; + +void vfs_init (void); +int vfs_mount (const char *path, vnode_t *fs_root); + +int vfs_mount_fs(const char *path, vnode_t *fs_root, + void *fs_priv, void (*unmount_fn)(void *), + void (*sync_fn)(void *)); + +int vfs_umount (const char *path); +int vfs_lookup (const char *path, vnode_t **out); + +int vfs_open (const char *path, int flags, uint32_t mode, vfs_file_t **out); +void vfs_close (vfs_file_t *file); +int64_t vfs_read (vfs_file_t *file, void *buf, size_t len); +int64_t vfs_write (vfs_file_t *file, const void *buf, size_t len); +int64_t vfs_seek (vfs_file_t *file, int64_t offset, int whence); +int vfs_stat (const char *path, vfs_stat_t *out); +int vfs_fstat (vfs_file_t *file, vfs_stat_t *out); +int64_t vfs_ioctl (vfs_file_t *file, uint64_t req, void *arg); +int vfs_readdir(vfs_file_t *file, vfs_dirent_t *out); +int vfs_mkdir (const char *path, uint32_t mode); + +void vnode_ref (vnode_t *node); +void vnode_unref (vnode_t *node); +vfs_file_t *vfs_file_alloc(void); +void vfs_file_free (vfs_file_t *file); + +fd_table_t *fd_table_create (void); +fd_table_t *fd_table_clone (const fd_table_t *src); +void fd_table_cloexec(fd_table_t *table); +void fd_table_destroy(fd_table_t *table); + +int fd_alloc (fd_table_t *table, vfs_file_t *file, int min_fd); +vfs_file_t *fd_get (const fd_table_t *table, int fd); +int fd_close (fd_table_t *table, int fd); +int fd_dup2 (fd_table_t *table, int oldfd, int newfd); +int fd_set_flags(fd_table_t *table, int fd, int flags); +int fd_get_flags(const fd_table_t *table, int fd); +void vfs_sync_all(void); +int vfs_init_stdio(void *task_ptr); + +typedef struct { + char path[VFS_MAX_PATH]; + char device[32]; + char fstype[16]; + uint32_t flags; +} vfs_mount_info_t; + +int vfs_set_mount_info(const char *path, const char *device, const char *fstype); +int vfs_list_mounts(vfs_mount_info_t *out, int max); + +typedef struct { + uint64_t f_bsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + uint32_t f_flag; + uint32_t f_namemax; +} vfs_statvfs_t; + +int vfs_statvfs(const char *path, vfs_statvfs_t *out); + +#endif \ No newline at end of file diff --git a/kernel/include/gdt/gdt.h b/kernel/include/gdt/gdt.h new file mode 100644 index 0000000..5b0a00d --- /dev/null +++ b/kernel/include/gdt/gdt.h @@ -0,0 +1,78 @@ +#ifndef GDT_H +#define GDT_H + +#include + +#define GDT_CODE_SEGMENT 0x08 +#define GDT_DATA_SEGMENT 0x10 +#define GDT_USER_DATA_SEGMENT 0x18 +#define GDT_USER_CODE_SEGMENT 0x20 + +#define GDT_USER_DATA_RPL3 (GDT_USER_DATA_SEGMENT | 3) +#define GDT_USER_CODE_RPL3 (GDT_USER_CODE_SEGMENT | 3) + +#define GDT_STAR_SYSRET_BASE GDT_DATA_SEGMENT +#define GDT_STAR_SYSCALL_CS GDT_CODE_SEGMENT + +#define TSS_SELECTOR_BASE 0x28 +#define KERNEL_STACK_SIZE (4096 * 8) +#define KERNEL_STACK_PAGES (KERNEL_STACK_SIZE / 0x1000) + +#define GDT_LIMIT_LOW(limit) (limit & 0xFFFF) +#define GDT_BASE_LOW(base) (base & 0xFFFF) +#define GDT_BASE_MIDDLE(base) ((base >> 16) & 0xFF) +#define GDT_FLAGS_HI_LIMIT(limit, flags) \ + (((limit >> 16) & 0xF) | ((flags << 4) & 0xF0)) +#define GDT_BASE_HIGH(base) ((base >> 24) & 0xFF) + +#define GDT_ENTRY(base, limit, access, flags) \ + {GDT_LIMIT_LOW(limit), \ + GDT_BASE_LOW(base), \ + GDT_BASE_MIDDLE(base), \ + access, \ + GDT_FLAGS_HI_LIMIT(limit, flags), \ + GDT_BASE_HIGH(base)} + +typedef struct { + uint32_t reserved0; + uint64_t rsp0; + uint64_t rsp1; + uint64_t rsp2; + uint64_t reserved1; + uint64_t ist[7]; + uint64_t reserved2; + uint32_t iobase; +} __attribute__((packed)) tss_t; + +typedef struct { + uint16_t limit_low; + uint16_t base_low; + uint8_t base_middle; + uint8_t access; + uint8_t limit_high_and_flags; + uint8_t base_high; +} __attribute__((packed)) gdt_entry_t; + +typedef struct { + uint16_t limit_low; + uint16_t base_low; + uint8_t base_middle; + uint8_t access; + uint8_t limit_high_and_flags; + uint8_t base_high; + uint32_t base_higher; + uint32_t zero; +} __attribute__((packed)) tss_entry_t; + +typedef struct { + uint16_t size; + gdt_entry_t *pointer; +} __attribute__((packed)) gdt_pointer_t; + +extern gdt_pointer_t gdtr; + +extern void load_tss(uint16_t sel); +void gdt_init(void); +void gdt_load(void); + +#endif \ No newline at end of file diff --git a/kernel/include/graphics/fb/fb.h b/kernel/include/graphics/fb/fb.h new file mode 100644 index 0000000..b61f3e9 --- /dev/null +++ b/kernel/include/graphics/fb/fb.h @@ -0,0 +1,58 @@ +#ifndef FB_H +#define FB_H + +#include +#include +#include + +#define RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b)) + +#define COLOR_BLACK RGB( 0, 0, 0) +#define COLOR_WHITE RGB(255, 255, 255) +#define COLOR_RED RGB(255, 0, 0) +#define COLOR_GREEN RGB( 0, 255, 0) +#define COLOR_BLUE RGB( 0, 0, 255) +#define COLOR_CYAN RGB( 0, 255, 255) +#define COLOR_MAGENTA RGB(255, 0, 255) +#define COLOR_YELLOW RGB(255, 255, 0) +#define COLOR_ORANGE RGB(255, 165, 0) +#define COLOR_GRAY RGB(128, 128, 128) +#define COLOR_DARKGRAY RGB( 64, 64, 64) +#define COLOR_BROWN RGB(165, 42, 42) + +struct psf_header { + uint32_t magic; + uint32_t version; + uint32_t headersize; + uint32_t flags; + uint32_t numglyph; + uint32_t bytesperglyph; + uint32_t height; + uint32_t width; +} __attribute__((packed)); + +extern uint8_t _binary_font_psf_start[]; +extern uint8_t _binary_font_psf_end[]; + +static inline const uint8_t* get_font_data(void) { + return (const uint8_t*)&_binary_font_psf_start; +} +static inline size_t get_font_data_size(void) { + return _binary_font_psf_end - _binary_font_psf_start; +} + +static inline const struct psf_header* get_psf_header(void) { + return (const struct psf_header*)&_binary_font_psf_start; +} + +int psf_validate(void); +void fb_draw_pixel(struct limine_framebuffer *fb, uint32_t x, uint32_t y, uint32_t color); +void fb_fill_rect(struct limine_framebuffer *fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color); +void fb_clear(struct limine_framebuffer *fb, uint32_t color); +void fb_draw_char(struct limine_framebuffer *fb, char c, uint32_t x, uint32_t y, uint32_t color); +void fb_draw_string(struct limine_framebuffer *fb, const char *str, uint32_t x, uint32_t y, uint32_t color); +void fb_init_backbuffer(struct limine_framebuffer *fb); +void fb_flush(struct limine_framebuffer *fb); +void fb_flush_lines(struct limine_framebuffer *fb, uint32_t y_start, uint32_t y_end); + +#endif diff --git a/kernel/include/interrupts/idt.h b/kernel/include/interrupts/idt.h new file mode 100644 index 0000000..18f37e9 --- /dev/null +++ b/kernel/include/interrupts/idt.h @@ -0,0 +1,47 @@ +#ifndef IDT_H +#define IDT_H + +#include +#include + +#define IDT_MAX_DESCRIPTORS 256 + +#define IS_FLAG_SETTED(x, flag) ((x) | (flag)) +#define FLAG_SET(x, flag) ((x) |= (flag)) +#define FLAG_UNSET(x, flag) ((x) &= ~(flag)) + +typedef enum { + IDT_FLAG_GATE_TASK = 0x5, + IDT_FLAG_GATE_16BIT_INT = 0x6, + IDT_FLAG_GATE_16BIT_TRAP = 0x7, + IDT_FLAG_GATE_32BIT_INT = 0xE, + IDT_FLAG_GATE_32BIT_TRAP = 0xF, + + IDT_FLAG_RING0 = (0 << 5), + IDT_FLAG_RING1 = (1 << 5), + IDT_FLAG_RING2 = (2 << 5), + IDT_FLAG_RING3 = (3 << 5), + + IDT_FLAG_PRESENT = 0x80, + +} IDT_FLAGS; + +typedef struct { + uint16_t base_low; + uint16_t kernel_cs; + uint8_t ist; + uint8_t attributes; + uint16_t base_mid; + uint32_t base_high; + uint32_t reserved; +}__attribute__((packed)) idt_entry_t; + +typedef struct { + uint16_t limit; + idt_entry_t *base; +}__attribute__((packed)) idtr_t; +extern idtr_t idtr; +void setup_interrupt_descriptor_table(uint64_t kernel_code_segment); +void idt_load(void); + +#endif diff --git a/kernel/include/interrupts/interrupts.h b/kernel/include/interrupts/interrupts.h new file mode 100644 index 0000000..42c9268 --- /dev/null +++ b/kernel/include/interrupts/interrupts.h @@ -0,0 +1,77 @@ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#include + +struct int_frame_t { + uint64_t ds; + + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + + uint64_t rbp; + + uint64_t rdi; + uint64_t rsi; + + uint64_t rdx; + uint64_t rcx; + uint64_t rbx; + uint64_t rax; + + uint64_t interrupt; + uint64_t error; + + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +} __attribute__((packed)); + +typedef void (*int_handler_f)(struct int_frame_t* frame); + +typedef struct { + uint64_t vector; + int_handler_f handler; +} int_desc_t; + +#define __CHECK_HANDLER(fn) \ + _Static_assert( \ + __builtin_types_compatible_p( \ + typeof(fn), void (*)(struct int_frame_t *)), \ + "Invalid interrupt handler signature") + +#define __CONCAT(a, b) a##b +#define __UNIQUE_NAME(base) __CONCAT(base, __COUNTER__) + +#define DEFINE_ISR(_vector, _name) \ + static void _name(struct int_frame_t *frame); \ + static const int_desc_t __UNIQUE_NAME(__isr_desc_##_name) \ + __attribute__((used, section(".isr_handlers"))) = { \ + .vector = (_vector), \ + .handler = _name, \ + }; \ + static void _name(struct int_frame_t *frame) + + +#define DEFINE_IRQ(_vector, _name) \ + static void _name(struct int_frame_t *frame); \ + static const int_desc_t __UNIQUE_NAME(__irq_desc_##_name) \ + __attribute__((used, section(".irq_handlers"))) = { \ + .vector = (_vector), \ + .handler = _name, \ + }; \ + static void _name(struct int_frame_t *frame) + +#define IPI_RESCHEDULE_VECTOR 0x40 +#define IPI_TLB_SHOOTDOWN 0x41 +void init_interrupt_system(); + +#endif diff --git a/kernel/include/interrupts/irq.h b/kernel/include/interrupts/irq.h new file mode 100644 index 0000000..30fba98 --- /dev/null +++ b/kernel/include/interrupts/irq.h @@ -0,0 +1,31 @@ +#ifndef IRQ_H +#define IRQ_H + +#include +#include "interrupts.h" + +#define IRQ_INTERRUPTS_COUNT 224 + +static const char* irq_default_names[] __attribute__((unused)) = { + "IRQ0 timer", + "IRQ1 keyboard", + "IRQ2 cascade", + "IRQ3 COM2", + "IRQ4 COM1", + "IRQ5 LPT2", + "IRQ6 floppy", + "IRQ7 LPT1", + "IRQ8 RTC", + "IRQ9 ACPI", + "IRQ10 reserved", + "IRQ11 reserved", + "IRQ12 mouse", + "IRQ13 FPU", + "IRQ14 ATA1", + "IRQ15 ATA2" +}; + +void irq_common_handler(struct int_frame_t* regs); +void setup_defined_irq_handlers(void); + +#endif diff --git a/kernel/include/interrupts/isr.h b/kernel/include/interrupts/isr.h new file mode 100644 index 0000000..04d5d93 --- /dev/null +++ b/kernel/include/interrupts/isr.h @@ -0,0 +1,81 @@ +#ifndef ISR_H +#define ISR_H + +#include "interrupts.h" + +#define ISR_EXCEPTION_COUNT 32 + +enum { + EXCEPTION_DIVIDE_ERROR = 0, + EXCEPTION_DEBUG, + EXCEPTION_NMI, + EXCEPTION_BREAKPOINT, + EXCEPTION_OVERFLOW, + EXCEPTION_BOUND_RANGE, + EXCEPTION_INVALID_OPCODE, + EXCEPTION_DEVICE_NOT_AVAILABLE, + EXCEPTION_DOUBLE_FAULT, + EXCEPTION_COPROCESSOR_SEGMENT_OVERRUN, + EXCEPTION_INVALID_TSS, + EXCEPTION_SEGMENT_NOT_PRESENT, + EXCEPTION_STACK_SEGMENT_FAULT, + EXCEPTION_GENERAL_PROTECTION_FAULT, + EXCEPTION_PAGE_FAULT, + EXCEPTION_RESERVED15, + EXCEPTION_X87_FPU_ERROR, + EXCEPTION_ALIGNMENT_CHECK, + EXCEPTION_MACHINE_CHECK, + EXCEPTION_SIMD_FPU_EXCEPTION, + EXCEPTION_VIRTUALIZATION_EXCEPTION, + EXCEPTION_RESERVED21, + EXCEPTION_RESERVED22, + EXCEPTION_RESERVED23, + EXCEPTION_RESERVED24, + EXCEPTION_RESERVED25, + EXCEPTION_RESERVED26, + EXCEPTION_RESERVED27, + EXCEPTION_RESERVED28, + EXCEPTION_RESERVED29, + EXCEPTION_SECURITY_EXCEPTION = 30, + EXCEPTION_RESERVED31 +}; + +static const char* exception_names[] __attribute__((unused)) = { + "Divide Error", + "Debug", + "Non-Maskable Interrupt", + "Breakpoint", + "Overflow", + "Bound Range Exceeded", + "Invalid Opcode", + "Device Not Available", + "Double Fault", + "Coprocessor Segment Overrun", + "Invalid TSS", + "Segment Not Present", + "Stack Segment Fault", + "General Protection Fault", + "Page Fault", + "Reserved", + "x87 Floating-Point Exception", + "Alignment Check", + "Machine Check", + "SIMD Floating-Point Exception", + "Virtualization Exception", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Security Exception", + "Reserved" +}; + +void isr_common_handler(struct int_frame_t* regs); +void setup_defined_isr_handlers(void); + +#endif diff --git a/kernel/include/io/ports.h b/kernel/include/io/ports.h new file mode 100644 index 0000000..15d2836 --- /dev/null +++ b/kernel/include/io/ports.h @@ -0,0 +1,40 @@ +#ifndef PORTS_H +#define PORTS_H + +#include + +static inline uint8_t inb(uint16_t port) { + uint8_t result; + asm volatile ("inb %1, %0" : "=a"(result) : "Nd"(port)); + return result; +} + +static inline void outb(uint16_t port, uint8_t data) { + asm volatile ("outb %0, %1" : : "a"(data), "Nd"(port)); +} + +static inline uint16_t inw(uint16_t port) { + uint16_t result; + asm volatile ("inw %1, %0" : "=a"(result) : "Nd"(port)); + return result; +} + +static inline void outw(uint16_t port, uint16_t data) { + asm volatile ("outw %0, %1" : : "a"(data), "Nd"(port)); +} + +static inline uint32_t inl(uint16_t port) { + uint32_t result; + asm volatile ("inl %1, %0" : "=a"(result) : "Nd"(port)); + return result; +} + +static inline void outl(uint16_t port, uint32_t data) { + asm volatile ("outl %0, %1" : : "a"(data), "Nd"(port)); +} + +static inline void io_wait(void) { + outb(0x80, 0); +} + +#endif \ No newline at end of file diff --git a/kernel/include/io/serial.h b/kernel/include/io/serial.h new file mode 100644 index 0000000..cd09b41 --- /dev/null +++ b/kernel/include/io/serial.h @@ -0,0 +1,51 @@ +#ifndef SERIAL_H +#define SERIAL_H + +#include +#include +#include +#include + +#define COM1 0x3F8 +#define COM2 0x2F8 +#define COM3 0x3E8 +#define COM4 0x2E8 + +#define SERIAL_DATA_PORT(base) (base) +#define SERIAL_FIFO_COMMAND_PORT(base) (base + 2) +#define SERIAL_LINE_COMMAND_PORT(base) (base + 3) +#define SERIAL_MODEM_COMMAND_PORT(base) (base + 4) +#define SERIAL_LINE_STATUS_PORT(base) (base + 5) + +#define SERIAL_LSR_DATA_READY 0x01 +#define SERIAL_LSR_OVERRUN_ERROR 0x02 +#define SERIAL_LSR_PARITY_ERROR 0x04 +#define SERIAL_LSR_FRAMING_ERROR 0x08 +#define SERIAL_LSR_BREAK_INDICATOR 0x10 +#define SERIAL_LSR_TRANSMIT_HOLDING_EMPTY 0x20 +#define SERIAL_LSR_TRANSMIT_EMPTY 0x40 +#define SERIAL_LSR_FIFO_ERROR 0x80 + +void serial_initialize(uint16_t port, uint32_t baud_rate); + +int serial_received_port(uint16_t port); +char serial_read_port(uint16_t port); +int serial_is_transmit_empty_port(uint16_t port); +void serial_write_port(uint16_t port, char c); +void serial_writestring_port(uint16_t port, const char* str); +void serial_printf_port(uint16_t port, const char* format, ...); + +int serial_received(void); +char serial_read(void); +int serial_is_transmit_empty(void); +void serial_write(char c); +void serial_writestring(const char* str); +void serial_writebuf(const char* buf, size_t len); +void serial_printf(const char* format, ...); + +uint16_t serial_get_default_port(void); + +void serial_set_default_port(uint16_t port); +void serial_force_unlock(void); + +#endif \ No newline at end of file diff --git a/kernel/include/memory/paging.h b/kernel/include/memory/paging.h new file mode 100644 index 0000000..440a902 --- /dev/null +++ b/kernel/include/memory/paging.h @@ -0,0 +1,44 @@ +#ifndef PAGING_H +#define PAGING_H + +#include +#include +#include +#include "vmm.h" +#include "../include/interrupts/interrupts.h" + +#define PAGING_PRESENT VMM_PRESENT +#define PAGING_WRITE VMM_WRITE +#define PAGING_USER VMM_USER +#define PAGING_NOEXEC VMM_NOEXEC + +#define PAGING_KERNEL (PAGING_PRESENT | PAGING_WRITE) +#define PAGING_USER_RW (PAGING_PRESENT | PAGING_WRITE | PAGING_USER) +#define PAGING_USER_RO (PAGING_PRESENT | PAGING_USER) +#define PAGING_USER_NOEXEC (PAGING_PRESENT | PAGING_USER | PAGING_NOEXEC) + +#define PAGING_LARGE_PAGE_SIZE 0x200000 +#define PAGING_HUGE_PAGE_SIZE 0x40000000 + +typedef struct { + uintptr_t virtual_start; + uintptr_t virtual_end; + uintptr_t physical_start; + uint64_t flags; + size_t page_count; + bool allocated; +} paging_region_t; + +void paging_init(void); +bool paging_map_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t phys_start, size_t page_count, uint64_t flags); +bool paging_unmap_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, size_t page_count); +bool paging_change_flags(vmm_pagemap_t* pagemap, uintptr_t virt_start, size_t page_count, uint64_t new_flags); +paging_region_t* paging_create_region(vmm_pagemap_t* pagemap, uintptr_t virt_start, size_t size, uint64_t flags); +bool paging_destroy_region(vmm_pagemap_t* pagemap, paging_region_t* region); +void* paging_alloc_pages(vmm_pagemap_t* pagemap, size_t page_count, uint64_t flags, uintptr_t preferred_virt); +void paging_free_pages(vmm_pagemap_t* pagemap, void* virt_addr, size_t page_count); +bool paging_reserve_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t virt_end); +bool paging_is_range_free(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t virt_end); +void paging_print_stats(vmm_pagemap_t* pagemap); +void paging_dump_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t virt_end); +#endif \ No newline at end of file diff --git a/kernel/include/memory/pmm.h b/kernel/include/memory/pmm.h new file mode 100644 index 0000000..c9acdd5 --- /dev/null +++ b/kernel/include/memory/pmm.h @@ -0,0 +1,89 @@ +#ifndef PMM_H +#define PMM_H + +#include +#include +#include +#include + +#define PAGE_SIZE 4096UL +#define PAGE_SHIFT 12 +#define PMM_PAGE_ALIGN(x) (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) + +#define PMM_MAX_ORDER 10 +#define PMM_MAX_ORDER_NR (PMM_MAX_ORDER + 1) + +#define SLAB_MIN_SIZE 8 +#define SLAB_MAX_SIZE 4096 +#define SLAB_NUM_CACHES 10 + +#define PMM_FREE_MIN_PHYS 0x100000ULL + +typedef struct pmm_block { + struct pmm_block *next; + struct pmm_block *prev; + int order; +} pmm_block_t; + +typedef struct { + pmm_block_t head; + size_t count; +} pmm_free_list_t; + +typedef struct { + uintptr_t hhdm_offset; + uintptr_t mem_start; + uintptr_t mem_end; + size_t total_pages; + size_t usable_pages; + size_t free_pages; + pmm_free_list_t orders[PMM_MAX_ORDER_NR]; +} pmm_buddy_state_t; + +typedef struct slab { + struct slab *next; + struct slab *prev; + void *freelist; + uint16_t obj_size; + uint16_t total; + uint16_t used; + uint16_t _pad; +} slab_t; + +typedef struct { + size_t obj_size; + slab_t *partial; + slab_t *full; + size_t total_allocs; + size_t total_frees; +} slab_cache_t; + +void pmm_init(struct limine_memmap_response *memmap, + struct limine_hhdm_response *hhdm); + +void *pmm_alloc(size_t pages); +void *pmm_alloc_zero(size_t pages); +void *pmm_alloc_aligned(size_t pages, size_t alignment); +void pmm_free(void *addr, size_t pages); +void pmm_free_single(void *addr); + +void *pmm_phys_to_virt(uintptr_t phys); +uintptr_t pmm_virt_to_phys(void *vaddr); +uint64_t pmm_get_hhdm_offset(void); + +size_t pmm_get_total_pages(void); +size_t pmm_get_usable_pages(void); +size_t pmm_get_free_pages(void); +size_t pmm_get_used_pages(void); +void pmm_print_stats(void); + +void slab_init(void); +void *kmalloc(size_t size); +void *kzalloc(size_t size); +void *krealloc(void *ptr, size_t new_size); +void kfree(void *ptr); +void slab_print_stats(void); + +extern slab_cache_t g_caches[SLAB_NUM_CACHES]; + +#endif \ No newline at end of file diff --git a/kernel/include/memory/vmm.h b/kernel/include/memory/vmm.h new file mode 100644 index 0000000..b22662d --- /dev/null +++ b/kernel/include/memory/vmm.h @@ -0,0 +1,41 @@ +#ifndef VMM_H +#define VMM_H + +#include +#include +#include + +#define VMM_PRESENT (1ULL << 0) +#define VMM_WRITE (1ULL << 1) +#define VMM_USER (1ULL << 2) +#define VMM_PWT (1ULL << 3) +#define VMM_PCD (1ULL << 4) +#define VMM_ACCESSED (1ULL << 5) +#define VMM_DIRTY (1ULL << 6) +#define VMM_PSE (1ULL << 7) +#define VMM_GLOBAL (1ULL << 8) +#define VMM_NOEXEC (1ULL << 63) + +typedef uint64_t vmm_pte_t; + +typedef struct { + vmm_pte_t* pml4; +} vmm_pagemap_t; + +extern uintptr_t kernel_pml4_phys; + +void vmm_init(void); +vmm_pagemap_t* vmm_create_pagemap(void); +void vmm_switch_pagemap(vmm_pagemap_t* map); +bool vmm_map_page(vmm_pagemap_t* map, uintptr_t virt, uintptr_t phys, uint64_t flags); +void vmm_unmap_page(vmm_pagemap_t* map, uintptr_t virt); +void vmm_unmap_page_noflush(vmm_pagemap_t* map, uintptr_t virt); +bool vmm_virt_to_phys(vmm_pagemap_t* map, uintptr_t virt, uintptr_t* phys_out); +bool vmm_get_page_flags(vmm_pagemap_t* map, uintptr_t virt, uint64_t* flags_out); +vmm_pagemap_t* vmm_get_kernel_pagemap(void); +vmm_pagemap_t* vmm_clone_pagemap(vmm_pagemap_t* src); +void vmm_free_pagemap(vmm_pagemap_t* map); +void vmm_sync_kernel_mappings(vmm_pagemap_t* map); +void vmm_test(void); + +#endif \ No newline at end of file diff --git a/kernel/include/panic/panic.h b/kernel/include/panic/panic.h new file mode 100644 index 0000000..e175b01 --- /dev/null +++ b/kernel/include/panic/panic.h @@ -0,0 +1,19 @@ +#ifndef PANIC_H +#define PANIC_H + +#include +#include "../interrupts/interrupts.h" + +__attribute__((noreturn)) +void kernel_panic(const char *msg); + +__attribute__((noreturn)) +void kernel_panic_regs(const char *msg, struct int_frame_t *regs); + +#define KPANIC(msg) \ + kernel_panic("[" __FILE__ ":" STRINGIFY(__LINE__) "] " msg) + +#define STRINGIFY_IMPL(x) #x +#define STRINGIFY(x) STRINGIFY_IMPL(x) + +#endif \ No newline at end of file diff --git a/kernel/include/sched/capabilities.h b/kernel/include/sched/capabilities.h new file mode 100644 index 0000000..f009750 --- /dev/null +++ b/kernel/include/sched/capabilities.h @@ -0,0 +1,49 @@ +#ifndef CAPABILITIES_H +#define CAPABILITIES_H + +#include +#include + +#define UID_ROOT 0 +#define GID_ROOT 0 +#define UID_NOBODY 65534 +#define GID_NOBODY 65534 + +#define CAP_IOPORT (1ULL << 0) +#define CAP_RAWMEM (1ULL << 1) +#define CAP_DMA (1ULL << 2) +#define CAP_IRQ (1ULL << 3) +#define CAP_KILL_ANY (1ULL << 4) +#define CAP_SET_PRIO (1ULL << 5) +#define CAP_TASK_SPAWN (1ULL << 6) +#define CAP_TASK_INFO (1ULL << 7) +#define CAP_MMAP_EXEC (1ULL << 8) +#define CAP_MMAP_PHYS (1ULL << 9) +#define CAP_FS_ROOT (1ULL << 10) +#define CAP_FS_OWNER (1ULL << 11) +#define CAP_NET_RAW (1ULL << 12) +#define CAP_NET_BIND (1ULL << 13) +#define CAP_SYSADMIN (1ULL << 14) +#define CAP_REBOOT (1ULL << 15) +#define CAP_MODULE (1ULL << 16) +#define CAP_SETUID (1ULL << 17) +#define CAP_AUDIT (1ULL << 18) +#define CAP_PTRACE (1ULL << 19) +#define CAP_DBG_SERIAL (1ULL << 20) +#define CAP_ALL (~0ULL) +#define CAP_BASIC_SET (CAP_MMAP_EXEC | CAP_TASK_SPAWN) +#define CAP_SERVICE_SET (CAP_BASIC_SET | CAP_TASK_INFO | CAP_SET_PRIO | CAP_NET_BIND) + +static inline bool cap_has(uint64_t caps, uint64_t cap) { + return (caps & cap) == cap; +} + +static inline uint64_t cap_drop(uint64_t caps, uint64_t cap) { + return caps & ~cap; +} + +static inline uint64_t cap_initial(uint32_t uid) { + return (uid == UID_ROOT) ? CAP_ALL : CAP_BASIC_SET; +} + +#endif \ No newline at end of file diff --git a/kernel/include/sched/sched.h b/kernel/include/sched/sched.h new file mode 100644 index 0000000..fe4af64 --- /dev/null +++ b/kernel/include/sched/sched.h @@ -0,0 +1,183 @@ +#ifndef TASK_H +#define TASK_H + +#include +#include +#include +#include "capabilities.h" +#include "../memory/vmm.h" +#include "../smp/smp.h" + +#ifndef __ATOMIC_RELAXED +#define __ATOMIC_RELAXED 0 +#define __ATOMIC_ACQUIRE 2 +#define __ATOMIC_RELEASE 3 +#endif + +typedef struct { volatile bool _val; } atomic_bool; + +static inline void atomic_init_bool(atomic_bool *a, bool v) { + __atomic_store_n(&a->_val, v, __ATOMIC_RELAXED); +} +static inline bool atomic_load_bool_acq(const atomic_bool *a) { + return __atomic_load_n(&a->_val, __ATOMIC_ACQUIRE); +} +static inline void atomic_store_bool_rel(atomic_bool *a, bool v) { + __atomic_store_n(&a->_val, v, __ATOMIC_RELEASE); +} + +static inline bool atomic_cas_bool(atomic_bool *a, bool *expected, bool desired) { + return __atomic_compare_exchange_n( + &a->_val, expected, desired, + false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); +} + +typedef struct fd_table fd_table_t; + +typedef struct { + uint8_t data[512] __attribute__((aligned(16))); +} fpu_state_t; + +typedef enum { + TASK_RUNNING = 0, + TASK_READY, + TASK_BLOCKED, + TASK_ZOMBIE, + TASK_DEAD, +} task_state_t; + +typedef enum { + TASK_TYPE_KERNEL = 0, + TASK_TYPE_USER = 1, +} task_type_t; + +#define MAX_PRIORITY 31 +#define DEFAULT_PRIORITY 16 +#define TASK_DEFAULT_TIMESLICE 10 + +typedef struct task { + uint64_t rsp; + uint64_t rip; + uint64_t rbp_save; + uint64_t cr3; + int priority; + bool runnable; + uint8_t is_userspace; + uint8_t _pad0[2]; + uint32_t cpu_id; + char name[32]; + + uint32_t time_slice; + uint32_t time_slice_init; + uint8_t _pad1[4]; + uint64_t total_runtime; + + fpu_state_t* fpu_state; + bool fpu_used; + uint8_t _pad2[3]; + uint32_t last_cpu; + uint64_t cpu_affinity; + + void (*entry)(void*); + void *arg; + + uintptr_t stack_base; + uint64_t user_rsp; + + task_state_t state; + uint8_t _pad3[4]; + + struct task* next; + + uint32_t pid; + uint32_t ppid; + uint32_t uid; + uint32_t gid; + uint64_t capabilities; + + struct task* parent; + struct task* children; + struct task* sibling; + + int exit_code; + volatile bool pending_kill; + uint8_t _pad4[3]; + + uintptr_t brk_start; + uintptr_t brk_current; + uintptr_t brk_max; + vmm_pagemap_t* pagemap; + + uint32_t flags; + uint32_t wait_for_pid; + + uint64_t wakeup_time_ns; + + uint64_t user_saved_rip; + uint64_t user_saved_rbp; + uint64_t user_saved_rbx; + uint64_t user_saved_r12; + uint64_t user_saved_r13; + uint64_t user_saved_r14; + uint64_t user_saved_r15; + uint64_t user_saved_r11; + + fd_table_t *fd_table; + + atomic_bool on_cpu; + +} task_t; + +#define TASK_FLAG_TRACE (1 << 0) +#define TASK_FLAG_VFORK (1 << 1) +#define TASK_FLAG_FORK (1 << 2) +#define TASK_FLAG_STARTED (1 << 3) +#define TASK_FLAG_OWN_PAGEMAP (1 << 4) +#define TASK_FLAG_STACK_DEFERRED (1 << 5) +#define TASK_FLAG_DESTROYED (1U << 31) + +_Static_assert(offsetof(task_t, rsp) == 0, "task_t: rsp"); +_Static_assert(offsetof(task_t, entry) == 120, "task_t: entry — update TASK_ENTRY_OFFSET"); +_Static_assert(offsetof(task_t, arg) == 128, "task_t: arg — update TASK_ARG_OFFSET"); +_Static_assert(offsetof(task_t, stack_base) == 136, "task_t: stack_base"); +_Static_assert(offsetof(task_t, user_rsp) == 144, "task_t: user_rsp — update TASK_USER_RSP_OFFSET"); +_Static_assert(offsetof(task_t, user_saved_rip) == 272, "task_t: user_saved_rip"); +_Static_assert(offsetof(task_t, user_saved_rbp) == 280, "task_t: user_saved_rbp — update TASK_USER_SAVED_RBP_OFFSET"); + +extern task_t* ready_queues[MAX_PRIORITY + 1]; +extern task_t* current_task[MAX_CPUS]; + +void sched_init(void); +void sched_reschedule(void); +void sched_print_stats(void); +void task_yield(void); + +task_t* task_create(const char* name, void (*entry)(void*), void* arg, int priority); + +task_t* task_create_user(const char* name, uintptr_t entry, uintptr_t user_rsp, uint64_t cr3, int priority, vmm_pagemap_t* pagemap, uint32_t uid, uint32_t gid); + +__attribute__((noreturn)) void task_exit(void); +void task_kill(task_t* task); +void task_destroy(task_t* task); +task_t* task_fork(task_t* parent); +task_t* task_find_by_pid(uint32_t pid); +uint32_t task_alloc_pid(void); +void task_reparent(task_t* child, task_t* new_parent); + +#include "spinlock.h" +extern spinlock_t children_lock; +void task_wakeup_waiters(uint32_t pid); +void task_unblock(task_t* t); +void sched_wakeup_sleepers(uint64_t now_ns); +task_t* task_find_foreground(void); +extern volatile uint32_t g_foreground_pid; +void task_set_foreground(uint32_t pid); + +extern void context_switch(task_t* old, task_t* next, task_t** current_task_slot, uint64_t new_cr3); +extern void first_task_start(task_t* task); +extern void task_trampoline(void); +extern void task_trampoline_user(void); +extern void task_trampoline_fork(void); +extern void fpu_save(fpu_state_t* state); +extern void fpu_restore(fpu_state_t* state); +#endif diff --git a/kernel/include/sched/spinlock.h b/kernel/include/sched/spinlock.h new file mode 100644 index 0000000..bfd5129 --- /dev/null +++ b/kernel/include/sched/spinlock.h @@ -0,0 +1,44 @@ +#ifndef SPINLOCK_H +#define SPINLOCK_H + +#include + +typedef struct { + volatile uint32_t ticket; + volatile uint32_t serving; +} spinlock_t; + +#define SPINLOCK_INIT { .ticket = 0, .serving = 0 } + +static inline void spinlock_acquire(spinlock_t* lock) { + uint32_t my_ticket = __atomic_fetch_add(&lock->ticket, 1, __ATOMIC_RELAXED); + while (__atomic_load_n(&lock->serving, __ATOMIC_ACQUIRE) != my_ticket) + asm volatile("pause"); +} + +static inline void spinlock_release(spinlock_t* lock) { + __atomic_fetch_add(&lock->serving, 1, __ATOMIC_RELEASE); +} + +static inline int spinlock_try_acquire(spinlock_t* lock) { + uint32_t serving = __atomic_load_n(&lock->serving, __ATOMIC_RELAXED); + uint32_t ticket = __atomic_load_n(&lock->ticket, __ATOMIC_RELAXED); + if (serving != ticket) return 0; + uint32_t expected = serving; + return __atomic_compare_exchange_n(&lock->ticket, &expected, serving + 1, + 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); +} + +static inline uint64_t spinlock_acquire_irqsave(spinlock_t* lock) { + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + spinlock_acquire(lock); + return flags; +} + +static inline void spinlock_release_irqrestore(spinlock_t* lock, uint64_t flags) { + spinlock_release(lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); +} + +#endif \ No newline at end of file diff --git a/kernel/include/smp/percpu.h b/kernel/include/smp/percpu.h new file mode 100644 index 0000000..bab9f86 --- /dev/null +++ b/kernel/include/smp/percpu.h @@ -0,0 +1,55 @@ +#ifndef PERCPU_H +#define PERCPU_H + +#include +#include "../include/smp/smp.h" + +#define PERCPU_SECTION __attribute__((section(".percpu"))) + +typedef struct { + uint64_t syscall_kernel_rsp; + uint64_t syscall_user_rsp; + uint32_t cpu_id; + uint32_t _pad; + void* current_task; + uint64_t some_counter; + bool need_resched; + uint8_t _pad2[7]; + uint64_t user_saved_rbp; + uint64_t user_saved_rbx; + + uint64_t user_saved_r12; + uint64_t user_saved_r13; + uint64_t user_saved_r14; + uint64_t user_saved_r15; + uint64_t user_saved_r11; + uint64_t user_saved_rip; + uint8_t _pad3[8]; + void* deferred_free_task; + uint64_t sched_stack_top; +} __attribute__((aligned(64))) percpu_t; + +_Static_assert(__builtin_offsetof(percpu_t, syscall_kernel_rsp) == 0, "percpu: kernel_rsp"); +_Static_assert(__builtin_offsetof(percpu_t, syscall_user_rsp) == 8, "percpu: user_rsp"); +_Static_assert(__builtin_offsetof(percpu_t, current_task) == 24, "percpu: current_task"); +_Static_assert(__builtin_offsetof(percpu_t, need_resched) == 40, "percpu: need_resched"); +_Static_assert(__builtin_offsetof(percpu_t, user_saved_rbp) == 48, "percpu: saved_rbp"); +_Static_assert(__builtin_offsetof(percpu_t, user_saved_rbx) == 56, "percpu: saved_rbx"); +_Static_assert(__builtin_offsetof(percpu_t, user_saved_r12) == 64, "percpu: saved_r12"); +_Static_assert(__builtin_offsetof(percpu_t, user_saved_r13) == 72, "percpu: saved_r13"); +_Static_assert(__builtin_offsetof(percpu_t, user_saved_r14) == 80, "percpu: saved_r14"); +_Static_assert(__builtin_offsetof(percpu_t, user_saved_r15) == 88, "percpu: saved_r15"); +_Static_assert(__builtin_offsetof(percpu_t, user_saved_r11) == 96, "percpu: saved_r11"); +_Static_assert(__builtin_offsetof(percpu_t, user_saved_rip) == 104, "percpu: saved_rip"); + +extern percpu_t percpu; +extern percpu_t* percpu_regions[MAX_CPUS]; +extern bool g_has_fsgsbase; + +percpu_t* get_percpu(void); +percpu_t* get_percpu_mut(void); +void init_percpu_regions(void); +void set_percpu_base(percpu_t* base); +#define current_cpu_id() (get_percpu()->cpu_id) + +#endif diff --git a/kernel/include/smp/smp.h b/kernel/include/smp/smp.h new file mode 100644 index 0000000..50cce88 --- /dev/null +++ b/kernel/include/smp/smp.h @@ -0,0 +1,60 @@ +#ifndef SMP_H +#define SMP_H + +#include +#include +#include +#include + +#define AP_STACK_SIZE 16384 +#define MAX_CPUS 256 + +#define MAX_TLB_ADDRESSES 32 + +typedef struct { + volatile bool pending; + uintptr_t addresses[MAX_TLB_ADDRESSES]; + size_t count; +} tlb_shootdown_t; + +extern tlb_shootdown_t tlb_shootdown_queue[MAX_CPUS]; +typedef enum { + CPU_UNINITIALIZED = 0, + CPU_BOOTED, + CPU_ONLINE, + CPU_OFFLINE, + CPU_FAULTED +} cpu_state_t; + +typedef struct { + uint32_t lapic_id; + uint32_t processor_id; + uint32_t acpi_id; + cpu_state_t state; + bool is_bsp; + uint64_t stack_top; + uint32_t cpu_index; + uint16_t tss_selector; +} cpu_info_t; + +typedef struct { + uint32_t cpu_count; + uint32_t online_count; + uint32_t bsp_lapic_id; + uint64_t lapic_base; + cpu_info_t cpus[256]; +} smp_info_t; + +void smp_init(struct limine_mp_response* mp_response); +void smp_boot_aps(struct limine_mp_response* mp_response); +smp_info_t* smp_get_info(void); +cpu_info_t* smp_get_current_cpu(void); +uint32_t smp_get_cpu_count(void); +uint32_t smp_get_online_count(void); +bool smp_is_bsp(void); +void smp_print_info(void); +void smp_print_info_fb(void); +void smp_wait_for_ready(void); +void ap_entry_point(struct limine_mp_info* cpu_info); +void sched_notify_ready(void); +#endif \ No newline at end of file diff --git a/kernel/include/sse/fpu.h b/kernel/include/sse/fpu.h new file mode 100644 index 0000000..17b8ec0 --- /dev/null +++ b/kernel/include/sse/fpu.h @@ -0,0 +1,17 @@ +#ifndef FPU_H +#define FPU_H + +#include +#include + +void fpu_init(void); +bool fpu_detect(void); +void fpu_set_control_word(uint16_t cw); +uint16_t fpu_get_control_word(void); +void fpu_set_status_word(uint16_t sw); +uint16_t fpu_get_status_word(void); +void fpu_set_tag_word(uint16_t tw); +uint16_t fpu_get_tag_word(void); +void fpu_reset(void); + +#endif \ No newline at end of file diff --git a/kernel/include/sse/sse.h b/kernel/include/sse/sse.h new file mode 100644 index 0000000..3bd11e5 --- /dev/null +++ b/kernel/include/sse/sse.h @@ -0,0 +1,31 @@ +#ifndef SSE_H +#define SSE_H + +#include +#include +#include + +#define MXCSR_DEFAULT 0x1F80 +#define MXCSR_FLUSH_TO_ZERO (1 << 15) +#define MXCSR_DENORMALS_ARE_ZERO (1 << 6) + +bool sse_supported(void); +bool sse2_supported(void); +bool sse3_supported(void); +bool ssse3_supported(void); +bool sse4_1_supported(void); +bool sse4_2_supported(void); +bool avx_supported(void); +bool avx2_supported(void); +void sse_init(void); +void sse_set_mxcsr(uint32_t mxcsr); +uint32_t sse_get_mxcsr(void); +void sse_memcpy_fast(void* dest, const void* src, size_t n); +void sse_memset_fast(void* dest, int value, size_t n); +bool mmx_supported(void); +void mmx_enter(void); +void mmx_exit(void); +void print_simd_cpuid(void); +void enable_fsgsbase(void); + +#endif \ No newline at end of file diff --git a/kernel/include/syscall/errno.h b/kernel/include/syscall/errno.h new file mode 100644 index 0000000..2b049cc --- /dev/null +++ b/kernel/include/syscall/errno.h @@ -0,0 +1,66 @@ +#ifndef ERRNO_H +#define ERRNO_H + +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define ERANGE 34 +#define EDEADLK 35 +#define ENAMETOOLONG 36 +#define ENOLCK 37 +#define ENOSYS 38 +#define ENOTEMPTY 39 +#define ELOOP 40 +#define ENOMSG 42 +#define EIDRM 43 +#define ENOSTR 60 +#define ENODATA 61 +#define ETIME 62 +#define ENOSR 63 +#define EREMOTE 66 +#define ENOLINK 67 +#define EPROTO 71 +#define EMULTIHOP 72 +#define EBADMSG 74 +#define EOVERFLOW 75 +#define EILSEQ 84 +#define EUSERS 87 +#define ENOTSOCK 88 +#define EOPNOTSUPP 95 +#define EADDRINUSE 98 +#define ECONNREFUSED 111 +#define ETIMEDOUT 110 + +#define ECERVUS_BASE 200 +#define ECAPABILITY 200 +#define ETASKDEAD 201 +#define EBADCR3 202 + +#endif \ No newline at end of file diff --git a/kernel/include/syscall/syscall.h b/kernel/include/syscall/syscall.h new file mode 100644 index 0000000..d8c3899 --- /dev/null +++ b/kernel/include/syscall/syscall.h @@ -0,0 +1,12 @@ +#ifndef SYSCALL_H +#define SYSCALL_H + +#include +#include "syscall_nums.h" +#include "../sched/capabilities.h" + +void syscall_init(void); + +int64_t syscall_handler_c(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t user_rip); + +#endif \ No newline at end of file diff --git a/kernel/include/syscall/syscall_nums.h b/kernel/include/syscall/syscall_nums.h new file mode 100644 index 0000000..ac526d5 --- /dev/null +++ b/kernel/include/syscall/syscall_nums.h @@ -0,0 +1,142 @@ +#ifndef SYSCALL_NUMS_H +#define SYSCALL_NUMS_H + +#define SYS_EXIT 0 +#define SYS_EXIT_GROUP 1 +#define SYS_GETPID 2 +#define SYS_GETPPID 3 +#define SYS_FORK 4 +#define SYS_WAIT 5 +#define SYS_EXECVE 14 +#define SYS_YIELD 6 +#define SYS_GETUID 7 +#define SYS_GETGID 8 +#define SYS_SETUID 9 +#define SYS_SETGID 10 +#define SYS_CAP_GET 11 +#define SYS_CAP_DROP 12 +#define SYS_TASK_INFO 13 + +#define SYS_READ 20 +#define SYS_WRITE 21 +#define SYS_OPEN 22 +#define SYS_CLOSE 23 +#define SYS_SEEK 24 +#define SYS_STAT 25 +#define SYS_FSTAT 26 +#define SYS_IOCTL 27 +#define SYS_DUP 28 +#define SYS_DUP2 29 +#define SYS_PIPE 30 +#define SYS_FCNTL 31 +#define SYS_READDIR 32 + +#define SYS_MMAP 40 +#define SYS_MUNMAP 41 +#define SYS_MPROTECT 42 +#define SYS_BRK 43 + +#define SYS_CLOCK_GET 60 +#define SYS_SLEEP_NS 61 +#define SYS_UPTIME 62 +#define SYS_MEMINFO 63 + +#define SYS_FUTEX_WAIT 80 +#define SYS_FUTEX_WAKE 81 + +#define SYS_CERVUS_BASE 512 + +#define SYS_DBG_PRINT 512 +#define SYS_DBG_DUMP 513 +#define SYS_TASK_SPAWN 514 +#define SYS_TASK_KILL 515 +#define SYS_SHMEM_CREATE 516 +#define SYS_SHMEM_MAP 517 +#define SYS_SHMEM_UNMAP 518 +#define SYS_IPC_SEND 519 +#define SYS_IPC_RECV 520 +#define SYS_IOPORT_READ 521 +#define SYS_IOPORT_WRITE 522 +#define SYS_SHUTDOWN 523 +#define SYS_REBOOT 524 + +#define SYS_DISK_MOUNT 530 +#define SYS_DISK_UMOUNT 531 +#define SYS_DISK_FORMAT 532 +#define SYS_DISK_INFO 533 +#define SYS_UNLINK 534 +#define SYS_RMDIR 535 +#define SYS_MKDIR 536 +#define SYS_RENAME 537 + +#define SYS_DISK_READ_RAW 540 +#define SYS_DISK_WRITE_RAW 541 +#define SYS_DISK_PARTITION 542 +#define SYS_DISK_MKFS_FAT32 543 +#define SYS_DISK_LIST_PARTS 544 + +#define SYS_DISK_BIOS_INSTALL 545 +#define SYS_LIST_MOUNTS 546 +#define SYS_STATVFS 547 + +#define SYSCALL_TABLE_SIZE 548 + +#define PROT_NONE 0x0 +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define MAP_PRIVATE 0x02 +#define MAP_ANONYMOUS 0x20 +#define MAP_FIXED 0x10 +#define MAP_FAILED ((void*)-1) + +#define WNOHANG 0x1 + +#define CLOCK_REALTIME 0 +#define CLOCK_MONOTONIC 1 + +typedef struct { + uint32_t pid; + uint32_t ppid; + uint32_t uid; + uint32_t gid; + uint64_t capabilities; + char name[32]; + uint32_t state; + uint32_t priority; + uint64_t total_runtime_ns; +} cervus_task_info_t; + +typedef struct { + int64_t tv_sec; + int64_t tv_nsec; +} cervus_timespec_t; + +typedef struct { + uint64_t total_bytes; + uint64_t free_bytes; + uint64_t used_bytes; + uint64_t usable_bytes; + uint64_t page_size; +} cervus_meminfo_t; + +typedef struct __attribute__((packed)) { + uint8_t boot_flag; + uint8_t type; + uint32_t lba_start; + uint32_t sector_count; +} cervus_mbr_part_t; + +typedef struct __attribute__((packed)) { + char disk_name[32]; + char part_name[32]; + uint32_t part_num; + uint8_t type; + uint8_t bootable; + uint64_t lba_start; + uint64_t sector_count; + uint64_t size_bytes; +} cervus_part_info_t; + +#endif \ No newline at end of file diff --git a/kernel/src/acpi/acpi.c b/kernel/src/acpi/acpi.c new file mode 100644 index 0000000..0f561f3 --- /dev/null +++ b/kernel/src/acpi/acpi.c @@ -0,0 +1,397 @@ +#include "../../include/acpi/acpi.h" +#include "../../include/io/serial.h" +#include "../../include/io/ports.h" +#include "../../include/memory/pmm.h" +#include + +static acpi_rsdp2_t *rsdp; +static acpi_xsdt_t *xsdt; +static acpi_rsdt_t *rsdt; + +static uint8_t s5_slp_typa = 0; +static uint8_t s5_slp_typb = 0; +static bool s5_parsed = false; + +static inline void *phys_to_virt(uintptr_t phys) { + return (void *)(phys + pmm_get_hhdm_offset()); +} + +static bool checksum(void *base, size_t len) { + uint8_t sum = 0; + uint8_t *b = base; + for (size_t i = 0; i < len; i++) + sum += b[i]; + return sum == 0; +} + +static bool parse_s5_from_aml(const uint8_t *aml, size_t aml_len) { + if (!aml || aml_len < 40) return false; + + for (size_t i = 0; i + 20 < aml_len; i++) { + if (aml[i] == '_' && aml[i+1] == 'S' && + aml[i+2] == '5' && aml[i+3] == '_') { + + size_t pos = i + 4; + + for (size_t j = pos; j < pos + 4 && j < aml_len; j++) { + if (aml[j] == 0x12) { + size_t pkg = j + 1; + + if (pkg >= aml_len) continue; + uint8_t lead = aml[pkg]; + size_t pkg_len_bytes = 1; + if (lead & 0xC0) { + pkg_len_bytes = (lead >> 6) + 1; + } + pkg += pkg_len_bytes; + + if (pkg >= aml_len) continue; + + pkg++; + + if (pkg >= aml_len) continue; + + if (aml[pkg] == 0x0A) { + pkg++; + if (pkg >= aml_len) continue; + s5_slp_typa = aml[pkg]; + pkg++; + } else if (aml[pkg] == 0x00) { + s5_slp_typa = 0; + pkg++; + } else if (aml[pkg] == 0x01) { + s5_slp_typa = 1; + pkg++; + } else { + s5_slp_typa = aml[pkg]; + pkg++; + } + + if (pkg >= aml_len) continue; + + if (aml[pkg] == 0x0A) { + pkg++; + if (pkg >= aml_len) continue; + s5_slp_typb = aml[pkg]; + } else if (aml[pkg] == 0x00) { + s5_slp_typb = 0; + } else if (aml[pkg] == 0x01) { + s5_slp_typb = 1; + } else { + s5_slp_typb = aml[pkg]; + } + + serial_printf("ACPI: parsed S5 from AML: SLP_TYPa=%u SLP_TYPb=%u\n", + s5_slp_typa, s5_slp_typb); + return true; + } + } + } + } + return false; +} + +static void parse_s5(void) { + if (s5_parsed) return; + s5_parsed = true; + + acpi_fadt_t *fadt = (acpi_fadt_t *)acpi_find_table("FACP", 0); + if (!fadt) { + serial_writestring("ACPI: no FADT, cannot parse S5\n"); + return; + } + + uintptr_t dsdt_phys = 0; + if (fadt->header.length >= 148 && fadt->x_dsdt) + dsdt_phys = (uintptr_t)fadt->x_dsdt; + if (!dsdt_phys) + dsdt_phys = (uintptr_t)fadt->dsdt; + + if (!dsdt_phys) { + serial_writestring("ACPI: no DSDT address in FADT\n"); + return; + } + + acpi_sdt_header_t *dsdt = phys_to_virt(dsdt_phys); + + if (memcmp(dsdt->signature, "DSDT", 4) != 0) { + serial_writestring("ACPI: invalid DSDT signature\n"); + return; + } + + serial_printf("ACPI: DSDT at phys=0x%llx length=%u\n", + (unsigned long long)dsdt_phys, dsdt->length); + + const uint8_t *aml = (const uint8_t *)dsdt + sizeof(acpi_sdt_header_t); + size_t aml_len = dsdt->length - sizeof(acpi_sdt_header_t); + + if (parse_s5_from_aml(aml, aml_len)) + return; + + for (uint64_t idx = 0; ; idx++) { + acpi_sdt_header_t *ssdt = acpi_find_table("SSDT", idx); + if (!ssdt) break; + + const uint8_t *s_aml = (const uint8_t *)ssdt + sizeof(acpi_sdt_header_t); + size_t s_len = ssdt->length - sizeof(acpi_sdt_header_t); + + if (parse_s5_from_aml(s_aml, s_len)) + return; + } + + serial_writestring("ACPI: S5 object not found in DSDT/SSDT, using defaults\n"); + s5_slp_typa = 5; + s5_slp_typb = 0; +} + +static void acpi_enable_mode(acpi_fadt_t *fadt) { + if (!fadt->smi_command_port || !fadt->acpi_enable) + return; + + uint16_t pm1a_val = inw(fadt->pm1a_control_block); + if (pm1a_val & 1) { + serial_writestring("ACPI: already in ACPI mode\n"); + return; + } + + serial_writestring("ACPI: enabling ACPI mode...\n"); + outb((uint16_t)fadt->smi_command_port, fadt->acpi_enable); + + for (int i = 0; i < 3000; i++) { + pm1a_val = inw(fadt->pm1a_control_block); + if (pm1a_val & 1) { + serial_writestring("ACPI: ACPI mode enabled\n"); + return; + } + for (volatile int j = 0; j < 10000; j++) + asm volatile("pause"); + } + serial_writestring("ACPI: WARNING - timeout enabling ACPI mode\n"); +} + +void acpi_init(void) { + if (!rsdp_request.response) { + serial_writestring("ACPI: no RSDP\n"); + return; + } + + rsdp = (acpi_rsdp2_t *)rsdp_request.response->address; + + if (!checksum(&rsdp->rsdp_v1, sizeof(acpi_rsdp_t))) { + serial_writestring("ACPI: bad RSDP checksum\n"); + return; + } + + if (rsdp->rsdp_v1.revision >= 2 && rsdp->xsdt_address) { + xsdt = phys_to_virt(rsdp->xsdt_address); + if (!checksum(xsdt, xsdt->header.length)) + xsdt = NULL; + } + + if (!xsdt && rsdp->rsdp_v1.rsdt_address) { + rsdt = phys_to_virt(rsdp->rsdp_v1.rsdt_address); + if (!checksum(rsdt, rsdt->header.length)) + rsdt = NULL; + } + + if (!xsdt && !rsdt) + return; + + parse_s5(); +} + +void *acpi_find_table(const char *sig, uint64_t index) { + uint64_t count = 0; + + if (xsdt) { + size_t n = (xsdt->header.length - sizeof(acpi_sdt_header_t)) / 8; + for (size_t i = 0; i < n; i++) { + acpi_sdt_header_t *h = phys_to_virt(xsdt->sdt_pointers[i]); + if (!memcmp(h->signature, sig, 4)) { + if (count++ == index) + return h; + } + } + } else if (rsdt) { + size_t n = (rsdt->header.length - sizeof(acpi_sdt_header_t)) / 4; + for (size_t i = 0; i < n; i++) { + acpi_sdt_header_t *h = phys_to_virt(rsdt->sdt_pointers[i]); + if (!memcmp(h->signature, sig, 4)) { + if (count++ == index) + return h; + } + } + } + + return NULL; +} + +void acpi_print_tables(void) { + serial_writestring("ACPI tables:\n"); + + for (uint64_t i = 0;; i++) { + acpi_sdt_header_t *h = acpi_find_table("APIC", i); + if (!h) break; + serial_writestring(" - APIC (MADT)\n"); + } + + for (uint64_t i = 0;; i++) { + acpi_sdt_header_t *h = acpi_find_table("HPET", i); + if (!h) break; + serial_writestring(" - HPET\n"); + } + + for (uint64_t i = 0;; i++) { + acpi_sdt_header_t *h = acpi_find_table("MCFG", i); + if (!h) break; + serial_writestring(" - MCFG (PCIe)\n"); + } + + for (uint64_t i = 0;; i++) { + acpi_sdt_header_t *h = acpi_find_table("FACP", i); + if (!h) break; + serial_writestring(" - FACP (FADT)\n"); + } +} + +static void acpi_write_gas(const acpi_gas_t *gas, uint64_t value) { + if (gas->address == 0) return; + + switch (gas->address_space_id) { + case 0x00: + { + volatile uint8_t *mmio = phys_to_virt(gas->address); + switch (gas->register_bit_width) { + case 8: *(volatile uint8_t *)mmio = (uint8_t)value; break; + case 16: *(volatile uint16_t *)mmio = (uint16_t)value; break; + case 32: *(volatile uint32_t *)mmio = (uint32_t)value; break; + case 64: *(volatile uint64_t *)mmio = value; break; + } + break; + } + case 0x01: + { + uint16_t port = (uint16_t)gas->address; + switch (gas->register_bit_width) { + case 8: outb(port, (uint8_t)value); break; + case 16: outw(port, (uint16_t)value); break; + case 32: outl(port, (uint32_t)value); break; + } + break; + } + } +} + +void acpi_shutdown(void) { + acpi_fadt_t *fadt = (acpi_fadt_t *)acpi_find_table("FACP", 0); + if (!fadt) { + serial_writestring("ACPI shutdown: FADT not found\n"); + goto fallback; + } + + acpi_enable_mode(fadt); + + parse_s5(); + + serial_printf("ACPI shutdown: SLP_TYPa=%u SLP_TYPb=%u\n", + s5_slp_typa, s5_slp_typb); + serial_printf("ACPI shutdown: PM1a_CNT=0x%x PM1b_CNT=0x%x\n", + fadt->pm1a_control_block, fadt->pm1b_control_block); + + asm volatile("cli"); + + uint16_t pm1a_value = (s5_slp_typa << 10) | (1 << 13); + outw(fadt->pm1a_control_block, pm1a_value); + + if (fadt->pm1b_control_block) { + uint16_t pm1b_value = (s5_slp_typb << 10) | (1 << 13); + outw(fadt->pm1b_control_block, pm1b_value); + } + + for (volatile int i = 0; i < 100000; i++) + asm volatile("pause"); + + if (fadt->header.length >= 244) { + if (fadt->x_pm1a_control_block.address) { + serial_writestring("ACPI shutdown: trying extended PM1a...\n"); + acpi_write_gas(&fadt->x_pm1a_control_block, pm1a_value); + } + if (fadt->x_pm1b_control_block.address) { + uint16_t pm1b_value = (s5_slp_typb << 10) | (1 << 13); + acpi_write_gas(&fadt->x_pm1b_control_block, pm1b_value); + } + + for (volatile int i = 0; i < 100000; i++) + asm volatile("pause"); + } + +fallback: + serial_writestring("ACPI shutdown: trying QEMU/Bochs port 0x604...\n"); + outw(0x604, 0x2000); + + for (volatile int i = 0; i < 100000; i++) + asm volatile("pause"); + + serial_writestring("ACPI shutdown: trying VirtualBox port 0x4004...\n"); + outw(0x4004, 0x3400); + + for (volatile int i = 0; i < 100000; i++) + asm volatile("pause"); + + serial_writestring("ACPI shutdown: trying legacy APM...\n"); + outw(0xB004, 0x2000); + + serial_writestring("ACPI shutdown: all methods failed, halting CPU\n"); + for (;;) + asm volatile("cli; hlt"); +} + +void acpi_reboot(void) { + acpi_fadt_t *fadt = (acpi_fadt_t *)acpi_find_table("FACP", 0); + asm volatile("cli"); + + if (fadt && fadt->header.length >= 129) { + if ((fadt->flags & (1 << 10)) && fadt->reset_reg.address) { + serial_printf("ACPI reboot: using FADT reset register " + "(space=%u addr=0x%llx val=0x%x)\n", + fadt->reset_reg.address_space_id, + (unsigned long long)fadt->reset_reg.address, + fadt->reset_value); + + acpi_write_gas(&fadt->reset_reg, fadt->reset_value); + + for (volatile int i = 0; i < 100000; i++) + asm volatile("pause"); + } + } + + serial_writestring("ACPI reboot: trying 8042 keyboard controller reset...\n"); + + for (int i = 0; i < 10000; i++) { + if (!(inb(0x64) & 0x02)) + break; + for (volatile int j = 0; j < 100; j++) + asm volatile("pause"); + } + + outb(0x64, 0xFE); + + for (volatile int i = 0; i < 100000; i++) + asm volatile("pause"); + + serial_writestring("ACPI reboot: triggering triple fault...\n"); + + struct { + uint16_t limit; + uint64_t base; + } __attribute__((packed)) null_idt = { 0, 0 }; + + asm volatile( + "lidt %0\n" + "int $3\n" + :: "m"(null_idt) + ); + + for (;;) + asm volatile("cli; hlt"); +} \ No newline at end of file diff --git a/kernel/src/apic/apic.c b/kernel/src/apic/apic.c new file mode 100644 index 0000000..f6b63e4 --- /dev/null +++ b/kernel/src/apic/apic.c @@ -0,0 +1,212 @@ +#include "../../include/apic/apic.h" +#include "../../include/io/serial.h" +#include "../../include/io/ports.h" +#include "../../include/acpi/acpi.h" +#include "../../include/memory/pmm.h" +#include "../../include/memory/vmm.h" +#include +#include + +uintptr_t lapic_base = 0; +uintptr_t ioapic_base = 0; +uintptr_t hpet_base = 0; +uint32_t hpet_period = 0; +static acpi_madt_t* madt = NULL; +static acpi_hpet_t* hpet_table = NULL; + +uint64_t g_hpet_boot_counter = 0; + +static inline uintptr_t phys_to_virt(uintptr_t phys) { + return phys + pmm_get_hhdm_offset(); +} + +static bool map_mmio_region(uintptr_t phys_base, size_t size) { + vmm_pagemap_t* kernel_pagemap = vmm_get_kernel_pagemap(); + if (!kernel_pagemap) return false; + + for (uintptr_t offset = 0; offset < size; offset += 0x1000) { + uintptr_t phys_addr = phys_base + offset; + uintptr_t virt_addr = phys_to_virt(phys_addr); + + uintptr_t mapped_phys; + if (vmm_virt_to_phys(kernel_pagemap, virt_addr, &mapped_phys)) { + if (mapped_phys != phys_addr) return false; + continue; + } + + if (!vmm_map_page(kernel_pagemap, virt_addr, phys_addr, + VMM_PRESENT | VMM_WRITE | VMM_NOEXEC)) { + return false; + } + } + + return true; +} + +bool hpet_init(void) { + hpet_table = (acpi_hpet_t*)acpi_find_table("HPET", 0); + if (!hpet_table) return false; + + uintptr_t phys_base = hpet_table->address; + if (!map_mmio_region(phys_base, 0x1000)) return false; + + hpet_base = phys_to_virt(phys_base); + + volatile uint32_t* hpet_regs = (volatile uint32_t*)hpet_base; + hpet_period = hpet_regs[HPET_PERIOD / 4]; + if (hpet_period == 0) return false; + + uint64_t config = *(volatile uint64_t*)(hpet_base + HPET_CONFIG); + config |= HPET_ENABLE_CNF; + if (hpet_table->legacy_replacement) config |= HPET_LEGACY_CNF; + *(volatile uint64_t*)(hpet_base + HPET_CONFIG) = config; + + for (volatile int _i = 0; _i < 1000; _i++) asm volatile("pause"); + g_hpet_boot_counter = hpet_read_counter(); + + return true; +} + +bool hpet_is_available(void) { + return hpet_base != 0 && hpet_period != 0; +} + +uint64_t hpet_read_counter(void) { + if (!hpet_base) return 0; + + if (hpet_table->counter_size) { + return *(volatile uint64_t*)(hpet_base + HPET_MAIN_COUNTER); + } else { + return *(volatile uint32_t*)(hpet_base + HPET_MAIN_COUNTER); + } +} + +uint64_t hpet_get_frequency(void) { + if (!hpet_period) return 0; + return 1000000000000000ULL / hpet_period; +} + +uint64_t hpet_elapsed_ns(void) { + if (!hpet_is_available()) return 0; + uint64_t delta = hpet_read_counter() - g_hpet_boot_counter; + return (delta * (uint64_t)hpet_period) / 1000000ULL; +} + +void hpet_sleep_ns(uint64_t nanoseconds) { + if (!hpet_base || !hpet_period) return; + + uint64_t ticks_needed = (nanoseconds * 1000000ULL) / hpet_period; + if (ticks_needed == 0) ticks_needed = 1; + + uint64_t start = hpet_read_counter(); + uint64_t target = start + ticks_needed; + + if (target > start) { + while (hpet_read_counter() < target) asm volatile("pause"); + } else { + while (hpet_read_counter() > start) asm volatile("pause"); + while (hpet_read_counter() < (target - 0xFFFFFFFFFFFFFFFFULL)) asm volatile("pause"); + } +} + +void hpet_sleep_us(uint64_t microseconds) { + hpet_sleep_ns(microseconds * 1000ULL); +} + +void hpet_sleep_ms(uint64_t milliseconds) { + hpet_sleep_ns(milliseconds * 1000000ULL); +} + +static void parse_madt(void) { + madt = (acpi_madt_t*)acpi_find_table("APIC", 0); + if (!madt) return; + + if (!map_mmio_region(madt->local_apic_address, 0x1000)) return; + lapic_base = phys_to_virt(madt->local_apic_address); + + uint8_t* entries = madt->entries; + uint32_t length = madt->header.length; + uint8_t* end = (uint8_t*)madt + length; + + while (entries < end) { + madt_entry_header_t* header = (madt_entry_header_t*)entries; + + switch (header->type) { + case MADT_ENTRY_LAPIC: { + madt_lapic_entry_t* lapic_entry = (madt_lapic_entry_t*)entries; + (void)lapic_entry; + break; + } + + case MADT_ENTRY_IOAPIC: { + madt_ioapic_entry_t* ioapic_entry = (madt_ioapic_entry_t*)entries; + if (!map_mmio_region(ioapic_entry->ioapic_address, 0x1000)) break; + ioapic_base = phys_to_virt(ioapic_entry->ioapic_address); + break; + } + + default: + break; + } + + entries += header->length; + } +} + +bool apic_is_available(void) { + return madt != NULL; +} + +void apic_init(void) { + parse_madt(); + if (!madt) return; + if (!lapic_base) return; + + hpet_init(); + lapic_enable(); + + if (ioapic_base) { + uint32_t max_redirects = ioapic_get_max_redirects(ioapic_base); + for (uint32_t i = 0; i < max_redirects; i++) { + ioapic_mask_irq(i); + } + } +} + +void apic_setup_irq(uint8_t irq, uint8_t vector, bool mask, uint32_t flags) { + if (!ioapic_base) return; + + uint32_t redir_flags = IOAPIC_DELIVERY_FIXED | flags; + if (mask) redir_flags |= IOAPIC_INT_MASKED; + + ioapic_redirect_irq(irq, vector, redir_flags); +} + +void apic_timer_calibrate(void) { + if (!hpet_is_available()) return; + + uint64_t measurement_time_ns = 10000000ULL; + uint64_t hpet_ticks_needed = (measurement_time_ns * 1000000ULL) / hpet_period; + + lapic_write(LAPIC_TIMER_DCR, 0x3); + lapic_write(LAPIC_TIMER_ICR, 0xFFFFFFFF); + lapic_write(LAPIC_TIMER, LAPIC_TIMER_MASKED | 0xFF); + lapic_write(LAPIC_TIMER, 0xFF); + + uint64_t hpet_start = hpet_read_counter(); + uint64_t hpet_target = hpet_start + hpet_ticks_needed; + + while (hpet_read_counter() < hpet_target) asm volatile("pause"); + + lapic_write(LAPIC_TIMER, LAPIC_TIMER_MASKED | 0xFF); + uint32_t remaining = lapic_read(LAPIC_TIMER_CCR); + + if (remaining == 0 || remaining == 0xFFFFFFFF) return; + + uint32_t ticks_elapsed = 0xFFFFFFFF - remaining; + uint32_t ticks_per_10ms = (uint32_t)((ticks_elapsed * 10000000ULL) / measurement_time_ns); + + if (ticks_per_10ms == 0) return; + + lapic_timer_init(0x20, ticks_per_10ms, true, 0x3); +} \ No newline at end of file diff --git a/kernel/src/apic/ioapic.c b/kernel/src/apic/ioapic.c new file mode 100644 index 0000000..c0917e6 --- /dev/null +++ b/kernel/src/apic/ioapic.c @@ -0,0 +1,79 @@ +#include "../../include/apic/apic.h" +#include "../../include/io/serial.h" +#include "../../include/memory/pmm.h" +#include + +static void ioapic_write_internal(uintptr_t base, uint32_t reg, uint32_t value) { + if (!base) { + serial_printf("IOAPIC: Attempt to write to unmapped IOAPIC (reg: 0x%x)\n", reg); + return; + } + + volatile uint32_t* ioregsel = (volatile uint32_t*)base; + volatile uint32_t* iowin = (volatile uint32_t*)(base + 0x10); + + *ioregsel = reg; + *iowin = value; +} + +static uint32_t ioapic_read_internal(uintptr_t base, uint32_t reg) { + if (!base) { + serial_printf("IOAPIC: Attempt to read from unmapped IOAPIC (reg: 0x%x)\n", reg); + return 0; + } + + volatile uint32_t* ioregsel = (volatile uint32_t*)base; + volatile uint32_t* iowin = (volatile uint32_t*)(base + 0x10); + + *ioregsel = reg; + return *iowin; +} + +void ioapic_write(uintptr_t base, uint32_t reg, uint32_t value) { + ioapic_write_internal(base, reg, value); +} + +uint32_t ioapic_read(uintptr_t base, uint32_t reg) { + return ioapic_read_internal(base, reg); +} + +uint32_t ioapic_get_max_redirects(uintptr_t base) { + uint32_t version = ioapic_read(base, IOAPIC_VERSION); + return ((version >> 16) & 0xFF) + 1; +} + +void ioapic_redirect_irq(uint8_t irq, uint8_t vector, uint32_t flags) { + if (!ioapic_base) return; + + uint32_t max_redirects = ioapic_get_max_redirects(ioapic_base); + if (irq >= max_redirects) { + serial_printf("IOAPIC: IRQ %u out of range (max %u)\n", irq, max_redirects); + return; + } + + uint32_t low = vector | flags; + uint32_t high = 0; + + uint32_t redir_reg = IOAPIC_REDIR_START + irq * 2; + + ioapic_write(ioapic_base, redir_reg, low); + ioapic_write(ioapic_base, redir_reg + 1, high); + + serial_printf("IOAPIC: IRQ %u redirected to vector 0x%x\n", irq, vector); +} + +void ioapic_mask_irq(uint8_t irq) { + if (!ioapic_base) return; + + uint32_t redir_reg = IOAPIC_REDIR_START + irq * 2; + uint32_t current = ioapic_read(ioapic_base, redir_reg); + ioapic_write(ioapic_base, redir_reg, current | IOAPIC_INT_MASKED); +} + +void ioapic_unmask_irq(uint8_t irq) { + if (!ioapic_base) return; + + uint32_t redir_reg = IOAPIC_REDIR_START + irq * 2; + uint32_t current = ioapic_read(ioapic_base, redir_reg); + ioapic_write(ioapic_base, redir_reg, current & ~IOAPIC_INT_MASKED); +} \ No newline at end of file diff --git a/kernel/src/apic/lapic.c b/kernel/src/apic/lapic.c new file mode 100644 index 0000000..56bc211 --- /dev/null +++ b/kernel/src/apic/lapic.c @@ -0,0 +1,207 @@ +#include "../../include/apic/apic.h" +#include "../../include/io/serial.h" +#include "../../include/io/ports.h" +#include "../../include/memory/pmm.h" +#include "../../include/smp/smp.h" +#include "../../include/interrupts/interrupts.h" +#include + +static inline uintptr_t phys_to_virt(uintptr_t phys) { + return phys + pmm_get_hhdm_offset(); +} + +void lapic_write(uint32_t reg, uint32_t value) { + if (!lapic_base) { + serial_printf("LAPIC: Attempt to write to unmapped LAPIC (reg: 0x%x)\n", reg); + return; + } + + if (reg & 0x3) { + serial_printf("LAPIC: Unaligned register access: 0x%x\n", reg); + return; + } + + volatile uint32_t* addr = (volatile uint32_t*)(lapic_base + reg); + *addr = value; + + (void)*addr; +} + +uint32_t lapic_read(uint32_t reg) { + if (!lapic_base) { + serial_printf("LAPIC: Attempt to read from unmapped LAPIC (reg: 0x%x)\n", reg); + return 0; + } + + if (reg & 0x3) { + serial_printf("LAPIC: Unaligned register access: 0x%x\n", reg); + return 0; + } + + volatile uint32_t* addr = (volatile uint32_t*)(lapic_base + reg); + return *addr; +} + +void lapic_enable(void) { + if (!lapic_base) return; + + lapic_write(LAPIC_SIVR, lapic_read(LAPIC_SIVR) | LAPIC_ENABLE | LAPIC_SPURIOUS_VECTOR); + serial_printf("LAPIC enabled, ID: 0x%x\n", lapic_get_id()); +} + +uint32_t lapic_get_id(void) { + return (lapic_read(LAPIC_ID) >> 24) & 0xFF; +} + +void lapic_eoi(void) { + lapic_write(LAPIC_EOI, 0); +} + +void lapic_timer_init(uint32_t vector, uint32_t count, bool periodic, uint8_t divisor) { + serial_printf("Initializing LAPIC timer: vector=0x%x, count=%u, periodic=%d, divisor=%u\n", + vector, count, periodic, divisor); + + if (count == 0) { + serial_writestring("Warning: APIC timer count is 0, timer will not generate interrupts\n"); + } + + lapic_write(LAPIC_TIMER, LAPIC_TIMER_MASKED); + + lapic_write(LAPIC_TIMER_DCR, divisor & 0x7); + + lapic_write(LAPIC_TIMER_ICR, count); + + uint32_t timer_config = vector & 0xFF; + if (periodic) { + timer_config |= LAPIC_TIMER_PERIODIC; + } + + lapic_write(LAPIC_TIMER, timer_config); + + uint32_t current = lapic_read(LAPIC_TIMER_CCR); + serial_printf("LAPIC timer started: current count: %u\n", current); +} + +void lapic_timer_stop(void) { + lapic_write(LAPIC_TIMER, LAPIC_TIMER_MASKED); +} + +uint32_t lapic_timer_get_current(void) { + return lapic_read(LAPIC_TIMER_CCR); +} + +void lapic_send_ipi(uint32_t target_lapic_id, uint8_t vector) +{ + uint32_t icr_low = vector | (0 << 8) | (1 << 14); + uint32_t icr_high = target_lapic_id << 24; + + lapic_write(0x310, icr_high); + lapic_write(0x300, icr_low); + + while (lapic_read(0x300) & (1 << 12)) + asm volatile ("pause"); + + serial_printf("Sent IPI vector 0x%02x to LAPIC %u\n", vector, target_lapic_id); +} + +void lapic_send_ipi_to_all_but_self(uint8_t vector) +{ + uint32_t icr_low = vector | (0 << 8) | (1 << 14) | (3 << 18); + + lapic_write(0x310, 0); + lapic_write(0x300, icr_low); + + while (lapic_read(0x300) & (1 << 12)) + asm volatile ("pause"); + + serial_printf("Broadcast IPI (all but self) vector 0x%02x sent\n", vector); +} + +void lapic_send_nmi_to_all_but_self(void) +{ + uint32_t icr_low = 0x02 | (0x4 << 8) | (1 << 14) | (3 << 18); + + lapic_write(0x310, 0); + lapic_write(0x300, icr_low); + + for (int _w = 0; _w < 10000 && (lapic_read(0x300) & (1 << 12)); _w++) + asm volatile ("pause"); + + serial_printf("NMI broadcast (all but self) sent\n"); +} + +void ipi_reschedule_all(void) { + lapic_send_ipi_to_all_but_self(IPI_RESCHEDULE_VECTOR); +} + +void ipi_reschedule_cpu(uint32_t lapic_id) { + lapic_send_ipi(lapic_id, IPI_RESCHEDULE_VECTOR); +} + +void ipi_reschedule_single(uint32_t target_lapic_id) { + uint32_t icr_high = target_lapic_id << 24; + uint32_t icr_low = IPI_RESCHEDULE_VECTOR | (0 << 8) | (1 << 14); + + lapic_write(0x310, icr_high); + lapic_write(0x300, icr_low); + + while (lapic_read(0x300) & (1 << 12)) + asm volatile ("pause"); + + serial_printf("Reschedule IPI sent to LAPIC %u\n", target_lapic_id); +} + +void ipi_tlb_shootdown_broadcast(const uintptr_t* addrs, size_t count) { + if (count > MAX_TLB_ADDRESSES) count = MAX_TLB_ADDRESSES; + + uint32_t my_lapic = lapic_get_id(); + smp_info_t* info = smp_get_info(); + + for (uint32_t i = 0; i < info->cpu_count; i++) { + uint32_t target_lapic = info->cpus[i].lapic_id; + if (target_lapic == my_lapic) continue; + + tlb_shootdown_t* q = &tlb_shootdown_queue[target_lapic]; + q->count = count; + for (size_t j = 0; j < count; j++) + q->addresses[j] = addrs[j]; + __atomic_store_n(&q->pending, true, __ATOMIC_RELEASE); + } + + asm volatile ("lock addl $0, (%%rsp)" ::: "memory", "cc"); + + uint32_t icr_low = IPI_TLB_SHOOTDOWN + | (0 << 8) + | (1 << 14) + | (3 << 18); + + lapic_write(0x310, 0); + lapic_write(0x300, icr_low); + + while (lapic_read(0x300) & (1 << 12)) + asm volatile ("pause"); + + serial_printf("TLB shootdown broadcast sent for %zu addresses\n", count); +} + +void ipi_tlb_shootdown_single(uint32_t target_lapic_id, uintptr_t addr) { + tlb_shootdown_t* q = &tlb_shootdown_queue[target_lapic_id]; + + q->addresses[0] = addr; + q->count = 1; + __atomic_store_n(&q->pending, true, __ATOMIC_RELEASE); + + asm volatile ("lock addl $0, (%%rsp)" ::: "memory", "cc"); + + uint32_t icr_high = target_lapic_id << 24; + uint32_t icr_low = IPI_TLB_SHOOTDOWN | (0 << 8) | (1 << 14); + + lapic_write(0x310, icr_high); + lapic_write(0x300, icr_low); + + while (lapic_read(0x300) & (1 << 12)) + asm volatile ("pause"); + + serial_printf("TLB shootdown sent to LAPIC %u for virt 0x%llx\n", + target_lapic_id, addr); +} \ No newline at end of file diff --git a/kernel/src/drivers/ata.c b/kernel/src/drivers/ata.c new file mode 100644 index 0000000..0ecc4f9 --- /dev/null +++ b/kernel/src/drivers/ata.c @@ -0,0 +1,371 @@ +#include "../../include/drivers/ata.h" +#include "../../include/io/ports.h" +#include "../../include/io/serial.h" +#include "../../include/memory/pmm.h" +#include "../../include/sched/spinlock.h" +#include "../../include/syscall/errno.h" +#include + +static ata_drive_t g_drives[ATA_MAX_DRIVES]; +static int g_drive_count = 0; +static spinlock_t g_ata_lock = SPINLOCK_INIT; + +static void ata_io_wait(uint16_t ctrl) { + inb(ctrl); inb(ctrl); inb(ctrl); inb(ctrl); +} + +static inline void ata_cpu_relax(void) { + asm volatile("pause" ::: "memory"); +} + +static void ata_soft_reset(uint16_t ctrl) { + outb(ctrl, 0x04); + ata_io_wait(ctrl); + outb(ctrl, 0x00); + ata_io_wait(ctrl); + + for (int i = 0; i < 2000000; i++) { + uint8_t s = inb(ctrl); + if (!(s & ATA_SR_BSY)) return; + ata_io_wait(ctrl); + ata_cpu_relax(); + } +} + +static int ata_wait_ready(uint16_t io, uint16_t ctrl, int timeout_us) { + (void)io; + ata_io_wait(ctrl); + for (int i = 0; i < timeout_us; i++) { + uint8_t s = inb(ctrl + ATA_REG_ALT_STATUS); + if (!(s & ATA_SR_BSY)) { + if (s & ATA_SR_ERR) return -EIO; + if (s & ATA_SR_DF) return -EIO; + return 0; + } + ata_io_wait(ctrl); + ata_cpu_relax(); + } + return -ETIMEDOUT; +} + +static int ata_wait_drq(uint16_t io, uint16_t ctrl, int timeout_us) { + (void)io; + ata_io_wait(ctrl); + for (int i = 0; i < timeout_us; i++) { + uint8_t s = inb(ctrl + ATA_REG_ALT_STATUS); + if (s & ATA_SR_ERR) return -EIO; + if (s & ATA_SR_DF) return -EIO; + if (!(s & ATA_SR_BSY) && (s & ATA_SR_DRQ)) return 0; + ata_io_wait(ctrl); + ata_cpu_relax(); + } + return -ETIMEDOUT; +} + +static void ata_fix_string(char *dst, const uint16_t *src, int words) { + for (int i = 0; i < words; i++) { + dst[i * 2 + 0] = (char)(src[i] >> 8); + dst[i * 2 + 1] = (char)(src[i] & 0xFF); + } + dst[words * 2] = '\0'; + for (int i = words * 2 - 1; i >= 0 && dst[i] == ' '; i--) + dst[i] = '\0'; +} + +static bool ata_identify_drive(uint16_t io, uint16_t ctrl, uint8_t drv_sel, ata_drive_t *out) { + memset(out, 0, sizeof(*out)); + out->io_base = io; + out->ctrl_base = ctrl; + out->drive_select = drv_sel; + + outb(io + ATA_REG_DRIVE, drv_sel); + ata_io_wait(ctrl); + + outb(io + ATA_REG_SECCOUNT, 0); + outb(io + ATA_REG_LBA_LO, 0); + outb(io + ATA_REG_LBA_MID, 0); + outb(io + ATA_REG_LBA_HI, 0); + + outb(io + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + ata_io_wait(ctrl); + + uint8_t status = inb(io + ATA_REG_STATUS); + if (status == 0) return false; + + for (int i = 0; i < 1000000; i++) { + status = inb(io + ATA_REG_STATUS); + if (!(status & ATA_SR_BSY)) break; + ata_cpu_relax(); + } + if (status & ATA_SR_BSY) return false; + + uint8_t lm = inb(io + ATA_REG_LBA_MID); + uint8_t lh = inb(io + ATA_REG_LBA_HI); + if (lm == 0x14 && lh == 0xEB) { + out->is_atapi = true; + return false; + } + if (lm == 0x3C && lh == 0xC3) { + + } + if (lm != 0 || lh != 0) { + return false; + } + + for (int i = 0; i < 1000000; i++) { + status = inb(io + ATA_REG_STATUS); + if (status & ATA_SR_ERR) return false; + if (status & ATA_SR_DRQ) break; + ata_cpu_relax(); + } + if (!(status & ATA_SR_DRQ)) return false; + + for (int i = 0; i < 256; i++) + out->identify[i] = inw(io + ATA_REG_DATA); + + ata_fix_string(out->model, &out->identify[27], 20); + ata_fix_string(out->serial, &out->identify[10], 10); + ata_fix_string(out->firmware, &out->identify[23], 4); + + if (out->identify[83] & (1 << 10)) { + out->lba48 = true; + out->sectors = (uint64_t)out->identify[100] + | ((uint64_t)out->identify[101] << 16) + | ((uint64_t)out->identify[102] << 32) + | ((uint64_t)out->identify[103] << 48); + } else { + out->lba48 = false; + out->sectors = (uint64_t)out->identify[60] + | ((uint64_t)out->identify[61] << 16); + } + out->size_bytes = out->sectors * ATA_SECTOR_SIZE; + out->present = true; + return true; +} + +void ata_init(void) { + serial_writestring("[ATA] probing drives...\n"); + g_drive_count = 0; + + struct { uint16_t io; uint16_t ctrl; uint8_t irq; } channels[] = { + { ATA_PRIMARY_IO, ATA_PRIMARY_CTRL, 14 }, + { ATA_SECONDARY_IO, ATA_SECONDARY_CTRL, 15 }, + }; + + for (int ch = 0; ch < 2; ch++) { + outb(channels[ch].ctrl, 0x02); + ata_soft_reset(channels[ch].ctrl); + + uint8_t drvs[] = { ATA_DRIVE_MASTER, ATA_DRIVE_SLAVE }; + for (int d = 0; d < 2; d++) { + int idx = ch * 2 + d; + ata_drive_t *drv = &g_drives[idx]; + if (ata_identify_drive(channels[ch].io, channels[ch].ctrl, + drvs[d], drv)) + { + drv->irq = channels[ch].irq; + g_drive_count++; + serial_printf("[ATA] drive %d: '%s' %llu sectors (%llu MB) %s\n", + idx, drv->model, drv->sectors, + drv->size_bytes / (1024 * 1024), + drv->lba48 ? "LBA48" : "LBA28"); + } + } + } + + if (g_drive_count == 0) + serial_writestring("[ATA] no drives found\n"); + else + serial_printf("[ATA] %d drive(s) detected\n", g_drive_count); +} + +ata_drive_t *ata_get_drive(int index) { + if (index < 0 || index >= ATA_MAX_DRIVES) return NULL; + if (!g_drives[index].present) return NULL; + return &g_drives[index]; +} + +int ata_get_drive_count(void) { + return g_drive_count; +} + +#define ATA_IO_TIMEOUT 20000000 +#define ATA_WRITE_TIMEOUT 40000000 +#define ATA_RETRY_COUNT 3 + +static int ata_read_sectors_once(ata_drive_t *drive, uint64_t lba, + uint32_t count, void *buffer) +{ + uint16_t io = drive->io_base; + uint16_t ctrl = drive->ctrl_base; + uint16_t *buf = (uint16_t *)buffer; + int ret = 0; + + outb(io + ATA_REG_DRIVE, drive->drive_select); + ata_io_wait(ctrl); + (void)inb(io + ATA_REG_STATUS); + ret = ata_wait_ready(io, ctrl, ATA_IO_TIMEOUT); + if (ret < 0) return ret; + + if (drive->lba48 && (lba > 0x0FFFFFFF || count > 256)) { + outb(io + ATA_REG_DRIVE, (drive->drive_select & 0xF0) | ATA_LBA_BIT); + ata_io_wait(ctrl); + + outb(io + ATA_REG_SECCOUNT, (uint8_t)(count >> 8)); + outb(io + ATA_REG_LBA_LO, (uint8_t)(lba >> 24)); + outb(io + ATA_REG_LBA_MID, (uint8_t)(lba >> 32)); + outb(io + ATA_REG_LBA_HI, (uint8_t)(lba >> 40)); + outb(io + ATA_REG_SECCOUNT, (uint8_t)(count)); + outb(io + ATA_REG_LBA_LO, (uint8_t)(lba)); + outb(io + ATA_REG_LBA_MID, (uint8_t)(lba >> 8)); + outb(io + ATA_REG_LBA_HI, (uint8_t)(lba >> 16)); + + outb(io + ATA_REG_COMMAND, ATA_CMD_READ_PIO_EXT); + } else { + outb(io + ATA_REG_DRIVE, + (drive->drive_select & 0xF0) | ATA_LBA_BIT | ((lba >> 24) & 0x0F)); + ata_io_wait(ctrl); + outb(io + ATA_REG_SECCOUNT, (uint8_t)count); + outb(io + ATA_REG_LBA_LO, (uint8_t)(lba)); + outb(io + ATA_REG_LBA_MID, (uint8_t)(lba >> 8)); + outb(io + ATA_REG_LBA_HI, (uint8_t)(lba >> 16)); + + outb(io + ATA_REG_COMMAND, ATA_CMD_READ_PIO); + } + + ata_io_wait(ctrl); + + for (uint32_t s = 0; s < count; s++) { + ret = ata_wait_drq(io, ctrl, ATA_IO_TIMEOUT); + if (ret < 0) return ret; + + for (int i = 0; i < 256; i++) + *buf++ = inw(io + ATA_REG_DATA); + + ata_io_wait(ctrl); + } + return 0; +} + +int ata_read_sectors(ata_drive_t *drive, uint64_t lba, + uint32_t count, void *buffer) +{ + if (!drive || !drive->present || !buffer) return -EINVAL; + if (count == 0) return 0; + if (lba + count > drive->sectors) return -EINVAL; + + uint64_t flags = spinlock_acquire_irqsave(&g_ata_lock); + + int ret = -EIO; + for (int attempt = 0; attempt < ATA_RETRY_COUNT; attempt++) { + ret = ata_read_sectors_once(drive, lba, count, buffer); + if (ret == 0) break; + serial_printf("[ATA] read lba=%llu count=%u attempt %d failed: %d\n", + lba, count, attempt + 1, ret); + ata_soft_reset(drive->ctrl_base); + for (volatile int k = 0; k < 100000; k++) ata_cpu_relax(); + } + + spinlock_release_irqrestore(&g_ata_lock, flags); + return ret; +} + +static int ata_write_sectors_once(ata_drive_t *drive, uint64_t lba, + uint32_t count, const void *buffer) +{ + uint16_t io = drive->io_base; + uint16_t ctrl = drive->ctrl_base; + const uint16_t *buf = (const uint16_t *)buffer; + int ret = 0; + + outb(io + ATA_REG_DRIVE, drive->drive_select); + ata_io_wait(ctrl); + (void)inb(io + ATA_REG_STATUS); + ret = ata_wait_ready(io, ctrl, ATA_IO_TIMEOUT); + if (ret < 0) return ret; + + if (drive->lba48 && (lba > 0x0FFFFFFF || count > 256)) { + outb(io + ATA_REG_DRIVE, (drive->drive_select & 0xF0) | ATA_LBA_BIT); + ata_io_wait(ctrl); + + outb(io + ATA_REG_SECCOUNT, (uint8_t)(count >> 8)); + outb(io + ATA_REG_LBA_LO, (uint8_t)(lba >> 24)); + outb(io + ATA_REG_LBA_MID, (uint8_t)(lba >> 32)); + outb(io + ATA_REG_LBA_HI, (uint8_t)(lba >> 40)); + + outb(io + ATA_REG_SECCOUNT, (uint8_t)(count)); + outb(io + ATA_REG_LBA_LO, (uint8_t)(lba)); + outb(io + ATA_REG_LBA_MID, (uint8_t)(lba >> 8)); + outb(io + ATA_REG_LBA_HI, (uint8_t)(lba >> 16)); + + outb(io + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO_EXT); + } else { + outb(io + ATA_REG_DRIVE, + (drive->drive_select & 0xF0) | ATA_LBA_BIT | ((lba >> 24) & 0x0F)); + ata_io_wait(ctrl); + outb(io + ATA_REG_SECCOUNT, (uint8_t)count); + outb(io + ATA_REG_LBA_LO, (uint8_t)(lba)); + outb(io + ATA_REG_LBA_MID, (uint8_t)(lba >> 8)); + outb(io + ATA_REG_LBA_HI, (uint8_t)(lba >> 16)); + + outb(io + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); + } + + ata_io_wait(ctrl); + + for (uint32_t s = 0; s < count; s++) { + ret = ata_wait_drq(io, ctrl, ATA_WRITE_TIMEOUT); + if (ret < 0) return ret; + + for (int i = 0; i < 256; i++) + outw(io + ATA_REG_DATA, *buf++); + + ata_io_wait(ctrl); + } + + ret = ata_wait_ready(io, ctrl, ATA_IO_TIMEOUT); + if (ret < 0) return ret; + + return 0; +} + +int ata_write_sectors(ata_drive_t *drive, uint64_t lba, + uint32_t count, const void *buffer) +{ + if (!drive || !drive->present || !buffer) return -EINVAL; + if (count == 0) return 0; + if (lba + count > drive->sectors) return -EINVAL; + + uint64_t flags = spinlock_acquire_irqsave(&g_ata_lock); + + int ret = -EIO; + for (int attempt = 0; attempt < ATA_RETRY_COUNT; attempt++) { + ret = ata_write_sectors_once(drive, lba, count, buffer); + if (ret == 0) break; + serial_printf("[ATA] write lba=%llu count=%u attempt %d failed: %d\n", + lba, count, attempt + 1, ret); + ata_soft_reset(drive->ctrl_base); + for (volatile int k = 0; k < 100000; k++) ata_cpu_relax(); + } + + spinlock_release_irqrestore(&g_ata_lock, flags); + return ret; +} + +int ata_flush(ata_drive_t *drive) { + if (!drive || !drive->present) return -EINVAL; + + uint64_t flags = spinlock_acquire_irqsave(&g_ata_lock); + + uint16_t io = drive->io_base; + uint16_t ctrl = drive->ctrl_base; + + outb(io + ATA_REG_DRIVE, drive->drive_select); + outb(io + ATA_REG_COMMAND, + drive->lba48 ? ATA_CMD_CACHE_FLUSH_EXT : ATA_CMD_CACHE_FLUSH); + + int ret = ata_wait_ready(io, ctrl, ATA_IO_TIMEOUT); + + spinlock_release_irqrestore(&g_ata_lock, flags); + return ret; +} \ No newline at end of file diff --git a/kernel/src/drivers/blkdev.c b/kernel/src/drivers/blkdev.c new file mode 100644 index 0000000..6ec2e75 --- /dev/null +++ b/kernel/src/drivers/blkdev.c @@ -0,0 +1,95 @@ +#include "../../include/drivers/blkdev.h" +#include "../../include/io/serial.h" +#include "../../include/memory/pmm.h" +#include "../../include/syscall/errno.h" +#include + +static blkdev_t *g_blkdevs[BLKDEV_MAX]; +static int g_blkdev_count = 0; + +void blkdev_init(void) { + memset(g_blkdevs, 0, sizeof(g_blkdevs)); + g_blkdev_count = 0; + serial_writestring("[blkdev] initialized\n"); +} + +int blkdev_register(blkdev_t *dev) { + if (!dev || g_blkdev_count >= BLKDEV_MAX) return -ENOMEM; + int idx = g_blkdev_count; + g_blkdevs[idx] = dev; + g_blkdev_count++; + serial_printf("[blkdev] registered '%s' (%llu sectors, %llu MB)\n", + dev->name, dev->sector_count, + dev->size_bytes / (1024 * 1024)); + return idx; +} + +blkdev_t *blkdev_get_by_name(const char *name) { + for (int i = 0; i < g_blkdev_count; i++) { + if (g_blkdevs[i] && strcmp(g_blkdevs[i]->name, name) == 0) + return g_blkdevs[i]; + } + return NULL; +} + +blkdev_t *blkdev_get(int index) { + if (index < 0 || index >= g_blkdev_count) return NULL; + return g_blkdevs[index]; +} + +int blkdev_count(void) { + return g_blkdev_count; +} + +int blkdev_read(blkdev_t *dev, uint64_t offset, void *buf, size_t len) { + if (!dev || !dev->ops || !dev->ops->read_sectors) return -EIO; + if (len == 0) return 0; + + uint32_t sec_size = dev->sector_size ? dev->sector_size : BLKDEV_SECTOR_SIZE; + uint64_t start_lba = offset / sec_size; + uint64_t end_byte = offset + len; + uint64_t end_lba = (end_byte + sec_size - 1) / sec_size; + uint32_t nsectors = (uint32_t)(end_lba - start_lba); + + uint8_t *tmp = kmalloc((size_t)nsectors * sec_size); + if (!tmp) return -ENOMEM; + + int ret = dev->ops->read_sectors(dev, start_lba, nsectors, tmp); + if (ret < 0) { + kfree(tmp); + return ret; + } + + uint64_t off_in_buf = offset - start_lba * sec_size; + memcpy(buf, tmp + off_in_buf, len); + kfree(tmp); + return 0; +} + +int blkdev_write(blkdev_t *dev, uint64_t offset, const void *buf, size_t len) { + if (!dev || !dev->ops || !dev->ops->write_sectors) return -EIO; + if (len == 0) return 0; + + uint32_t sec_size = dev->sector_size ? dev->sector_size : BLKDEV_SECTOR_SIZE; + uint64_t start_lba = offset / sec_size; + uint64_t end_byte = offset + len; + uint64_t end_lba = (end_byte + sec_size - 1) / sec_size; + uint32_t nsectors = (uint32_t)(end_lba - start_lba); + + uint8_t *tmp = kmalloc((size_t)nsectors * sec_size); + if (!tmp) return -ENOMEM; + + int ret = dev->ops->read_sectors(dev, start_lba, nsectors, tmp); + if (ret < 0) { + kfree(tmp); + return ret; + } + + uint64_t off_in_buf = offset - start_lba * sec_size; + memcpy(tmp + off_in_buf, buf, len); + + ret = dev->ops->write_sectors(dev, start_lba, nsectors, tmp); + kfree(tmp); + + return ret; +} \ No newline at end of file diff --git a/kernel/src/drivers/disk.c b/kernel/src/drivers/disk.c new file mode 100644 index 0000000..915bd54 --- /dev/null +++ b/kernel/src/drivers/disk.c @@ -0,0 +1,164 @@ +#include "../../include/drivers/disk.h" +#include "../../include/drivers/ata.h" +#include "../../include/drivers/blkdev.h" +#include "../../include/drivers/partition.h" +#include "../../include/fs/ext2.h" +#include "../../include/fs/fat32.h" +#include "../../include/fs/vfs.h" +#include "../../include/io/serial.h" +#include "../../include/memory/pmm.h" +#include "../../include/syscall/errno.h" +#include +#include + +static int ata_blk_read(blkdev_t *dev, uint64_t lba, uint32_t count, void *buf) { + ata_drive_t *drv = (ata_drive_t *)dev->priv; + return ata_read_sectors(drv, lba, count, buf); +} +static int ata_blk_write(blkdev_t *dev, uint64_t lba, uint32_t count, const void *buf) { + ata_drive_t *drv = (ata_drive_t *)dev->priv; + return ata_write_sectors(drv, lba, count, buf); +} +static int ata_blk_flush(blkdev_t *dev) { + ata_drive_t *drv = (ata_drive_t *)dev->priv; + return ata_flush(drv); +} + +static const blkdev_ops_t ata_blkdev_ops = { + .read_sectors = ata_blk_read, + .write_sectors = ata_blk_write, + .flush = ata_blk_flush, +}; + +static blkdev_t g_ata_blkdevs[ATA_MAX_DRIVES]; +extern void devfs_register(const char *name, vnode_t *node); + +static int64_t blk_vnode_read(vnode_t *node, void *buf, size_t len, uint64_t offset) { + blkdev_t *dev = (blkdev_t *)node->fs_data; + if (!dev) return -EIO; + int r = blkdev_read(dev, offset, buf, len); + return (r < 0) ? r : (int64_t)len; +} +static int64_t blk_vnode_write(vnode_t *node, const void *buf, size_t len, uint64_t offset) { + blkdev_t *dev = (blkdev_t *)node->fs_data; + if (!dev) return -EIO; + int r = blkdev_write(dev, offset, buf, len); + return (r < 0) ? r : (int64_t)len; +} +static int blk_vnode_stat(vnode_t *node, vfs_stat_t *out) { + blkdev_t *dev = (blkdev_t *)node->fs_data; + memset(out, 0, sizeof(*out)); + out->st_ino = node->ino; + out->st_type = VFS_NODE_BLKDEV; + out->st_mode = 0660; + out->st_size = dev ? dev->size_bytes : 0; + return 0; +} +static void blk_vnode_ref(vnode_t *n) { (void)n; } +static void blk_vnode_unref(vnode_t *n) { (void)n; } + +static const vnode_ops_t blk_vnode_ops = { + .read = blk_vnode_read, .write = blk_vnode_write, + .stat = blk_vnode_stat, .ref = blk_vnode_ref, .unref = blk_vnode_unref, +}; + +static vnode_t g_blk_vnodes[ATA_MAX_DRIVES]; +static uint64_t g_blk_ino_base = 200; + +void disk_init(void) { + serial_writestring("[disk] initializing...\n"); + blkdev_init(); + ata_init(); + int count = 0; + const char *names[] = { "hda", "hdb", "hdc", "hdd" }; + for (int i = 0; i < ATA_MAX_DRIVES; i++) { + ata_drive_t *drv = ata_get_drive(i); + if (!drv) continue; + blkdev_t *bdev = &g_ata_blkdevs[count]; + memset(bdev, 0, sizeof(*bdev)); + strncpy(bdev->name, names[i], BLKDEV_NAME_MAX - 1); + bdev->present = true; + bdev->sector_count = drv->sectors; + bdev->size_bytes = drv->size_bytes; + bdev->sector_size = ATA_SECTOR_SIZE; + bdev->ops = &ata_blkdev_ops; + bdev->priv = drv; + blkdev_register(bdev); + vnode_t *vn = &g_blk_vnodes[count]; + memset(vn, 0, sizeof(*vn)); + vn->type = VFS_NODE_BLKDEV; + vn->mode = 0660; + vn->ino = g_blk_ino_base + (uint64_t)count; + vn->ops = &blk_vnode_ops; + vn->fs_data = bdev; + vn->size = drv->size_bytes; + vn->refcount = 1; + devfs_register(names[i], vn); + serial_printf("[disk] /dev/%s -> %s (%llu MB)\n", + names[i], drv->model, drv->size_bytes / (1024 * 1024)); + printf("[disk] /dev/%s -> %s (%llu MB)\n", + names[i], drv->model, drv->size_bytes / (1024 * 1024)); + + partition_scan(bdev); + count++; + } + if (count == 0) serial_writestring("[disk] no disks available\n"); + else { serial_printf("[disk] %d disk(s) ready\n", count); printf("[disk] %d disk(s) ready\n", count); } +} + +static const char *strip_dev_prefix(const char *name) { + if (strncmp(name, "/dev/", 5) == 0) return name + 5; + return name; +} + +int disk_format(const char *devname, const char *label) { + const char *raw = strip_dev_prefix(devname); + blkdev_t *dev = blkdev_get_by_name(raw); + if (!dev) return -ENODEV; + return ext2_format(dev, label ? label : raw); +} + +static int detect_fs_type(blkdev_t *dev) { + uint8_t sec[512]; + if (dev->ops->read_sectors(dev, 0, 1, sec) < 0) return -1; + if (sec[510] == 0x55 && sec[511] == (uint8_t)0xAA) { + if (memcmp(sec + 82, "FAT32", 5) == 0) return 1; + if (memcmp(sec + 54, "FAT", 3) == 0) return 1; + } + uint16_t magic = 0; + if (blkdev_read(dev, EXT2_SUPER_OFFSET + 56, &magic, sizeof(magic)) == 0 + && magic == EXT2_SUPER_MAGIC) return 2; + return 0; +} + +int disk_mount(const char *devname, const char *path) { + const char *raw = strip_dev_prefix(devname); + blkdev_t *dev = blkdev_get_by_name(raw); + if (!dev) return -ENODEV; + + int t = detect_fs_type(dev); + vnode_t *root = NULL; + if (t == 1) { + root = fat32_mount(dev); + serial_printf("[disk] mounting FAT32 %s -> %s\n", raw, path); + } else if (t == 2) { + root = ext2_mount(dev); + serial_printf("[disk] mounting ext2 %s -> %s\n", raw, path); + } else { + serial_printf("[disk] %s: no recognizable FS\n", raw); + return -EINVAL; + } + if (!root) return -EIO; + int r = vfs_mount(path, root); + if (r < 0) { vnode_unref(root); return r; } + + const char *fsname = (t == 1) ? "fat32" : "ext2"; + int si = vfs_set_mount_info(path, raw, fsname); + serial_printf("[disk_mount] set_mount_info path='%s' dev='%s' fs='%s' -> %d\n", + path, raw, fsname, si); + return 0; +} + +int disk_umount(const char *path) { + return vfs_umount(path); +} \ No newline at end of file diff --git a/kernel/src/drivers/partition.c b/kernel/src/drivers/partition.c new file mode 100644 index 0000000..33fac01 --- /dev/null +++ b/kernel/src/drivers/partition.c @@ -0,0 +1,204 @@ +#include "../../include/drivers/partition.h" +#include "../../include/drivers/blkdev.h" +#include "../../include/fs/vfs.h" +#include "../../include/io/serial.h" +#include "../../include/syscall/errno.h" +#include "../../include/memory/pmm.h" +#include +#include + +#define MAX_PARTITIONS 16 + +typedef struct { + blkdev_t base; + blkdev_t *parent; + uint64_t offset_sectors; + uint64_t count_sectors; + uint8_t type; + uint8_t bootable; + uint32_t partnum; +} partition_blkdev_t; + +static partition_blkdev_t g_partitions[MAX_PARTITIONS]; +static int g_partition_count = 0; + +extern void devfs_register(const char *name, vnode_t *node); + +static int64_t part_vnode_read(vnode_t *node, void *buf, size_t len, uint64_t offset) { + blkdev_t *dev = (blkdev_t *)node->fs_data; + if (!dev) return -EIO; + int r = blkdev_read(dev, offset, buf, len); + return (r < 0) ? r : (int64_t)len; +} +static int64_t part_vnode_write(vnode_t *node, const void *buf, size_t len, uint64_t offset) { + blkdev_t *dev = (blkdev_t *)node->fs_data; + if (!dev) return -EIO; + int r = blkdev_write(dev, offset, buf, len); + return (r < 0) ? r : (int64_t)len; +} +static int part_vnode_stat(vnode_t *node, vfs_stat_t *out) { + blkdev_t *dev = (blkdev_t *)node->fs_data; + memset(out, 0, sizeof(*out)); + out->st_ino = node->ino; + out->st_type = VFS_NODE_BLKDEV; + out->st_mode = 0660; + out->st_size = dev ? dev->size_bytes : 0; + return 0; +} +static void part_vnode_ref(vnode_t *n) { (void)n; } +static void part_vnode_unref(vnode_t *n) { (void)n; } + +static const vnode_ops_t part_vnode_ops = { + .read = part_vnode_read, .write = part_vnode_write, + .stat = part_vnode_stat, .ref = part_vnode_ref, .unref = part_vnode_unref, +}; + +static vnode_t g_part_vnodes[MAX_PARTITIONS]; +static uint64_t g_part_ino_base = 300; + +static int part_read_sectors(blkdev_t *dev, uint64_t lba, uint32_t count, void *buf) { + partition_blkdev_t *p = (partition_blkdev_t *)dev->priv; + if (!p || !p->parent) return -EIO; + if (lba + count > p->count_sectors) return -EINVAL; + return p->parent->ops->read_sectors(p->parent, p->offset_sectors + lba, count, buf); +} + +static int part_write_sectors(blkdev_t *dev, uint64_t lba, uint32_t count, const void *buf) { + partition_blkdev_t *p = (partition_blkdev_t *)dev->priv; + if (!p || !p->parent) return -EIO; + if (lba + count > p->count_sectors) return -EINVAL; + return p->parent->ops->write_sectors(p->parent, p->offset_sectors + lba, count, buf); +} + +static int part_flush(blkdev_t *dev) { + partition_blkdev_t *p = (partition_blkdev_t *)dev->priv; + if (!p || !p->parent) return -EIO; + return p->parent->ops->flush ? p->parent->ops->flush(p->parent) : 0; +} + +static const blkdev_ops_t part_blkdev_ops = { + .read_sectors = part_read_sectors, + .write_sectors = part_write_sectors, + .flush = part_flush, +}; + +int partition_read_mbr(blkdev_t *disk, mbr_t *out) { + if (!disk || !out) return -EINVAL; + uint8_t sector[512]; + int r = disk->ops->read_sectors(disk, 0, 1, sector); + if (r < 0) return r; + memcpy(out, sector, 512); + return 0; +} + +int partition_write_mbr(blkdev_t *disk, const mbr_partition_t parts[4], + uint32_t disk_signature) +{ + if (!disk || !parts) return -EINVAL; + uint8_t sector[512]; + int r = disk->ops->read_sectors(disk, 0, 1, sector); + if (r < 0) return r; + + mbr_t *mbr = (mbr_t *)sector; + mbr->disk_signature = disk_signature; + mbr->reserved = 0; + for (int i = 0; i < 4; i++) mbr->partitions[i] = parts[i]; + mbr->signature = MBR_SIGNATURE; + + return disk->ops->write_sectors(disk, 0, 1, sector); +} + +static const char *part_type_name(uint8_t t) { + switch (t) { + case MBR_TYPE_EMPTY: return "empty"; + case MBR_TYPE_FAT12: return "FAT12"; + case MBR_TYPE_FAT16_S: return "FAT16 <32M"; + case MBR_TYPE_FAT16: return "FAT16"; + case MBR_TYPE_EXTENDED: return "Extended"; + case MBR_TYPE_FAT32_CHS: return "FAT32 CHS"; + case MBR_TYPE_FAT32_LBA: return "FAT32 LBA"; + case MBR_TYPE_FAT16_LBA: return "FAT16 LBA"; + case MBR_TYPE_LINUX: return "Linux"; + case MBR_TYPE_ESP: return "EFI System"; + default: return "unknown"; + } +} + +int partition_scan(blkdev_t *disk) { + if (!disk || !disk->present) return -ENODEV; + + mbr_t mbr; + int r = partition_read_mbr(disk, &mbr); + if (r < 0) { + serial_printf("[part] %s: cannot read MBR: %d\n", disk->name, r); + return r; + } + + if (mbr.signature != MBR_SIGNATURE) { + serial_printf("[part] %s: no MBR signature (raw disk / unpartitioned)\n", + disk->name); + return 0; + } + + int found = 0; + for (int i = 0; i < 4; i++) { + mbr_partition_t *p = &mbr.partitions[i]; + if (p->type == 0 || p->sector_count == 0) continue; + if (g_partition_count >= MAX_PARTITIONS) break; + + partition_blkdev_t *pb = &g_partitions[g_partition_count]; + memset(pb, 0, sizeof(*pb)); + + pb->parent = disk; + pb->offset_sectors = p->lba_start; + pb->count_sectors = p->sector_count; + pb->type = p->type; + pb->bootable = (p->boot_flag == 0x80) ? 1 : 0; + pb->partnum = (uint32_t)(i + 1); + + snprintf(pb->base.name, BLKDEV_NAME_MAX, "%s%u", disk->name, pb->partnum); + pb->base.present = true; + pb->base.sector_count = pb->count_sectors; + pb->base.size_bytes = pb->count_sectors * (uint64_t)disk->sector_size; + pb->base.sector_size = disk->sector_size; + pb->base.ops = &part_blkdev_ops; + pb->base.priv = pb; + + blkdev_register(&pb->base); + + vnode_t *vn = &g_part_vnodes[g_partition_count]; + memset(vn, 0, sizeof(*vn)); + vn->type = VFS_NODE_BLKDEV; + vn->mode = 0660; + vn->ino = g_part_ino_base + (uint64_t)g_partition_count; + vn->ops = &part_vnode_ops; + vn->fs_data = &pb->base; + vn->size = pb->base.size_bytes; + vn->refcount = 1; + devfs_register(pb->base.name, vn); + + serial_printf("[part] /dev/%s: type=0x%02x (%s) lba=%u sectors=%u %s\n", + pb->base.name, pb->type, part_type_name(pb->type), + p->lba_start, p->sector_count, + pb->bootable ? "[bootable]" : ""); + printf("[part] /dev/%s: 0x%02x (%s) %u MB %s\n", + pb->base.name, pb->type, part_type_name(pb->type), + (unsigned)(pb->base.size_bytes / (1024 * 1024)), + pb->bootable ? "*" : ""); + + g_partition_count++; + found++; + } + + if (found == 0) { + serial_printf("[part] %s: MBR present but no valid partitions\n", disk->name); + } + return found; +} + +blkdev_t *partition_get(const char *name) { + for (int i = 0; i < g_partition_count; i++) { + if (strcmp(g_partitions[i].base.name, name) == 0) return &g_partitions[i].base; + } + return NULL; +} \ No newline at end of file diff --git a/kernel/src/drivers/ps2.c b/kernel/src/drivers/ps2.c new file mode 100644 index 0000000..6d98683 --- /dev/null +++ b/kernel/src/drivers/ps2.c @@ -0,0 +1,505 @@ +#include "../../include/drivers/ps2.h" +#include "../../include/sched/sched.h" +#include "../../include/fs/devfs.h" +#include "../../include/drivers/timer.h" +#include "../../include/interrupts/interrupts.h" +#include "../../include/apic/apic.h" +#include "../../include/io/ports.h" +#include "../../include/io/serial.h" +#include "../../include/graphics/fb/fb.h" +#include +#include + +#define KB_IRQ_VECTOR 0x21 +#define MOUSE_IRQ_VECTOR 0x2C +#define KB_IRQ_LINE 1 +#define MOUSE_IRQ_LINE 12 + +typedef enum { MOUSE_MODE_RELATIVE = 0, MOUSE_MODE_ABSOLUTE } mouse_mode_t; + +static volatile kb_state_t kb_state; +static volatile mouse_state_t mouse_state; +static volatile mouse_mode_t mouse_mode = MOUSE_MODE_RELATIVE; +static volatile int32_t mouse_screen_w = 1024; +static volatile int32_t mouse_screen_h = 768; + +static volatile uint8_t mouse_packet[4]; +static volatile uint8_t mouse_packet_idx = 0; +static volatile bool mouse_has_scroll = false; +static volatile uint32_t mouse_lost_sync = 0; + +static volatile kb_buf_t kb_buf; + +static const char sc_lower[89] = { + 0, '\x1b','1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\b', '\t', + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + 'o', 'p', '[', ']', '\n', 0, 'a', 's', + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', 0, '*', + 0, ' ', 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const char sc_upper[89] = { + 0, '\x1b','!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', '\b', '\t', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', '\n', 0, 'A', 'S', + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', + '"', '~', 0, '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', 0, '*', + 0, ' ', 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + +static void ps2_wait_read(void) { + for (int i = 0; i < 100000; i++) { + if (inb(PS2_STATUS_PORT) & PS2_STATUS_OUTPUT_FULL) return; + io_wait(); + } +} + +static void ps2_wait_write(void) { + for (int i = 0; i < 100000; i++) { + if (!(inb(PS2_STATUS_PORT) & PS2_STATUS_INPUT_FULL)) return; + io_wait(); + } +} + +static void ps2_send_cmd(uint8_t cmd) { ps2_wait_write(); outb(PS2_CMD_PORT, cmd); } +static void ps2_send_data(uint8_t data) { ps2_wait_write(); outb(PS2_DATA_PORT, data); } +static uint8_t ps2_recv_data(void) { ps2_wait_read(); return inb(PS2_DATA_PORT); } + +static void ps2_flush_output(void) { + for (int i = 0; i < 32; i++) { + if (!(inb(PS2_STATUS_PORT) & PS2_STATUS_OUTPUT_FULL)) break; + inb(PS2_DATA_PORT); + io_wait(); + } +} + +static bool ps2_mouse_wait_ack(void) { + for (int i = 0; i < 100000; i++) { + if (inb(PS2_STATUS_PORT) & PS2_STATUS_OUTPUT_FULL) { + uint8_t r = inb(PS2_DATA_PORT); + if (r == 0xFA) return true; + if (r == 0xFE || r == 0xFC) return false; + } + io_wait(); + } + serial_writestring("[PS2] mouse_wait_ack: TIMEOUT\n"); + return false; +} + +static bool ps2_mouse_cmd(uint8_t cmd) { + ps2_send_cmd(PS2_CMD_WRITE_PORT2); + ps2_send_data(cmd); + return ps2_mouse_wait_ack(); +} + +static bool ps2_mouse_cmd_param(uint8_t cmd, uint8_t param) { + return ps2_mouse_cmd(cmd) && ps2_mouse_cmd(param); +} + +static uint8_t ps2_mouse_read_byte(void) { + for (int i = 0; i < 100000; i++) { + if (inb(PS2_STATUS_PORT) & PS2_STATUS_OUTPUT_FULL) + return inb(PS2_DATA_PORT); + io_wait(); + } + return 0xFF; +} + +static uint8_t ps2_mouse_get_id(void) { + ps2_mouse_cmd(0xF2); + return ps2_mouse_read_byte(); +} + +static bool ps2_mouse_init_scroll(void) { + ps2_mouse_cmd_param(0xF3, 200); + ps2_mouse_cmd_param(0xF3, 100); + ps2_mouse_cmd_param(0xF3, 80); + uint8_t id = ps2_mouse_get_id(); + serial_printf("[PS2] Mouse ID after IntelliMouse knock: 0x%02x\n", id); + return (id == 0x03); +} + +static bool ps2_detect_absolute(void) { + uint8_t id = ps2_mouse_get_id(); + serial_printf("[PS2] Mouse base device ID: 0x%02x\n", id); + + if (!ps2_mouse_cmd(0xE9)) { + serial_writestring("[PS2] Status request failed\n"); + return false; + } + + uint8_t status = ps2_mouse_read_byte(); + uint8_t resolution = ps2_mouse_read_byte(); + uint8_t sample_rate = ps2_mouse_read_byte(); + serial_printf("[PS2] Mouse status: flags=0x%02x res=0x%02x rate=%d\n", + status, resolution, sample_rate); + + if (resolution == 0x08) { + serial_writestring("[PS2] Detected: QEMU absolute tablet mode\n"); + return true; + } + + ps2_mouse_cmd_param(0xF3, 200); ps2_mouse_cmd_param(0xF3, 100); ps2_mouse_cmd_param(0xF3, 80); + ps2_mouse_cmd_param(0xF3, 200); ps2_mouse_cmd_param(0xF3, 100); ps2_mouse_cmd_param(0xF3, 80); + + id = ps2_mouse_get_id(); + serial_printf("[PS2] Mouse ID after abs knock: 0x%02x\n", id); + if (id == 0x08) { + serial_writestring("[PS2] Detected: QEMU absolute mode (ID=0x08)\n"); + return true; + } + + return false; +} + +static char scancode_to_char(uint8_t sc) { + if (sc >= sizeof(sc_lower) / sizeof(sc_lower[0])) return 0; + bool use_upper = kb_state.shift; + if ((sc >= 0x10 && sc <= 0x19) || + (sc >= 0x1E && sc <= 0x26) || + (sc >= 0x2C && sc <= 0x32)) + use_upper = kb_state.caps_lock ^ kb_state.shift; + return use_upper ? sc_upper[sc] : sc_lower[sc]; +} + +void kb_buf_push(char c) { + uint8_t next = (kb_buf.tail + 1) % KB_BUF_SIZE; + if (next != kb_buf.head) { + kb_buf.buf[kb_buf.tail] = c; + kb_buf.tail = next; + } +} + +extern uint32_t cursor_x; +extern uint32_t cursor_y; +extern uint32_t bg_color; +extern struct limine_framebuffer *global_framebuffer; +extern void get_cursor_position(uint32_t *x, uint32_t *y); +extern uint32_t get_screen_width(void); + +/*static void mouse_print_status(void) { + const mouse_state_t *m = (const mouse_state_t *)&mouse_state; + const char *scroll_str = "NONE"; + if (m->scroll == MOUSE_SCROLL_UP) scroll_str = "UP "; + if (m->scroll == MOUSE_SCROLL_DOWN) scroll_str = "DOWN"; + + serial_printf("[MOUSE] X:%5d Y:%5d L:%d M:%d R:%d Scroll:%s\n", + m->x, m->y, + (int)m->btn_left, (int)m->btn_middle, (int)m->btn_right, + scroll_str); + + uint32_t saved_x, saved_y; + get_cursor_position(&saved_x, &saved_y); + + if (global_framebuffer) + fb_fill_rect(global_framebuffer, 0, 0, global_framebuffer->width, 16, bg_color); + + cursor_x = 0; cursor_y = 0; + printf("[MOUSE] X:%-5d Y:%-5d [L:%d M:%d R:%d] Wheel:%s", + m->x, m->y, + (int)m->btn_left, (int)m->btn_middle, (int)m->btn_right, + scroll_str); + + cursor_x = saved_x; + cursor_y = saved_y; +}*/ + +DEFINE_IRQ(KB_IRQ_VECTOR, ps2_kb_handler) +{ + (void)frame; + static bool e0_prefix = false; + uint8_t sc = inb(PS2_DATA_PORT); + bool released = (sc & PS2_KEY_RELEASE_BIT) != 0; + uint8_t key = sc & ~PS2_KEY_RELEASE_BIT; + + if (sc == 0xE0) { e0_prefix = true; lapic_eoi(); return; } + + if (e0_prefix) { + e0_prefix = false; + if (!released) { + switch (key) { + case 0x48: kb_buf_push('\x1b'); kb_buf_push('['); kb_buf_push('A'); break; + case 0x50: kb_buf_push('\x1b'); kb_buf_push('['); kb_buf_push('B'); break; + case 0x4D: kb_buf_push('\x1b'); kb_buf_push('['); kb_buf_push('C'); break; + case 0x4B: kb_buf_push('\x1b'); kb_buf_push('['); kb_buf_push('D'); break; + case 0x47: kb_buf_push('\x1b'); kb_buf_push('['); kb_buf_push('H'); break; + case 0x4F: kb_buf_push('\x1b'); kb_buf_push('['); kb_buf_push('F'); break; + case 0x53: kb_buf_push('\x1b'); kb_buf_push('['); kb_buf_push('3'); kb_buf_push('~'); break; + default: break; + } + } + lapic_eoi(); + return; + } + + if (key == SC_LSHIFT || key == SC_RSHIFT) { kb_state.shift = !released; lapic_eoi(); return; } + if (key == SC_LCTRL) { kb_state.ctrl = !released; lapic_eoi(); return; } + if (key == SC_LALT) { kb_state.alt = !released; lapic_eoi(); return; } + if (key == SC_CAPS && !released) { kb_state.caps_lock = !kb_state.caps_lock; lapic_eoi(); return; } + if (released) { lapic_eoi(); return; } + + if (kb_state.ctrl) { + char base = scancode_to_char(key); + serial_printf("[PS2] ctrl+key sc=0x%02x base='%c'(0x%02x)\n", (unsigned)key, (base>=0x20&&base<0x7f)?base:'?', (unsigned)(uint8_t)base); + if (base >= 'a' && base <= 'z') { + uint8_t ctrl_char = (uint8_t)(base - 'a' + 1); + serial_printf("[PS2] ctrl char generated: 0x%02x\n", ctrl_char); + if (ctrl_char == 0x03) { + g_ctrlc_pending = 1; + lapic_eoi(); + return; + } + kb_buf_push((char)ctrl_char); + lapic_eoi(); + return; + } + if (base >= 'A' && base <= 'Z') { + kb_buf_push((char)(base - 'A' + 1)); + lapic_eoi(); + return; + } + } + + char c = scancode_to_char(key); + if (c != 0) + kb_buf_push(c); + + lapic_eoi(); +} + +DEFINE_IRQ(MOUSE_IRQ_VECTOR, ps2_mouse_handler) +{ + (void)frame; + uint8_t data = inb(PS2_DATA_PORT); + uint8_t idx = mouse_packet_idx; + + if (idx == 0 && !(data & 0x08)) { + mouse_lost_sync++; + lapic_eoi(); + return; + } + + mouse_packet[idx] = data; + mouse_packet_idx = (uint8_t)(idx + 1); + + uint8_t pkt_size = mouse_has_scroll ? 4 : 3; + if (mouse_packet_idx < pkt_size) { lapic_eoi(); return; } + mouse_packet_idx = 0; + + uint8_t flags = mouse_packet[0]; + if ((flags & MOUSE_X_OVERFLOW) || (flags & MOUSE_Y_OVERFLOW)) { lapic_eoi(); return; } + + mouse_state.btn_left = (flags & MOUSE_BTN_LEFT) != 0; + mouse_state.btn_right = (flags & MOUSE_BTN_RIGHT) != 0; + mouse_state.btn_middle = (flags & MOUSE_BTN_MIDDLE) != 0; + + if (mouse_mode == MOUSE_MODE_ABSOLUTE) { + uint16_t abs_x = (uint16_t)mouse_packet[1] | ((flags & 0x10) ? 0x100 : 0); + uint16_t abs_y = (uint16_t)mouse_packet[2] | ((flags & 0x20) ? 0x100 : 0); + mouse_state.x = (int32_t)((uint32_t)abs_x * (uint32_t)mouse_screen_w / 0x1FF); + mouse_state.y = (int32_t)((uint32_t)abs_y * (uint32_t)mouse_screen_h / 0x1FF); + } else { + int32_t dx = mouse_packet[1]; + int32_t dy = mouse_packet[2]; + if (flags & MOUSE_X_SIGN) dx |= 0xFFFFFF00; + if (flags & MOUSE_Y_SIGN) dy |= 0xFFFFFF00; + mouse_state.x += dx; + mouse_state.y -= dy; + } + + if (mouse_state.x < 0) mouse_state.x = 0; + if (mouse_state.y < 0) mouse_state.y = 0; + if (mouse_state.x >= mouse_screen_w) mouse_state.x = mouse_screen_w - 1; + if (mouse_state.y >= mouse_screen_h) mouse_state.y = mouse_screen_h - 1; + + if (mouse_has_scroll) { + uint8_t z_raw = mouse_packet[3] & 0x0F; + int8_t z = (z_raw & 0x08) ? (int8_t)(z_raw | 0xF0) : (int8_t)z_raw; + if (z > 0) mouse_state.scroll = MOUSE_SCROLL_DOWN; + else if (z < 0) mouse_state.scroll = MOUSE_SCROLL_UP; + else mouse_state.scroll = MOUSE_SCROLL_NONE; + } + + //mouse_print_status(); + lapic_eoi(); +} + +bool ps2_init(void) { + serial_writestring("[PS2] Initializing PS/2 driver...\n"); + + if (!apic_is_available()) { + serial_writestring("[PS2] ERROR: APIC not available\n"); + return false; + } + + serial_writestring("[PS2] Initializing PS/2 controller...\n"); + ps2_send_cmd(PS2_CMD_DISABLE_PORT1); + ps2_send_cmd(PS2_CMD_DISABLE_PORT2); + ps2_flush_output(); + + ps2_send_cmd(PS2_CMD_READ_CONFIG); + uint8_t cfg = ps2_recv_data(); + cfg &= ~(PS2_CFG_PORT1_IRQ | PS2_CFG_PORT2_IRQ | PS2_CFG_PORT1_XLAT); + ps2_send_cmd(PS2_CMD_WRITE_CONFIG); + ps2_send_data(cfg); + + ps2_send_cmd(PS2_CMD_SELF_TEST); + uint8_t result = ps2_recv_data(); + if (result != 0x55) { serial_printf("[PS2] Self-test FAILED (0x%02x)\n", result); return false; } + serial_writestring("[PS2] Self-test PASSED\n"); + ps2_send_cmd(PS2_CMD_WRITE_CONFIG); + ps2_send_data(cfg); + + ps2_send_cmd(PS2_CMD_TEST_PORT1); + bool kb_ok = (ps2_recv_data() == 0x00); + serial_printf("[PS2] Port 1 (keyboard): %s\n", kb_ok ? "OK" : "FAIL"); + + ps2_send_cmd(PS2_CMD_TEST_PORT2); + bool mouse_ok = (ps2_recv_data() == 0x00); + serial_printf("[PS2] Port 2 (mouse): %s\n", mouse_ok ? "OK" : "FAIL"); + + if (kb_ok) ps2_send_cmd(PS2_CMD_ENABLE_PORT1); + if (mouse_ok) ps2_send_cmd(PS2_CMD_ENABLE_PORT2); + + if (kb_ok) { + ps2_send_data(0xFF); + for (int i = 0; i < 200000; i++) { + if (inb(PS2_STATUS_PORT) & PS2_STATUS_OUTPUT_FULL) + if (inb(PS2_DATA_PORT) == 0xAA) break; + io_wait(); + } + ps2_flush_output(); + ps2_send_data(0xF0); ps2_flush_output(); + ps2_send_data(0x01); ps2_flush_output(); + ps2_send_data(0xF4); ps2_flush_output(); + serial_writestring("[PS2] Keyboard ready (scancode set 1)\n"); + } + + if (mouse_ok) { + ps2_mouse_cmd(0xFF); + for (int i = 0; i < 200000; i++) { + if (inb(PS2_STATUS_PORT) & PS2_STATUS_OUTPUT_FULL) inb(PS2_DATA_PORT); + io_wait(); + } + ps2_flush_output(); + ps2_mouse_cmd(0xF6); + + bool is_abs = ps2_detect_absolute(); + if (is_abs) { + mouse_mode = MOUSE_MODE_ABSOLUTE; + mouse_has_scroll = false; + serial_writestring("[PS2] Mouse mode: ABSOLUTE (QEMU tablet)\n"); + } else { + mouse_mode = MOUSE_MODE_RELATIVE; + mouse_has_scroll = ps2_mouse_init_scroll(); + serial_printf("[PS2] Mouse mode: RELATIVE, scroll=%s\n", + mouse_has_scroll ? "YES" : "NO"); + } + ps2_mouse_cmd_param(0xF3, 100); + ps2_mouse_cmd(0xF4); + serial_writestring("[PS2] Mouse: data reporting enabled\n"); + } + + ps2_send_cmd(PS2_CMD_READ_CONFIG); + cfg = ps2_recv_data(); + if (kb_ok) cfg |= PS2_CFG_PORT1_IRQ; + if (mouse_ok) cfg |= PS2_CFG_PORT2_IRQ; + ps2_send_cmd(PS2_CMD_WRITE_CONFIG); + ps2_send_data(cfg); + + if (kb_ok) { + apic_setup_irq(KB_IRQ_LINE, KB_IRQ_VECTOR, false, 0); + serial_printf("[PS2] Keyboard IRQ%d -> vector 0x%02x\n", KB_IRQ_LINE, KB_IRQ_VECTOR); + } + + if (mouse_ok) { + apic_setup_irq(MOUSE_IRQ_LINE, MOUSE_IRQ_VECTOR, false, 0); + serial_printf("[PS2] Mouse IRQ%d -> vector 0x%02x\n", MOUSE_IRQ_LINE, MOUSE_IRQ_VECTOR); + } + + kb_state = (kb_state_t){0}; + kb_buf = (kb_buf_t){0}; + + mouse_state = (mouse_state_t){0}; + mouse_packet_idx = 0; + mouse_lost_sync = 0; + + if (global_framebuffer) { + mouse_screen_w = (int32_t)global_framebuffer->width; + mouse_screen_h = (int32_t)global_framebuffer->height; + mouse_state.x = mouse_screen_w / 2; + mouse_state.y = mouse_screen_h / 2; + } + + serial_printf("[PS2] Screen: %dx%d, cursor start: %d,%d\n", + (int)mouse_screen_w, (int)mouse_screen_h, + (int)mouse_state.x, (int)mouse_state.y); + serial_writestring("[PS2] Driver ready.\n"); + return true; +} + +const kb_state_t* ps2_kb_get_state(void) { + return (const kb_state_t*)&kb_state; +} +const mouse_state_t* ps2_mouse_get_state(void) { + return (const mouse_state_t*)&mouse_state; +} + +bool kb_buf_empty(void) { + return kb_buf.head == kb_buf.tail; +} + +bool kb_buf_try_getc(char *out) { + if (kb_buf_empty()) return false; + *out = kb_buf.buf[kb_buf.head]; + kb_buf.head = (kb_buf.head + 1) % KB_BUF_SIZE; + return true; +} + +bool kb_buf_has_ctrlc(void) { + uint8_t h = kb_buf.head; + while (h != kb_buf.tail) { + if (kb_buf.buf[h] == 0x03) return true; + h = (h + 1) % KB_BUF_SIZE; + } + return false; +} + +void kb_buf_consume_ctrlc(void) { + uint8_t h = kb_buf.head, t = kb_buf.tail; + uint8_t pos = h; + bool found = false; + while (pos != t) { + if (kb_buf.buf[pos] == 0x03) { found = true; break; } + pos = (pos + 1) % KB_BUF_SIZE; + } + if (!found) return; + uint8_t cur = pos; + uint8_t nxt = (cur + 1) % KB_BUF_SIZE; + while (nxt != t) { + kb_buf.buf[cur] = kb_buf.buf[nxt]; + cur = nxt; + nxt = (nxt + 1) % KB_BUF_SIZE; + } + kb_buf.tail = cur; +} + +char kb_buf_getc(void) { + char c; + while (!kb_buf_try_getc(&c)) { + //wait + } + return c; +} \ No newline at end of file diff --git a/kernel/src/drivers/timer.c b/kernel/src/drivers/timer.c new file mode 100644 index 0000000..f6e3c5c --- /dev/null +++ b/kernel/src/drivers/timer.c @@ -0,0 +1,145 @@ +#include "../include/drivers/timer.h" +#include "../include/apic/apic.h" +#include "../include/io/serial.h" +#include "../include/interrupts/interrupts.h" +#include "../include/io/ports.h" +#include "../include/sched/sched.h" +#include "../include/smp/percpu.h" +#include "../include/memory/pmm.h" +#include "../include/gdt/gdt.h" +#include + +static volatile uint64_t ticks = 0; +volatile uint32_t g_ctrlc_pending = 0; +extern task_t* task_find_foreground(void); +extern void task_kill(task_t* target); +extern void sched_wakeup_sleepers(uint64_t now_ns); + +DEFINE_IRQ(0x20, timer_handler) +{ + ticks++; + lapic_eoi(); + + uint32_t cpu = lapic_get_id(); + task_t* current = current_task[cpu]; + percpu_t* pc = get_percpu(); + + if (cpu == 0 && g_ctrlc_pending) { + g_ctrlc_pending = 0; + task_t *fg = task_find_foreground(); + if (fg) { + task_kill(fg); + } else { + extern void kb_buf_push(char c); + extern bool kb_buf_has_ctrlc(void); + if (!kb_buf_has_ctrlc()) + kb_buf_push(0x03); + } + } + + if (cpu == 0 && hpet_is_available()) { + sched_wakeup_sleepers(hpet_elapsed_ns()); + } + + if (!current) return; + + if (current->pending_kill && pc) { + current->time_slice = 0; + pc->need_resched = true; + (void)frame; + return; + } + + if (current->time_slice > 0) + current->time_slice--; + + if (current->time_slice == 0 && pc) + pc->need_resched = true; + + (void)frame; +} + +bool timer_init(void) { + serial_writestring("Initializing timer subsystem...\n"); + + if (!apic_is_available()) { + serial_writestring("ERROR: APIC not available\n"); + return false; + } + + apic_timer_calibrate(); + + outb(0x21, 0xFF); + outb(0xA1, 0xFF); + + serial_writestring("Timer subsystem initialized\n"); + + if (hpet_is_available()) { + serial_printf("HPET frequency: %llu Hz\n", hpet_get_frequency()); + } else { + serial_writestring("HPET not available\n"); + } + + serial_writestring("Checking APIC Timer Status\n"); + + uint32_t timer_config = lapic_read(LAPIC_TIMER); + uint32_t initial_count = lapic_read(LAPIC_TIMER_ICR); + uint32_t current_count = lapic_read(LAPIC_TIMER_CCR); + + serial_printf("APIC Timer Config: 0x%x\n", timer_config); + serial_printf(" Vector: 0x%x\n", timer_config & 0xFF); + serial_printf(" Masked: %s\n", (timer_config & LAPIC_TIMER_MASKED) ? "YES" : "NO"); + serial_printf(" Periodic: %s\n", (timer_config & LAPIC_TIMER_PERIODIC) ? "YES" : "NO"); + serial_printf("Initial Count: %u\n", initial_count); + serial_printf("Current Count: %u\n", current_count); + + if (timer_config & LAPIC_TIMER_MASKED) { + serial_writestring("WARNING: APIC timer is masked! Unmasking...\n"); + lapic_write(LAPIC_TIMER, (timer_config & ~LAPIC_TIMER_MASKED)); + } + + uint64_t rflags; + asm volatile("pushfq; pop %0" : "=r"(rflags)); + serial_printf("RFLAGS: 0x%llx (IF=%s)\n", rflags, (rflags & 0x200) ? "ON" : "OFF"); + + if (!(rflags & 0x200)) { + serial_writestring("WARNING: Interrupts are DISABLED! Enabling...\n"); + asm volatile("sti"); + } + + return true; +} + +uint64_t timer_get_ticks(void) { + return ticks; +} + +void timer_sleep_ms(uint64_t milliseconds) { + if (hpet_is_available()) { + hpet_sleep_ms(milliseconds); + } else { + volatile uint64_t i; + for (i = 0; i < milliseconds * 1000; i++) { + asm volatile("pause"); + } + } +} + +void timer_sleep_us(uint64_t microseconds) { + if (hpet_is_available()) { + hpet_sleep_us(microseconds); + } else { + volatile uint64_t i; + for (i = 0; i < microseconds; i++) { + asm volatile("pause"); + } + } +} + +void timer_sleep_ns(uint64_t nanoseconds) { + if (hpet_is_available()) { + hpet_sleep_ns(nanoseconds); + } else { + timer_sleep_us(nanoseconds / 1000); + } +} diff --git a/kernel/src/elf/elf.c b/kernel/src/elf/elf.c new file mode 100644 index 0000000..ff82b85 --- /dev/null +++ b/kernel/src/elf/elf.c @@ -0,0 +1,374 @@ +#include "../../include/elf/elf.h" +#include "../../include/memory/vmm.h" +#include "../../include/memory/pmm.h" +#include "../../include/memory/paging.h" +#include "../../include/io/serial.h" +#include +#include + +#define ELF_PIE_BASE 0x0000000000400000ULL +#define ELF_USER_STACK_TOP 0x00007FFFFFFFE000ULL +#define ELF_DEFAULT_STACK (64 * 1024) + +#define PML4_KERNEL_START 256 +#define PML4_ENTRIES 512 + +#ifndef SHF_WRITE +#define SHF_WRITE 0x1 +#endif +#ifndef SHF_ALLOC +#define SHF_ALLOC 0x2 +#endif +#ifndef SHF_EXECINSTR +#define SHF_EXECINSTR 0x4 +#endif + +static inline uintptr_t page_align_down(uintptr_t addr) { + return addr & ~(uintptr_t)(PAGE_SIZE - 1); +} +static inline uintptr_t page_align_up(uintptr_t addr) { + return (addr + PAGE_SIZE - 1) & ~(uintptr_t)(PAGE_SIZE - 1); +} +static uint64_t phdr_flags_to_vmm(uint32_t pf) { + uint64_t flags = VMM_PRESENT | VMM_USER; + if (pf & PF_W) flags |= VMM_WRITE; + if (!(pf & PF_X)) flags |= VMM_NOEXEC; + return flags; +} + +static elf_error_t elf_validate(const elf64_ehdr_t* hdr, size_t size) { + if (size < sizeof(elf64_ehdr_t)) return ELF_ERR_TOO_SMALL; + + uint32_t magic; + memcpy(&magic, hdr->e_ident, 4); + if (magic != ELF_MAGIC) return ELF_ERR_BAD_MAGIC; + if (hdr->e_ident[EI_CLASS] != ELFCLASS64) return ELF_ERR_NOT_64; + if (hdr->e_ident[EI_DATA] != ELFDATA2LSB) return ELF_ERR_NOT_LE; + if (hdr->e_ident[EI_VERSION] != EV_CURRENT || + hdr->e_version != EV_CURRENT) return ELF_ERR_BAD_VERSION; + if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) return ELF_ERR_NOT_EXEC; + if (hdr->e_machine != EM_X86_64) return ELF_ERR_WRONG_ARCH; + if (hdr->e_phnum == 0) return ELF_ERR_NO_LOAD; + + uint64_t pht_end = (uint64_t)hdr->e_phoff + + (uint64_t)hdr->e_phentsize * hdr->e_phnum; + if (pht_end > size) return ELF_ERR_TOO_SMALL; + + if (hdr->e_shnum && hdr->e_shoff) { + uint64_t sht_end = (uint64_t)hdr->e_shoff + + (uint64_t)hdr->e_shentsize * hdr->e_shnum; + if (sht_end > size) return ELF_ERR_TOO_SMALL; + } + return ELF_OK; +} + +static bool ensure_page_mapped(vmm_pagemap_t* map, uintptr_t virt, uint64_t flags) { + uint64_t pf = 0; + if (vmm_get_page_flags(map, virt, &pf) && (pf & VMM_PRESENT)) { + return true; + } + void* page = pmm_alloc_zero(1); + if (!page) return false; + if (!vmm_map_page(map, virt, pmm_virt_to_phys(page), flags)) { + pmm_free(page, 1); + return false; + } + return true; +} + +static elf_error_t load_segment(vmm_pagemap_t* map, + const uint8_t* data, + size_t file_size, + const elf64_phdr_t* phdr, + uintptr_t load_bias) +{ + if (phdr->p_memsz == 0) return ELF_OK; + + uintptr_t virt_start = phdr->p_vaddr + load_bias; + uintptr_t virt_end = virt_start + phdr->p_memsz; + uintptr_t page_start = page_align_down(virt_start); + uintptr_t page_end = page_align_up(virt_end); + size_t page_count = (page_end - page_start) / PAGE_SIZE; + + if (phdr->p_filesz > 0 && phdr->p_offset + phdr->p_filesz > file_size) { + serial_printf("[ELF] Segment data out of file bounds\n"); + return ELF_ERR_TOO_SMALL; + } + + uint64_t vmm_flags = phdr_flags_to_vmm(phdr->p_flags); + + for (size_t i = 0; i < page_count; i++) { + uintptr_t virt = page_start + i * PAGE_SIZE; + + uint64_t cur_flags = 0; + bool already_mapped = + vmm_get_page_flags(map, virt, &cur_flags) && (cur_flags & VMM_PRESENT); + + if (!already_mapped) { + void* page = pmm_alloc_zero(1); + if (!page) { + serial_printf("[ELF] pmm_alloc_zero(1) failed at page %zu for vaddr 0x%llx\n", + i, virt_start); + return ELF_ERR_NO_MEM; + } + if (!vmm_map_page(map, virt, pmm_virt_to_phys(page), vmm_flags)) { + serial_printf("[ELF] vmm_map_page failed: virt=0x%llx\n", virt); + pmm_free(page, 1); + return ELF_ERR_MAP_FAIL; + } + } + + if (phdr->p_filesz > 0) { + uintptr_t pv_start = virt; + uintptr_t pv_end = pv_start + PAGE_SIZE; + uintptr_t data_end = virt_start + phdr->p_filesz; + uintptr_t cp_start = (pv_start > virt_start) ? pv_start : virt_start; + uintptr_t cp_end = (pv_end < data_end) ? pv_end : data_end; + + if (cp_start < cp_end) { + uintptr_t phys = 0; + if (!vmm_virt_to_phys(map, cp_start, &phys)) { + return ELF_ERR_MAP_FAIL; + } + phys &= ~(uintptr_t)0xFFF; + size_t dst_off = cp_start - pv_start; + size_t src_off = cp_start - virt_start; + memcpy((uint8_t*)pmm_phys_to_virt(phys) + dst_off, + data + phdr->p_offset + src_off, + cp_end - cp_start); + } + } + } + + serial_printf("[ELF] Segment loaded: virt=0x%llx-0x%llx flags=%s%s%s " + "phys= pages=%zu\n", + virt_start, virt_end, + (phdr->p_flags & PF_R) ? "R" : "-", + (phdr->p_flags & PF_W) ? "W" : "-", + (phdr->p_flags & PF_X) ? "X" : "-", + page_count); + return ELF_OK; +} + +static uintptr_t cover_orphan_sections(vmm_pagemap_t* map, + const elf64_ehdr_t* ehdr, + const uint8_t* bytes, + size_t file_size, + uintptr_t load_bias, + uintptr_t cur_load_end) +{ + if (!ehdr->e_shnum || !ehdr->e_shoff) { + serial_printf("[ELF] no section headers; skipping orphan-section pass\n"); + return cur_load_end; + } + if (ehdr->e_shentsize < sizeof(elf64_shdr_t)) { + serial_printf("[ELF] e_shentsize=%u too small; skipping orphan-section pass\n", + (unsigned)ehdr->e_shentsize); + return cur_load_end; + } + uint64_t sht_end = (uint64_t)ehdr->e_shoff + + (uint64_t)ehdr->e_shentsize * ehdr->e_shnum; + if (sht_end > file_size) { + serial_printf("[ELF] section table out of file bounds; skip\n"); + return cur_load_end; + } + + serial_printf("[ELF] section scan: e_shnum=%u\n", (unsigned)ehdr->e_shnum); + + uintptr_t new_end = cur_load_end; + + for (uint16_t i = 0; i < ehdr->e_shnum; i++) { + const elf64_shdr_t* sh = (const elf64_shdr_t*) + (bytes + ehdr->e_shoff + (uint64_t)ehdr->e_shentsize * i); + + if (!(sh->sh_flags & SHF_ALLOC)) continue; + if (sh->sh_size == 0) continue; + if (sh->sh_addr == 0) continue; + + uintptr_t s_start = (uintptr_t)sh->sh_addr + load_bias; + uintptr_t s_end = s_start + sh->sh_size; + uintptr_t p_start = page_align_down(s_start); + uintptr_t p_end = page_align_up(s_end); + + uint64_t flags = VMM_PRESENT | VMM_USER; + if (sh->sh_flags & SHF_WRITE) flags |= VMM_WRITE; + if (!(sh->sh_flags & SHF_EXECINSTR)) flags |= VMM_NOEXEC; + + size_t added_pages = 0; + for (uintptr_t p = p_start; p < p_end; p += PAGE_SIZE) { + uint64_t pf = 0; + if (vmm_get_page_flags(map, p, &pf) && (pf & VMM_PRESENT)) + continue; + if (!ensure_page_mapped(map, p, flags)) { + serial_printf("[ELF] orphan-section: alloc/map failed at 0x%llx\n", + (unsigned long long)p); + return new_end; + } + added_pages++; + } + + if (added_pages > 0) { + serial_printf("[ELF] ORPHAN section #%u type=%u: virt=0x%llx-0x%llx " + "added=%zu pages flags=%s%s%s\n", + (unsigned)i, (unsigned)sh->sh_type, + (unsigned long long)s_start, + (unsigned long long)s_end, + added_pages, + (sh->sh_flags & SHF_ALLOC) ? "A" : "-", + (sh->sh_flags & SHF_WRITE) ? "W" : "-", + (sh->sh_flags & SHF_EXECINSTR) ? "X" : "-"); + + if (sh->sh_type != SHT_NOBITS && sh->sh_size > 0) { + if (sh->sh_offset + sh->sh_size <= file_size) { + for (uintptr_t p = p_start; p < p_end; p += PAGE_SIZE) { + uintptr_t pv_end = p + PAGE_SIZE; + uintptr_t cp_start = (p > s_start) ? p : s_start; + uintptr_t cp_end = (pv_end < s_end) ? pv_end : s_end; + if (cp_start >= cp_end) continue; + uintptr_t phys = 0; + if (!vmm_virt_to_phys(map, cp_start, &phys)) continue; + phys &= ~(uintptr_t)0xFFF; + size_t dst_off = cp_start - p; + size_t src_off = cp_start - s_start; + memcpy((uint8_t*)pmm_phys_to_virt(phys) + dst_off, + bytes + sh->sh_offset + src_off, + cp_end - cp_start); + } + } + } + } + + if (p_end > new_end) new_end = p_end; + } + return new_end; +} + +static uintptr_t alloc_user_stack(vmm_pagemap_t* map, size_t stack_size) { + size_t page_count = page_align_up(stack_size) / PAGE_SIZE; + uintptr_t stack_bottom = ELF_USER_STACK_TOP - page_count * PAGE_SIZE; + uint64_t flags = VMM_PRESENT | VMM_WRITE | VMM_USER | VMM_NOEXEC; + + for (size_t i = 0; i < page_count; i++) { + void* page = pmm_alloc_zero(1); + if (!page) { + serial_printf("[ELF] Stack alloc failed at page %zu\n", i); + for (size_t j = 0; j < i; j++) + vmm_unmap_page_noflush(map, stack_bottom + j * PAGE_SIZE); + return 0; + } + if (!vmm_map_page(map, stack_bottom + i * PAGE_SIZE, + pmm_virt_to_phys(page), flags)) { + serial_printf("[ELF] Stack map failed at page %zu\n", i); + pmm_free(page, 1); + for (size_t j = 0; j < i; j++) + vmm_unmap_page_noflush(map, stack_bottom + j * PAGE_SIZE); + return 0; + } + } + + serial_printf("[ELF] Stack: virt=0x%llx-0x%llx (%zu KiB)\n", + stack_bottom, ELF_USER_STACK_TOP, + (page_count * PAGE_SIZE) / 1024); + + return (ELF_USER_STACK_TOP - 8) & ~(uintptr_t)0xF; +} + +elf_load_result_t elf_load(const void* data, size_t size, size_t stack_sz) { + elf_load_result_t result = {0}; + + if (!data) { result.error = ELF_ERR_NULL; return result; } + + const elf64_ehdr_t* ehdr = (const elf64_ehdr_t*)data; + result.error = elf_validate(ehdr, size); + if (result.error != ELF_OK) { + serial_printf("[ELF] Validation failed: %s\n", elf_strerror(result.error)); + return result; + } + + uintptr_t load_bias = (ehdr->e_type == ET_DYN) ? ELF_PIE_BASE : 0; + if (load_bias) serial_printf("[ELF] PIE binary, bias=0x%llx\n", load_bias); + + vmm_pagemap_t* map = vmm_create_pagemap(); + if (!map) { + serial_printf("[ELF] vmm_create_pagemap() failed\n"); + result.error = ELF_ERR_NO_MEM; + return result; + } + result.pagemap = map; + + serial_printf("[ELF] Kernel PML4[256..511] inherited via vmm_create_pagemap\n"); + + const uint8_t* bytes = (const uint8_t*)data; + const elf64_phdr_t* phdrs = (const elf64_phdr_t*)(bytes + ehdr->e_phoff); + bool has_load = false; + uintptr_t max_vaddr = 0; + + for (uint16_t i = 0; i < ehdr->e_phnum; i++) { + const elf64_phdr_t* ph = &phdrs[i]; + if (ph->p_type != PT_LOAD) continue; + has_load = true; + + serial_printf("[ELF] PT_LOAD[%u]: off=0x%llx vaddr=0x%llx " + "filesz=0x%llx memsz=0x%llx flags=0x%x\n", + i, ph->p_offset, ph->p_vaddr, + ph->p_filesz, ph->p_memsz, ph->p_flags); + + elf_error_t err = load_segment(map, bytes, size, ph, load_bias); + if (err != ELF_OK) { + result.error = err; + return result; + } + + uintptr_t seg_end = ph->p_vaddr + load_bias + ph->p_memsz; + if (seg_end > max_vaddr) max_vaddr = seg_end; + } + + if (!has_load) { result.error = ELF_ERR_NO_LOAD; return result; } + + uintptr_t load_end = page_align_up(max_vaddr); + + load_end = cover_orphan_sections(map, ehdr, bytes, size, load_bias, load_end); + + result.entry = ehdr->e_entry + load_bias; + result.load_base = load_bias; + result.load_end = load_end; + + serial_printf("[ELF] Entry point: 0x%llx load_end (brk_start): 0x%llx\n", + result.entry, result.load_end); + + if (stack_sz == 0) stack_sz = ELF_DEFAULT_STACK; + result.stack_size = stack_sz; + result.stack_top = alloc_user_stack(map, stack_sz); + if (result.stack_top == 0) { result.error = ELF_ERR_NO_MEM; return result; } + + serial_printf("[ELF] Load complete. entry=0x%llx stack_top=0x%llx\n", + result.entry, result.stack_top); + return result; +} + +void elf_unload(elf_load_result_t* result) { + if (!result) return; + if (result->pagemap) { + vmm_free_pagemap(result->pagemap); + result->pagemap = NULL; + } + serial_printf("[ELF] Process unloaded.\n"); +} + +const char* elf_strerror(elf_error_t err) { + switch (err) { + case ELF_OK: return "OK"; + case ELF_ERR_NULL: return "NULL pointer"; + case ELF_ERR_TOO_SMALL: return "file too small / data out of bounds"; + case ELF_ERR_BAD_MAGIC: return "not an ELF file (bad magic)"; + case ELF_ERR_NOT_64: return "not ELF64"; + case ELF_ERR_NOT_LE: return "not little-endian"; + case ELF_ERR_BAD_VERSION: return "unsupported ELF version"; + case ELF_ERR_NOT_EXEC: return "not an executable or shared object"; + case ELF_ERR_WRONG_ARCH: return "not x86_64"; + case ELF_ERR_NO_LOAD: return "no PT_LOAD segments"; + case ELF_ERR_MAP_FAIL: return "vmm_map_page failed"; + case ELF_ERR_NO_MEM: return "out of memory"; + default: return "unknown error"; + } +} \ No newline at end of file diff --git a/kernel/src/font.psf b/kernel/src/font.psf new file mode 100644 index 0000000000000000000000000000000000000000..13a44896846cf2821bc74957cc3a25f34997a9b5 GIT binary patch literal 9975 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 F@IOy3wEqAA literal 0 HcmV?d00001 diff --git a/kernel/src/fs/devfs.c b/kernel/src/fs/devfs.c new file mode 100644 index 0000000..2cdf02a --- /dev/null +++ b/kernel/src/fs/devfs.c @@ -0,0 +1,352 @@ +#include +#include +#include +#include +#include "../../include/fs/devfs.h" +#include "../../include/fs/vfs.h" +#include "../../include/memory/pmm.h" +#include "../../include/io/serial.h" +#include "../../include/drivers/ps2.h" +#include "../../include/sched/sched.h" +#include "../../include/apic/apic.h" +#include "../../include/smp/percpu.h" + +extern void draw_cursor(void); +extern void erase_cursor(void); + +extern uint32_t get_screen_width(void); +extern uint32_t get_screen_height(void); +extern uint32_t get_cursor_row(void); +extern uint32_t get_cursor_col(void); + +#define TIOCGWINSZ 0x5413 +#define TIOCGCURSOR 0x5480 +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TIOCSNONBLOCK 0x5481 + +static int tty_nonblock = 0; + +#define T_ICANON 0x0002 +#define T_ECHO 0x0008 +#define T_ISIG 0x0001 + +struct cervus_winsize { + uint16_t ws_row; + uint16_t ws_col; + uint16_t ws_xpixel; + uint16_t ws_ypixel; +}; + +struct cervus_cursor_pos { + uint32_t row; + uint32_t col; +}; + +struct cervus_termios { + uint32_t c_iflag; + uint32_t c_oflag; + uint32_t c_cflag; + uint32_t c_lflag; + uint8_t c_cc[32]; +}; + +static struct cervus_termios g_tty_termios = { + .c_iflag = 0, + .c_oflag = 0, + .c_cflag = 0, + .c_lflag = T_ICANON | T_ECHO | T_ISIG, + .c_cc = {0}, +}; + +static inline int tty_is_canonical(void) { + return (g_tty_termios.c_lflag & T_ICANON) != 0; +} +static inline int tty_has_isig(void) { + return (g_tty_termios.c_lflag & T_ISIG) != 0; +} + +static inline task_t* devfs_cur_task(void) { + percpu_t* pc = get_percpu(); + return pc ? (task_t*)pc->current_task : NULL; +} + +static int64_t tty_read(vnode_t *node, void *buf, size_t len, uint64_t offset) { + (void)node; (void)offset; + if (len == 0) return 0; + + char *dst = buf; + + uint64_t freq = hpet_is_available() ? hpet_get_frequency() : 0; + uint64_t half_tick = freq ? freq / 2 : 0; + uint64_t next_blink = half_tick ? (hpet_read_counter() + half_tick) : 0; + int cursor_on = 1; + int canonical = tty_is_canonical(); + int isig = tty_has_isig(); + + if (tty_nonblock && kb_buf_empty()) return -EAGAIN; + + draw_cursor(); + + while (kb_buf_empty()) { + task_t *me = devfs_cur_task(); + if (me && me->pending_kill) { + erase_cursor(); + return -EINTR; + } + + if (half_tick) { + uint64_t now = hpet_read_counter(); + if (now >= next_blink) { + if (cursor_on) { erase_cursor(); cursor_on = 0; } + else { draw_cursor(); cursor_on = 1; } + next_blink = now + half_tick; + } + } + task_yield(); + } + + erase_cursor(); + + task_t *me = devfs_cur_task(); + if (me && me->pending_kill) { + kb_buf_consume_ctrlc(); + return -EINTR; + } + + char first = kb_buf_getc(); + if (isig && canonical && first == 0x03) { + return -EINTR; + } + + dst[0] = first; + size_t got = 1; + + if (!canonical) { + while (got < len) { + char c; + if (!kb_buf_try_getc(&c)) break; + dst[got++] = c; + } + return (int64_t)got; + } + + while (got < len) { + char c; + if (!kb_buf_try_getc(&c)) break; + if (isig && c == 0x03) break; + dst[got++] = c; + if (c == '\n') break; + } + return (int64_t)got; +} + +static int64_t tty_write(vnode_t *node, const void *buf, size_t len, uint64_t offset) { + (void)node; (void)offset; + serial_writebuf((const char *)buf, len); + const unsigned char *p = (const unsigned char *)buf; + for (size_t i = 0; i < len; i++) putchar((int)p[i]); + return (int64_t)len; +} + +static int64_t tty_ioctl(vnode_t *node, uint64_t req, void *arg) { + (void)node; + + if (req == TIOCGWINSZ) { + if (!arg) return -EFAULT; + struct cervus_winsize *ws = (struct cervus_winsize *)arg; + uint32_t w = get_screen_width(); + uint32_t h = get_screen_height(); + ws->ws_col = (uint16_t)(w / 8); + ws->ws_row = (uint16_t)(h / 16); + ws->ws_xpixel = (uint16_t)w; + ws->ws_ypixel = (uint16_t)h; + return 0; + } + + if (req == TIOCGCURSOR) { + if (!arg) return -EFAULT; + struct cervus_cursor_pos *cp = (struct cervus_cursor_pos *)arg; + cp->row = get_cursor_row(); + cp->col = get_cursor_col(); + return 0; + } + + if (req == TIOCSNONBLOCK) { + if (!arg) return -EFAULT; + tty_nonblock = *((int *)arg) ? 1 : 0; + return 0; + } + + if (req == TCGETS) { + if (!arg) return -EFAULT; + memcpy(arg, &g_tty_termios, sizeof(g_tty_termios)); + return 0; + } + + if (req == TCSETS || req == TCSETSW || req == TCSETSF) { + if (!arg) return -EFAULT; + memcpy(&g_tty_termios, arg, sizeof(g_tty_termios)); + return 0; + } + + return -ENOTTY; +} + +static void devfs_ref(vnode_t *node) { + (void)node; +} + +static void devfs_unref(vnode_t *node) { + (void)node; +} + +static int devfs_stat(vnode_t *node, vfs_stat_t *out) { + memset(out, 0, sizeof(*out)); + out->st_ino = node->ino; + out->st_type = node->type; + out->st_mode = node->mode; + return 0; +} + +static const vnode_ops_t tty_ops = { + .read = tty_read, + .write = tty_write, + .ioctl = tty_ioctl, + .stat = devfs_stat, + .ref = devfs_ref, + .unref = devfs_unref, +}; + +static int64_t null_read(vnode_t *n, void *buf, size_t len, uint64_t off) { + (void)n; (void)buf; (void)len; (void)off; + return 0; +} + +static int64_t null_write(vnode_t *n, const void *buf, size_t len, uint64_t off) { + (void)n; (void)buf; (void)off; + return (int64_t)len; +} + +static const vnode_ops_t null_ops = { + .read = null_read, + .write = null_write, + .stat = devfs_stat, + .ref = devfs_ref, + .unref = devfs_unref, +}; + +static int64_t zero_read(vnode_t *n, void *buf, size_t len, uint64_t off) { + (void)n; (void)off; + memset(buf, 0, len); + return (int64_t)len; +} + +static const vnode_ops_t zero_ops = { + .read = zero_read, + .write = null_write, + .stat = devfs_stat, + .ref = devfs_ref, + .unref = devfs_unref, +}; + +#define DEVFS_MAX_ENTRIES 32 + +typedef struct { + char name[VFS_MAX_NAME]; + vnode_t *node; +} devfs_entry_t; + +typedef struct { + devfs_entry_t entries[DEVFS_MAX_ENTRIES]; + int count; +} devfs_dir_data_t; + +static devfs_dir_data_t g_devdir; +static vnode_t g_devroot; +static vnode_t g_tty_node; +static vnode_t g_null_node; +static vnode_t g_zero_node; + +static uint64_t g_devfs_ino = 100; + +static int devfs_dir_lookup(vnode_t *dir, const char *name, vnode_t **out) { + (void)dir; + for (int i = 0; i < g_devdir.count; i++) { + if (strcmp(g_devdir.entries[i].name, name) == 0) { + vnode_ref(g_devdir.entries[i].node); + *out = g_devdir.entries[i].node; + return 0; + } + } + return -ENOENT; +} + +static int devfs_dir_readdir(vnode_t *dir, uint64_t index, vfs_dirent_t *out) { + (void)dir; + if ((int64_t)index >= g_devdir.count) return -ENOENT; + devfs_entry_t *e = &g_devdir.entries[index]; + out->d_ino = e->node->ino; + out->d_type = (uint8_t)e->node->type; + strncpy(out->d_name, e->name, VFS_MAX_NAME - 1); + out->d_name[VFS_MAX_NAME - 1] = '\0'; + return 0; +} + +static const vnode_ops_t devfs_dir_ops = { + .lookup = devfs_dir_lookup, + .readdir = devfs_dir_readdir, + .stat = devfs_stat, + .ref = devfs_ref, + .unref = devfs_unref, +}; + +void devfs_register(const char *name, vnode_t *node) { + if (g_devdir.count >= DEVFS_MAX_ENTRIES) return; + devfs_entry_t *e = &g_devdir.entries[g_devdir.count++]; + strncpy(e->name, name, VFS_MAX_NAME - 1); + e->name[VFS_MAX_NAME - 1] = '\0'; + e->node = node; +} + +vnode_t *devfs_create_root(void) { + memset(&g_devdir, 0, sizeof(g_devdir)); + memset(&g_devroot, 0, sizeof(g_devroot)); + memset(&g_tty_node, 0, sizeof(g_tty_node)); + memset(&g_null_node, 0, sizeof(g_null_node)); + memset(&g_zero_node, 0, sizeof(g_zero_node)); + + g_devroot.type = VFS_NODE_DIR; + g_devroot.mode = 0755; + g_devroot.ino = g_devfs_ino++; + g_devroot.ops = &devfs_dir_ops; + g_devroot.fs_data = &g_devdir; + g_devroot.refcount = 1; + + g_tty_node.type = VFS_NODE_CHARDEV; + g_tty_node.mode = 0666; + g_tty_node.ino = g_devfs_ino++; + g_tty_node.ops = &tty_ops; + g_tty_node.refcount = 1; + + g_null_node.type = VFS_NODE_CHARDEV; + g_null_node.mode = 0666; + g_null_node.ino = g_devfs_ino++; + g_null_node.ops = &null_ops; + g_null_node.refcount = 1; + + g_zero_node.type = VFS_NODE_CHARDEV; + g_zero_node.mode = 0666; + g_zero_node.ino = g_devfs_ino++; + g_zero_node.ops = &zero_ops; + g_zero_node.refcount = 1; + + devfs_register("tty", &g_tty_node); + devfs_register("null", &g_null_node); + devfs_register("zero", &g_zero_node); + + serial_writestring("[devfs] /dev/tty, /dev/null, /dev/zero registered\n"); + return &g_devroot; +} \ No newline at end of file diff --git a/kernel/src/fs/ext2.c b/kernel/src/fs/ext2.c new file mode 100644 index 0000000..f97f197 --- /dev/null +++ b/kernel/src/fs/ext2.c @@ -0,0 +1,935 @@ +#include "../../include/fs/ext2.h" +#include "../../include/fs/vfs.h" +#include "../../include/drivers/blkdev.h" +#include "../../include/memory/pmm.h" +#include "../../include/io/serial.h" +#include "../../include/syscall/errno.h" +#include +#include + +static int block_read(ext2_t *fs, uint32_t block, void *buf) { + return blkdev_read(fs->dev, (uint64_t)block * fs->block_size, buf, fs->block_size); +} + +static int block_write(ext2_t *fs, uint32_t block, const void *buf) { + return blkdev_write(fs->dev, (uint64_t)block * fs->block_size, buf, fs->block_size); +} + +static int sb_flush(ext2_t *fs) { + return blkdev_write(fs->dev, EXT2_SUPER_OFFSET, &fs->sb, sizeof(fs->sb)); +} + +static int gdt_flush(ext2_t *fs) { + uint32_t gdt_block = (fs->block_size == 1024) ? 2 : 1; + return blkdev_write(fs->dev, (uint64_t)gdt_block * fs->block_size, + fs->gdt, fs->groups_count * sizeof(ext2_group_desc_t)); +} + +static int inode_read(ext2_t *fs, uint32_t ino, ext2_inode_t *out) { + if (ino == 0) return -EINVAL; + uint32_t idx = ino - 1; + uint32_t group = idx / fs->sb.s_inodes_per_group; + uint32_t local = idx % fs->sb.s_inodes_per_group; + if (group >= fs->groups_count) return -EINVAL; + uint64_t off = (uint64_t)fs->gdt[group].bg_inode_table * fs->block_size + + (uint64_t)local * fs->inode_size; + return blkdev_read(fs->dev, off, out, sizeof(*out)); +} + +static int inode_write(ext2_t *fs, uint32_t ino, const ext2_inode_t *in) { + if (ino == 0) return -EINVAL; + uint32_t idx = ino - 1; + uint32_t group = idx / fs->sb.s_inodes_per_group; + uint32_t local = idx % fs->sb.s_inodes_per_group; + if (group >= fs->groups_count) return -EINVAL; + uint64_t off = (uint64_t)fs->gdt[group].bg_inode_table * fs->block_size + + (uint64_t)local * fs->inode_size; + return blkdev_write(fs->dev, off, in, sizeof(*in)); +} + +static bool bmp_test(const uint8_t *bmp, uint32_t bit) { + return (bmp[bit / 8] >> (bit % 8)) & 1; +} +static void bmp_set(uint8_t *bmp, uint32_t bit) { + bmp[bit / 8] |= (uint8_t)(1 << (bit % 8)); +} +static void bmp_clear(uint8_t *bmp, uint32_t bit) { + bmp[bit / 8] &= (uint8_t)~(1 << (bit % 8)); +} + +static int32_t alloc_inode(ext2_t *fs) { + uint8_t *bmp = kmalloc(fs->block_size); + if (!bmp) return -ENOMEM; + for (uint32_t g = 0; g < fs->groups_count; g++) { + if (fs->gdt[g].bg_free_inodes_count == 0) continue; + block_read(fs, fs->gdt[g].bg_inode_bitmap, bmp); + for (uint32_t i = 0; i < fs->sb.s_inodes_per_group; i++) { + if (!bmp_test(bmp, i)) { + bmp_set(bmp, i); + block_write(fs, fs->gdt[g].bg_inode_bitmap, bmp); + fs->gdt[g].bg_free_inodes_count--; + fs->sb.s_free_inodes_count--; + fs->dirty = true; + kfree(bmp); + return (int32_t)(g * fs->sb.s_inodes_per_group + i + 1); + } + } + } + kfree(bmp); + return -ENOSPC; +} + +static void free_inode(ext2_t *fs, uint32_t ino) { + uint32_t idx = ino - 1; + uint32_t group = idx / fs->sb.s_inodes_per_group; + uint32_t local = idx % fs->sb.s_inodes_per_group; + uint8_t *bmp = kmalloc(fs->block_size); + if (!bmp) return; + block_read(fs, fs->gdt[group].bg_inode_bitmap, bmp); + bmp_clear(bmp, local); + block_write(fs, fs->gdt[group].bg_inode_bitmap, bmp); + fs->gdt[group].bg_free_inodes_count++; + fs->sb.s_free_inodes_count++; + fs->dirty = true; + kfree(bmp); +} + +static int32_t alloc_block(ext2_t *fs) { + uint8_t *bmp = kmalloc(fs->block_size); + if (!bmp) return -ENOMEM; + for (uint32_t g = 0; g < fs->groups_count; g++) { + if (fs->gdt[g].bg_free_blocks_count == 0) continue; + block_read(fs, fs->gdt[g].bg_block_bitmap, bmp); + for (uint32_t i = 0; i < fs->sb.s_blocks_per_group; i++) { + uint32_t abs_block = g * fs->sb.s_blocks_per_group + i + fs->sb.s_first_data_block; + if (abs_block >= fs->sb.s_blocks_count) break; + if (!bmp_test(bmp, i)) { + bmp_set(bmp, i); + block_write(fs, fs->gdt[g].bg_block_bitmap, bmp); + fs->gdt[g].bg_free_blocks_count--; + fs->sb.s_free_blocks_count--; + fs->dirty = true; + kfree(bmp); + return (int32_t)abs_block; + } + } + } + kfree(bmp); + return -ENOSPC; +} + +static void free_block(ext2_t *fs, uint32_t blk) { + if (blk < fs->sb.s_first_data_block) return; + uint32_t adj = blk - fs->sb.s_first_data_block; + uint32_t group = adj / fs->sb.s_blocks_per_group; + uint32_t local = adj % fs->sb.s_blocks_per_group; + if (group >= fs->groups_count) return; + uint8_t *bmp = kmalloc(fs->block_size); + if (!bmp) return; + block_read(fs, fs->gdt[group].bg_block_bitmap, bmp); + bmp_clear(bmp, local); + block_write(fs, fs->gdt[group].bg_block_bitmap, bmp); + fs->gdt[group].bg_free_blocks_count++; + fs->sb.s_free_blocks_count++; + fs->dirty = true; + kfree(bmp); +} + +static int32_t get_block_num(ext2_t *fs, ext2_inode_t *di, uint32_t file_block) { + if (file_block < EXT2_NDIR_BLOCKS) + return (int32_t)di->i_block[file_block]; + uint32_t ppb = fs->ptrs_per_block; + file_block -= EXT2_NDIR_BLOCKS; + if (file_block < ppb) { + if (di->i_block[EXT2_IND_BLOCK] == 0) return 0; + uint32_t *ind = kmalloc(fs->block_size); + if (!ind) return -ENOMEM; + block_read(fs, di->i_block[EXT2_IND_BLOCK], ind); + int32_t ret = (int32_t)ind[file_block]; + kfree(ind); + return ret; + } + file_block -= ppb; + if (file_block < ppb * ppb) { + if (di->i_block[EXT2_DIND_BLOCK] == 0) return 0; + uint32_t *dind = kmalloc(fs->block_size); + if (!dind) return -ENOMEM; + block_read(fs, di->i_block[EXT2_DIND_BLOCK], dind); + uint32_t i1 = file_block / ppb; + uint32_t i2 = file_block % ppb; + if (dind[i1] == 0) { kfree(dind); return 0; } + uint32_t ib = dind[i1]; + kfree(dind); + uint32_t *ind = kmalloc(fs->block_size); + if (!ind) return -ENOMEM; + block_read(fs, ib, ind); + int32_t ret = (int32_t)ind[i2]; + kfree(ind); + return ret; + } + return -EFBIG; +} + +static int set_block_num(ext2_t *fs, ext2_inode_t *di, uint32_t file_block, uint32_t disk_block) { + if (file_block < EXT2_NDIR_BLOCKS) { + di->i_block[file_block] = disk_block; + return 0; + } + uint32_t ppb = fs->ptrs_per_block; + file_block -= EXT2_NDIR_BLOCKS; + if (file_block < ppb) { + if (di->i_block[EXT2_IND_BLOCK] == 0) { + int32_t nb = alloc_block(fs); + if (nb < 0) return nb; + di->i_block[EXT2_IND_BLOCK] = (uint32_t)nb; + uint8_t *z = kzalloc(fs->block_size); + block_write(fs, (uint32_t)nb, z); + kfree(z); + } + uint32_t *ind = kmalloc(fs->block_size); + if (!ind) return -ENOMEM; + block_read(fs, di->i_block[EXT2_IND_BLOCK], ind); + ind[file_block] = disk_block; + block_write(fs, di->i_block[EXT2_IND_BLOCK], ind); + kfree(ind); + return 0; + } + file_block -= ppb; + if (file_block < ppb * ppb) { + if (di->i_block[EXT2_DIND_BLOCK] == 0) { + int32_t nb = alloc_block(fs); + if (nb < 0) return nb; + di->i_block[EXT2_DIND_BLOCK] = (uint32_t)nb; + uint8_t *z = kzalloc(fs->block_size); + block_write(fs, (uint32_t)nb, z); + kfree(z); + } + uint32_t *dind = kmalloc(fs->block_size); + if (!dind) return -ENOMEM; + block_read(fs, di->i_block[EXT2_DIND_BLOCK], dind); + uint32_t i1 = file_block / ppb; + uint32_t i2 = file_block % ppb; + if (dind[i1] == 0) { + int32_t nb = alloc_block(fs); + if (nb < 0) { kfree(dind); return nb; } + dind[i1] = (uint32_t)nb; + block_write(fs, di->i_block[EXT2_DIND_BLOCK], dind); + uint8_t *z = kzalloc(fs->block_size); + block_write(fs, (uint32_t)nb, z); + kfree(z); + } + uint32_t ib = dind[i1]; + kfree(dind); + uint32_t *ind = kmalloc(fs->block_size); + if (!ind) return -ENOMEM; + block_read(fs, ib, ind); + ind[i2] = disk_block; + block_write(fs, ib, ind); + kfree(ind); + return 0; + } + return -EFBIG; +} + +static const vnode_ops_t ext2_file_ops; +static const vnode_ops_t ext2_dir_ops; + +static vnode_t *ext2_make_vnode(ext2_t *fs, uint32_t ino, ext2_inode_t *di) { + vnode_t *v = kzalloc(sizeof(vnode_t)); + if (!v) return NULL; + ext2_vdata_t *vd = kzalloc(sizeof(ext2_vdata_t)); + if (!vd) { kfree(v); return NULL; } + vd->fs = fs; + vd->ino = ino; + if ((di->i_mode & 0xF000) == EXT2_S_IFDIR) { + v->type = VFS_NODE_DIR; + v->ops = &ext2_dir_ops; + } else { + v->type = VFS_NODE_FILE; + v->ops = &ext2_file_ops; + } + v->mode = di->i_mode & 0x0FFF; + v->uid = di->i_uid; + v->gid = di->i_gid; + v->ino = ino; + v->size = di->i_size; + v->fs_data = vd; + v->refcount = 1; + return v; +} + +static int64_t ext2_file_read(vnode_t *node, void *buf, size_t len, uint64_t offset) { + ext2_vdata_t *vd = node->fs_data; + ext2_t *fs = vd->fs; + ext2_inode_t di; + int r = inode_read(fs, vd->ino, &di); + if (r < 0) return r; + if (offset >= di.i_size) return 0; + if (offset + len > di.i_size) len = di.i_size - (size_t)offset; + if (len == 0) return 0; + uint8_t *dst = (uint8_t *)buf; + size_t done = 0; + uint8_t *bb = kmalloc(fs->block_size); + if (!bb) return -ENOMEM; + while (done < len) { + uint32_t co = (uint32_t)(offset + done); + uint32_t fb = co / fs->block_size; + uint32_t bo = co % fs->block_size; + int32_t db = get_block_num(fs, &di, fb); + if (db <= 0) { + if (db < 0) { kfree(bb); return db; } + memset(bb, 0, fs->block_size); + } else { + r = block_read(fs, (uint32_t)db, bb); + if (r < 0) { kfree(bb); return r; } + } + size_t ch = fs->block_size - bo; + if (ch > len - done) ch = len - done; + memcpy(dst + done, bb + bo, ch); + done += ch; + } + kfree(bb); + return (int64_t)done; +} + +static int64_t ext2_file_write(vnode_t *node, const void *buf, size_t len, uint64_t offset) { + ext2_vdata_t *vd = node->fs_data; + ext2_t *fs = vd->fs; + ext2_inode_t di; + int r = inode_read(fs, vd->ino, &di); + if (r < 0) return r; + const uint8_t *src = (const uint8_t *)buf; + size_t done = 0; + uint8_t *bb = kmalloc(fs->block_size); + if (!bb) return -ENOMEM; + while (done < len) { + uint32_t co = (uint32_t)(offset + done); + uint32_t fb = co / fs->block_size; + uint32_t bo = co % fs->block_size; + int32_t db = get_block_num(fs, &di, fb); + if (db == 0) { + int32_t nb = alloc_block(fs); + if (nb < 0) { kfree(bb); return (done > 0) ? (int64_t)done : nb; } + set_block_num(fs, &di, fb, (uint32_t)nb); + db = nb; + memset(bb, 0, fs->block_size); + di.i_blocks += fs->block_size / 512; + } else if (db < 0) { + kfree(bb); return db; + } else { + if (bo != 0 || (len - done) < fs->block_size) + block_read(fs, (uint32_t)db, bb); + } + size_t ch = fs->block_size - bo; + if (ch > len - done) ch = len - done; + memcpy(bb + bo, src + done, ch); + block_write(fs, (uint32_t)db, bb); + done += ch; + } + uint32_t ne = (uint32_t)(offset + done); + if (ne > di.i_size) { di.i_size = ne; node->size = ne; } + inode_write(fs, vd->ino, &di); + fs->dirty = true; + kfree(bb); + return (int64_t)done; +} + +static void free_all_blocks(ext2_t *fs, ext2_inode_t *di) { + for (int i = 0; i < EXT2_NDIR_BLOCKS; i++) { + if (di->i_block[i]) { free_block(fs, di->i_block[i]); di->i_block[i] = 0; } + } + if (di->i_block[EXT2_IND_BLOCK]) { + uint32_t *ind = kmalloc(fs->block_size); + if (ind) { + block_read(fs, di->i_block[EXT2_IND_BLOCK], ind); + for (uint32_t i = 0; i < fs->ptrs_per_block; i++) + if (ind[i]) free_block(fs, ind[i]); + kfree(ind); + } + free_block(fs, di->i_block[EXT2_IND_BLOCK]); + di->i_block[EXT2_IND_BLOCK] = 0; + } + if (di->i_block[EXT2_DIND_BLOCK]) { + uint32_t *dind = kmalloc(fs->block_size); + if (dind) { + block_read(fs, di->i_block[EXT2_DIND_BLOCK], dind); + for (uint32_t i = 0; i < fs->ptrs_per_block; i++) { + if (dind[i]) { + uint32_t *ind = kmalloc(fs->block_size); + if (ind) { + block_read(fs, dind[i], ind); + for (uint32_t j = 0; j < fs->ptrs_per_block; j++) + if (ind[j]) free_block(fs, ind[j]); + kfree(ind); + } + free_block(fs, dind[i]); + } + } + kfree(dind); + } + free_block(fs, di->i_block[EXT2_DIND_BLOCK]); + di->i_block[EXT2_DIND_BLOCK] = 0; + } + di->i_blocks = 0; +} + +static int ext2_file_truncate(vnode_t *node, uint64_t new_size) { + ext2_vdata_t *vd = node->fs_data; + ext2_t *fs = vd->fs; + ext2_inode_t di; + int r = inode_read(fs, vd->ino, &di); + if (r < 0) return r; + if (new_size == 0) free_all_blocks(fs, &di); + di.i_size = (uint32_t)new_size; + node->size = new_size; + inode_write(fs, vd->ino, &di); + fs->dirty = true; + return 0; +} + +static int ext2_stat(vnode_t *node, vfs_stat_t *out) { + memset(out, 0, sizeof(*out)); + out->st_ino = node->ino; + out->st_type = node->type; + out->st_mode = node->mode; + out->st_uid = node->uid; + out->st_gid = node->gid; + out->st_size = node->size; + out->st_blocks = (node->size + 511) / 512; + return 0; +} + +static void ext2_vnode_ref(vnode_t *node) { (void)node; } +static void ext2_vnode_unref(vnode_t *node) { + if (node->fs_data) kfree(node->fs_data); + kfree(node); +} + +static const vnode_ops_t ext2_file_ops = { + .read = ext2_file_read, + .write = ext2_file_write, + .truncate = ext2_file_truncate, + .stat = ext2_stat, + .ref = ext2_vnode_ref, + .unref = ext2_vnode_unref, +}; + +static int ext2_dir_lookup(vnode_t *dir, const char *name, vnode_t **out) { + ext2_vdata_t *vd = dir->fs_data; + ext2_t *fs = vd->fs; + ext2_inode_t di; + int r = inode_read(fs, vd->ino, &di); + if (r < 0) return r; + uint8_t *bb = kmalloc(fs->block_size); + if (!bb) return -ENOMEM; + size_t nl = strlen(name); + uint32_t ds = di.i_size; + uint32_t pos = 0, fb = 0; + while (pos < ds) { + int32_t db = get_block_num(fs, &di, fb); + if (db <= 0) { fb++; pos += fs->block_size; continue; } + block_read(fs, (uint32_t)db, bb); + uint32_t off = 0; + while (off < fs->block_size && (pos + off) < ds) { + ext2_dir_entry_t *de = (ext2_dir_entry_t *)(bb + off); + if (de->rec_len == 0) break; + if (de->inode != 0 && de->name_len == nl && memcmp(de->name, name, nl) == 0) { + ext2_inode_t ci; + inode_read(fs, de->inode, &ci); + *out = ext2_make_vnode(fs, de->inode, &ci); + kfree(bb); + return *out ? 0 : -ENOMEM; + } + off += de->rec_len; + } + fb++; pos += fs->block_size; + } + kfree(bb); + return -ENOENT; +} + +static int ext2_dir_readdir(vnode_t *dir, uint64_t index, vfs_dirent_t *out) { + ext2_vdata_t *vd = dir->fs_data; + ext2_t *fs = vd->fs; + ext2_inode_t di; + int r = inode_read(fs, vd->ino, &di); + if (r < 0) return r; + uint8_t *bb = kmalloc(fs->block_size); + if (!bb) return -ENOMEM; + uint32_t ds = di.i_size, pos = 0, fb = 0; + uint64_t cur = 0; + while (pos < ds) { + int32_t db = get_block_num(fs, &di, fb); + if (db <= 0) { fb++; pos += fs->block_size; continue; } + block_read(fs, (uint32_t)db, bb); + uint32_t off = 0; + while (off < fs->block_size && (pos + off) < ds) { + ext2_dir_entry_t *de = (ext2_dir_entry_t *)(bb + off); + if (de->rec_len == 0) break; + if (de->inode != 0 && de->name_len > 0) { + bool skip = (de->name_len == 1 && de->name[0] == '.') || + (de->name_len == 2 && de->name[0] == '.' && de->name[1] == '.'); + if (!skip) { + if (cur == index) { + out->d_ino = de->inode; + out->d_type = (de->file_type == EXT2_FT_DIR) ? VFS_NODE_DIR : VFS_NODE_FILE; + size_t n = de->name_len; + if (n >= VFS_MAX_NAME) n = VFS_MAX_NAME - 1; + memcpy(out->d_name, de->name, n); + out->d_name[n] = '\0'; + kfree(bb); + return 0; + } + cur++; + } + } + off += de->rec_len; + } + fb++; pos += fs->block_size; + } + kfree(bb); + return -ENOENT; +} + +static int ext2_dir_add_entry(ext2_t *fs, uint32_t dir_ino, uint32_t child_ino, + uint8_t file_type, const char *name) { + if (!name || !name[0]) return -EINVAL; + ext2_inode_t di; + int r = inode_read(fs, dir_ino, &di); + if (r < 0) return r; + uint8_t nl = (uint8_t)strlen(name); + uint16_t need = (uint16_t)((8 + nl + 3) & ~3); + uint8_t *bb = kmalloc(fs->block_size); + if (!bb) return -ENOMEM; + uint32_t nb = (di.i_size + fs->block_size - 1) / fs->block_size; + for (uint32_t fb = 0; fb < nb; fb++) { + int32_t db = get_block_num(fs, &di, fb); + if (db <= 0) continue; + block_read(fs, (uint32_t)db, bb); + uint32_t off = 0; + while (off < fs->block_size) { + ext2_dir_entry_t *de = (ext2_dir_entry_t *)(bb + off); + if (de->rec_len == 0) break; + if (de->inode == 0 && de->rec_len >= need) { + de->inode = child_ino; + de->name_len = nl; + de->file_type = file_type; + memcpy(de->name, name, nl); + block_write(fs, (uint32_t)db, bb); + kfree(bb); + return 0; + } + uint16_t actual = (uint16_t)((8 + de->name_len + 3) & ~3); + uint16_t slack = de->rec_len - actual; + if (slack >= need) { + de->rec_len = actual; + ext2_dir_entry_t *ne = (ext2_dir_entry_t *)(bb + off + actual); + ne->inode = child_ino; + ne->rec_len = slack; + ne->name_len = nl; + ne->file_type = file_type; + memcpy(ne->name, name, nl); + block_write(fs, (uint32_t)db, bb); + kfree(bb); + return 0; + } + off += de->rec_len; + } + } + int32_t new_blk = alloc_block(fs); + if (new_blk < 0) { kfree(bb); return (int)new_blk; } + set_block_num(fs, &di, nb, (uint32_t)new_blk); + di.i_size += fs->block_size; + di.i_blocks += fs->block_size / 512; + memset(bb, 0, fs->block_size); + ext2_dir_entry_t *de = (ext2_dir_entry_t *)bb; + de->inode = child_ino; + de->rec_len = (uint16_t)fs->block_size; + de->name_len = nl; + de->file_type = file_type; + memcpy(de->name, name, nl); + block_write(fs, (uint32_t)new_blk, bb); + inode_write(fs, dir_ino, &di); + kfree(bb); + return 0; +} + +static int ext2_dir_mkdir(vnode_t *dir, const char *name, uint32_t mode) { + if (!name || !name[0]) return -EINVAL; + ext2_vdata_t *vd = dir->fs_data; + ext2_t *fs = vd->fs; + vnode_t *ex = NULL; + if (ext2_dir_lookup(dir, name, &ex) == 0) { vnode_unref(ex); return -EEXIST; } + int32_t ino = alloc_inode(fs); + if (ino < 0) return (int)ino; + ext2_inode_t ndi; + memset(&ndi, 0, sizeof(ndi)); + ndi.i_mode = EXT2_S_IFDIR | (uint16_t)(mode ? mode : 0755); + ndi.i_links_count = 2; + int32_t blk = alloc_block(fs); + if (blk < 0) { free_inode(fs, (uint32_t)ino); return (int)blk; } + ndi.i_block[0] = (uint32_t)blk; + ndi.i_size = fs->block_size; + ndi.i_blocks = fs->block_size / 512; + uint8_t *bb = kzalloc(fs->block_size); + if (!bb) { free_block(fs, (uint32_t)blk); free_inode(fs, (uint32_t)ino); return -ENOMEM; } + ext2_dir_entry_t *dot = (ext2_dir_entry_t *)bb; + dot->inode = (uint32_t)ino; dot->rec_len = 12; dot->name_len = 1; + dot->file_type = EXT2_FT_DIR; dot->name[0] = '.'; + ext2_dir_entry_t *dotdot = (ext2_dir_entry_t *)(bb + 12); + dotdot->inode = vd->ino; dotdot->rec_len = (uint16_t)(fs->block_size - 12); + dotdot->name_len = 2; dotdot->file_type = EXT2_FT_DIR; + dotdot->name[0] = '.'; dotdot->name[1] = '.'; + block_write(fs, (uint32_t)blk, bb); + kfree(bb); + inode_write(fs, (uint32_t)ino, &ndi); + int r = ext2_dir_add_entry(fs, vd->ino, (uint32_t)ino, EXT2_FT_DIR, name); + if (r < 0) { free_block(fs, (uint32_t)blk); free_inode(fs, (uint32_t)ino); return r; } + ext2_inode_t pdi; + inode_read(fs, vd->ino, &pdi); + pdi.i_links_count++; + inode_write(fs, vd->ino, &pdi); + uint32_t grp = ((uint32_t)ino - 1) / fs->sb.s_inodes_per_group; + fs->gdt[grp].bg_used_dirs_count++; + fs->dirty = true; + dir->size++; + return 0; +} + +static int ext2_dir_create(vnode_t *dir, const char *name, uint32_t mode, vnode_t **out) { + if (!name || !name[0]) return -EINVAL; + ext2_vdata_t *vd = dir->fs_data; + ext2_t *fs = vd->fs; + if (ext2_dir_lookup(dir, name, out) == 0) return 0; + int32_t ino = alloc_inode(fs); + if (ino < 0) return (int)ino; + ext2_inode_t ndi; + memset(&ndi, 0, sizeof(ndi)); + ndi.i_mode = EXT2_S_IFREG | (uint16_t)(mode ? mode : 0644); + ndi.i_links_count = 1; + inode_write(fs, (uint32_t)ino, &ndi); + int r = ext2_dir_add_entry(fs, vd->ino, (uint32_t)ino, EXT2_FT_REG_FILE, name); + if (r < 0) { free_inode(fs, (uint32_t)ino); return r; } + *out = ext2_make_vnode(fs, (uint32_t)ino, &ndi); + if (!*out) return -ENOMEM; + fs->dirty = true; + dir->size++; + return 0; +} + +static int ext2_dir_unlink(vnode_t *dir, const char *name) { + ext2_vdata_t *vd = dir->fs_data; + ext2_t *fs = vd->fs; + ext2_inode_t di; + int r = inode_read(fs, vd->ino, &di); + if (r < 0) return r; + uint8_t *bb = kmalloc(fs->block_size); + if (!bb) return -ENOMEM; + size_t nl = strlen(name); + uint32_t nblocks = (di.i_size + fs->block_size - 1) / fs->block_size; + for (uint32_t fb = 0; fb < nblocks; fb++) { + int32_t db = get_block_num(fs, &di, fb); + if (db <= 0) continue; + block_read(fs, (uint32_t)db, bb); + uint32_t off = 0; + ext2_dir_entry_t *prev = NULL; + while (off < fs->block_size) { + ext2_dir_entry_t *de = (ext2_dir_entry_t *)(bb + off); + if (de->rec_len == 0) break; + if (de->inode != 0 && de->name_len == nl && memcmp(de->name, name, nl) == 0) { + uint32_t cino = de->inode; + ext2_inode_t ci; + inode_read(fs, cino, &ci); + bool is_dir = ((ci.i_mode & 0xF000) == EXT2_S_IFDIR); + free_all_blocks(fs, &ci); + free_inode(fs, cino); + if (prev) prev->rec_len += de->rec_len; + else de->inode = 0; + block_write(fs, (uint32_t)db, bb); + if (is_dir) { + ext2_inode_t pdi; + inode_read(fs, vd->ino, &pdi); + if (pdi.i_links_count > 1) pdi.i_links_count--; + inode_write(fs, vd->ino, &pdi); + uint32_t grp = (cino - 1) / fs->sb.s_inodes_per_group; + if (fs->gdt[grp].bg_used_dirs_count > 0) + fs->gdt[grp].bg_used_dirs_count--; + } + dir->size--; + fs->dirty = true; + kfree(bb); + return 0; + } + prev = de; + off += de->rec_len; + } + } + kfree(bb); + return -ENOENT; +} + +static int ext2_dir_rename(vnode_t *src_dir, const char *src_name, + vnode_t *dst_dir, const char *dst_name) { + ext2_vdata_t *svd = src_dir->fs_data; + ext2_t *fs = svd->fs; + vnode_t *child = NULL; + int r = ext2_dir_lookup(src_dir, src_name, &child); + if (r < 0) return r; + uint8_t ft = (child->type == VFS_NODE_DIR) ? EXT2_FT_DIR : EXT2_FT_REG_FILE; + uint32_t cino = (uint32_t)child->ino; + vnode_unref(child); + vnode_t *ex = NULL; + if (ext2_dir_lookup(dst_dir, dst_name, &ex) == 0) { + vnode_unref(ex); + ext2_dir_unlink(dst_dir, dst_name); + } + ext2_vdata_t *dvd = dst_dir->fs_data; + r = ext2_dir_add_entry(fs, dvd->ino, cino, ft, dst_name); + if (r < 0) return r; + ext2_inode_t sdi; + inode_read(fs, svd->ino, &sdi); + uint8_t *bb = kmalloc(fs->block_size); + if (!bb) return -ENOMEM; + size_t snl = strlen(src_name); + uint32_t nblocks = (sdi.i_size + fs->block_size - 1) / fs->block_size; + for (uint32_t fb = 0; fb < nblocks; fb++) { + int32_t db = get_block_num(fs, &sdi, fb); + if (db <= 0) continue; + block_read(fs, (uint32_t)db, bb); + uint32_t off = 0; + ext2_dir_entry_t *prev = NULL; + while (off < fs->block_size) { + ext2_dir_entry_t *de = (ext2_dir_entry_t *)(bb + off); + if (de->rec_len == 0) break; + if (de->inode == cino && de->name_len == snl && + memcmp(de->name, src_name, snl) == 0) { + if (prev) prev->rec_len += de->rec_len; + else de->inode = 0; + block_write(fs, (uint32_t)db, bb); + kfree(bb); + fs->dirty = true; + return 0; + } + prev = de; + off += de->rec_len; + } + } + kfree(bb); + fs->dirty = true; + return 0; +} + +static const vnode_ops_t ext2_dir_ops = { + .lookup = ext2_dir_lookup, + .readdir = ext2_dir_readdir, + .mkdir = ext2_dir_mkdir, + .create = ext2_dir_create, + .unlink = ext2_dir_unlink, + .rename = ext2_dir_rename, + .stat = ext2_stat, + .ref = ext2_vnode_ref, + .unref = ext2_vnode_unref, +}; + +int ext2_format(blkdev_t *dev, const char *label) { + if (!dev) return -EINVAL; + uint64_t disk_bytes = dev->size_bytes; + if (disk_bytes < 64 * 1024) return -ENOSPC; + uint32_t block_size = 1024; + uint32_t total_blocks = (uint32_t)(disk_bytes / block_size); + uint32_t blocks_per_group = block_size * 8; + uint32_t inodes_per_group = (total_blocks < 8192) ? 128 : 256; + uint32_t groups_count = (total_blocks + blocks_per_group - 1) / blocks_per_group; + if (groups_count == 0) groups_count = 1; + uint32_t total_inodes = inodes_per_group * groups_count; + uint32_t inode_size = 128; + uint32_t it_blocks_pg = (inodes_per_group * inode_size + block_size - 1) / block_size; + uint32_t first_data_block = 1; + uint8_t *zb = kzalloc(block_size); + if (!zb) return -ENOMEM; + for (uint32_t b = 0; b < total_blocks && b < 16; b++) + blkdev_write(dev, (uint64_t)b * block_size, zb, block_size); + ext2_superblock_t sb; + memset(&sb, 0, sizeof(sb)); + sb.s_inodes_count = total_inodes; + sb.s_blocks_count = total_blocks; + sb.s_r_blocks_count = total_blocks / 20; + sb.s_free_blocks_count = total_blocks; + sb.s_free_inodes_count = total_inodes; + sb.s_first_data_block = first_data_block; + sb.s_log_block_size = 0; + sb.s_blocks_per_group = blocks_per_group; + sb.s_frags_per_group = blocks_per_group; + sb.s_inodes_per_group = inodes_per_group; + sb.s_magic = EXT2_SUPER_MAGIC; + sb.s_state = EXT2_VALID_FS; + sb.s_errors = 1; + sb.s_rev_level = EXT2_DYNAMIC_REV; + sb.s_first_ino = 11; + sb.s_inode_size = (uint16_t)inode_size; + sb.s_max_mnt_count = 20; + if (label) strncpy(sb.s_volume_name, label, 15); + uint32_t gdt_block = first_data_block + 1; + uint32_t gdt_blocks = (groups_count * sizeof(ext2_group_desc_t) + block_size - 1) / block_size; + ext2_group_desc_t *gdt = kzalloc(gdt_blocks * block_size); + if (!gdt) { kfree(zb); return -ENOMEM; } + uint32_t used_total = first_data_block; + printf(" ext2: "); + uint32_t last_pct_ext2 = 999; + uint32_t spinner_ext2 = 0; + for (uint32_t g = 0; g < groups_count; g++) { + uint32_t gs = g * blocks_per_group + first_data_block; + uint32_t cb = (g == 0) ? (gdt_block + gdt_blocks) : gs; + gdt[g].bg_block_bitmap = cb++; + gdt[g].bg_inode_bitmap = cb++; + gdt[g].bg_inode_table = cb; + cb += it_blocks_pg; + uint32_t meta = cb - gs; + if (g == 0) meta = cb - first_data_block; + uint32_t gb = blocks_per_group; + if (g == groups_count - 1) gb = total_blocks - gs; + gdt[g].bg_free_blocks_count = (gb > meta) ? (uint16_t)(gb - meta) : 0; + gdt[g].bg_free_inodes_count = (uint16_t)inodes_per_group; + used_total += meta; + for (uint32_t t = 0; t < it_blocks_pg; t++) + blkdev_write(dev, (uint64_t)(gdt[g].bg_inode_table + t) * block_size, zb, block_size); + uint8_t *bbmp = kzalloc(block_size); + for (uint32_t i = 0; i < meta; i++) bmp_set(bbmp, i); + if (g == 0) + for (uint32_t i = 0; i < (gdt_block + gdt_blocks - first_data_block); i++) + bmp_set(bbmp, i); + for (uint32_t i = gb; i < blocks_per_group; i++) bmp_set(bbmp, i); + blkdev_write(dev, (uint64_t)gdt[g].bg_block_bitmap * block_size, bbmp, block_size); + kfree(bbmp); + uint8_t *ibmp = kzalloc(block_size); + if (g == 0) { + for (uint32_t i = 0; i < 11; i++) { bmp_set(ibmp, i); gdt[g].bg_free_inodes_count--; } + } + for (uint32_t i = inodes_per_group; i < block_size * 8; i++) bmp_set(ibmp, i); + blkdev_write(dev, (uint64_t)gdt[g].bg_inode_bitmap * block_size, ibmp, block_size); + kfree(ibmp); + + uint32_t pct = ((g + 1) * 100) / groups_count; + if (pct != last_pct_ext2) { + static const char glyphs[4] = { '|', '/', '-', '\\' }; + printf("\r \r %c ext2: %u%% (group %u/%u)", + glyphs[spinner_ext2 & 3], pct, g + 1, groups_count); + spinner_ext2++; + last_pct_ext2 = pct; + } + } + printf("\r \r ext2: done\n"); + sb.s_free_blocks_count = total_blocks - used_total; + sb.s_free_inodes_count = total_inodes - 11; + int32_t root_blk = -1; + { + uint8_t *bbmp = kmalloc(block_size); + blkdev_read(dev, (uint64_t)gdt[0].bg_block_bitmap * block_size, bbmp, block_size); + for (uint32_t i = 0; i < blocks_per_group; i++) { + if (!bmp_test(bbmp, i)) { + bmp_set(bbmp, i); + blkdev_write(dev, (uint64_t)gdt[0].bg_block_bitmap * block_size, bbmp, block_size); + root_blk = (int32_t)(i + first_data_block); + gdt[0].bg_free_blocks_count--; + sb.s_free_blocks_count--; + break; + } + } + kfree(bbmp); + } + if (root_blk < 0) { kfree(gdt); kfree(zb); return -ENOSPC; } + ext2_inode_t ri; + memset(&ri, 0, sizeof(ri)); + ri.i_mode = EXT2_S_IFDIR | 0755; + ri.i_links_count = 2; + ri.i_block[0] = (uint32_t)root_blk; + ri.i_size = block_size; + ri.i_blocks = block_size / 512; + uint64_t roff = (uint64_t)gdt[0].bg_inode_table * block_size + (uint64_t)(EXT2_ROOT_INO - 1) * inode_size; + blkdev_write(dev, roff, &ri, sizeof(ri)); + uint8_t *rdb = kzalloc(block_size); + ext2_dir_entry_t *dot = (ext2_dir_entry_t *)rdb; + dot->inode = EXT2_ROOT_INO; dot->rec_len = 12; dot->name_len = 1; + dot->file_type = EXT2_FT_DIR; dot->name[0] = '.'; + ext2_dir_entry_t *dotdot = (ext2_dir_entry_t *)(rdb + 12); + dotdot->inode = EXT2_ROOT_INO; dotdot->rec_len = (uint16_t)(block_size - 12); + dotdot->name_len = 2; dotdot->file_type = EXT2_FT_DIR; + dotdot->name[0] = '.'; dotdot->name[1] = '.'; + blkdev_write(dev, (uint64_t)root_blk * block_size, rdb, block_size); + kfree(rdb); + gdt[0].bg_used_dirs_count = 1; + blkdev_write(dev, EXT2_SUPER_OFFSET, &sb, sizeof(sb)); + blkdev_write(dev, (uint64_t)gdt_block * block_size, gdt, gdt_blocks * block_size); + kfree(gdt); + kfree(zb); + serial_printf("[ext2] formatted: %u blocks (%u KiB), %u inodes, bs=%u, label='%s'\n", + total_blocks, total_blocks * block_size / 1024, total_inodes, block_size, + label ? label : ""); + return 0; +} + +vnode_t *ext2_mount(blkdev_t *dev) { + if (!dev) return NULL; + ext2_t *fs = kzalloc(sizeof(ext2_t)); + if (!fs) return NULL; + fs->dev = dev; + if (blkdev_read(dev, EXT2_SUPER_OFFSET, &fs->sb, sizeof(fs->sb)) < 0) { kfree(fs); return NULL; } + if (fs->sb.s_magic != EXT2_SUPER_MAGIC) { + serial_printf("[ext2] bad magic: 0x%x (expected 0x%x)\n", fs->sb.s_magic, EXT2_SUPER_MAGIC); + kfree(fs); + return NULL; + } + fs->block_size = 1024 << fs->sb.s_log_block_size; + fs->inode_size = (fs->sb.s_rev_level >= EXT2_DYNAMIC_REV) ? fs->sb.s_inode_size : 128; + fs->groups_count = (fs->sb.s_blocks_count + fs->sb.s_blocks_per_group - 1) / fs->sb.s_blocks_per_group; + fs->inodes_per_block = fs->block_size / fs->inode_size; + fs->ptrs_per_block = fs->block_size / 4; + uint32_t gdt_block = (fs->block_size == 1024) ? 2 : 1; + uint32_t gdt_sz = fs->groups_count * sizeof(ext2_group_desc_t); + uint32_t gdt_blocks = (gdt_sz + fs->block_size - 1) / fs->block_size; + fs->gdt = kmalloc(gdt_blocks * fs->block_size); + if (!fs->gdt) { kfree(fs); return NULL; } + if (blkdev_read(dev, (uint64_t)gdt_block * fs->block_size, fs->gdt, gdt_blocks * fs->block_size) < 0) { + kfree(fs->gdt); kfree(fs); return NULL; + } + ext2_inode_t root_di; + if (inode_read(fs, EXT2_ROOT_INO, &root_di) < 0) { kfree(fs->gdt); kfree(fs); return NULL; } + vnode_t *root = ext2_make_vnode(fs, EXT2_ROOT_INO, &root_di); + if (!root) { kfree(fs->gdt); kfree(fs); return NULL; } + serial_printf("[ext2] mounted '%s': %u blocks (%u free), %u inodes (%u free), bs=%u\n", + fs->sb.s_volume_name, fs->sb.s_blocks_count, fs->sb.s_free_blocks_count, + fs->sb.s_inodes_count, fs->sb.s_free_inodes_count, fs->block_size); + return root; +} + +void ext2_sync(ext2_t *fs) { + if (!fs || !fs->dirty) return; + sb_flush(fs); + gdt_flush(fs); + if (fs->dev->ops && fs->dev->ops->flush) fs->dev->ops->flush(fs->dev); + fs->dirty = false; +} + +void ext2_unmount(ext2_t *fs) { + if (!fs) return; + ext2_sync(fs); + if (fs->gdt) kfree(fs->gdt); + kfree(fs); +} + +int ext2_statvfs(vnode_t *root, vfs_statvfs_t *out) { + if (!root || !root->fs_data || !out) return -EINVAL; + ext2_vdata_t *vd = (ext2_vdata_t *)root->fs_data; + ext2_t *fs = vd->fs; + if (!fs) return -EINVAL; + + out->f_bsize = fs->block_size; + out->f_blocks = fs->sb.s_blocks_count; + out->f_bfree = fs->sb.s_free_blocks_count; + out->f_bavail = fs->sb.s_free_blocks_count; + out->f_files = fs->sb.s_inodes_count; + out->f_ffree = fs->sb.s_free_inodes_count; + out->f_flag = 0; + out->f_namemax = 255; + return 0; +} \ No newline at end of file diff --git a/kernel/src/fs/fat32.c b/kernel/src/fs/fat32.c new file mode 100644 index 0000000..67e42c3 --- /dev/null +++ b/kernel/src/fs/fat32.c @@ -0,0 +1,1198 @@ +#include "../../include/fs/fat32.h" +#include "../../include/fs/vfs.h" +#include "../../include/drivers/blkdev.h" +#include "../../include/io/serial.h" +#include "../../include/memory/pmm.h" +#include "../../include/syscall/errno.h" +#include +#include +#include + +#define MAX_CLUSTER_BYTES 32768 + +static int read_sector(fat32_t *fs, uint32_t lba, void *buf) { + return fs->dev->ops->read_sectors(fs->dev, lba, 1, buf); +} +static int write_sector(fat32_t *fs, uint32_t lba, const void *buf) { + if (fs->readonly) return -EROFS; + return fs->dev->ops->write_sectors(fs->dev, lba, 1, buf); +} + +static uint32_t cluster_to_lba(fat32_t *fs, uint32_t cluster) { + return fs->first_data_sector + (cluster - 2) * fs->sectors_per_cluster; +} + +static uint32_t fat_read_entry(fat32_t *fs, uint32_t cluster) { + uint32_t fat_offset = cluster * 4; + uint32_t fat_sector = fs->first_fat_sector + (fat_offset / fs->bytes_per_sector); + uint32_t ent_offset = fat_offset % fs->bytes_per_sector; + + uint8_t sector[FAT32_SECTOR_SIZE]; + if (read_sector(fs, fat_sector, sector) < 0) return FAT32_EOC; + + uint32_t val; + memcpy(&val, sector + ent_offset, 4); + return val & FAT32_CLUSTER_MASK; +} + +static int fat_write_entry(fat32_t *fs, uint32_t cluster, uint32_t value) { + if (fs->readonly) return -EROFS; + uint32_t fat_offset = cluster * 4; + uint32_t ent_offset = fat_offset % fs->bytes_per_sector; + + for (uint32_t i = 0; i < fs->num_fats; i++) { + uint32_t fat_sector = fs->first_fat_sector + i * fs->fat_size_sectors + + (fat_offset / fs->bytes_per_sector); + uint8_t sector[FAT32_SECTOR_SIZE]; + int r = read_sector(fs, fat_sector, sector); + if (r < 0) return r; + uint32_t existing; + memcpy(&existing, sector + ent_offset, 4); + uint32_t reserved = existing & 0xF0000000; + uint32_t merged = (value & FAT32_CLUSTER_MASK) | reserved; + memcpy(sector + ent_offset, &merged, 4); + r = write_sector(fs, fat_sector, sector); + if (r < 0) return r; + } + fs->dirty = true; + return 0; +} + +static bool fat32_is_eoc(uint32_t cluster) { + return (cluster & FAT32_CLUSTER_MASK) >= FAT32_EOC_MIN; +} + +static int read_cluster(fat32_t *fs, uint32_t cluster, void *buf) { + uint32_t lba = cluster_to_lba(fs, cluster); + return fs->dev->ops->read_sectors(fs->dev, lba, fs->sectors_per_cluster, buf); +} +static int write_cluster(fat32_t *fs, uint32_t cluster, const void *buf) { + if (fs->readonly) return -EROFS; + uint32_t lba = cluster_to_lba(fs, cluster); + return fs->dev->ops->write_sectors(fs->dev, lba, fs->sectors_per_cluster, buf); +} + +static uint32_t allocate_cluster(fat32_t *fs) { + if (fs->readonly) return 0; + uint32_t start = fs->next_free_hint; + if (start < 2) start = 2; + for (uint32_t i = 0; i < fs->total_clusters; i++) { + uint32_t c = 2 + ((start - 2 + i) % fs->total_clusters); + uint32_t v = fat_read_entry(fs, c); + if (v == FAT32_FREE_CLUSTER) { + if (fat_write_entry(fs, c, FAT32_EOC) < 0) return 0; + fs->next_free_hint = c + 1; + if (fs->free_count != 0xFFFFFFFF) fs->free_count--; + + uint8_t *zero = (uint8_t *)malloc(fs->bytes_per_cluster); + if (zero) { + memset(zero, 0, fs->bytes_per_cluster); + write_cluster(fs, c, zero); + free(zero); + } + return c; + } + } + return 0; +} + +static int free_cluster_chain(fat32_t *fs, uint32_t first) { + if (fs->readonly) return -EROFS; + uint32_t c = first; + while (c >= 2 && !fat32_is_eoc(c)) { + uint32_t next = fat_read_entry(fs, c); + fat_write_entry(fs, c, FAT32_FREE_CLUSTER); + if (fs->free_count != 0xFFFFFFFF) fs->free_count++; + c = next; + } + return 0; +} + +int fat32_sync(fat32_t *fs) { + if (!fs || fs->readonly) return 0; + if (fs->fsinfo_sector) { + uint8_t sec[FAT32_SECTOR_SIZE]; + if (read_sector(fs, fs->fsinfo_sector, sec) == 0) { + fat32_fsinfo_t *fsi = (fat32_fsinfo_t *)sec; + if (fsi->lead_sig == FAT32_FSINFO_LEAD_SIG + && fsi->struct_sig == FAT32_FSINFO_STRUCT_SIG) { + fsi->free_count = fs->free_count; + fsi->next_free = fs->next_free_hint; + write_sector(fs, fs->fsinfo_sector, sec); + } + } + } + if (fs->dev->ops->flush) fs->dev->ops->flush(fs->dev); + fs->dirty = false; + return 0; +} + +static void fat_name_to_string(const uint8_t raw[11], char *out) { + int o = 0; + for (int i = 0; i < 8; i++) { + if (raw[i] == ' ') break; + out[o++] = raw[i]; + } + if (raw[8] != ' ') { + out[o++] = '.'; + for (int i = 8; i < 11; i++) { + if (raw[i] == ' ') break; + out[o++] = raw[i]; + } + } + out[o] = '\0'; + for (int i = 0; out[i]; i++) + if (out[i] >= 'A' && out[i] <= 'Z') out[i] = (char)(out[i] - 'A' + 'a'); +} + +static void string_to_fat_name(const char *name, uint8_t out[11]) { + memset(out, ' ', 11); + const char *dot = NULL; + for (const char *p = name; *p; p++) if (*p == '.') dot = p; + int base_len = dot ? (int)(dot - name) : (int)strlen(name); + if (base_len > 8) base_len = 8; + for (int i = 0; i < base_len; i++) { + char c = name[i]; + if (c >= 'a' && c <= 'z') c = (char)(c - 'a' + 'A'); + out[i] = (uint8_t)c; + } + if (dot) { + const char *ext = dot + 1; + int el = (int)strlen(ext); + if (el > 3) el = 3; + for (int i = 0; i < el; i++) { + char c = ext[i]; + if (c >= 'a' && c <= 'z') c = (char)(c - 'a' + 'A'); + out[8 + i] = (uint8_t)c; + } + } +} +static uint8_t lfn_checksum(const uint8_t sfn[11]) { + uint8_t s = 0; + for (int i = 0; i < 11; i++) s = (uint8_t)(((s & 1) << 7) + (s >> 1) + sfn[i]); + return s; +} + +static void lfn_append(char *out, int *out_len, int out_cap, const uint8_t *src, int count) { + for (int i = 0; i < count; i++) { + uint16_t wc = (uint16_t)(src[i*2] | (src[i*2+1] << 8)); + if (wc == 0x0000 || wc == 0xFFFF) return; + if (*out_len + 1 >= out_cap) return; + out[(*out_len)++] = (wc < 128) ? (char)wc : '?'; + } + out[*out_len] = '\0'; +} + +static vnode_t *fat32_alloc_vnode(fat32_t *fs, uint32_t first_cluster, + uint32_t size, uint8_t attr, + uint32_t dir_cluster, uint32_t dir_entry_off); +static const vnode_ops_t fat32_file_ops; +static const vnode_ops_t fat32_dir_ops; + +static int fat32_traverse_dir(fat32_t *fs, uint32_t start_cluster, + int (*cb)(fat32_t *fs, uint32_t cluster, + uint32_t entry_off, + fat32_dirent_t *e, + const char *name, void *ud), + void *ud) +{ + uint32_t cluster = start_cluster ? start_cluster : fs->root_cluster; + char lfn_buf[260]; + int lfn_len = 0; + lfn_buf[0] = '\0'; + + uint8_t *cluster_buf = fs->shared_buf; + while (!fat32_is_eoc(cluster) && cluster >= 2) { + if (read_cluster(fs, cluster, cluster_buf) < 0) return -EIO; + + uint32_t entries = fs->bytes_per_cluster / 32; + for (uint32_t i = 0; i < entries; i++) { + fat32_dirent_t *e = (fat32_dirent_t *)(cluster_buf + i * 32); + if (e->name[0] == 0x00) return -ENOENT; + if ((uint8_t)e->name[0] == 0xE5) { lfn_len = 0; lfn_buf[0] = '\0'; continue; } + + if (e->attr == FAT_ATTR_LONG_NAME) { + fat32_lfn_t *lfn = (fat32_lfn_t *)e; + char part[14]; int pl = 0; + lfn_append(part, &pl, sizeof(part), lfn->name1, 5); + lfn_append(part, &pl, sizeof(part), lfn->name2, 6); + lfn_append(part, &pl, sizeof(part), lfn->name3, 2); + char merged[260]; + int ml = 0; + for (int k = 0; k < pl && ml < 259; k++) merged[ml++] = part[k]; + for (int k = 0; k < lfn_len && ml < 259; k++) merged[ml++] = lfn_buf[k]; + merged[ml] = '\0'; + memcpy(lfn_buf, merged, ml + 1); + lfn_len = ml; + continue; + } + + if (e->attr & FAT_ATTR_VOLUME_ID) { lfn_len = 0; lfn_buf[0] = '\0'; continue; } + + char sfn[13]; + fat_name_to_string(e->name, sfn); + const char *name = (lfn_len > 0) ? lfn_buf : sfn; + int r = cb(fs, cluster, i * 32, e, name, ud); + if (r != 0) return r; + lfn_len = 0; lfn_buf[0] = '\0'; + } + cluster = fat_read_entry(fs, cluster); + } + return -ENOENT; +} + +typedef struct { + const char *target; + vnode_t **out; + uint32_t found; +} lookup_ctx_t; + +static int lookup_cb(fat32_t *fs, uint32_t cluster, uint32_t entry_off, + fat32_dirent_t *e, const char *name, void *ud) +{ + lookup_ctx_t *ctx = (lookup_ctx_t *)ud; + bool match = true; + for (int k = 0; ctx->target[k] || name[k]; k++) { + char a = ctx->target[k]; + char b = name[k]; + if (a >= 'A' && a <= 'Z') a = (char)(a - 'A' + 'a'); + if (b >= 'A' && b <= 'Z') b = (char)(b - 'A' + 'a'); + if (a != b) { match = false; break; } + } + if (match) { + uint32_t first = ((uint32_t)e->cluster_hi << 16) | e->cluster_lo; + vnode_t *vn = fat32_alloc_vnode(fs, first, e->file_size, e->attr, + cluster, entry_off); + if (!vn) return -ENOMEM; + *ctx->out = vn; + ctx->found = 1; + return 1; + } + return 0; +} + +static int fat32_dir_lookup(vnode_t *dir, const char *name, vnode_t **out) { + fat32_vdata_t *vd = (fat32_vdata_t *)dir->fs_data; + if (!vd || !vd->fs) return -EIO; + lookup_ctx_t ctx = { .target = name, .out = out, .found = 0 }; + int r = fat32_traverse_dir(vd->fs, vd->first_cluster, lookup_cb, &ctx); + if (ctx.found) return 0; + return (r == -ENOENT) ? -ENOENT : r; +} + +typedef struct { + uint64_t wanted; + uint64_t cur; + vfs_dirent_t *out; + int got; +} readdir_ctx_t; + +static int readdir_cb(fat32_t *fs, uint32_t cluster, uint32_t entry_off, + fat32_dirent_t *e, const char *name, void *ud) +{ + (void)fs; (void)cluster; (void)entry_off; + readdir_ctx_t *ctx = (readdir_ctx_t *)ud; + if (ctx->cur == ctx->wanted) { + memset(ctx->out, 0, sizeof(*ctx->out)); + int n = 0; + while (name[n] && n < (int)sizeof(ctx->out->d_name) - 1) { + ctx->out->d_name[n] = name[n]; n++; + } + ctx->out->d_name[n] = '\0'; + ctx->out->d_type = (e->attr & FAT_ATTR_DIRECTORY) ? 1 : 0; + ctx->got = 1; + return 1; + } + ctx->cur++; + return 0; +} + +static int fat32_dir_readdir(vnode_t *dir, uint64_t index, vfs_dirent_t *out) { + fat32_vdata_t *vd = (fat32_vdata_t *)dir->fs_data; + if (!vd || !vd->fs) return -EIO; + readdir_ctx_t ctx = { .wanted = index, .cur = 0, .out = out, .got = 0 }; + int r = fat32_traverse_dir(vd->fs, vd->first_cluster, readdir_cb, &ctx); + if (ctx.got) return 0; + return (r == -ENOENT) ? -ENOENT : r; +} + +static int64_t fat32_file_read(vnode_t *node, void *buf, size_t len, uint64_t offset) { + fat32_vdata_t *vd = (fat32_vdata_t *)node->fs_data; + if (!vd || !vd->fs) return -EIO; + if (offset >= vd->file_size) return 0; + if (offset + len > vd->file_size) len = vd->file_size - offset; + + fat32_t *fs = vd->fs; + uint32_t cluster = vd->first_cluster; + uint32_t cluster_off = (uint32_t)(offset / fs->bytes_per_cluster); + for (uint32_t i = 0; i < cluster_off; i++) { + if (fat32_is_eoc(cluster) || cluster < 2) return 0; + cluster = fat_read_entry(fs, cluster); + } + + size_t done = 0; + uint32_t in_cluster_off = (uint32_t)(offset % fs->bytes_per_cluster); + uint8_t *cluster_buf = fs->shared_buf; + if (!cluster_buf) return -EIO; + + while (done < len && !fat32_is_eoc(cluster) && cluster >= 2) { + if (read_cluster(fs, cluster, cluster_buf) < 0) return -EIO; + uint32_t avail = fs->bytes_per_cluster - in_cluster_off; + uint32_t take = (avail < (len - done)) ? avail : (uint32_t)(len - done); + memcpy((uint8_t *)buf + done, cluster_buf + in_cluster_off, take); + done += take; + in_cluster_off = 0; + if (done < len) cluster = fat_read_entry(fs, cluster); + } + return (int64_t)done; +} + +static int64_t fat32_file_write(vnode_t *node, const void *buf, size_t len, uint64_t offset) { + fat32_vdata_t *vd = (fat32_vdata_t *)node->fs_data; + if (!vd || !vd->fs) return -EIO; + if (vd->fs->readonly) return -EROFS; + fat32_t *fs = vd->fs; + + if (vd->first_cluster == 0) { + uint32_t c = allocate_cluster(fs); + if (c == 0) return -ENOSPC; + vd->first_cluster = c; + vd->cached_cluster = c; + vd->cached_index = 0; + } + + uint32_t target_index = (uint32_t)(offset / fs->bytes_per_cluster); + uint32_t cluster; + uint32_t start_index; + + if (vd->cached_cluster != 0 && vd->cached_index <= target_index) { + cluster = vd->cached_cluster; + start_index = vd->cached_index; + } else { + cluster = vd->first_cluster; + start_index = 0; + } + + for (uint32_t i = start_index; i < target_index; i++) { + uint32_t next = fat_read_entry(fs, cluster); + if (fat32_is_eoc(next) || next < 2) { + uint32_t nc = allocate_cluster(fs); + if (nc == 0) return -ENOSPC; + fat_write_entry(fs, cluster, nc); + cluster = nc; + } else { + cluster = next; + } + } + + size_t done = 0; + uint32_t in_cluster_off = (uint32_t)(offset % fs->bytes_per_cluster); + uint32_t current_index = target_index; + + if (!vd->io_buf) { + vd->io_buf = (uint8_t *)malloc(fs->bytes_per_cluster); + if (!vd->io_buf) return -ENOMEM; + } + + while (done < len) { + uint32_t avail = fs->bytes_per_cluster - in_cluster_off; + uint32_t take = (avail < (len - done)) ? avail : (uint32_t)(len - done); + + if (in_cluster_off == 0 && take == fs->bytes_per_cluster) { + if (fs->dev->ops->write_sectors(fs->dev, + cluster_to_lba(fs, cluster), + fs->sectors_per_cluster, + (const uint8_t *)buf + done) < 0) return -EIO; + } else { + if (read_cluster(fs, cluster, vd->io_buf) < 0) return -EIO; + memcpy(vd->io_buf + in_cluster_off, (const uint8_t *)buf + done, take); + if (write_cluster(fs, cluster, vd->io_buf) < 0) return -EIO; + } + + done += take; + in_cluster_off = 0; + + if (done < len) { + uint32_t next = fat_read_entry(fs, cluster); + if (fat32_is_eoc(next) || next < 2) { + uint32_t nc = allocate_cluster(fs); + if (nc == 0) break; + fat_write_entry(fs, cluster, nc); + next = nc; + } + cluster = next; + current_index++; + } + } + + vd->cached_cluster = cluster; + vd->cached_index = current_index; + + uint64_t new_size = offset + done; + if (new_size > vd->file_size) { + vd->file_size = (uint32_t)new_size; + node->size = new_size; + vd->size_dirty = true; + } + + return (int64_t)done; +} + +static int fat32_file_stat(vnode_t *node, vfs_stat_t *out) { + fat32_vdata_t *vd = (fat32_vdata_t *)node->fs_data; + memset(out, 0, sizeof(*out)); + out->st_ino = node->ino; + out->st_type = node->type; + out->st_mode = 0644; + out->st_size = vd ? vd->file_size : 0; + return 0; +} + +static void fat32_common_ref(vnode_t *n) { n->refcount++; } +static void fat32_common_unref(vnode_t *n) { + if (--n->refcount <= 0) { + fat32_vdata_t *vd = (fat32_vdata_t *)n->fs_data; + if (vd && vd->fs && vd->size_dirty && n->type == VFS_NODE_FILE) { + uint8_t *tmp = (uint8_t *)malloc(vd->fs->bytes_per_cluster); + if (tmp) { + if (read_cluster(vd->fs, vd->dir_cluster, tmp) == 0) { + fat32_dirent_t ent; + memcpy(&ent, tmp + vd->dir_entry_offset, sizeof(ent)); + ent.file_size = vd->file_size; + ent.cluster_lo = (uint16_t)(vd->first_cluster & 0xFFFF); + ent.cluster_hi = (uint16_t)((vd->first_cluster >> 16) & 0xFFFF); + ent.attr = vd->attr ? vd->attr : FAT_ATTR_ARCHIVE; + memcpy(tmp + vd->dir_entry_offset, &ent, sizeof(ent)); + write_cluster(vd->fs, vd->dir_cluster, tmp); + } + free(tmp); + } + fat32_sync(vd->fs); + } + if (vd) { + if (vd->io_buf) { free(vd->io_buf); vd->io_buf = NULL; } + free(vd); + n->fs_data = NULL; + } + free(n); + } +} + +static bool name_fits_sfn(const char *name) { + int dot = -1; + int len = 0; + for (int i = 0; name[i]; i++) len++; + if (len > 12) return false; + for (int i = 0; i < len; i++) { + if (name[i] == '.') { + if (dot != -1) return false; + dot = i; + } + } + int base_len = (dot == -1) ? len : dot; + int ext_len = (dot == -1) ? 0 : (len - dot - 1); + if (base_len == 0 || base_len > 8) return false; + if (ext_len > 3) return false; + for (int i = 0; i < len; i++) { + char c = name[i]; + if (c == '.') continue; + if (c >= 'a' && c <= 'z') return false; + if (c == ' ') return false; + } + return true; +} + +static void generate_short_name(const char *lfn, uint8_t out[11]) { + memset(out, ' ', 11); + int oi = 0; + int i = 0; + int last_dot = -1; + for (int k = 0; lfn[k]; k++) if (lfn[k] == '.') last_dot = k; + + int base_end = (last_dot >= 0) ? last_dot : -1; + while (lfn[i] && (base_end < 0 || i < base_end) && oi < 6) { + char c = lfn[i++]; + if (c == ' ' || c == '.') continue; + if (c >= 'a' && c <= 'z') c = (char)(c - 'a' + 'A'); + if (!((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || + c == '_' || c == '-')) c = '_'; + out[oi++] = (uint8_t)c; + } + out[oi++] = '~'; + out[oi++] = '1'; + + if (last_dot >= 0) { + int ei = 8; + int k = last_dot + 1; + while (lfn[k] && ei < 11) { + char c = lfn[k++]; + if (c >= 'a' && c <= 'z') c = (char)(c - 'a' + 'A'); + if (!((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || + c == '_' || c == '-')) c = '_'; + out[ei++] = (uint8_t)c; + } + } +} + +static int find_free_slots(fat32_t *fs, uint32_t dir_cluster, uint32_t count, + uint32_t *out_cluster, uint32_t *out_off) +{ + uint32_t cluster = dir_cluster ? dir_cluster : fs->root_cluster; + uint8_t *cluster_buf = fs->shared_buf; + uint32_t run_cluster = 0, run_off = 0, run_len = 0; + + while (true) { + if (read_cluster(fs, cluster, cluster_buf) < 0) return -EIO; + uint32_t entries = fs->bytes_per_cluster / 32; + for (uint32_t i = 0; i < entries; i++) { + uint8_t first = cluster_buf[i * 32]; + if (first == 0x00 || first == 0xE5) { + if (run_len == 0) { run_cluster = cluster; run_off = i * 32; } + run_len++; + if (run_len >= count) { + *out_cluster = run_cluster; + *out_off = run_off; + return 0; + } + } else { + run_len = 0; + } + } + uint32_t next = fat_read_entry(fs, cluster); + if (fat32_is_eoc(next) || next < 2) { + uint32_t nc = allocate_cluster(fs); + if (nc == 0) return -ENOSPC; + fat_write_entry(fs, cluster, nc); + if (run_len == 0) { + *out_cluster = nc; + *out_off = 0; + } else { + *out_cluster = run_cluster; + *out_off = run_off; + } + return 0; + } + cluster = next; + } +} + +static void lfn_put_chars(uint8_t *slot_bytes, const char *src_utf8, int src_len, int offset) { + static const uint8_t positions1[5] = { 1, 3, 5, 7, 9 }; + static const uint8_t positions2[6] = { 14, 16, 18, 20, 22, 24 }; + static const uint8_t positions3[2] = { 28, 30 }; + + for (int i = 0; i < 5; i++) { + int idx = offset + i; + uint16_t ch; + if (idx < src_len) ch = (uint8_t)src_utf8[idx]; + else if (idx == src_len) ch = 0; + else ch = 0xFFFF; + slot_bytes[positions1[i]] = (uint8_t)(ch & 0xFF); + slot_bytes[positions1[i] + 1] = (uint8_t)(ch >> 8); + } + for (int i = 0; i < 6; i++) { + int idx = offset + 5 + i; + uint16_t ch; + if (idx < src_len) ch = (uint8_t)src_utf8[idx]; + else if (idx == src_len) ch = 0; + else ch = 0xFFFF; + slot_bytes[positions2[i]] = (uint8_t)(ch & 0xFF); + slot_bytes[positions2[i] + 1] = (uint8_t)(ch >> 8); + } + for (int i = 0; i < 2; i++) { + int idx = offset + 11 + i; + uint16_t ch; + if (idx < src_len) ch = (uint8_t)src_utf8[idx]; + else if (idx == src_len) ch = 0; + else ch = 0xFFFF; + slot_bytes[positions3[i]] = (uint8_t)(ch & 0xFF); + slot_bytes[positions3[i] + 1] = (uint8_t)(ch >> 8); + } +} + +static int write_dirents_with_lfn(fat32_t *fs, uint32_t host_cluster, uint32_t host_off, + const char *name, const fat32_dirent_t *sfn_entry, + int slot_count) +{ + uint8_t *buf = fs->shared_buf; + if (read_cluster(fs, host_cluster, buf) < 0) return -EIO; + + int name_len = 0; + while (name[name_len]) name_len++; + + uint8_t csum = lfn_checksum(sfn_entry->name); + + int lfn_count = slot_count - 1; + uint32_t off = host_off; + + for (int i = 0; i < lfn_count; i++) { + int seq = lfn_count - i; + int char_off = (seq - 1) * 13; + uint8_t entry[32]; + memset(entry, 0, 32); + uint8_t ord = (uint8_t)seq; + if (i == 0) ord |= 0x40; + entry[0] = ord; + entry[11] = 0x0F; + entry[12] = 0; + entry[13] = csum; + entry[26] = 0; + entry[27] = 0; + lfn_put_chars(entry, name, name_len, char_off); + + if (off >= fs->bytes_per_cluster) { + if (write_cluster(fs, host_cluster, buf) < 0) return -EIO; + uint32_t next = fat_read_entry(fs, host_cluster); + if (fat32_is_eoc(next) || next < 2) { + uint32_t nc = allocate_cluster(fs); + if (nc == 0) return -ENOSPC; + fat_write_entry(fs, host_cluster, nc); + next = nc; + } + host_cluster = next; + if (read_cluster(fs, host_cluster, buf) < 0) return -EIO; + off = 0; + } + memcpy(buf + off, entry, 32); + off += 32; + } + + if (off >= fs->bytes_per_cluster) { + if (write_cluster(fs, host_cluster, buf) < 0) return -EIO; + uint32_t next = fat_read_entry(fs, host_cluster); + if (fat32_is_eoc(next) || next < 2) { + uint32_t nc = allocate_cluster(fs); + if (nc == 0) return -ENOSPC; + fat_write_entry(fs, host_cluster, nc); + next = nc; + } + host_cluster = next; + if (read_cluster(fs, host_cluster, buf) < 0) return -EIO; + off = 0; + } + memcpy(buf + off, sfn_entry, 32); + if (write_cluster(fs, host_cluster, buf) < 0) return -EIO; + + return 0; +} + +static int fat32_dir_create(vnode_t *dir, const char *name, uint32_t mode, + vnode_t **out) +{ + (void)mode; + fat32_vdata_t *vd = (fat32_vdata_t *)dir->fs_data; + if (!vd || !vd->fs) return -EIO; + if (vd->fs->readonly) return -EROFS; + fat32_t *fs = vd->fs; + + vnode_t *tmp = NULL; + if (fat32_dir_lookup(dir, name, &tmp) == 0) { + if (out) *out = tmp; + else fat32_common_unref(tmp); + return -EEXIST; + } + + int name_len = 0; + while (name[name_len]) name_len++; + + bool use_lfn = !name_fits_sfn(name); + int lfn_entries = 0; + if (use_lfn) { + lfn_entries = (name_len + 12) / 13; + } + int slot_count = lfn_entries + 1; + + uint32_t parent_cluster = vd->first_cluster ? vd->first_cluster : fs->root_cluster; + uint32_t host_cluster, host_off; + int r = find_free_slots(fs, parent_cluster, slot_count, &host_cluster, &host_off); + if (r < 0) return r; + + fat32_dirent_t e; + memset(&e, 0, sizeof(e)); + if (use_lfn) generate_short_name(name, e.name); + else string_to_fat_name(name, e.name); + e.attr = FAT_ATTR_ARCHIVE; + e.cluster_lo = 0; + e.cluster_hi = 0; + e.file_size = 0; + + if (use_lfn) { + r = write_dirents_with_lfn(fs, host_cluster, host_off, name, &e, slot_count); + if (r < 0) return r; + } else { + uint8_t *cluster_buf = fs->shared_buf; + if (read_cluster(fs, host_cluster, cluster_buf) < 0) return -EIO; + memcpy(cluster_buf + host_off, &e, sizeof(e)); + if (write_cluster(fs, host_cluster, cluster_buf) < 0) return -EIO; + } + + if (out) { + uint32_t sfn_cluster = host_cluster; + uint32_t sfn_off = host_off + lfn_entries * 32; + if (sfn_off >= fs->bytes_per_cluster) { + uint32_t next = fat_read_entry(fs, host_cluster); + sfn_cluster = next; + sfn_off = sfn_off - fs->bytes_per_cluster; + } + vnode_t *vn = fat32_alloc_vnode(fs, 0, 0, FAT_ATTR_ARCHIVE, + sfn_cluster, sfn_off); + if (!vn) return -ENOMEM; + *out = vn; + } + fat32_sync(fs); + return 0; +} + +static int fat32_dir_mkdir(vnode_t *dir, const char *name, uint32_t mode) { + (void)mode; + fat32_vdata_t *vd = (fat32_vdata_t *)dir->fs_data; + if (!vd || !vd->fs) return -EIO; + if (vd->fs->readonly) return -EROFS; + fat32_t *fs = vd->fs; + + vnode_t *tmp = NULL; + if (fat32_dir_lookup(dir, name, &tmp) == 0) { + fat32_common_unref(tmp); + return -EEXIST; + } + + uint32_t new_cluster = allocate_cluster(fs); + if (new_cluster == 0) return -ENOSPC; + + uint32_t parent_cluster = vd->first_cluster ? vd->first_cluster : fs->root_cluster; + uint8_t *dir_buf = fs->shared_buf; + memset(dir_buf, 0, fs->bytes_per_cluster); + fat32_dirent_t dot, dotdot; + memset(&dot, 0, sizeof(dot)); + memset(&dotdot, 0, sizeof(dotdot)); + memcpy(dot.name, ". ", 11); + dot.attr = FAT_ATTR_DIRECTORY; + dot.cluster_lo = (uint16_t)(new_cluster & 0xFFFF); + dot.cluster_hi = (uint16_t)((new_cluster >> 16) & 0xFFFF); + memcpy(dotdot.name, ".. ", 11); + dotdot.attr = FAT_ATTR_DIRECTORY; + uint32_t parent_ref = (parent_cluster == fs->root_cluster) ? 0 : parent_cluster; + dotdot.cluster_lo = (uint16_t)(parent_ref & 0xFFFF); + dotdot.cluster_hi = (uint16_t)((parent_ref >> 16) & 0xFFFF); + memcpy(dir_buf, &dot, 32); + memcpy(dir_buf + 32, &dotdot, 32); + if (write_cluster(fs, new_cluster, dir_buf) < 0) { + free_cluster_chain(fs, new_cluster); + return -EIO; + } + + int name_len = 0; + while (name[name_len]) name_len++; + bool use_lfn = !name_fits_sfn(name); + int lfn_entries = use_lfn ? (name_len + 12) / 13 : 0; + int slot_count = lfn_entries + 1; + + uint32_t host_cluster, host_off; + int r = find_free_slots(fs, parent_cluster, slot_count, &host_cluster, &host_off); + if (r < 0) { free_cluster_chain(fs, new_cluster); return r; } + + fat32_dirent_t e; + memset(&e, 0, sizeof(e)); + if (use_lfn) generate_short_name(name, e.name); + else string_to_fat_name(name, e.name); + e.attr = FAT_ATTR_DIRECTORY; + e.cluster_lo = (uint16_t)(new_cluster & 0xFFFF); + e.cluster_hi = (uint16_t)((new_cluster >> 16) & 0xFFFF); + e.file_size = 0; + + if (use_lfn) { + r = write_dirents_with_lfn(fs, host_cluster, host_off, name, &e, slot_count); + if (r < 0) { free_cluster_chain(fs, new_cluster); return r; } + } else { + uint8_t *buf2 = fs->shared_buf; + if (read_cluster(fs, host_cluster, buf2) < 0) { + free_cluster_chain(fs, new_cluster); + return -EIO; + } + memcpy(buf2 + host_off, &e, sizeof(e)); + if (write_cluster(fs, host_cluster, buf2) < 0) { + free_cluster_chain(fs, new_cluster); + return -EIO; + } + } + + fat32_sync(fs); + return 0; +} + +typedef struct { + const char *target; + int done; +} unlink_ctx_t; + +static int unlink_cb(fat32_t *fs, uint32_t cluster, uint32_t entry_off, + fat32_dirent_t *e, const char *name, void *ud) +{ + unlink_ctx_t *ctx = (unlink_ctx_t *)ud; + bool match = true; + for (int k = 0; ctx->target[k] || name[k]; k++) { + char a = ctx->target[k]; + char b = name[k]; + if (a >= 'A' && a <= 'Z') a = (char)(a - 'A' + 'a'); + if (b >= 'A' && b <= 'Z') b = (char)(b - 'A' + 'a'); + if (a != b) { match = false; break; } + } + if (!match) return 0; + + uint32_t first = ((uint32_t)e->cluster_hi << 16) | e->cluster_lo; + if (first != 0) free_cluster_chain(fs, first); + + uint8_t *buf = fs->shared_buf; + if (read_cluster(fs, cluster, buf) < 0) return -EIO; + buf[entry_off] = 0xE5; + if (write_cluster(fs, cluster, buf) < 0) return -EIO; + ctx->done = 1; + return 1; +} + +static int fat32_dir_unlink(vnode_t *dir, const char *name) { + fat32_vdata_t *vd = (fat32_vdata_t *)dir->fs_data; + if (!vd || !vd->fs) return -EIO; + if (vd->fs->readonly) return -EROFS; + unlink_ctx_t ctx = { .target = name, .done = 0 }; + fat32_traverse_dir(vd->fs, vd->first_cluster, unlink_cb, &ctx); + if (!ctx.done) return -ENOENT; + fat32_sync(vd->fs); + return 0; +} + +static int fat32_dir_stat(vnode_t *node, vfs_stat_t *out) { + memset(out, 0, sizeof(*out)); + out->st_ino = node->ino; + out->st_type = VFS_NODE_DIR; + out->st_mode = 0755; + out->st_size = 0; + return 0; +} + +static const vnode_ops_t fat32_file_ops = { + .read = fat32_file_read, + .write = fat32_file_write, + .stat = fat32_file_stat, + .ref = fat32_common_ref, + .unref = fat32_common_unref, +}; + +static const vnode_ops_t fat32_dir_ops = { + .lookup = fat32_dir_lookup, + .readdir = fat32_dir_readdir, + .create = fat32_dir_create, + .mkdir = fat32_dir_mkdir, + .unlink = fat32_dir_unlink, + .stat = fat32_dir_stat, + .ref = fat32_common_ref, + .unref = fat32_common_unref, +}; + +static uint64_t g_fat32_ino = 1000; + +static vnode_t *fat32_alloc_vnode(fat32_t *fs, uint32_t first_cluster, + uint32_t size, uint8_t attr, + uint32_t dir_cluster, uint32_t dir_entry_off) +{ + vnode_t *vn = calloc(1, sizeof(vnode_t)); + if (!vn) return NULL; + fat32_vdata_t *vd = calloc(1, sizeof(fat32_vdata_t)); + if (!vd) { free(vn); return NULL; } + + vd->fs = fs; + vd->first_cluster = first_cluster; + vd->file_size = size; + vd->attr = attr; + vd->dir_cluster = dir_cluster; + vd->dir_entry_offset = dir_entry_off; + vd->cached_cluster = first_cluster; + vd->cached_index = 0; + vd->size_dirty = false; + + vn->ino = g_fat32_ino++; + vn->refcount = 1; + vn->fs_data = vd; + + if (attr & FAT_ATTR_DIRECTORY) { + vn->type = VFS_NODE_DIR; + vn->mode = 0755; + vn->ops = &fat32_dir_ops; + } else { + vn->type = VFS_NODE_FILE; + vn->mode = 0644; + vn->size = size; + vn->ops = &fat32_file_ops; + } + return vn; +} + +vnode_t *fat32_mount(blkdev_t *dev) { + if (!dev) return NULL; + + uint8_t sec[FAT32_SECTOR_SIZE]; + if (dev->ops->read_sectors(dev, 0, 1, sec) < 0) { + serial_printf("[FAT32] cannot read BPB on %s\n", dev->name); + return NULL; + } + + fat32_bpb_t *bpb = (fat32_bpb_t *)sec; + if (bpb->bs_signature != 0xAA55) { + serial_printf("[FAT32] %s: no boot signature\n", dev->name); + return NULL; + } + if (bpb->bpb_bytes_per_sector != 512) { + serial_printf("[FAT32] %s: unsupported sector size %u\n", + dev->name, bpb->bpb_bytes_per_sector); + return NULL; + } + if (bpb->bpb_root_entries != 0 || bpb->bpb_fat_size_16 != 0) { + serial_printf("[FAT32] %s: not FAT32 (FAT12/16 detected)\n", dev->name); + return NULL; + } + if (bpb->bpb_fat_size_32 == 0) { + serial_printf("[FAT32] %s: FAT size 0\n", dev->name); + return NULL; + } + + fat32_t *fs = calloc(1, sizeof(fat32_t)); + if (!fs) return NULL; + + fs->dev = dev; + fs->bytes_per_sector = bpb->bpb_bytes_per_sector; + fs->sectors_per_cluster = bpb->bpb_sectors_per_cluster; + fs->bytes_per_cluster = fs->bytes_per_sector * fs->sectors_per_cluster; + fs->reserved_sectors = bpb->bpb_reserved_sectors; + fs->num_fats = bpb->bpb_num_fats; + fs->fat_size_sectors = bpb->bpb_fat_size_32; + fs->total_sectors = bpb->bpb_total_sectors_32 + ? bpb->bpb_total_sectors_32 + : bpb->bpb_total_sectors_16; + fs->root_cluster = bpb->bpb_root_cluster; + fs->first_fat_sector = fs->reserved_sectors; + fs->first_data_sector = fs->reserved_sectors + + (fs->num_fats * fs->fat_size_sectors); + uint32_t data_sectors = fs->total_sectors - fs->first_data_sector; + fs->total_clusters = data_sectors / fs->sectors_per_cluster; + fs->fsinfo_sector = bpb->bpb_fs_info; + fs->next_free_hint = 2; + fs->free_count = 0xFFFFFFFF; + fs->readonly = false; + + fs->shared_buf = (uint8_t *)malloc(fs->bytes_per_cluster); + if (!fs->shared_buf) { free(fs); return NULL; } + if (fs->bytes_per_cluster > MAX_CLUSTER_BYTES) { + serial_printf("[FAT32] %s: cluster too large %u, bailing\n", + dev->name, fs->bytes_per_cluster); + free(fs); + return NULL; + } + + if (fs->fsinfo_sector) { + uint8_t fsibuf[FAT32_SECTOR_SIZE]; + if (read_sector(fs, fs->fsinfo_sector, fsibuf) == 0) { + fat32_fsinfo_t *fsi = (fat32_fsinfo_t *)fsibuf; + if (fsi->lead_sig == FAT32_FSINFO_LEAD_SIG + && fsi->struct_sig == FAT32_FSINFO_STRUCT_SIG) { + fs->free_count = fsi->free_count; + if (fsi->next_free >= 2 && fsi->next_free < fs->total_clusters + 2) + fs->next_free_hint = fsi->next_free; + } + } + } + + serial_printf("[FAT32] mounted %s: clusters=%u cluster_size=%u root_cluster=%u free=%u\n", + dev->name, fs->total_clusters, fs->bytes_per_cluster, + fs->root_cluster, fs->free_count); + + vnode_t *root = fat32_alloc_vnode(fs, fs->root_cluster, 0, + FAT_ATTR_DIRECTORY, 0, 0); + return root; +} + +void fat32_unmount(fat32_t *fs) { + if (!fs) return; + fat32_sync(fs); + if (fs->shared_buf) { free(fs->shared_buf); fs->shared_buf = NULL; } + free(fs); +} + +int fat32_format(blkdev_t *dev, const char *label) { + if (!dev) return -EINVAL; + + uint32_t total_sectors = (uint32_t)dev->sector_count; + if (total_sectors < 65536) { + serial_printf("[FAT32] device too small (%u sectors) for FAT32\n", total_sectors); + return -EINVAL; + } + + uint32_t sectors_per_cluster; + if (total_sectors <= 532480) sectors_per_cluster = 1; + else if (total_sectors <= 16777216) sectors_per_cluster = 8; + else if (total_sectors <= 33554432) sectors_per_cluster = 16; + else if (total_sectors <= 67108864) sectors_per_cluster = 32; + else sectors_per_cluster = 64; + + uint32_t reserved = 32; + uint32_t num_fats = 2; + + uint32_t data_sectors = total_sectors - reserved; + uint32_t fat_size; + uint32_t cluster_count; + for (fat_size = 1; ; fat_size++) { + uint32_t total_fat_sectors = fat_size * num_fats; + if (total_fat_sectors >= data_sectors) return -EINVAL; + uint32_t remaining = data_sectors - total_fat_sectors; + cluster_count = remaining / sectors_per_cluster; + uint32_t need_entries = cluster_count + 2; + uint32_t need_bytes = need_entries * 4; + uint32_t need_sectors = (need_bytes + 511) / 512; + if (need_sectors <= fat_size) break; + if (fat_size > 1024 * 1024) return -EINVAL; + } + + if (cluster_count < 65525) { + serial_printf("[FAT32] ERROR: only %u clusters on %u-sector volume.\n" + " FAT32 requires >= 65525 clusters.\n" + " Minimum volume size is ~33 MB with 512-byte clusters.\n" + " Use a larger partition.\n", + cluster_count, total_sectors); + return -EINVAL; + } + + uint8_t sec[FAT32_SECTOR_SIZE]; + + memset(sec, 0, sizeof(sec)); + fat32_bpb_t *bpb = (fat32_bpb_t *)sec; + bpb->bs_jmp[0] = 0xEB; bpb->bs_jmp[1] = 0x58; bpb->bs_jmp[2] = 0x90; + memcpy(bpb->bs_oem, "CERVUS ", 8); + bpb->bpb_bytes_per_sector = 512; + bpb->bpb_sectors_per_cluster = (uint8_t)sectors_per_cluster; + bpb->bpb_reserved_sectors = (uint16_t)reserved; + bpb->bpb_num_fats = (uint8_t)num_fats; + bpb->bpb_root_entries = 0; + bpb->bpb_total_sectors_16 = 0; + bpb->bpb_media = 0xF8; + bpb->bpb_fat_size_16 = 0; + bpb->bpb_sectors_per_track = 63; + bpb->bpb_num_heads = 255; + bpb->bpb_hidden_sectors = 0; + bpb->bpb_total_sectors_32 = total_sectors; + bpb->bpb_fat_size_32 = fat_size; + bpb->bpb_ext_flags = 0; + bpb->bpb_fs_version = 0; + bpb->bpb_root_cluster = 2; + bpb->bpb_fs_info = 1; + bpb->bpb_backup_boot = 6; + bpb->bs_drive_num = 0x80; + bpb->bs_boot_sig = 0x29; + bpb->bs_vol_id = 0xCE7005; + memset(bpb->bs_vol_label, ' ', 11); + if (label) { + for (int i = 0; i < 11 && label[i]; i++) { + char c = label[i]; + if (c >= 'a' && c <= 'z') c = (char)(c - 'a' + 'A'); + bpb->bs_vol_label[i] = (uint8_t)c; + } + } + memcpy(bpb->bs_fs_type, "FAT32 ", 8); + bpb->bs_signature = 0xAA55; + if (dev->ops->write_sectors(dev, 0, 1, sec) < 0) return -EIO; + if (dev->ops->write_sectors(dev, 6, 1, sec) < 0) return -EIO; + + memset(sec, 0, sizeof(sec)); + fat32_fsinfo_t *fsi = (fat32_fsinfo_t *)sec; + fsi->lead_sig = FAT32_FSINFO_LEAD_SIG; + fsi->struct_sig = FAT32_FSINFO_STRUCT_SIG; + fsi->free_count = cluster_count - 1; + fsi->next_free = 3; + fsi->trail_sig = FAT32_FSINFO_TRAIL_SIG; + if (dev->ops->write_sectors(dev, 1, 1, sec) < 0) return -EIO; + if (dev->ops->write_sectors(dev, 7, 1, sec) < 0) return -EIO; + + { + static uint8_t zeros_batch[128 * FAT32_SECTOR_SIZE]; + memset(zeros_batch, 0, sizeof(zeros_batch)); + for (uint32_t f = 0; f < num_fats; f++) { + uint32_t fat_start = reserved + f * fat_size; + uint32_t remaining = fat_size; + uint32_t sector = fat_start; + serial_printf("[fat32] zeroing FAT#%u: %u sectors starting at LBA %u\n", + f, fat_size, fat_start); + printf(" FAT#%u: ", f); + uint32_t last_pct = 0; + uint32_t spinner = 0; + while (remaining > 0) { + uint32_t batch = (remaining > 128) ? 128 : remaining; + int r = dev->ops->write_sectors(dev, sector, batch, zeros_batch); + if (r < 0) { + serial_printf("[fat32] FAT zero-fill FAILED at LBA %u (batch=%u): %d\n", + sector, batch, r); + printf("\n"); + return -EIO; + } + sector += batch; + remaining -= batch; + uint32_t done = fat_size - remaining; + uint32_t pct = (done * 100) / fat_size; + if (pct != last_pct) { + const char glyphs[4] = { '|', '/', '-', '\\' }; + printf("\r\033[K %c FAT#%u: %u%%", + glyphs[spinner & 3], f, pct); + spinner++; + last_pct = pct; + } + } + printf("\r\033[K FAT#%u: done\n", f); + if (dev->ops->flush) dev->ops->flush(dev); + } + } + uint32_t fat0[3] = { 0x0FFFFF00 | 0xF8, 0x0FFFFFFF, FAT32_EOC }; + for (uint32_t f = 0; f < num_fats; f++) { + uint8_t fat_first[FAT32_SECTOR_SIZE]; + memset(fat_first, 0, FAT32_SECTOR_SIZE); + memcpy(fat_first, fat0, sizeof(fat0)); + if (dev->ops->write_sectors(dev, reserved + f * fat_size, 1, fat_first) < 0) + return -EIO; + } + + uint32_t first_data_sector = reserved + num_fats * fat_size; + uint32_t root_lba = first_data_sector; + uint8_t zero[FAT32_SECTOR_SIZE]; + memset(zero, 0, sizeof(zero)); + for (uint32_t i = 0; i < sectors_per_cluster; i++) { + if (dev->ops->write_sectors(dev, root_lba + i, 1, zero) < 0) return -EIO; + } + + if (dev->ops->flush) dev->ops->flush(dev); + serial_printf("[FAT32] formatted %s: %u clusters, cluster_size=%u, fat_size=%u sectors\n", + dev->name, cluster_count, sectors_per_cluster * 512, fat_size); + return 0; +} + +int fat32_statvfs(vnode_t *root, vfs_statvfs_t *out) { + if (!root || !root->fs_data || !out) return -EINVAL; + fat32_vdata_t *vd = (fat32_vdata_t *)root->fs_data; + fat32_t *fs = vd->fs; + if (!fs) return -EINVAL; + + out->f_bsize = fs->bytes_per_cluster; + out->f_blocks = fs->total_clusters; + + if (fs->free_count == 0xFFFFFFFF) { + uint32_t free = 0; + for (uint32_t cl = 2; cl < fs->total_clusters + 2; cl++) { + uint32_t entry = fat_read_entry(fs, cl) & 0x0FFFFFFF; + if (entry == 0) free++; + } + fs->free_count = free; + } + + out->f_bfree = fs->free_count; + out->f_bavail = fs->free_count; + out->f_files = 0; + out->f_ffree = 0; + out->f_flag = 0; + out->f_namemax = 255; + return 0; +} \ No newline at end of file diff --git a/kernel/src/fs/initramfs.c b/kernel/src/fs/initramfs.c new file mode 100644 index 0000000..358026d --- /dev/null +++ b/kernel/src/fs/initramfs.c @@ -0,0 +1,311 @@ +#include +#include +#include +#include "../../include/fs/initramfs.h" +#include "../../include/fs/vfs.h" +#include "../../include/io/serial.h" + +typedef struct { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; + char _pad[12]; +} __attribute__((packed)) ustar_header_t; + +#define USTAR_BLOCK 512 + +static uint64_t octal_parse(const char *s, size_t n) { + uint64_t v = 0; + for (size_t i = 0; i < n && s[i] >= '0' && s[i] <= '7'; i++) + v = v * 8 + (uint64_t)(s[i] - '0'); + return v; +} + +static size_t align_block(size_t n) { + return (n + USTAR_BLOCK - 1) & ~(size_t)(USTAR_BLOCK - 1); +} + +static void path_normalize(const char *in, char *out, size_t maxlen) { + if (maxlen == 0) return; + + const char *p = in; + + while (p[0] == '.' && p[1] == '/') p += 2; + + while (*p == '/') p++; + + if (*p == '\0' || (p[0] == '.' && p[1] == '\0')) { + out[0] = '/'; + out[1] = '\0'; + return; + } + + char tmp[VFS_MAX_PATH]; + size_t j = 0; + tmp[j++] = '/'; + + while (*p && j < sizeof(tmp) - 1) { + const char *start = p; + while (*p && *p != '/') p++; + size_t len = (size_t)(p - start); + + if (len == 1 && start[0] == '.') { + while (*p == '/') p++; + continue; + } + + if (j > 1) { + if (j < sizeof(tmp) - 1) + tmp[j++] = '/'; + } + + size_t avail = sizeof(tmp) - 1 - j; + size_t copy = len < avail ? len : avail; + memcpy(tmp + j, start, copy); + j += copy; + + while (*p == '/') p++; + } + tmp[j] = '\0'; + + strncpy(out, tmp, maxlen - 1); + out[maxlen - 1] = '\0'; +} + +static int mkdir_p(const char *abspath) { + if (!abspath || strcmp(abspath, "/") == 0) return 0; + + char buf[VFS_MAX_PATH]; + strncpy(buf, abspath, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + + for (char *p = buf + 1; *p; p++) { + if (*p == '/') { + *p = '\0'; + int r = vfs_mkdir(buf, 0755); + if (r < 0 && r != -EEXIST) { + serial_printf("[initramfs] mkdir_p: mkdir '%s' failed: %d\n", buf, r); + *p = '/'; + return r; + } + *p = '/'; + } + } + + int r = vfs_mkdir(buf, 0755); + if (r < 0 && r != -EEXIST) { + serial_printf("[initramfs] mkdir_p: mkdir '%s' failed: %d\n", buf, r); + return r; + } + return 0; +} + +static int write_file(const char *abspath, const void *data, + size_t size, uint32_t mode) +{ + serial_printf("[initramfs] write_file '%s' size=%zu\n", abspath, size); + + char parent[VFS_MAX_PATH]; + strncpy(parent, abspath, sizeof(parent) - 1); + parent[sizeof(parent) - 1] = '\0'; + + char *last_slash = NULL; + for (int i = (int)strlen(parent) - 1; i > 0; i--) { + if (parent[i] == '/') { last_slash = &parent[i]; break; } + } + + if (last_slash) { + *last_slash = '\0'; + if (strlen(parent) > 0) { + serial_printf("[initramfs] ensuring parent dir '%s'\n", parent); + + vnode_t *check = NULL; + int lr = vfs_lookup(parent, &check); + serial_printf("[initramfs] vfs_lookup('%s') before mkdir_p = %d\n", parent, lr); + if (lr == 0) { + serial_printf("[initramfs] parent exists, type=%d\n", check->type); + vnode_unref(check); + } else { + serial_printf("[initramfs] parent not found, calling mkdir_p\n"); + int mr = mkdir_p(parent); + if (mr < 0) { + serial_printf("[initramfs] mkdir_p('%s') failed: %d\n", parent, mr); + *last_slash = '/'; + return mr; + } + lr = vfs_lookup(parent, &check); + serial_printf("[initramfs] vfs_lookup('%s') after mkdir_p = %d\n", parent, lr); + if (lr == 0) { + serial_printf("[initramfs] parent now exists, type=%d\n", check->type); + vnode_unref(check); + } else { + serial_printf("[initramfs] ERROR: parent still not found after mkdir_p!\n"); + *last_slash = '/'; + return -ENOENT; + } + } + } + *last_slash = '/'; + } + + vfs_file_t *file = NULL; + int ret = vfs_open(abspath, O_WRONLY | O_CREAT | O_TRUNC, mode ? mode : 0644, &file); + serial_printf("[initramfs] vfs_open('%s') = %d\n", abspath, ret); + + if (ret < 0) { + serial_printf("[initramfs] open '%s' failed: %d\n", abspath, ret); + return ret; + } + + if (size > 0 && data != NULL) { + int64_t w = vfs_write(file, data, size); + vfs_close(file); + if (w < 0) { + serial_printf("[initramfs] write '%s' failed: %lld\n", + abspath, (long long)w); + return (int)w; + } + serial_printf("[initramfs] wrote %lld bytes\n", (long long)w); + } else { + vfs_close(file); + } + return 0; +} + +int initramfs_mount(const void *data, size_t size) { + if (!data || size < USTAR_BLOCK) return -EINVAL; + + const uint8_t *ptr = data; + const uint8_t *end = ptr + size; + int files_ok = 0, dirs_ok = 0, skipped = 0, errors = 0; + + serial_printf("[initramfs] parsing TAR @ %p, size=%zu\n", data, size); + + { + vnode_t *root_check = NULL; + int r = vfs_lookup("/", &root_check); + serial_printf("[initramfs] pre-parse: vfs_lookup('/') = %d\n", r); + if (r == 0) { + serial_printf("[initramfs] pre-parse: root type=%d refcnt=%d\n", + root_check->type, root_check->refcount); + vnode_unref(root_check); + } + + const char *test_dirs[] = { "/bin", "/etc", "/dev", "/tmp", "/proc", NULL }; + for (int i = 0; test_dirs[i]; i++) { + vnode_t *n = NULL; + int rv = vfs_lookup(test_dirs[i], &n); + serial_printf("[initramfs] pre-parse: vfs_lookup('%s') = %d\n", test_dirs[i], rv); + if (rv == 0) vnode_unref(n); + } + } + + while (ptr + USTAR_BLOCK <= end) { + const ustar_header_t *hdr = (const ustar_header_t *)ptr; + + if (hdr->name[0] == '\0') { + ptr += USTAR_BLOCK; + if (ptr + USTAR_BLOCK <= end && + ((const ustar_header_t *)ptr)->name[0] == '\0') + break; + continue; + } + + if (memcmp(hdr->magic, "ustar", 5) != 0) { + serial_writestring("[initramfs] bad magic, stopping\n"); + break; + } + + uint64_t file_size = octal_parse(hdr->size, sizeof(hdr->size)); + uint32_t mode = (uint32_t)octal_parse(hdr->mode, sizeof(hdr->mode)); + + char raw[VFS_MAX_PATH]; + if (hdr->prefix[0]) { + size_t pl = strnlen(hdr->prefix, sizeof(hdr->prefix)); + size_t nl = strnlen(hdr->name, sizeof(hdr->name)); + if (pl + nl + 2 < sizeof(raw)) { + memcpy(raw, hdr->prefix, pl); + raw[pl] = '/'; + memcpy(raw + pl + 1, hdr->name, nl); + raw[pl + 1 + nl] = '\0'; + } else { + strncpy(raw, hdr->name, sizeof(raw) - 1); + raw[sizeof(raw) - 1] = '\0'; + } + } else { + strncpy(raw, hdr->name, sizeof(raw) - 1); + raw[sizeof(raw) - 1] = '\0'; + } + + char abspath[VFS_MAX_PATH]; + path_normalize(raw, abspath, sizeof(abspath)); + + serial_printf("[initramfs] entry: raw='%s' -> abs='%s' type='%c' size=%llu\n", + raw, abspath, hdr->typeflag ? hdr->typeflag : '0', + (unsigned long long)file_size); + + ptr += USTAR_BLOCK; + + switch (hdr->typeflag) { + + case '5': + if (strcmp(abspath, "/") != 0) { + int r = mkdir_p(abspath); + if (r == 0) { + serial_printf("[initramfs] dir %s\n", abspath); + dirs_ok++; + } else { + serial_printf("[initramfs] dir %s FAILED: %d\n", abspath, r); + errors++; + } + } + break; + + case '0': + case '\0': + { + const void *filedata = (file_size > 0) ? (const void *)ptr : NULL; + int r = write_file(abspath, filedata, (size_t)file_size, + mode ? mode : 0644); + if (r == 0) { + serial_printf("[initramfs] file %s (%llu bytes)\n", + abspath, (unsigned long long)file_size); + files_ok++; + } else { + errors++; + } + break; + } + + case '2': + serial_printf("[initramfs] skip symlink %s\n", abspath); + skipped++; + break; + + default: + serial_printf("[initramfs] skip type='%c' %s\n", + hdr->typeflag ? hdr->typeflag : '0', abspath); + skipped++; + break; + } + + ptr += align_block(file_size); + } + + serial_printf("[initramfs] done: %d files, %d dirs, %d skipped, %d errors\n", + files_ok, dirs_ok, skipped, errors); + return (errors > 0 && files_ok == 0 && dirs_ok == 0) ? -EIO : 0; +} \ No newline at end of file diff --git a/kernel/src/fs/ramfs.c b/kernel/src/fs/ramfs.c new file mode 100644 index 0000000..c0b8360 --- /dev/null +++ b/kernel/src/fs/ramfs.c @@ -0,0 +1,283 @@ +#include +#include +#include +#include "../../include/fs/ramfs.h" +#include "../../include/fs/vfs.h" +#include "../../include/memory/pmm.h" +#include "../../include/io/serial.h" + +typedef struct { + char *name; + vnode_t *node; +} ramfs_child_t; + +typedef struct { + uint8_t *data; + size_t capacity; + + ramfs_child_t *children; + int child_count; + int child_cap; + + uint64_t ino; +} ramfs_node_t; + +static uint64_t g_next_ino = 1; +static const vnode_ops_t ramfs_file_ops; +static const vnode_ops_t ramfs_dir_ops; + + +static vnode_t *ramfs_alloc_vnode(vnode_type_t type, uint32_t mode) { + vnode_t *v = kzalloc(sizeof(vnode_t)); + if (!v) return NULL; + + ramfs_node_t *rn = kzalloc(sizeof(ramfs_node_t)); + if (!rn) { kfree(v); return NULL; } + + rn->ino = g_next_ino++; + v->type = type; + v->mode = mode; + v->ino = rn->ino; + v->fs_data = rn; + return v; +} + +static void ramfs_ref(vnode_t *node) { + (void)node; +} + +static void ramfs_unref(vnode_t *node) { + ramfs_node_t *rn = node->fs_data; + + if (rn->data) kfree(rn->data); + + if (rn->children) { + for (int i = 0; i < rn->child_count; i++) { + if (rn->children[i].name) kfree(rn->children[i].name); + if (rn->children[i].node) vnode_unref(rn->children[i].node); + } + kfree(rn->children); + } + + kfree(rn); + kfree(node); +} + +static int64_t ramfs_file_read(vnode_t *node, void *buf, + size_t len, uint64_t offset) +{ + ramfs_node_t *rn = node->fs_data; + if (offset >= node->size) return 0; + size_t avail = node->size - (size_t)offset; + if (len > avail) len = avail; + if (len == 0) return 0; + memcpy(buf, rn->data + offset, len); + return (int64_t)len; +} + +static int64_t ramfs_file_write(vnode_t *node, const void *buf, + size_t len, uint64_t offset) +{ + ramfs_node_t *rn = node->fs_data; + size_t end = (size_t)offset + len; + if (end > RAMFS_MAX_FILE_SIZE) return -EFBIG; + + if (end > rn->capacity) { + size_t newcap = (end + 4095) & ~(size_t)4095; + if (newcap > RAMFS_MAX_FILE_SIZE) newcap = RAMFS_MAX_FILE_SIZE; + uint8_t *newdata = kmalloc(newcap); + if (!newdata) return -ENOMEM; + + size_t copy_size = rn->data ? node->size : 0; + if (copy_size > 0) + memcpy(newdata, rn->data, copy_size); + memset(newdata + copy_size, 0, newcap - copy_size); + + if (rn->data) kfree(rn->data); + rn->data = newdata; + rn->capacity = newcap; + } + + memcpy(rn->data + offset, buf, len); + if (end > node->size) node->size = end; + return (int64_t)len; +} + +static int ramfs_file_truncate(vnode_t *node, uint64_t new_size) { + ramfs_node_t *rn = node->fs_data; + if (new_size == 0) { + if (rn->data) { + kfree(rn->data); + rn->data = NULL; + rn->capacity = 0; + } + node->size = 0; + } else if (new_size < node->size) { + node->size = new_size; + } + return 0; +} + +static int ramfs_stat(vnode_t *node, vfs_stat_t *out) { + ramfs_node_t *rn = node->fs_data; + out->st_ino = rn->ino; + out->st_type = node->type; + out->st_mode = node->mode; + out->st_uid = node->uid; + out->st_gid = node->gid; + out->st_size = node->size; + out->st_blocks = (node->size + 511) / 512; + return 0; +} + +static const vnode_ops_t ramfs_file_ops = { + .read = ramfs_file_read, + .write = ramfs_file_write, + .truncate = ramfs_file_truncate, + .stat = ramfs_stat, + .ref = ramfs_ref, + .unref = ramfs_unref, +}; + +static int ramfs_dir_grow(ramfs_node_t *rn) { + int newcap = rn->child_cap == 0 ? 8 : rn->child_cap * 2; + if (newcap > RAMFS_MAX_CHILDREN) return -ENOSPC; + ramfs_child_t *nb = kmalloc((size_t)newcap * sizeof(ramfs_child_t)); + if (!nb) return -ENOMEM; + if (rn->children && rn->child_count > 0) + memcpy(nb, rn->children, (size_t)rn->child_count * sizeof(ramfs_child_t)); + if (rn->children) kfree(rn->children); + rn->children = nb; + rn->child_cap = newcap; + return 0; +} + +static int ramfs_dir_lookup(vnode_t *dir, const char *name, vnode_t **out) { + ramfs_node_t *rn = dir->fs_data; + for (int i = 0; i < rn->child_count; i++) { + if (strcmp(rn->children[i].name, name) == 0) { + vnode_ref(rn->children[i].node); + *out = rn->children[i].node; + return 0; + } + } + return -ENOENT; +} + +static int ramfs_dir_readdir(vnode_t *dir, uint64_t index, vfs_dirent_t *out) { + ramfs_node_t *rn = dir->fs_data; + if ((int64_t)index >= rn->child_count) return -ENOENT; + ramfs_child_t *ch = &rn->children[index]; + out->d_ino = ch->node->ino; + out->d_type = (uint8_t)ch->node->type; + strncpy(out->d_name, ch->name, VFS_MAX_NAME - 1); + out->d_name[VFS_MAX_NAME - 1] = '\0'; + return 0; +} + +static int ramfs_dir_add_child(vnode_t *dir, const char *name, vnode_t *child) { + ramfs_node_t *rn = dir->fs_data; + + if (rn->child_count >= rn->child_cap) { + int r = ramfs_dir_grow(rn); + if (r < 0) return r; + } + + char *dup = kmalloc(strlen(name) + 1); + if (!dup) return -ENOMEM; + strcpy(dup, name); + + rn->children[rn->child_count].name = dup; + rn->children[rn->child_count].node = child; + rn->child_count++; + dir->size = (uint64_t)rn->child_count; + + vnode_ref(child); + return 0; +} + +static int ramfs_dir_mkdir(vnode_t *dir, const char *name, uint32_t mode) { + vnode_t *existing = NULL; + if (ramfs_dir_lookup(dir, name, &existing) == 0) { + vnode_unref(existing); + return -EEXIST; + } + + vnode_t *child = ramfs_alloc_vnode(VFS_NODE_DIR, mode ? mode : 0755); + if (!child) return -ENOMEM; + + child->ops = &ramfs_dir_ops; + child->refcount = 1; + + int ret = ramfs_dir_add_child(dir, name, child); + if (ret < 0) { + kfree(child->fs_data); + kfree(child); + return ret; + } + + vnode_unref(child); + return 0; +} + +static int ramfs_dir_create(vnode_t *dir, const char *name, uint32_t mode, vnode_t **out) { + vnode_t *existing = NULL; + if (ramfs_dir_lookup(dir, name, &existing) == 0) { + *out = existing; + return 0; + } + + vnode_t *child = ramfs_alloc_vnode(VFS_NODE_FILE, mode ? mode : 0644); + if (!child) return -ENOMEM; + + child->ops = &ramfs_file_ops; + child->refcount = 1; + + int ret = ramfs_dir_add_child(dir, name, child); + if (ret < 0) { + kfree(child->fs_data); + kfree(child); + return ret; + } + + *out = child; + return 0; +} + +static int ramfs_dir_unlink(vnode_t *dir, const char *name) { + ramfs_node_t *rn = dir->fs_data; + for (int i = 0; i < rn->child_count; i++) { + if (strcmp(rn->children[i].name, name) == 0) { + kfree(rn->children[i].name); + vnode_unref(rn->children[i].node); + for (int j = i; j < rn->child_count - 1; j++) + rn->children[j] = rn->children[j + 1]; + rn->child_count--; + dir->size = (uint64_t)rn->child_count; + return 0; + } + } + return -ENOENT; +} + +static const vnode_ops_t ramfs_dir_ops = { + .lookup = ramfs_dir_lookup, + .readdir = ramfs_dir_readdir, + .mkdir = ramfs_dir_mkdir, + .create = ramfs_dir_create, + .unlink = ramfs_dir_unlink, + .stat = ramfs_stat, + .ref = ramfs_ref, + .unref = ramfs_unref, +}; + +vnode_t *ramfs_create_root(void) { + vnode_t *root = ramfs_alloc_vnode(VFS_NODE_DIR, 0755); + if (!root) return NULL; + + root->ops = &ramfs_dir_ops; + root->refcount = 1; + + serial_writestring("[ramfs] root created\n"); + return root; +} \ No newline at end of file diff --git a/kernel/src/fs/vfs.c b/kernel/src/fs/vfs.c new file mode 100644 index 0000000..a413cfc --- /dev/null +++ b/kernel/src/fs/vfs.c @@ -0,0 +1,617 @@ +#include "../../include/fs/vfs.h" +#include "../../include/sched/sched.h" +#include "../../include/memory/pmm.h" +#include "../../include/io/serial.h" +#include + +static vfs_mount_t g_mounts[VFS_MAX_MOUNTS]; +static vfs_file_t g_open_files[VFS_MAX_OPEN_FILES]; +static bool g_vfs_ready = false; + +void vfs_init(void) { + memset(g_mounts, 0, sizeof(g_mounts)); + memset(g_open_files, 0, sizeof(g_open_files)); + g_vfs_ready = true; + serial_writestring("[VFS] initialized\n"); +} + +void vnode_ref(vnode_t *node) { + if (!node) return; + __atomic_fetch_add(&node->refcount, 1, __ATOMIC_RELAXED); +} + +void vnode_unref(vnode_t *node) { + if (!node) return; + int old = __atomic_fetch_sub(&node->refcount, 1, __ATOMIC_ACQ_REL); + if (old <= 1) { + if (node->ops && node->ops->unref) + node->ops->unref(node); + } +} + +int vfs_mount(const char *path, vnode_t *fs_root) { + if (!path || !fs_root) return -EINVAL; + + for (int i = 0; i < VFS_MAX_MOUNTS; i++) { + if (g_mounts[i].used && strcmp(g_mounts[i].path, path) == 0) { + serial_printf("[VFS] mount: '%s' already mounted\n", path); + return -EBUSY; + } + } + + int slot = -1; + if (strcmp(path, "/") == 0) { + slot = 0; + } else { + for (int i = 1; i < VFS_MAX_MOUNTS; i++) { + if (!g_mounts[i].used) { slot = i; break; } + } + } + if (slot < 0) return -ENOMEM; + + strncpy(g_mounts[slot].path, path, VFS_MAX_PATH - 1); + g_mounts[slot].root = fs_root; + g_mounts[slot].used = true; + g_mounts[slot].fs_priv = NULL; + g_mounts[slot].unmount = NULL; + vnode_ref(fs_root); + serial_printf("[VFS] mounted '%s' at slot %d\n", path, slot); + return 0; +} + +int vfs_mount_fs(const char *path, vnode_t *fs_root, + void *fs_priv, void (*unmount_fn)(void *), + void (*sync_fn)(void *)) { + int ret = vfs_mount(path, fs_root); + if (ret < 0) return ret; + + for (int i = 0; i < VFS_MAX_MOUNTS; i++) { + if (g_mounts[i].used && strcmp(g_mounts[i].path, path) == 0) { + g_mounts[i].fs_priv = fs_priv; + g_mounts[i].unmount = unmount_fn; + g_mounts[i].sync = sync_fn; + break; + } + } + return 0; +} + +void vfs_sync_all(void) { + for (int i = 0; i < VFS_MAX_MOUNTS; i++) { + if (g_mounts[i].used && g_mounts[i].fs_priv) { + serial_printf("[VFS] sync_all: flushing mount '%s'\n", g_mounts[i].path); + if (g_mounts[i].sync) + g_mounts[i].sync(g_mounts[i].fs_priv); + } + } +} + +int vfs_umount(const char *path) { + for (int i = 0; i < VFS_MAX_MOUNTS; i++) { + if (g_mounts[i].used && strcmp(g_mounts[i].path, path) == 0) { + if (g_mounts[i].unmount && g_mounts[i].fs_priv) + g_mounts[i].unmount(g_mounts[i].fs_priv); + vnode_unref(g_mounts[i].root); + memset(&g_mounts[i], 0, sizeof(vfs_mount_t)); + return 0; + } + } + return -ENOENT; +} + +static vfs_mount_t *find_mount(const char *path, const char **rel_out) { + vfs_mount_t *best = NULL; + size_t best_len = 0; + + for (int i = 0; i < VFS_MAX_MOUNTS; i++) { + if (!g_mounts[i].used) continue; + size_t mlen = strlen(g_mounts[i].path); + if (strncmp(path, g_mounts[i].path, mlen) == 0) { + if (path[mlen] == '/' || path[mlen] == '\0' || mlen == 1) { + if (mlen > best_len) { + best = &g_mounts[i]; + best_len = mlen; + } + } + } + } + + if (best && rel_out) { + const char *rel = path + best_len; + while (*rel == '/') rel++; + *rel_out = rel; + } + return best; +} + +static const char *path_next_component(const char *src, char *dst, size_t maxlen) { + while (*src == '/') src++; + size_t i = 0; + while (*src && *src != '/' && i < maxlen - 1) + dst[i++] = *src++; + dst[i] = '\0'; + return src; +} + +int vfs_lookup(const char *path, vnode_t **out) { + if (!path || !out) return -EINVAL; + if (!g_vfs_ready) return -EIO; + if (path[0] != '/') return -EINVAL; + + const char *rel; + vfs_mount_t *mnt = find_mount(path, &rel); + if (!mnt) { + serial_printf("[VFS] lookup '%s': no mount found\n", path); + return -ENOENT; + } + + vnode_t *cur = mnt->root; + if (!cur) { + serial_printf("[VFS] lookup '%s': mount root is NULL!\n", path); + return -EIO; + } + vnode_ref(cur); + + if (*rel == '\0') { + *out = cur; + return 0; + } + + char comp[VFS_MAX_NAME]; + const char *p = rel; + while (*p) { + p = path_next_component(p, comp, sizeof(comp)); + if (comp[0] == '\0') continue; + + if (cur->type != VFS_NODE_DIR) { + serial_printf("[VFS] lookup '%s': '%s' is not a dir (type=%d)\n", + path, comp, cur->type); + vnode_unref(cur); + return -ENOTDIR; + } + if (!cur->ops || !cur->ops->lookup) { + serial_printf("[VFS] lookup '%s': no lookup op for comp '%s'\n", path, comp); + vnode_unref(cur); + return -EIO; + } + + vnode_t *next = NULL; + int ret = cur->ops->lookup(cur, comp, &next); + if (ret < 0) { + serial_printf("[VFS] lookup '%s': ops->lookup('%s') = %d\n", path, comp, ret); + vnode_unref(cur); + return ret; + } + + vnode_unref(cur); + cur = next; + + if (cur->mounted) { + vnode_t *mroot = cur->mounted->root; + vnode_ref(mroot); + vnode_unref(cur); + cur = mroot; + } + } + + *out = cur; + return 0; +} + +vfs_file_t *vfs_file_alloc(void) { + for (int i = 0; i < VFS_MAX_OPEN_FILES; i++) { + if (g_open_files[i].refcount == 0) { + memset(&g_open_files[i], 0, sizeof(vfs_file_t)); + g_open_files[i].refcount = 1; + return &g_open_files[i]; + } + } + return NULL; +} + +void vfs_file_free(vfs_file_t *file) { + if (!file) return; + int old = __atomic_fetch_sub(&file->refcount, 1, __ATOMIC_ACQ_REL); + if (old == 1) { + vnode_unref(file->vnode); + file->vnode = NULL; + } +} + +int vfs_open(const char *path, int flags, uint32_t mode, vfs_file_t **out) { + if (!path || !out) return -EINVAL; + + vnode_t *node = NULL; + int ret = vfs_lookup(path, &node); + + if (ret == -ENOENT && (flags & O_CREAT)) { + char dirpath[VFS_MAX_PATH]; + strncpy(dirpath, path, VFS_MAX_PATH - 1); + dirpath[VFS_MAX_PATH - 1] = '\0'; + + char *slash = NULL; + for (int i = (int)strlen(dirpath) - 1; i >= 0; i--) { + if (dirpath[i] == '/') { slash = &dirpath[i]; break; } + } + if (!slash) return -EINVAL; + + char filename[VFS_MAX_NAME]; + strncpy(filename, slash + 1, VFS_MAX_NAME - 1); + filename[VFS_MAX_NAME - 1] = '\0'; + + if (filename[0] == '\0') return -EINVAL; + + if (slash == dirpath) + dirpath[1] = '\0'; + else + *slash = '\0'; + + serial_printf("[VFS] open O_CREAT: parent='%s' name='%s'\n", dirpath, filename); + + vnode_t *dir = NULL; + ret = vfs_lookup(dirpath, &dir); + if (ret < 0) { + serial_printf("[VFS] open O_CREAT: lookup parent '%s' failed: %d\n", dirpath, ret); + return ret; + } + + if (!dir->ops || !dir->ops->create) { + serial_printf("[VFS] open O_CREAT: parent has no create op\n"); + vnode_unref(dir); + return -ENOSYS; + } + ret = dir->ops->create(dir, filename, mode, &node); + vnode_unref(dir); + if (ret < 0) { + serial_printf("[VFS] open O_CREAT: create '%s' failed: %d\n", filename, ret); + return ret; + } + } else if (ret < 0) { + return ret; + } + + int acc = flags & O_ACCMODE; + if ((acc == O_WRONLY || acc == O_RDWR) && node->type == VFS_NODE_DIR) { + vnode_unref(node); + return -EISDIR; + } + + vfs_file_t *file = vfs_file_alloc(); + if (!file) { + vnode_unref(node); + return -ENFILE; + } + + file->vnode = node; + file->flags = flags; + file->offset = (flags & O_APPEND) ? node->size : 0; + + if ((flags & O_TRUNC) && (acc == O_WRONLY || acc == O_RDWR)) { + if (node->ops && node->ops->truncate) { + node->ops->truncate(node, 0); + } else { + node->size = 0; + } + file->offset = 0; + } + + *out = file; + return 0; +} + +void vfs_close(vfs_file_t *file) { + if (file) { + int acc = file->flags & O_ACCMODE; + if (acc == O_WRONLY || acc == O_RDWR) { + vfs_sync_all(); + } + } + vfs_file_free(file); +} + +int64_t vfs_read(vfs_file_t *file, void *buf, size_t len) { + if (!file || !file->vnode) return -EBADF; + if (len == 0) return 0; + if ((file->flags & O_ACCMODE) == O_WRONLY) return -EBADF; + if (!file->vnode->ops || !file->vnode->ops->read) return -EIO; + + int64_t n = file->vnode->ops->read(file->vnode, buf, len, file->offset); + if (n > 0) file->offset += (uint64_t)n; + return n; +} + +int64_t vfs_write(vfs_file_t *file, const void *buf, size_t len) { + if (!file || !file->vnode) return -EBADF; + if (len == 0) return 0; + if ((file->flags & O_ACCMODE) == O_RDONLY) return -EBADF; + if (!file->vnode->ops || !file->vnode->ops->write) return -EIO; + + if (file->flags & O_APPEND) file->offset = file->vnode->size; + + int64_t n = file->vnode->ops->write(file->vnode, buf, len, file->offset); + if (n > 0) file->offset += (uint64_t)n; + return n; +} + +int64_t vfs_seek(vfs_file_t *file, int64_t offset, int whence) { + if (!file || !file->vnode) return -EBADF; + vnode_type_t t = file->vnode->type; + if (t == VFS_NODE_CHARDEV || t == VFS_NODE_PIPE) return -ESPIPE; + + int64_t new_off; + switch (whence) { + case SEEK_SET: new_off = offset; break; + case SEEK_CUR: new_off = (int64_t)file->offset + offset; break; + case SEEK_END: new_off = (int64_t)file->vnode->size + offset; break; + default: return -EINVAL; + } + if (new_off < 0) return -EINVAL; + file->offset = (uint64_t)new_off; + return new_off; +} + +int vfs_stat(const char *path, vfs_stat_t *out) { + if (!path || !out) return -EINVAL; + vnode_t *node = NULL; + int ret = vfs_lookup(path, &node); + if (ret < 0) return ret; + + if (node->ops && node->ops->stat) { + ret = node->ops->stat(node, out); + } else { + memset(out, 0, sizeof(*out)); + out->st_ino = node->ino; + out->st_type = node->type; + out->st_mode = node->mode; + out->st_uid = node->uid; + out->st_gid = node->gid; + out->st_size = node->size; + ret = 0; + } + vnode_unref(node); + return ret; +} + +int vfs_fstat(vfs_file_t *file, vfs_stat_t *out) { + if (!file || !file->vnode || !out) return -EBADF; + vnode_t *node = file->vnode; + if (node->ops && node->ops->stat) return node->ops->stat(node, out); + memset(out, 0, sizeof(*out)); + out->st_ino = node->ino; + out->st_type = node->type; + out->st_mode = node->mode; + out->st_uid = node->uid; + out->st_gid = node->gid; + out->st_size = node->size; + return 0; +} + +int64_t vfs_ioctl(vfs_file_t *file, uint64_t req, void *arg) { + if (!file || !file->vnode) return -EBADF; + if (!file->vnode->ops || !file->vnode->ops->ioctl) return -ENOTTY; + return file->vnode->ops->ioctl(file->vnode, req, arg); +} + +int vfs_readdir(vfs_file_t *file, vfs_dirent_t *out) { + if (!file || !file->vnode || !out) return -EBADF; + if (file->vnode->type != VFS_NODE_DIR) return -ENOTDIR; + if (!file->vnode->ops || !file->vnode->ops->readdir) return -EIO; + int ret = file->vnode->ops->readdir(file->vnode, file->offset, out); + if (ret == 0) file->offset++; + return ret; +} + +int vfs_mkdir(const char *path, uint32_t mode) { + if (!path) return -EINVAL; + char dirpath[VFS_MAX_PATH]; + strncpy(dirpath, path, VFS_MAX_PATH - 1); + dirpath[VFS_MAX_PATH - 1] = '\0'; + + char *slash = NULL; + for (int i = (int)strlen(dirpath) - 1; i >= 0; i--) { + if (dirpath[i] == '/') { slash = &dirpath[i]; break; } + } + if (!slash) return -EINVAL; + + char dirname[VFS_MAX_NAME]; + strncpy(dirname, slash + 1, VFS_MAX_NAME - 1); + dirname[VFS_MAX_NAME - 1] = '\0'; + + if (dirname[0] == '\0') return -EINVAL; + + if (slash == dirpath) dirpath[1] = '\0'; + else *slash = '\0'; + + vnode_t *dir = NULL; + int ret = vfs_lookup(dirpath, &dir); + if (ret < 0) return ret; + if (!dir->ops || !dir->ops->mkdir) { vnode_unref(dir); return -ENOSYS; } + ret = dir->ops->mkdir(dir, dirname, mode); + vnode_unref(dir); + return ret; +} + +fd_table_t *fd_table_create(void) { + fd_table_t *t = kzalloc(sizeof(fd_table_t)); + return t; +} + +fd_table_t *fd_table_clone(const fd_table_t *src) { + if (!src) return NULL; + fd_table_t *dst = kzalloc(sizeof(fd_table_t)); + if (!dst) return NULL; + for (int i = 0; i < TASK_MAX_FDS; i++) { + if (src->entries[i].file) { + dst->entries[i] = src->entries[i]; + __atomic_fetch_add(&dst->entries[i].file->refcount, 1, __ATOMIC_RELAXED); + } + } + return dst; +} + +void fd_table_cloexec(fd_table_t *table) { + if (!table) return; + for (int i = 0; i < TASK_MAX_FDS; i++) { + if (table->entries[i].file && (table->entries[i].fd_flags & FD_CLOEXEC)) { + vfs_file_free(table->entries[i].file); + table->entries[i].file = NULL; + table->entries[i].fd_flags = 0; + } + } +} + +void fd_table_destroy(fd_table_t *table) { + if (!table) return; + for (int i = 0; i < TASK_MAX_FDS; i++) { + if (table->entries[i].file) { + vfs_file_free(table->entries[i].file); + table->entries[i].file = NULL; + } + } + kfree(table); +} + +int fd_alloc(fd_table_t *table, vfs_file_t *file, int min_fd) { + if (!table || !file) return -EINVAL; + if (min_fd < 0 || min_fd >= TASK_MAX_FDS) return -EINVAL; + for (int i = min_fd; i < TASK_MAX_FDS; i++) { + if (!table->entries[i].file) { + table->entries[i].file = file; + table->entries[i].fd_flags = 0; + return i; + } + } + return -EMFILE; +} + +vfs_file_t *fd_get(const fd_table_t *table, int fd) { + if (!table || fd < 0 || fd >= TASK_MAX_FDS) return NULL; + return table->entries[fd].file; +} + +int fd_close(fd_table_t *table, int fd) { + if (!table || fd < 0 || fd >= TASK_MAX_FDS) return -EBADF; + vfs_file_t *file = table->entries[fd].file; + if (!file) return -EBADF; + vfs_file_free(file); + table->entries[fd].file = NULL; + table->entries[fd].fd_flags = 0; + return 0; +} + +int fd_dup2(fd_table_t *table, int oldfd, int newfd) { + if (!table) return -EBADF; + if (oldfd < 0 || oldfd >= TASK_MAX_FDS) return -EBADF; + if (newfd < 0 || newfd >= TASK_MAX_FDS) return -EBADF; + if (oldfd == newfd) return newfd; + + vfs_file_t *src = table->entries[oldfd].file; + if (!src) return -EBADF; + + if (table->entries[newfd].file) + vfs_file_free(table->entries[newfd].file); + + table->entries[newfd].file = src; + table->entries[newfd].fd_flags = 0; + __atomic_fetch_add(&src->refcount, 1, __ATOMIC_RELAXED); + return newfd; +} + +int fd_set_flags(fd_table_t *table, int fd, int flags) { + if (!table || fd < 0 || fd >= TASK_MAX_FDS) return -EBADF; + if (!table->entries[fd].file) return -EBADF; + table->entries[fd].fd_flags = flags; + return 0; +} + +int fd_get_flags(const fd_table_t *table, int fd) { + if (!table || fd < 0 || fd >= TASK_MAX_FDS) return -EBADF; + if (!table->entries[fd].file) return -EBADF; + return table->entries[fd].fd_flags; +} + +int vfs_init_stdio(void *task_ptr) { + task_t *t = (task_t *)task_ptr; + if (!t || !t->fd_table) return -EINVAL; + + vfs_file_t *in = NULL; + int ret = vfs_open("/dev/tty", O_RDONLY, 0, &in); + if (ret < 0) return ret; + fd_alloc(t->fd_table, in, 0); + + vfs_file_t *out = NULL; + ret = vfs_open("/dev/tty", O_WRONLY, 0, &out); + if (ret < 0) return ret; + fd_alloc(t->fd_table, out, 1); + + vfs_file_t *err = NULL; + ret = vfs_open("/dev/tty", O_WRONLY, 0, &err); + if (ret < 0) return ret; + fd_alloc(t->fd_table, err, 2); + + return 0; +} + +int vfs_set_mount_info(const char *path, const char *device, const char *fstype) { + for (int i = 0; i < VFS_MAX_MOUNTS; i++) { + if (g_mounts[i].used && strcmp(g_mounts[i].path, path) == 0) { + if (device) { + strncpy(g_mounts[i].device, device, sizeof(g_mounts[i].device) - 1); + g_mounts[i].device[sizeof(g_mounts[i].device) - 1] = '\0'; + } + if (fstype) { + strncpy(g_mounts[i].fstype, fstype, sizeof(g_mounts[i].fstype) - 1); + g_mounts[i].fstype[sizeof(g_mounts[i].fstype) - 1] = '\0'; + } + return 0; + } + } + return -ENOENT; +} + +int vfs_list_mounts(vfs_mount_info_t *out, int max) { + int n = 0; + for (int i = 0; i < VFS_MAX_MOUNTS && n < max; i++) { + if (!g_mounts[i].used) continue; + strncpy(out[n].path, g_mounts[i].path, VFS_MAX_PATH - 1); + out[n].path[VFS_MAX_PATH - 1] = '\0'; + strncpy(out[n].device, g_mounts[i].device, sizeof(out[n].device) - 1); + out[n].device[sizeof(out[n].device) - 1] = '\0'; + strncpy(out[n].fstype, g_mounts[i].fstype, sizeof(out[n].fstype) - 1); + out[n].fstype[sizeof(out[n].fstype) - 1] = '\0'; + out[n].flags = 0; + n++; + } + return n; +} + +extern int ext2_statvfs(vnode_t *root, vfs_statvfs_t *out); +extern int fat32_statvfs(vnode_t *root, vfs_statvfs_t *out); + +int vfs_statvfs(const char *path, vfs_statvfs_t *out) { + if (!path || !out) return -EINVAL; + memset(out, 0, sizeof(*out)); + + vfs_mount_t *best = NULL; + size_t best_len = 0; + for (int i = 0; i < VFS_MAX_MOUNTS; i++) { + if (!g_mounts[i].used) continue; + size_t mlen = strlen(g_mounts[i].path); + if (strncmp(path, g_mounts[i].path, mlen) == 0) { + if (path[mlen] == '/' || path[mlen] == '\0' || mlen == 1) { + if (mlen > best_len) { best = &g_mounts[i]; best_len = mlen; } + } + } + } + if (!best) return -ENOENT; + + if (strcmp(best->fstype, "ext2") == 0) { + return ext2_statvfs(best->root, out); + } + if (strcmp(best->fstype, "fat32") == 0) { + return fat32_statvfs(best->root, out); + } + out->f_bsize = 4096; + out->f_namemax = 255; + return 0; +} \ No newline at end of file diff --git a/kernel/src/gdt/gdt.c b/kernel/src/gdt/gdt.c new file mode 100644 index 0000000..62fd783 --- /dev/null +++ b/kernel/src/gdt/gdt.c @@ -0,0 +1,41 @@ +#include "../../include/gdt/gdt.h" +#include "../../include/smp/smp.h" +#include "../../include/io/serial.h" +#include +#include + +gdt_pointer_t gdtr; + +struct { + gdt_entry_t gdt_entries[5 + (MAX_CPUS * 2)]; +} __attribute__((packed)) gdt; + +tss_t *tss[MAX_CPUS] = {0}; +__attribute__((aligned(16))) char kernel_stacks[MAX_CPUS][KERNEL_STACK_SIZE]; +__attribute__((aligned(16))) char def_ist_stacks[MAX_CPUS][KERNEL_STACK_SIZE]; +__attribute__((aligned(16))) char df_stacks[MAX_CPUS][KERNEL_STACK_SIZE]; +__attribute__((aligned(16))) char nmi_stacks[MAX_CPUS][KERNEL_STACK_SIZE]; +__attribute__((aligned(16))) char pf_stacks[MAX_CPUS][KERNEL_STACK_SIZE]; + +extern void _load_gdt(gdt_pointer_t *descriptor); +extern void _reload_segments(uint64_t cs, uint64_t ds); + +void gdt_init(void) { + memset(&gdt, 0, sizeof(gdt)); + gdt.gdt_entries[0] = (gdt_entry_t)GDT_ENTRY(0, 0, 0x00, 0x0); + gdt.gdt_entries[1] = (gdt_entry_t)GDT_ENTRY(0, 0xFFFFF, 0x9A, 0xA); + gdt.gdt_entries[2] = (gdt_entry_t)GDT_ENTRY(0, 0xFFFFF, 0x92, 0xC); + gdt.gdt_entries[3] = (gdt_entry_t)GDT_ENTRY(0, 0xFFFFF, 0xF2, 0x8); + gdt.gdt_entries[4] = (gdt_entry_t)GDT_ENTRY(0, 0xFFFFF, 0xFA, 0xA); + gdtr.size = (5 * sizeof(gdt_entry_t)) - 1; + gdtr.pointer = &gdt.gdt_entries[0]; + + serial_printf("Installing temporary GDT for BSP...\n"); + gdt_load(); + serial_printf("Temporary GDT installed\n"); +} + +void gdt_load(void) { + _load_gdt(&gdtr); + _reload_segments(GDT_CODE_SEGMENT, GDT_DATA_SEGMENT); +} \ No newline at end of file diff --git a/kernel/src/gdt/gdt_asm.asm b/kernel/src/gdt/gdt_asm.asm new file mode 100644 index 0000000..4e0c950 --- /dev/null +++ b/kernel/src/gdt/gdt_asm.asm @@ -0,0 +1,28 @@ +section .text +global _reload_segments +global _load_gdt +global load_tss + +_load_gdt: + lgdt [rdi] + ret + +load_tss: + ltr di + ret + +_reload_segments: + push rdi + + lea rax, [rel .reload_cs] + push rax + + retfq +.reload_cs: + mov ax, si + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + ret \ No newline at end of file diff --git a/kernel/src/graphics/fb/fb.c b/kernel/src/graphics/fb/fb.c new file mode 100644 index 0000000..cb58130 --- /dev/null +++ b/kernel/src/graphics/fb/fb.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include "../../../include/graphics/fb/fb.h" +#include "../../../include/io/serial.h" + +uint32_t *g_backbuf = NULL; +uint32_t g_bb_pitch = 0; +static uint32_t g_bb_w = 0; +static uint32_t g_bb_h = 0; + +void fb_init_backbuffer(struct limine_framebuffer *fb) { + if (!fb) return; + g_bb_w = fb->width; + g_bb_h = fb->height; + g_bb_pitch = fb->pitch / 4; + size_t sz = (size_t)g_bb_pitch * g_bb_h * sizeof(uint32_t); + g_backbuf = (uint32_t *)malloc(sz); + if (g_backbuf) { + memcpy(g_backbuf, fb->address, sz); + serial_printf("[FB] Backbuffer allocated: %ux%u (%zu KB)\n", + g_bb_w, g_bb_h, sz / 1024); + } else { + serial_printf("[FB] WARNING: backbuffer alloc failed, using direct VRAM\n"); + } +} + +static inline uint32_t *fb_get_buf(struct limine_framebuffer *fb) { + return g_backbuf ? g_backbuf : (uint32_t *)fb->address; +} + +static inline uint32_t fb_get_pitch(struct limine_framebuffer *fb) { + return g_backbuf ? g_bb_pitch : (fb->pitch / 4); +} + +void fb_flush(struct limine_framebuffer *fb) { + if (!fb || !g_backbuf) return; + memcpy(fb->address, g_backbuf, (size_t)g_bb_pitch * g_bb_h * sizeof(uint32_t)); +} + +void fb_flush_lines(struct limine_framebuffer *fb, uint32_t y_start, uint32_t y_end) { + if (!fb || !g_backbuf) return; + if (y_start >= g_bb_h) return; + if (y_end > g_bb_h) y_end = g_bb_h; + if (y_start >= y_end) return; + uint32_t *dst = (uint32_t *)fb->address + y_start * g_bb_pitch; + uint32_t *src = g_backbuf + y_start * g_bb_pitch; + size_t bytes = (size_t)(y_end - y_start) * g_bb_pitch * sizeof(uint32_t); + memcpy(dst, src, bytes); +} + +void fb_draw_pixel(struct limine_framebuffer *fb, uint32_t x, uint32_t y, uint32_t color) { + if (x >= fb->width || y >= fb->height) return; + uint32_t *buf = fb_get_buf(fb); + uint32_t pitch = fb_get_pitch(fb); + buf[y * pitch + x] = color; +} + +void fb_fill_rect(struct limine_framebuffer *fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color) { + if (!fb) return; + uint32_t *buf = fb_get_buf(fb); + uint32_t pitch = fb_get_pitch(fb); + + if (x >= fb->width || y >= fb->height) return; + if (x + w > fb->width) w = fb->width - x; + if (y + h > fb->height) h = fb->height - y; + + for (uint32_t py = 0; py < h; py++) { + uint32_t *row = buf + (y + py) * pitch + x; + if (color == 0) { + memset(row, 0, w * sizeof(uint32_t)); + } else { + for (uint32_t px = 0; px < w; px++) + row[px] = color; + } + } +} + +void fb_clear(struct limine_framebuffer *fb, uint32_t color) { + if (!fb) return; + uint32_t *buf = fb_get_buf(fb); + size_t total = (size_t)fb_get_pitch(fb) * fb->height; + if (color == 0) { + memset(buf, 0, total * sizeof(uint32_t)); + } else { + for (size_t i = 0; i < total; i++) + buf[i] = color; + } +} + +int psf_validate(void) { + const uint8_t *raw = get_font_data(); + if (raw[0] == 0x72 && raw[1] == 0xb5 && + raw[2] == 0x4a && raw[3] == 0x86) + return 2; + if (raw[0] == 0x36 && raw[1] == 0x04) + return 1; + return 0; +} + +void fb_draw_char(struct limine_framebuffer *fb, char c, uint32_t x, uint32_t y, uint32_t color) { + const uint8_t *raw = get_font_data(); + uint32_t headersize = 32; + uint32_t charsiz = *(uint32_t*)(raw + 20); + uint8_t *glyphs = (uint8_t*)raw + headersize; + + uint32_t glyph_index = ((uint8_t)c < 128) ? (uint8_t)c : '?'; + if (glyph_index >= 512) glyph_index = '?'; + + uint8_t *glyph = &glyphs[glyph_index * charsiz]; + uint32_t *buf = fb_get_buf(fb); + uint32_t pitch = fb_get_pitch(fb); + + if (x + 8 > fb->width || y + 16 > fb->height) return; + + for (uint32_t row = 0; row < 16; row++) { + uint8_t byte = glyph[row]; + uint32_t *line = buf + (y + row) * pitch + x; + for (uint32_t col = 0; col < 8; col++) { + if (byte & (0x80 >> col)) + line[col] = color; + } + } +} + +void fb_draw_string(struct limine_framebuffer *fb, const char *str, uint32_t x, uint32_t y, uint32_t color) { + uint32_t orig_x = x; + if (!psf_validate()) return; + while (*str) { + if (*str == '\n') { x = orig_x; y += 16; } + else { fb_draw_char(fb, *str, x, y, color); x += 8; } + str++; + } +} diff --git a/kernel/src/interrupts/idt.c b/kernel/src/interrupts/idt.c new file mode 100644 index 0000000..efb1b71 --- /dev/null +++ b/kernel/src/interrupts/idt.c @@ -0,0 +1,79 @@ +#include "../../include/interrupts/idt.h" +#include "../../include/interrupts/isr.h" +#include "../../include/interrupts/irq.h" +#include "../../include/io/serial.h" +#include +#include + +extern void *interrupts_stub_table[]; + +__attribute__(( + aligned(0x10))) static idt_entry_t idt_entries[IDT_MAX_DESCRIPTORS]; + +idtr_t idtr; + +void idt_set_gate(uint8_t index, void *base, uint16_t selector, uint8_t flags, uint8_t ist) { + idt_entries[index].base_low = (uint64_t)base & 0xFFFF; + idt_entries[index].kernel_cs = selector; + idt_entries[index].ist = ist; + idt_entries[index].attributes = flags; + idt_entries[index].base_mid = ((uint64_t)base >> 16) & 0xFFFF; + idt_entries[index].base_high = ((uint64_t)base >> 32) & 0xFFFFFFFF; + idt_entries[index].reserved = 0; +} + +void idt_gate_enable(int interrupt) { + FLAG_SET(idt_entries[interrupt].attributes, IDT_FLAG_PRESENT); +} + +void idt_gate_disable(int interrupt) { + FLAG_UNSET(idt_entries[interrupt].attributes, IDT_FLAG_PRESENT); +} + +bool setup_specific_vectors(uint64_t kernel_code_segment, uint64_t vector) { + if(vector == EXCEPTION_DOUBLE_FAULT) { + idt_set_gate(vector, interrupts_stub_table[vector], kernel_code_segment, 0x8E, 1); + return true; + } + + if(vector == EXCEPTION_NMI) { + idt_set_gate(vector, interrupts_stub_table[vector], kernel_code_segment, 0x8E, 2); + return true; + } + + if(vector == EXCEPTION_PAGE_FAULT) { + idt_set_gate(vector, interrupts_stub_table[vector], kernel_code_segment, 0x8E, 3); + return true; + } + + if(vector == 0x40) { + idt_set_gate(vector, interrupts_stub_table[vector], kernel_code_segment, 0x8E, 4); + return true; + } + + return false; +} + +void idt_load(void) { + __asm__ volatile("lidt %0" : : "m"(idtr)); +} + +void setup_interrupt_descriptor_table(uint64_t kernel_code_segment) { + serial_printf("[IDT] Initializing IDT...\n"); + + idtr.base = (idt_entry_t *)&idt_entries[0]; + idtr.limit = (uint16_t)sizeof(idt_entry_t) * IDT_MAX_DESCRIPTORS - 1; + + for (uint16_t vector = 0; vector < IDT_MAX_DESCRIPTORS; vector++) { + + if(setup_specific_vectors(kernel_code_segment, vector)) { + continue; + } + + idt_set_gate(vector, interrupts_stub_table[vector], kernel_code_segment, 0x8E, 0); + } + + idt_load(); + + serial_printf("[IDT] IDT initialized successfully\n"); +} \ No newline at end of file diff --git a/kernel/src/interrupts/interrupt_trap.asm b/kernel/src/interrupts/interrupt_trap.asm new file mode 100644 index 0000000..3e90e3b --- /dev/null +++ b/kernel/src/interrupts/interrupt_trap.asm @@ -0,0 +1,133 @@ +section .text +extern base_trap +extern sched_reschedule +extern get_percpu + +PERCPU_NEED_RESCHED equ 40 + +common_stub: + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + mov rax, ds + push rax + + mov rax, [rsp + 19*8] + and rax, 3 + jz .kernel_entry + swapgs +.kernel_entry: + mov ax, 0x10 + mov ds, ax + mov es, ax + mov rdi, rsp + call base_trap + + pop rax + mov ds, ax + mov es, ax + + mov rax, [rsp + 18*8] + and rax, 3 + jz .kernel_resched + +.check_resched: + call get_percpu + test rax, rax + jz .do_swapgs + cmp byte [rax + PERCPU_NEED_RESCHED], 0 + je .do_swapgs + mov byte [rax + PERCPU_NEED_RESCHED], 0 + call sched_reschedule + jmp .check_resched + +.do_swapgs: + swapgs + jmp .kernel_exit + +.kernel_resched: + call get_percpu + test rax, rax + jz .kernel_check_cs + cmp byte [rax + PERCPU_NEED_RESCHED], 0 + je .kernel_check_cs + mov byte [rax + PERCPU_NEED_RESCHED], 0 + call sched_reschedule + jmp .kernel_resched + +.kernel_check_cs: + mov rax, [rsp + 18*8] + and rax, 3 + jz .kernel_exit + swapgs + jmp .kernel_exit + +.kernel_exit: + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + + add rsp, 16 + iretq + +%macro INTERRUPT_ERR_STUB 1 +interrupt_stub_%1: + push qword %1 + jmp common_stub +%endmacro + +%macro INTERRUPT_NO_ERR_STUB 1 +interrupt_stub_%1: + push qword 0 + push qword %1 + jmp common_stub +%endmacro + +%assign i 0 +%rep 32 + %if i = 8 || i = 10 || i = 11 || i = 12 || i = 13 || i = 14 || i = 17 || i = 21 || i = 29 || i = 30 + INTERRUPT_ERR_STUB i + %else + INTERRUPT_NO_ERR_STUB i + %endif + %assign i i+1 +%endrep + +%rep 224 + INTERRUPT_NO_ERR_STUB i + %assign i i+1 +%endrep + +section .data +global interrupts_stub_table +interrupts_stub_table: +%assign i 0 +%rep 256 + dq interrupt_stub_%+i + %assign i i+1 +%endrep diff --git a/kernel/src/interrupts/interrupts.c b/kernel/src/interrupts/interrupts.c new file mode 100644 index 0000000..3ebdc7c --- /dev/null +++ b/kernel/src/interrupts/interrupts.c @@ -0,0 +1,32 @@ +#include "../../include/interrupts/interrupts.h" +#include "../../include/io/serial.h" +#include "../../include/interrupts/isr.h" +#include "../../include/interrupts/irq.h" +#include "../../include/interrupts/idt.h" +#include "../../include/gdt/gdt.h" +#include "../../include/io/ports.h" + +extern const int_desc_t __start_int_handlers[]; +extern const int_desc_t __stop_int_handlers[]; + +void init_interrupt_system(void) { + asm volatile("cli"); + + setup_interrupt_descriptor_table(GDT_CODE_SEGMENT); + + setup_defined_isr_handlers(); + + setup_defined_irq_handlers(); + + asm volatile("sti"); +} + +void base_trap(void *ctx) { + struct int_frame_t *regs = (struct int_frame_t*)ctx; + + if(regs->interrupt < ISR_EXCEPTION_COUNT) { + return isr_common_handler(regs); + } + + return irq_common_handler(regs); +} \ No newline at end of file diff --git a/kernel/src/interrupts/irq/irq.c b/kernel/src/interrupts/irq/irq.c new file mode 100644 index 0000000..4a9a13e --- /dev/null +++ b/kernel/src/interrupts/irq/irq.c @@ -0,0 +1,82 @@ +#include "../../../include/interrupts/interrupts.h" +#include "../../../include/io/serial.h" +#include "../../../include/interrupts/irq.h" +#include "../../../include/interrupts/idt.h" +#include "../../../include/io/ports.h" +#include "../../../include/smp/percpu.h" +#include "../../../include/apic/apic.h" + +extern const int_desc_t __start_irq_handlers[]; +extern const int_desc_t __stop_irq_handlers[]; +static int_handler_f registered_irq_interrupts[IRQ_INTERRUPTS_COUNT]__attribute__((aligned(64))); + +void irq_common_handler(struct int_frame_t* regs) { + uint64_t vec = regs->interrupt; + + if (vec >= IRQ_INTERRUPTS_COUNT || vec < (IDT_MAX_DESCRIPTORS - IRQ_INTERRUPTS_COUNT)) { + serial_printf("IRQ vector out of range: %d\n", vec); + while (1) + { + asm volatile ("hlt"); + } + } + + if(registered_irq_interrupts[vec]) { + return registered_irq_interrupts[vec](regs); + } + + serial_printf("IRQ interrupt handler\n"); + + while (1) + { + asm volatile ("hlt"); + } +} + +void setup_defined_irq_handlers(void) { + const int_desc_t* desc; + for (desc = __start_irq_handlers; desc < __stop_irq_handlers; desc++) { + if(desc->vector >= IRQ_INTERRUPTS_COUNT) { + serial_printf("Invalid IRQ vector number! Must be < %d\n", IRQ_INTERRUPTS_COUNT); + continue; + } + registered_irq_interrupts[desc->vector] = desc->handler; + serial_printf("Registered IRQ vector 0x%d\n", desc->vector); + } +} + +extern percpu_t* percpu_regions[MAX_CPUS]; + +DEFINE_IRQ(IPI_RESCHEDULE_VECTOR, ipi_reschedule_handler) +{ + (void)frame; + + uint32_t id = lapic_get_id(); + if (id < MAX_CPUS && percpu_regions[id] != NULL) { + percpu_regions[id]->need_resched = true; + } + + lapic_eoi(); +} + +DEFINE_IRQ(IPI_TLB_SHOOTDOWN, ipi_tlb_shootdown_handler) +{ + (void)frame; + + uint32_t id = lapic_get_id(); + tlb_shootdown_t* q = &tlb_shootdown_queue[id]; + + if (q->pending) { + for (size_t i = 0; i < q->count; i++) { + uintptr_t addr = q->addresses[i]; + if (addr != 0) { + asm volatile ("invlpg (%0)" :: "r"(addr) : "memory"); + } + } + + q->pending = false; + q->count = 0; + } + + lapic_eoi(); +} \ No newline at end of file diff --git a/kernel/src/interrupts/isr/isr.c b/kernel/src/interrupts/isr/isr.c new file mode 100644 index 0000000..6a69bf3 --- /dev/null +++ b/kernel/src/interrupts/isr/isr.c @@ -0,0 +1,271 @@ +#include "../../../include/interrupts/interrupts.h" +#include "../../../include/io/serial.h" +#include "../../../include/interrupts/isr.h" +#include "../../../include/sched/sched.h" +#include "../../../include/smp/percpu.h" +#include "../../../include/apic/apic.h" +#include "../../../include/memory/vmm.h" +#include "../../../include/memory/pmm.h" +#include "../../../include/panic/panic.h" +#include + +extern const int_desc_t __start_isr_handlers[]; +extern const int_desc_t __stop_isr_handlers[]; +static int_handler_f registered_isr_interrupts[ISR_EXCEPTION_COUNT] __attribute__((aligned(64))); + +extern volatile int g_panic_owner; + +void registers_dump(struct int_frame_t *regs) { + uint64_t cr2 = 0; + asm volatile("mov %%cr2, %0" : "=r"(cr2)); + + serial_printf("\nRegisters Dump:\n"); + serial_printf("\tRAX:0x%llx\n\tRBX:0x%llx\n\tRCX:0x%llx\n\tRDX:0x%llx\n", + regs->rax, regs->rbx, regs->rcx, regs->rdx); + serial_printf("\tRSI:0x%llx\n\tRDI:0x%llx\n\tRBP:0x%llx\n\tRSP:0x%llx\n", + regs->rsi, regs->rdi, regs->rbp, regs->rsp); + serial_printf("\tRIP:0x%llx\n\tRFL:0x%llx\n\tCS:0x%llx\n\tERR:0x%llx\n", + regs->rip, regs->rflags, regs->cs, regs->error); + serial_printf("\tCR2:0x%llx\n", cr2); + serial_printf("\nInt:%d (%s)\n", regs->interrupt, exception_names[regs->interrupt]); +} + +static void dump_rip_bytes_safe(uint64_t rip) { + uintptr_t hhdm = (uintptr_t)pmm_phys_to_virt(0); + uint64_t vpage = rip & ~0xFFFULL; + uintptr_t off = rip & 0xFFF; + + if (off > PAGE_SIZE - 8) { + serial_printf("[ISR-UD] RIP=0x%llx near page boundary, skipping byte dump\n", rip); + return; + } + + uint64_t cr3_val = 0; + asm volatile("mov %%cr3, %0" : "=r"(cr3_val)); + + volatile uint64_t *pml4v = (volatile uint64_t*)(hhdm + (cr3_val & ~0xFFFULL)); + uint64_t e4 = pml4v[(vpage >> 39) & 0x1FF]; + if (!(e4 & 1)) { + serial_printf("[ISR-UD] RIP=0x%llx: PML4 not present\n", rip); + return; + } + + volatile uint64_t *pdpt = (volatile uint64_t*)(hhdm + (e4 & ~0xFFFULL)); + uint64_t e3 = pdpt[(vpage >> 30) & 0x1FF]; + if (!(e3 & 1)) { + serial_printf("[ISR-UD] RIP=0x%llx: PDPT not present\n", rip); + return; + } + + volatile uint64_t *pd = (volatile uint64_t*)(hhdm + (e3 & ~0xFFFULL)); + uint64_t e2 = pd[(vpage >> 21) & 0x1FF]; + if (!(e2 & 1)) { + serial_printf("[ISR-UD] RIP=0x%llx: PD not present\n", rip); + return; + } + + if (e2 & (1ULL << 7)) { + uintptr_t hp_phys = (e2 & ~0x1FFFFFULL) + (vpage & 0x1FFFFFULL); + volatile uint8_t *bytes = (volatile uint8_t*)(hhdm + hp_phys + off); + serial_printf("[ISR-UD] RIP=0x%llx (huge page) bytes: " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + rip, + (unsigned)bytes[0], (unsigned)bytes[1], + (unsigned)bytes[2], (unsigned)bytes[3], + (unsigned)bytes[4], (unsigned)bytes[5], + (unsigned)bytes[6], (unsigned)bytes[7]); + return; + } + + volatile uint64_t *pt = (volatile uint64_t*)(hhdm + (e2 & ~0xFFFULL)); + uint64_t pte = pt[(vpage >> 12) & 0x1FF]; + if (!(pte & 1)) { + serial_printf("[ISR-UD] RIP=0x%llx: PT not present (pte=0x%llx)\n", rip, pte); + return; + } + + uintptr_t phys_page = pte & ~0xFFFULL; + volatile uint8_t *bytes = (volatile uint8_t*)(hhdm + phys_page + off); + + serial_printf("[ISR-UD] RIP=0x%llx phys=0x%llx flags=0x%03llx bytes: " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + rip, phys_page, pte & 0xFFFULL, + (unsigned)bytes[0], (unsigned)bytes[1], + (unsigned)bytes[2], (unsigned)bytes[3], + (unsigned)bytes[4], (unsigned)bytes[5], + (unsigned)bytes[6], (unsigned)bytes[7]); + + if (off >= 16) { + volatile uint8_t *prev = (volatile uint8_t*)(hhdm + phys_page + off - 16); + serial_printf("[ISR-UD] RIP-16..RIP-1: " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + (unsigned)prev[0], (unsigned)prev[1], + (unsigned)prev[2], (unsigned)prev[3], + (unsigned)prev[4], (unsigned)prev[5], + (unsigned)prev[6], (unsigned)prev[7], + (unsigned)prev[8], (unsigned)prev[9], + (unsigned)prev[10], (unsigned)prev[11], + (unsigned)prev[12], (unsigned)prev[13], + (unsigned)prev[14], (unsigned)prev[15]); + } +} + +static void dump_user_qword_via_task(uint64_t uaddr, const char *label) { + percpu_t *pc = get_percpu(); + task_t *me = pc ? (task_t *)pc->current_task : NULL; + if (!me) { uint32_t cpu = lapic_get_id(); me = current_task[cpu]; } + if (!me || !me->pagemap) { + serial_printf("[ISR-PF] %s: no task/pagemap\n", label); + return; + } + if ((uaddr & 0x7) != 0) { + serial_printf("[ISR-PF] %s addr 0x%llx not 8-aligned\n", label, uaddr); + return; + } + uint64_t flags = 0; + if (!vmm_get_page_flags(me->pagemap, uaddr, &flags) || !(flags & 1)) { + serial_printf("[ISR-PF] %s addr 0x%llx not mapped (flags=0x%llx)\n", + label, uaddr, flags); + return; + } + uintptr_t phys = 0; + if (!vmm_virt_to_phys(me->pagemap, uaddr, &phys)) { + serial_printf("[ISR-PF] %s virt_to_phys failed for 0x%llx\n", label, uaddr); + return; + } + volatile uint64_t *p = (volatile uint64_t *)pmm_phys_to_virt(phys & ~7ULL); + uint64_t v = *p; + serial_printf("[ISR-PF] %s [0x%llx] = 0x%llx\n", label, uaddr, v); +} + +static __attribute__((noreturn)) void kill_current_task(int exit_code) { + percpu_t *pc = get_percpu(); + task_t *me = pc ? (task_t *)pc->current_task : NULL; + if (!me) { uint32_t cpu = lapic_get_id(); me = current_task[cpu]; } + if (me) me->exit_code = exit_code; + vmm_switch_pagemap(vmm_get_kernel_pagemap()); + task_exit(); +} + +void handle_intercpu_interrupt(struct int_frame_t *regs) +{ + if (regs->interrupt == 2) { + if (__atomic_load_n(&g_panic_owner, __ATOMIC_ACQUIRE) != 0) { + for (;;) asm volatile("cli; hlt"); + } + kernel_panic_regs("Non-Maskable Interrupt (hardware)", regs); + } + + serial_force_unlock(); + registers_dump(regs); + + switch (regs->interrupt) { + case EXCEPTION_DIVIDE_ERROR: + case EXCEPTION_OVERFLOW: + case EXCEPTION_BOUND_RANGE: + case EXCEPTION_INVALID_OPCODE: + case EXCEPTION_DEVICE_NOT_AVAILABLE: + case EXCEPTION_X87_FPU_ERROR: + if ((regs->cs & 3) == 3) { + if (regs->interrupt == EXCEPTION_INVALID_OPCODE) { + dump_rip_bytes_safe(regs->rip); + + serial_printf("[ISR-UD] RBP=0x%llx RSP=0x%llx\n", + regs->rbp, regs->rsp); + } + serial_printf("[ISR] %s in userspace at RIP=0x%llx — killing task\n", + exception_names[regs->interrupt], regs->rip); + kill_current_task(139); + } + kernel_panic_regs(exception_names[regs->interrupt], regs); + + case EXCEPTION_DOUBLE_FAULT: + kernel_panic_regs("Double Fault", regs); + + case EXCEPTION_INVALID_TSS: + case EXCEPTION_SEGMENT_NOT_PRESENT: + case EXCEPTION_STACK_SEGMENT_FAULT: + kernel_panic_regs(exception_names[regs->interrupt], regs); + + case EXCEPTION_GENERAL_PROTECTION_FAULT: + if ((regs->cs & 3) == 3) { + serial_printf("[ISR] GPF in userspace at RIP=0x%llx — killing task\n", + regs->rip); + kill_current_task(139); + } + kernel_panic_regs("General Protection Fault (kernel)", regs); + + case EXCEPTION_PAGE_FAULT: { + uint64_t cr2val = 0; + asm volatile("mov %%cr2, %0" : "=r"(cr2val)); + if ((regs->cs & 3) == 3) { + percpu_t *pc = get_percpu(); + task_t *me = pc ? (task_t *)pc->current_task : NULL; + if (!me) { uint32_t cpu = lapic_get_id(); me = current_task[cpu]; } + serial_printf("[ISR] Page Fault in userspace: RIP=0x%llx CR2=0x%llx ERR=0x%llx task='%s' pid=%u\n", + regs->rip, cr2val, regs->error, + me ? me->name : "?", me ? me->pid : 0); + dump_rip_bytes_safe(regs->rip); + dump_user_qword_via_task(regs->rsp, "[rsp] "); + dump_user_qword_via_task(regs->rsp + 8, "[rsp+8] "); + dump_user_qword_via_task(regs->rsp + 16, "[rsp+16] "); + dump_user_qword_via_task(regs->rsp + 24, "[rsp+24] "); + kill_current_task(139); + } + kernel_panic_regs("Page Fault (kernel)", regs); + } + + case EXCEPTION_MACHINE_CHECK: + kernel_panic_regs("Machine Check Exception", regs); + + default: { + char buf[64]; + serial_printf("UNKNOWN EXCEPTION %llu\n", regs->interrupt); + const char *pfx = "Unknown Exception #"; + int i = 0; + while (pfx[i] && i < 50) { buf[i] = pfx[i]; i++; } + uint64_t v = regs->interrupt; + if (v >= 100) buf[i++] = '0' + (int)(v / 100); + if (v >= 10) buf[i++] = '0' + (int)((v / 10) % 10); + buf[i++] = '0' + (int)(v % 10); + buf[i] = '\0'; + kernel_panic_regs(buf, regs); + } + } +} + +DEFINE_ISR(0x3, isr_breakpoint) { + (void)frame; + serial_printf("Breakpoint hit\n"); +} + +void isr_common_handler(struct int_frame_t *regs) +{ + uint64_t vec = regs->interrupt; + + if (vec >= ISR_EXCEPTION_COUNT) { + serial_printf("Invalid ISR vector %d\n", vec); + while (1) asm volatile("hlt"); + } + + if (registered_isr_interrupts[vec]) { + registered_isr_interrupts[vec](regs); + return; + } + + handle_intercpu_interrupt(regs); +} + +void setup_defined_isr_handlers(void) +{ + const int_desc_t *desc; + for (desc = __start_isr_handlers; desc < __stop_isr_handlers; desc++) { + if (desc->vector >= ISR_EXCEPTION_COUNT) { + serial_printf("ISR: vector %d out of range\n", desc->vector); + continue; + } + registered_isr_interrupts[desc->vector] = desc->handler; + serial_printf("ISR: Registered vector %d\n", desc->vector); + } +} \ No newline at end of file diff --git a/kernel/src/io/serial.c b/kernel/src/io/serial.c new file mode 100644 index 0000000..e129704 --- /dev/null +++ b/kernel/src/io/serial.c @@ -0,0 +1,826 @@ +#include +#include +#include +#include +#include +#include +#include "../../include/io/ports.h" +#include "../../include/io/serial.h" + +static volatile uint8_t serial_lock = 0; +static uint16_t default_serial_port = 0; + +void serial_initialize(uint16_t port, uint32_t baud_rate) { + outb(port + 1, 0x00); + + uint16_t divisor = 115200 / baud_rate; + outb(port + 3, 0x80); + outb(port + 0, divisor & 0xFF); + outb(port + 1, (divisor >> 8) & 0xFF); + + outb(port + 3, 0x03); + outb(port + 2, 0xC7); + outb(port + 4, 0x0B); + outb(port + 4, 0x1E); + outb(port + 0, 0xAE); + + if (inb(port + 0) != 0xAE) { + return; + } + + outb(port + 4, 0x0F); + + default_serial_port = port; +} + +uint16_t serial_get_default_port(void) { + return default_serial_port; +} + +void serial_set_default_port(uint16_t port) { + default_serial_port = port; +} + +void serial_force_unlock(void) { + __sync_lock_release(&serial_lock); + asm volatile("sti"); +} + +int serial_received_port(uint16_t port) { + return inb(port + 5) & 1; +} + +int serial_received(void) { + if (default_serial_port == 0) return 0; + return serial_received_port(default_serial_port); +} + +char serial_read_port(uint16_t port) { + while (serial_received_port(port) == 0); + return inb(port); +} + +char serial_read(void) { + if (default_serial_port == 0) return 0; + return serial_read_port(default_serial_port); +} + +int serial_is_transmit_empty_port(uint16_t port) { + return inb(port + 5) & 0x20; +} + +int serial_is_transmit_empty(void) { + if (default_serial_port == 0) return 1; + return serial_is_transmit_empty_port(default_serial_port); +} + +void serial_write_port(uint16_t port, char c) { + while (serial_is_transmit_empty_port(port) == 0); + outb(port, c); +} + +void serial_write(char c) { + if (default_serial_port == 0) return; + serial_write_port(default_serial_port, c); +} + +void serial_writestring_port(uint16_t port, const char* str) { + while (*str) { + serial_write_port(port, *str++); + } +} + +void serial_writestring(const char* str) { + if (default_serial_port == 0) return; + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + while (__sync_lock_test_and_set(&serial_lock, 1)) + __asm__ volatile("pause" ::: "memory"); + serial_writestring_port(default_serial_port, str); + __sync_lock_release(&serial_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); +} + + +void serial_writebuf(const char* buf, size_t len) { + if (default_serial_port == 0 || !buf || len == 0) return; + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + while (__sync_lock_test_and_set(&serial_lock, 1)) + __asm__ volatile("pause" ::: "memory"); + for (size_t i = 0; i < len; i++) + serial_write_port(default_serial_port, buf[i]); + __sync_lock_release(&serial_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); +} + + + +static void reverse_string(char* str, int length) { + int start = 0; + int end = length - 1; + while (start < end) { + char temp = str[start]; + str[start] = str[end]; + str[end] = temp; + start++; + end--; + } +} + +static void uint_to_str(uint64_t value, char* buffer, int base, bool uppercase) { + char* ptr = buffer; + + if (base < 2 || base > 36) { + *ptr = '\0'; + return; + } + + const char* digits = uppercase ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" : + "0123456789abcdefghijklmnopqrstuvwxyz"; + + if (value == 0) { + *ptr++ = '0'; + *ptr = '\0'; + return; + } + + while (value > 0) { + int digit = value % base; + *ptr++ = digits[digit]; + value /= base; + } + + *ptr = '\0'; + reverse_string(buffer, ptr - buffer); +} + +static void int_to_str(int64_t value, char* buffer, int base, bool uppercase) { + if (value < 0 && (base == 10 || base == 8)) { + buffer[0] = '-'; + uint_to_str(-value, buffer + 1, base, uppercase); + } else { + uint_to_str(value, buffer, base, uppercase); + } +} + +static uint64_t pow10_u64(int n) { + uint64_t r = 1; + while (n-- > 0) r *= 10; + return r; +} + +static int double_to_string(double value, char* buffer, int precision) { + if (isnan(value)) { + strcpy(buffer, "nan"); + return 3; + } + + if (isinf(value)) { + if (value < 0) { + strcpy(buffer, "-inf"); + return 4; + } else { + strcpy(buffer, "inf"); + return 3; + } + } + + if (precision < 0) precision = 6; + if (precision > 16) precision = 16; + + bool negative = (value < 0); + double abs_val = negative ? -value : value; + + uint64_t mult = pow10_u64(precision); + double scaled = abs_val * mult + 0.5; + uint64_t int_scaled = (uint64_t)scaled; + + uint64_t int_part = int_scaled / mult; + uint64_t frac_part = int_scaled % mult; + + char* ptr = buffer; + if (negative) *ptr++ = '-'; + + char int_buf[32]; + char* p = int_buf + sizeof(int_buf) - 1; + *p = '\0'; + + if (int_part == 0) { + *--p = '0'; + } else { + uint64_t n = int_part; + while (n > 0) { + *--p = '0' + (n % 10); + n /= 10; + } + } + + size_t int_len = (int_buf + sizeof(int_buf) - 1) - p; + memcpy(ptr, p, int_len); + ptr += int_len; + + if (precision > 0) { + *ptr++ = '.'; + + char frac_buf[32]; + char* f = frac_buf + sizeof(frac_buf) - 1; + *f = '\0'; + + if (frac_part == 0) { + for (int i = 0; i < precision; i++) { + *--f = '0'; + } + } else { + uint64_t n = frac_part; + int count = 0; + while (n > 0) { + *--f = '0' + (n % 10); + n /= 10; + count++; + } + while (count < precision) { + *--f = '0'; + count++; + } + } + + size_t frac_len = (frac_buf + sizeof(frac_buf) - 1) - f; + memcpy(ptr, f, frac_len); + ptr += frac_len; + } + + *ptr = '\0'; + return ptr - buffer; +} + +static int double_to_scientific(double value, char* buffer, int precision, bool uppercase) { + if (isnan(value)) { + strcpy(buffer, "nan"); + return 3; + } + + if (isinf(value)) { + if (value < 0) { + strcpy(buffer, "-inf"); + return 4; + } else { + strcpy(buffer, "inf"); + return 3; + } + } + + if (value == 0.0) { + if (precision < 0) precision = 6; + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 0; i < precision; i++) { + buffer[2 + i] = '0'; + } + buffer[2 + precision] = uppercase ? 'E' : 'e'; + buffer[3 + precision] = '+'; + buffer[4 + precision] = '0'; + buffer[5 + precision] = '0'; + buffer[6 + precision] = '\0'; + return 6 + precision; + } + + if (precision < 0) precision = 6; + if (precision > 16) precision = 16; + + double abs_val = value < 0 ? -value : value; + int exponent = 0; + + if (abs_val >= 10.0) { + while (abs_val >= 10.0) { + abs_val /= 10.0; + exponent++; + } + } else if (abs_val < 1.0 && abs_val > 0.0) { + while (abs_val < 1.0) { + abs_val *= 10.0; + exponent--; + } + } + + if (value < 0) abs_val = -abs_val; + + int len = double_to_string(abs_val, buffer, precision); + + char e_char = uppercase ? 'E' : 'e'; + buffer[len++] = e_char; + + if (exponent >= 0) { + buffer[len++] = '+'; + } else { + buffer[len++] = '-'; + exponent = -exponent; + } + + if (exponent < 10) { + buffer[len++] = '0'; + buffer[len++] = '0' + exponent; + } else { + buffer[len++] = '0' + (exponent / 10); + buffer[len++] = '0' + (exponent % 10); + } + + buffer[len] = '\0'; + return len; +} + +static int double_to_general(double value, char* buffer, int precision, bool uppercase) { + double abs_val = value < 0 ? -value : value; + + if (abs_val == 0.0) { + strcpy(buffer, "0"); + return 1; + } + + if (precision < 0) precision = 6; + if (precision == 0) precision = 1; + + bool use_scientific = (abs_val >= 1e6 || (abs_val < 1e-4 && abs_val > 0)); + + if (use_scientific) { + return double_to_scientific(value, buffer, precision - 1, uppercase); + } + + int digits_before = 0; + double temp = abs_val; + while (temp >= 1.0) { + temp /= 10.0; + digits_before++; + } + if (digits_before == 0) digits_before = 1; + + int decimal_places = precision - digits_before; + if (decimal_places < 0) decimal_places = 0; + + return double_to_string(value, buffer, decimal_places); +} + +void serial_printf_port(uint16_t port, const char* format, ...) { + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + while (__sync_lock_test_and_set(&serial_lock, 1)) { + __asm__ volatile("pause" ::: "memory"); + } + + va_list args; + va_start(args, format); + + char buffer[256]; + const char* ptr = format; + + while (*ptr) { + if (*ptr != '%') { + serial_write_port(port, *ptr); + ptr++; + continue; + } + + const char* percent_start = ptr++; + + while (*ptr == '0' || *ptr == '-' || *ptr == '+' || *ptr == ' ' || *ptr == '#') { + ptr++; + } + + int width = 0; + while (*ptr >= '0' && *ptr <= '9') { + width = width * 10 + (*ptr - '0'); + ptr++; + } + + int precision = -1; + if (*ptr == '.') { + ptr++; + precision = 0; + while (*ptr >= '0' && *ptr <= '9') { + precision = precision * 10 + (*ptr - '0'); + ptr++; + } + } + + bool has_ll = false; + bool has_l = false; + bool has_size_t = false; + + if (*ptr == 'z') { + ptr++; + has_size_t = true; + } else if (*ptr == 'l') { + ptr++; + if (*ptr == 'l') { + ptr++; + has_ll = true; + } else { + has_l = true; + } + } else if (*ptr == 'h') { + ptr++; + if (*ptr == 'h') ptr++; + } else if (*ptr == 'L' || *ptr == 'j' || *ptr == 't') { + ptr++; + } + + switch (*ptr) { + case 'c': { + char c = (char)va_arg(args, int); + serial_write_port(port, c); + break; + } + + case 's': { + const char* str = va_arg(args, const char*); + if (!str) { + str = "(null)"; + } + serial_writestring_port(port, str); + break; + } + + case 'd': + case 'i': { + int64_t num; + if (has_size_t) { + num = (int64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, int64_t); + } else if (has_l) { + num = (int64_t)va_arg(args, long); + } else { + num = (int64_t)va_arg(args, int); + } + int_to_str(num, buffer, 10, false); + serial_writestring_port(port, buffer); + break; + } + + case 'u': { + uint64_t num; + if (has_size_t) { + num = (uint64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, uint64_t); + } else if (has_l) { + num = (uint64_t)va_arg(args, unsigned long); + } else { + num = (uint64_t)va_arg(args, unsigned int); + } + uint_to_str(num, buffer, 10, false); + serial_writestring_port(port, buffer); + break; + } + + case 'x': { + uint64_t num; + if (has_size_t) { + num = (uint64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, uint64_t); + } else if (has_l) { + num = (uint64_t)va_arg(args, unsigned long); + } else { + num = (uint64_t)va_arg(args, unsigned int); + } + uint_to_str(num, buffer, 16, false); + serial_writestring_port(port, buffer); + break; + } + + case 'X': { + uint64_t num; + if (has_size_t) { + num = (uint64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, uint64_t); + } else if (has_l) { + num = (uint64_t)va_arg(args, unsigned long); + } else { + num = (uint64_t)va_arg(args, unsigned int); + } + uint_to_str(num, buffer, 16, true); + serial_writestring_port(port, buffer); + break; + } + + case 'o': { + uint64_t num; + if (has_size_t) { + num = (uint64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, uint64_t); + } else if (has_l) { + num = (uint64_t)va_arg(args, unsigned long); + } else { + num = (uint64_t)va_arg(args, unsigned int); + } + uint_to_str(num, buffer, 8, false); + serial_writestring_port(port, buffer); + break; + } + + case 'p': { + void* ptr_val = va_arg(args, void*); + serial_writestring_port(port, "0x"); + uint_to_str((uintptr_t)ptr_val, buffer, 16, false); + serial_writestring_port(port, buffer); + break; + } + + case 'f': + case 'F': { + double num = va_arg(args, double); + double_to_string(num, buffer, precision); + serial_writestring_port(port, buffer); + break; + } + + case 'e': + case 'E': { + double num = va_arg(args, double); + double_to_scientific(num, buffer, precision, (*ptr == 'E')); + serial_writestring_port(port, buffer); + break; + } + + case 'g': + case 'G': { + double num = va_arg(args, double); + double_to_general(num, buffer, precision, (*ptr == 'G')); + serial_writestring_port(port, buffer); + break; + } + + case 'a': + case 'A': { + double num = va_arg(args, double); + double_to_scientific(num, buffer, precision, (*ptr == 'A')); + buffer[0] = '0'; + buffer[1] = 'x'; + serial_writestring_port(port, buffer); + break; + } + + case 'n': { + int* count_ptr = va_arg(args, int*); + *count_ptr = 0; + break; + } + + case '%': { + serial_write_port(port, '%'); + break; + } + + default: { + for (const char* p = percent_start; p <= ptr; p++) { + serial_write_port(port, *p); + } + break; + } + } + + if (*ptr != '\0') { + ptr++; + } + } + + va_end(args); + __sync_lock_release(&serial_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); +} + +void serial_printf(const char* format, ...) { + if (default_serial_port == 0) return; + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + while (__sync_lock_test_and_set(&serial_lock, 1)) { + __asm__ volatile("pause" ::: "memory"); + } + + va_list args; + va_start(args, format); + + char buffer[256]; + const char* ptr = format; + + while (*ptr) { + if (*ptr != '%') { + serial_write_port(default_serial_port, *ptr); + ptr++; + continue; + } + + const char* percent_start = ptr++; + + while (*ptr == '0' || *ptr == '-' || *ptr == '+' || *ptr == ' ' || *ptr == '#') { + ptr++; + } + + int width = 0; + while (*ptr >= '0' && *ptr <= '9') { + width = width * 10 + (*ptr - '0'); + ptr++; + } + + int precision = -1; + if (*ptr == '.') { + ptr++; + precision = 0; + while (*ptr >= '0' && *ptr <= '9') { + precision = precision * 10 + (*ptr - '0'); + ptr++; + } + } + + bool has_ll = false; + bool has_l = false; + bool has_size_t = false; + + if (*ptr == 'z') { + ptr++; + has_size_t = true; + } else if (*ptr == 'l') { + ptr++; + if (*ptr == 'l') { + ptr++; + has_ll = true; + } else { + has_l = true; + } + } else if (*ptr == 'h') { + ptr++; + if (*ptr == 'h') ptr++; + } else if (*ptr == 'L' || *ptr == 'j' || *ptr == 't') { + ptr++; + } + + switch (*ptr) { + case 'c': { + char c = (char)va_arg(args, int); + serial_write_port(default_serial_port, c); + break; + } + + case 's': { + const char* str = va_arg(args, const char*); + if (!str) { + str = "(null)"; + } + serial_writestring_port(default_serial_port, str); + break; + } + + case 'd': + case 'i': { + int64_t num; + if (has_size_t) { + num = (int64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, int64_t); + } else if (has_l) { + num = (int64_t)va_arg(args, long); + } else { + num = (int64_t)va_arg(args, int); + } + int_to_str(num, buffer, 10, false); + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'u': { + uint64_t num; + if (has_size_t) { + num = (uint64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, uint64_t); + } else if (has_l) { + num = (uint64_t)va_arg(args, unsigned long); + } else { + num = (uint64_t)va_arg(args, unsigned int); + } + uint_to_str(num, buffer, 10, false); + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'x': { + uint64_t num; + if (has_size_t) { + num = (uint64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, uint64_t); + } else if (has_l) { + num = (uint64_t)va_arg(args, unsigned long); + } else { + num = (uint64_t)va_arg(args, unsigned int); + } + uint_to_str(num, buffer, 16, false); + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'X': { + uint64_t num; + if (has_size_t) { + num = (uint64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, uint64_t); + } else if (has_l) { + num = (uint64_t)va_arg(args, unsigned long); + } else { + num = (uint64_t)va_arg(args, unsigned int); + } + uint_to_str(num, buffer, 16, true); + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'o': { + uint64_t num; + if (has_size_t) { + num = (uint64_t)va_arg(args, size_t); + } else if (has_ll) { + num = va_arg(args, uint64_t); + } else if (has_l) { + num = (uint64_t)va_arg(args, unsigned long); + } else { + num = (uint64_t)va_arg(args, unsigned int); + } + uint_to_str(num, buffer, 8, false); + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'p': { + void* ptr_val = va_arg(args, void*); + serial_writestring_port(default_serial_port, "0x"); + uint_to_str((uintptr_t)ptr_val, buffer, 16, false); + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'f': + case 'F': { + double num = va_arg(args, double); + double_to_string(num, buffer, precision); + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'e': + case 'E': { + double num = va_arg(args, double); + double_to_scientific(num, buffer, precision, (*ptr == 'E')); + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'g': + case 'G': { + double num = va_arg(args, double); + double_to_general(num, buffer, precision, (*ptr == 'G')); + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'a': + case 'A': { + double num = va_arg(args, double); + double_to_scientific(num, buffer, precision, (*ptr == 'A')); + buffer[0] = '0'; + buffer[1] = 'x'; + serial_writestring_port(default_serial_port, buffer); + break; + } + + case 'n': { + int* count_ptr = va_arg(args, int*); + *count_ptr = 0; + break; + } + + case '%': { + serial_write_port(default_serial_port, '%'); + break; + } + + default: { + for (const char* p = percent_start; p <= ptr; p++) { + serial_write_port(default_serial_port, *p); + } + break; + } + } + + if (*ptr != '\0') { + ptr++; + } + } + + va_end(args); + __sync_lock_release(&serial_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); +} \ No newline at end of file diff --git a/kernel/src/kernel.c b/kernel/src/kernel.c new file mode 100644 index 0000000..b9989e3 --- /dev/null +++ b/kernel/src/kernel.c @@ -0,0 +1,300 @@ +#include +#include +#include +#include +#include +#include +#include +#include "../include/graphics/fb/fb.h" +#include "../include/io/serial.h" +#include "../include/gdt/gdt.h" +#include "../include/interrupts/interrupts.h" +#include "../include/interrupts/idt.h" +#include "../include/sse/fpu.h" +#include "../include/sse/sse.h" +#include "../include/memory/pmm.h" +#include "../include/memory/vmm.h" +#include "../include/memory/paging.h" +#include "../include/acpi/acpi.h" +#include "../include/apic/apic.h" +#include "../include/io/ports.h" +#include "../include/drivers/timer.h" +#include "../include/smp/smp.h" +#include "../include/smp/percpu.h" +#include "../include/sched/sched.h" +#include "../include/elf/elf.h" +#include "../include/syscall/syscall.h" +#include "../include/drivers/ps2.h" +#include "../include/fs/vfs.h" +#include "../include/fs/ramfs.h" +#include "../include/fs/devfs.h" +#include "../include/fs/initramfs.h" +#include "../include/drivers/ata.h" +#include "../include/drivers/blkdev.h" +#include "../include/drivers/disk.h" +#include "../include/drivers/partition.h" +#include "../include/fs/ext2.h" +#include "../include/fs/fat32.h" + +__attribute__((used, section(".limine_requests"))) +static volatile uint64_t limine_base_revision[] = LIMINE_BASE_REVISION(4); + +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_framebuffer_request framebuffer_request = { + .id = LIMINE_FRAMEBUFFER_REQUEST_ID, + .revision = 0 +}; + +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_memmap_request memmap_request = { + .id = LIMINE_MEMMAP_REQUEST_ID, + .revision = 0 +}; + +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_mp_request mp_request = { + .id = LIMINE_MP_REQUEST_ID, + .revision = 0, + .flags = 0 +}; + +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_hhdm_request hhdm_request = { + .id = LIMINE_HHDM_REQUEST_ID, + .revision = 0 +}; + +__attribute__((used, section(".limine_requests"))) +volatile struct limine_rsdp_request rsdp_request = { + .id = LIMINE_RSDP_REQUEST_ID, + .revision = 0, + .response = NULL +}; + +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_module_request module_request = { + .id = LIMINE_MODULE_REQUEST_ID, + .revision = 0 +}; + +__attribute__((used, section(".limine_requests_start"))) +static volatile uint64_t limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER; + +__attribute__((used, section(".limine_requests_end"))) +static volatile uint64_t limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER; + +struct limine_framebuffer *global_framebuffer = NULL; + +static void hcf(void) { + for (;;) { + asm ("hlt"); + } +} + +static void load_elf_module(void) { + if (!module_request.response) { + serial_writestring("[ELF] No module response from Limine\n"); + return; + } + if (module_request.response->module_count == 0) { + serial_writestring("[ELF] No modules provided\n"); + return; + } + + struct limine_file *mod = module_request.response->modules[0]; + serial_printf("[ELF] Module: path='%s' size=%llu addr=%p\n", mod->path, mod->size, mod->address); + + elf_load_result_t r = elf_load(mod->address, (size_t)mod->size, 0); + if (r.error != ELF_OK) { + serial_printf("[ELF] LOAD FAILED: %s\n", elf_strerror(r.error)); + return; + } + + serial_printf("[ELF] Load OK! entry=0x%llx stack_top=0x%llx\n", r.entry, r.stack_top); + + uint64_t cr3 = (uint64_t)pmm_virt_to_phys(r.pagemap->pml4); + + task_t *t = task_create_user("init", r.entry, r.stack_top, cr3, 16, r.pagemap, 0, 0); + + if (!t) { + serial_writestring("[ELF] task_create_user failed\n"); + elf_unload(&r); + return; + } + + t->brk_start = r.load_end; + t->brk_current = r.load_end; + + int sr = vfs_init_stdio(t); + if (sr < 0) + serial_printf("[VFS] vfs_init_stdio failed: %d\n", sr); + else + serial_writestring("[VFS] stdio assigned to task\n"); + + serial_printf("[ELF] Task 'init' created: cr3=0x%llx\n", t->cr3); +} + +void ps2_task(void* arg) { + (void)arg; + asm volatile ("sti"); + ps2_init(); +} + +static bool detect_installed_system(void) { + blkdev_t *hda2 = blkdev_get_by_name("hda2"); + if (hda2) { + uint16_t magic = 0; + if (blkdev_read(hda2, EXT2_SUPER_OFFSET + 56, &magic, sizeof(magic)) == 0 + && magic == EXT2_SUPER_MAGIC) { + serial_writestring("[boot] ext2 on hda2 -> installed system\n"); + return true; + } + } + + blkdev_t *hda1 = blkdev_get_by_name("hda1"); + if (hda1) { + uint8_t sector[512]; + if (hda1->ops->read_sectors(hda1, 0, 1, sector) == 0) { + if (sector[510] == 0x55 && sector[511] == (uint8_t)0xAA + && memcmp(sector + 82, "FAT32", 5) == 0) { + serial_writestring("[boot] FAT32 on hda1 -> looks like installed system\n"); + return true; + } + } + } + + blkdev_t *hda = blkdev_get_by_name("hda"); + if (hda) { + uint16_t magic = 0; + if (blkdev_read(hda, EXT2_SUPER_OFFSET + 56, &magic, sizeof(magic)) == 0 + && magic == EXT2_SUPER_MAGIC) { + serial_writestring("[boot] legacy ext2-on-whole-disk detected\n"); + return true; + } + } + return false; +} + +void kernel_main(void) { + serial_initialize(COM1, 115200); + serial_writestring("\n=== SERIAL PORT INITIALIZED ===\n"); + + if (LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) { + serial_writestring("ERROR: Unsupported Limine base revision\n"); + hcf(); + } + + gdt_init(); + init_interrupt_system(); + serial_writestring("GDT&IDT [OK]\n"); + fpu_init(); + sse_init(); + enable_fsgsbase(); + serial_writestring("FPU/SSE/FSGSBASE [OK]\n"); + + if (!framebuffer_request.response || + framebuffer_request.response->framebuffer_count < 1) { + serial_writestring("ERROR: No framebuffer available\n"); + hcf(); + } + if (!memmap_request.response) { + serial_writestring("ERROR: No memory map available\n"); + hcf(); + } + if (!hhdm_request.response) { + serial_writestring("ERROR: No HHDM available\n"); + hcf(); + } + + global_framebuffer = framebuffer_request.response->framebuffers[0]; + + pmm_init(memmap_request.response, hhdm_request.response); + slab_init(); + serial_writestring("PMM [OK]\n"); + paging_init(); + serial_writestring("Paging [OK]\n"); + vmm_init(); + serial_writestring("VMM [OK]\n"); + vfs_init(); + serial_writestring("VFS [OK]\n"); + + vnode_t *rootfs = ramfs_create_root(); + vfs_mount("/", rootfs); + vfs_set_mount_info("/", "ramfs", "ramfs"); + vnode_unref(rootfs); + serial_writestring("rootfs [OK]\n"); + + vfs_mkdir("/dev", 0755); + vfs_mkdir("/bin", 0755); + vfs_mkdir("/etc", 0755); + vfs_mkdir("/tmp", 0755); + vfs_mkdir("/proc", 0755); + vfs_mkdir("/mnt", 0755); + + vnode_t *devroot = devfs_create_root(); + vfs_mount("/dev", devroot); + vfs_set_mount_info("/dev", "devfs", "devfs"); + serial_writestring("devfs [OK]\n"); + acpi_init(); + acpi_print_tables(); + serial_writestring("ACPI [OK]\n"); + apic_init(); + serial_writestring("APIC [OK]\n"); + clear_screen(); + smp_init(mp_request.response); + serial_writestring("SMP [OK]\n"); + + serial_writestring("Waiting until all APs are fully ready...\n"); + while (smp_get_online_count() < (smp_get_cpu_count() - 1)) { + timer_sleep_ms(100); + } + serial_writestring("All APs ready.\n"); + + printf("Kernel initialized successfully!\n\n"); + printf("Framebuffer: %dx%d, %d bpp\n", global_framebuffer->width, global_framebuffer->height, global_framebuffer->bpp); + printf("\nMemory Information:\n"); + printf("HHDM offset: 0x%llx\n", hhdm_request.response->offset); + printf("Memory map entries: %llu\n", memmap_request.response->entry_count); + pmm_print_stats(); + + smp_print_info_fb(); + printf("\nSystem: %u CPU cores detected\n\n", smp_get_cpu_count()); + syscall_init(); + + disk_init(); + serial_writestring("Disk subsystem [OK]\n"); + + bool skip_initramfs = detect_installed_system(); + if (skip_initramfs) { + printf("[boot] installed Cervus detected on disk -- booting from disk\n"); + } else { + serial_writestring("[boot] no installed system detected, using initramfs\n"); + } + + if (!skip_initramfs && module_request.response && + module_request.response->module_count >= 2) { + struct limine_file *tar = module_request.response->modules[1]; + serial_printf("[initramfs] module: '%s' size=%llu\n", tar->path, tar->size); + int r = initramfs_mount(tar->address, (size_t)tar->size); + if (r == 0) + serial_writestring("[initramfs] mounted OK\n"); + else + serial_printf("[initramfs] mount FAILED: %d\n", r); + } else if (!skip_initramfs) { + serial_writestring("[initramfs] no TAR module (modules[1] missing)\n"); + } + + timer_init(); + sched_init(); + sched_notify_ready(); + timer_sleep_ms(10); + clear_screen(); + load_elf_module(); + task_create("PS/2", ps2_task, NULL, 10); + serial_writestring("Manually triggering first reschedule...\n"); + sched_reschedule(); + + while (1) { + hcf(); + } +} \ No newline at end of file diff --git a/kernel/src/memory/paging.c b/kernel/src/memory/paging.c new file mode 100644 index 0000000..0d78fbb --- /dev/null +++ b/kernel/src/memory/paging.c @@ -0,0 +1,320 @@ +#include "../../include/memory/paging.h" +#include "../../include/memory/pmm.h" +#include "../../include/io/serial.h" +#include +#include + +#define MAX_REGIONS 256 +#define MAX_RESERVED 64 +#define DEFAULT_ALLOC_BASE 0xFFFFFE0000000000ULL + +static paging_region_t regions[MAX_REGIONS]; +static size_t region_count = 0; + +static struct { + uintptr_t start; + uintptr_t end; +} reserved_ranges[MAX_RESERVED]; +static size_t reserved_count = 0; + +static uintptr_t next_alloc_virt = DEFAULT_ALLOC_BASE; + +static inline uintptr_t align_up(uintptr_t addr, size_t alignment) { + return (addr + alignment - 1) & ~(alignment - 1); +} + +static inline bool is_aligned(uintptr_t addr, size_t alignment) { + return (addr & (alignment - 1)) == 0; +} + +static inline bool ranges_overlap(uintptr_t s1, uintptr_t e1, uintptr_t s2, uintptr_t e2) { + return s1 < e2 && s2 < e1; +} + +void paging_init(void) { + memset(regions, 0, sizeof(regions)); + memset(reserved_ranges, 0, sizeof(reserved_ranges)); + region_count = 0; + reserved_count = 0; + next_alloc_virt = DEFAULT_ALLOC_BASE; + + paging_reserve_range(vmm_get_kernel_pagemap(), + 0xFFFFFFFF80000000ULL, + 0xFFFFFFFFC0000000ULL); + + serial_printf("Paging: subsystem initialized\n"); +} + +bool paging_reserve_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t virt_end) { + (void)pagemap; + + if (reserved_count >= MAX_RESERVED) { + serial_printf("PAGING ERROR: too many reserved ranges\n"); + return false; + } + + if (virt_start >= virt_end) { + serial_printf("PAGING ERROR: invalid reserved range\n"); + return false; + } + + for (size_t i = 0; i < reserved_count; i++) { + if (ranges_overlap(virt_start, virt_end, + reserved_ranges[i].start, + reserved_ranges[i].end)) { + serial_printf("PAGING ERROR: reserved range overlaps\n"); + return false; + } + } + + reserved_ranges[reserved_count].start = virt_start; + reserved_ranges[reserved_count].end = virt_end; + reserved_count++; + + serial_printf("Paging: reserved range 0x%llx-0x%llx\n", virt_start, virt_end); + return true; +} + +static bool is_range_reserved(uintptr_t start, uintptr_t end) { + for (size_t i = 0; i < reserved_count; i++) { + if (ranges_overlap(start, end, reserved_ranges[i].start, reserved_ranges[i].end)) + return true; + } + return false; +} + +bool paging_is_range_free(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t virt_end) { + if (is_range_reserved(virt_start, virt_end)) + return false; + + for (uintptr_t virt = virt_start; virt < virt_end; virt += PAGE_SIZE) { + uintptr_t phys; + if (vmm_virt_to_phys(pagemap, virt, &phys)) + return false; + } + return true; +} + +bool paging_map_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, + uintptr_t phys_start, size_t page_count, uint64_t flags) { + if (!pagemap || page_count == 0) + return false; + + if (!is_aligned(virt_start, PAGE_SIZE) || !is_aligned(phys_start, PAGE_SIZE)) { + serial_printf("PAGING ERROR: unaligned addresses\n"); + return false; + } + + uintptr_t virt_end = virt_start + page_count * PAGE_SIZE; + if (is_range_reserved(virt_start, virt_end)) { + serial_printf("PAGING ERROR: range overlaps reserved area\n"); + return false; + } + + for (size_t i = 0; i < page_count; i++) { + uintptr_t virt = virt_start + i * PAGE_SIZE; + uintptr_t phys = phys_start + i * PAGE_SIZE; + + uintptr_t existing_phys; + if (vmm_virt_to_phys(pagemap, virt, &existing_phys)) { + if (existing_phys != phys) { + serial_printf("PAGING ERROR: page at 0x%llx already mapped to 0x%llx\n", + virt, existing_phys); + return false; + } + uint64_t existing_flags; + if (vmm_get_page_flags(pagemap, virt, &existing_flags)) { + if (existing_flags != (flags & 0xFFF)) { + vmm_unmap_page(pagemap, virt); + vmm_map_page(pagemap, virt, phys, flags); + } + } + } else { + if (!vmm_map_page(pagemap, virt, phys, flags)) { + serial_printf("PAGING ERROR: failed to map 0x%llx -> 0x%llx\n", virt, phys); + for (size_t j = 0; j < i; j++) + vmm_unmap_page(pagemap, virt_start + j * PAGE_SIZE); + return false; + } + } + } + return true; +} + +bool paging_unmap_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, size_t page_count) { + if (!pagemap || page_count == 0) + return false; + + for (size_t i = 0; i < page_count; i++) + vmm_unmap_page(pagemap, virt_start + i * PAGE_SIZE); + + return true; +} + +bool paging_change_flags(vmm_pagemap_t* pagemap, uintptr_t virt_start, + size_t page_count, uint64_t new_flags) { + if (!pagemap || page_count == 0) + return false; + + if (!is_aligned(virt_start, PAGE_SIZE)) { + serial_printf("PAGING ERROR: unaligned address 0x%llx\n", virt_start); + return false; + } + + for (size_t i = 0; i < page_count; i++) { + uintptr_t virt = virt_start + i * PAGE_SIZE; + uintptr_t phys; + + if (!vmm_virt_to_phys(pagemap, virt, &phys)) { + serial_printf("PAGING ERROR: page at 0x%llx not mapped\n", virt); + return false; + } + + vmm_unmap_page(pagemap, virt); + if (!vmm_map_page(pagemap, virt, phys, new_flags)) { + serial_printf("PAGING ERROR: failed to remap 0x%llx\n", virt); + return false; + } + } + return true; +} + +paging_region_t* paging_create_region(vmm_pagemap_t* pagemap, + uintptr_t virt_start, size_t size, + uint64_t flags) { + if (region_count >= MAX_REGIONS) { + serial_printf("PAGING ERROR: too many regions\n"); + return NULL; + } + + size_t page_count = align_up(size, PAGE_SIZE) / PAGE_SIZE; + uintptr_t virt_end = virt_start + page_count * PAGE_SIZE; + + if (!paging_is_range_free(pagemap, virt_start, virt_end)) { + serial_printf("PAGING ERROR: region overlaps existing mapping\n"); + return NULL; + } + + void* phys_mem = pmm_alloc_zero(page_count); + if (!phys_mem) { + serial_printf("PAGING ERROR: out of physical memory\n"); + return NULL; + } + + uintptr_t phys_start = pmm_virt_to_phys(phys_mem); + if (!paging_map_range(pagemap, virt_start, phys_start, page_count, flags)) { + pmm_free(phys_mem, page_count); + serial_printf("PAGING ERROR: failed to map region\n"); + return NULL; + } + + paging_region_t* region = ®ions[region_count++]; + region->virtual_start = virt_start; + region->virtual_end = virt_end; + region->physical_start = phys_start; + region->flags = flags; + region->page_count = page_count; + region->allocated = true; + + serial_printf("Paging: created region 0x%llx-0x%llx (%zu pages)\n", + virt_start, virt_end, page_count); + return region; +} + +bool paging_destroy_region(vmm_pagemap_t* pagemap, paging_region_t* region) { + if (!pagemap || !region || !region->allocated) + return false; + + paging_unmap_range(pagemap, region->virtual_start, region->page_count); + void* phys_virt = pmm_phys_to_virt(region->physical_start); + pmm_free(phys_virt, region->page_count); + memset(region, 0, sizeof(paging_region_t)); + return true; +} + +void* paging_alloc_pages(vmm_pagemap_t* pagemap, size_t page_count, + uint64_t flags, uintptr_t preferred_virt) { + if (!pagemap || page_count == 0) + return NULL; + + uintptr_t virt_start; + if (preferred_virt != 0) { + virt_start = align_up(preferred_virt, PAGE_SIZE); + if (!paging_is_range_free(pagemap, virt_start, virt_start + page_count * PAGE_SIZE)) + return NULL; + } else { + virt_start = next_alloc_virt; + while (!paging_is_range_free(pagemap, virt_start, virt_start + page_count * PAGE_SIZE)) + virt_start += PAGE_SIZE; + next_alloc_virt = virt_start + page_count * PAGE_SIZE; + } + + void* phys_mem = pmm_alloc_zero(page_count); + if (!phys_mem) + return NULL; + + uintptr_t phys_start = pmm_virt_to_phys(phys_mem); + if (!paging_map_range(pagemap, virt_start, phys_start, page_count, flags)) { + pmm_free(phys_mem, page_count); + return NULL; + } + + serial_printf("Paging: allocated %zu pages at virt 0x%llx\n", page_count, virt_start); + return (void*)virt_start; +} + +void paging_free_pages(vmm_pagemap_t* pagemap, void* virt_addr, size_t page_count) { + if (!pagemap || !virt_addr || page_count == 0) + return; + + uintptr_t virt_start = (uintptr_t)virt_addr; + paging_unmap_range(pagemap, virt_start, page_count); + serial_printf("Paging: freed %zu pages at virt 0x%llx\n", page_count, virt_start); +} + +void paging_print_stats(vmm_pagemap_t* pagemap) { + (void)pagemap; + + serial_printf("\n=== Paging Statistics ===\n"); + serial_printf("Regions: %zu, Reserved: %zu\n", region_count, reserved_count); + + size_t active = 0, total_pages = 0, total_bytes = 0; + for (size_t i = 0; i < region_count; i++) { + if (regions[i].allocated) { + active++; + total_pages += regions[i].page_count; + total_bytes += regions[i].page_count * PAGE_SIZE; + } + } + + serial_printf("Active regions: %zu\n", active); + serial_printf("Total pages: %zu (%zu KiB)\n", total_pages, total_bytes / 1024); + serial_printf("Next alloc: 0x%llx\n", next_alloc_virt); + + serial_printf("\nReserved ranges:\n"); + for (size_t i = 0; i < reserved_count; i++) { + serial_printf(" 0x%llx - 0x%llx\n", + reserved_ranges[i].start, reserved_ranges[i].end); + } +} + +void paging_dump_range(vmm_pagemap_t* pagemap, uintptr_t virt_start, uintptr_t virt_end) { + serial_printf("\n=== Page Table Dump (0x%llx - 0x%llx) ===\n", virt_start, virt_end); + + size_t mapped = 0, total = 0; + for (uintptr_t virt = virt_start; virt < virt_end; virt += PAGE_SIZE) { + total++; + uintptr_t phys; + uint64_t flags; + if (vmm_virt_to_phys(pagemap, virt, &phys) && vmm_get_page_flags(pagemap, virt, &flags)) { + mapped++; + serial_printf("0x%llx -> 0x%llx [", virt, phys); + if (flags & PAGING_PRESENT) serial_printf("P"); + if (flags & PAGING_WRITE) serial_printf("W"); + if (flags & PAGING_USER) serial_printf("U"); + if (flags & PAGING_NOEXEC) serial_printf("NX"); + serial_printf("]\n"); + } + } + serial_printf("Mapped: %zu/%zu pages (%zu%%)\n", mapped, total, total ? mapped * 100 / total : 0); +} \ No newline at end of file diff --git a/kernel/src/memory/pmm.c b/kernel/src/memory/pmm.c new file mode 100644 index 0000000..ca63675 --- /dev/null +++ b/kernel/src/memory/pmm.c @@ -0,0 +1,614 @@ +#include "../../include/memory/pmm.h" +#include "../../include/io/serial.h" +#include "../../include/sched/spinlock.h" +#include +#include + +static pmm_buddy_state_t g_buddy; +static spinlock_t g_pmm_lock = SPINLOCK_INIT; + +static inline uintptr_t _align_up(uintptr_t v, uintptr_t a) { + return (v + a - 1) & ~(a - 1); +} + +static inline int _pages_to_order(size_t pages) { + int order = 0; + size_t cap = 1; + while (cap < pages) { cap <<= 1; order++; } + return (order > PMM_MAX_ORDER) ? -1 : order; +} + +static inline uintptr_t _block_phys(pmm_block_t *b) { + return (uintptr_t)b - g_buddy.hhdm_offset; +} + +static inline pmm_block_t *_phys_to_block(uintptr_t phys) { + return (pmm_block_t *)(phys + g_buddy.hhdm_offset); +} + +static inline void _fl_init(pmm_free_list_t *fl) { + fl->head.next = fl->head.prev = &fl->head; + fl->head.order = -1; + fl->count = 0; +} + +static inline void _fl_push(pmm_free_list_t *fl, pmm_block_t *b, int order) { + b->order = order; + b->next = fl->head.next; + b->prev = &fl->head; + fl->head.next->prev = b; + fl->head.next = b; + fl->count++; +} + +static inline void _fl_del(pmm_free_list_t *fl, pmm_block_t *b) { + b->prev->next = b->next; + b->next->prev = b->prev; + b->next = b->prev = NULL; + b->order = -1; + fl->count--; +} + +static inline pmm_block_t *_fl_first(pmm_free_list_t *fl) { + return (fl->head.next == &fl->head) ? NULL : fl->head.next; +} + +static inline int _block_ptr_valid(pmm_free_list_t *fl, pmm_block_t *b) { + uintptr_t p = (uintptr_t)b; + if (p == (uintptr_t)&fl->head) return 1; + if (p < g_buddy.hhdm_offset) return 0; + uintptr_t phys = p - g_buddy.hhdm_offset; + if (phys < g_buddy.mem_start || phys >= g_buddy.mem_end) return 0; + if (phys & 0xFFFULL) return 0; + return 1; +} + +static pmm_block_t *_fl_find(pmm_free_list_t *fl, uintptr_t phys) { + size_t limit = g_buddy.total_pages + 16; + pmm_block_t *b = fl->head.next; + while (b != &fl->head) { + if (!_block_ptr_valid(fl, b)) { + serial_printf("[PMM_FREELIST_CORRUPT] bad ptr=%p in freelist walk\n", (void*)b); + return NULL; + } + if (_block_phys(b) == phys) return b; + pmm_block_t *next = b->next; + if (!_block_ptr_valid(fl, next)) { + serial_printf("[PMM_FREELIST_CORRUPT] bad next=%p at block=%p (phys=0x%llx)\n", + (void*)next, (void*)b, + (unsigned long long)_block_phys(b)); + return NULL; + } + b = next; + if (limit-- == 0) return NULL; + } + return NULL; +} + +static uintptr_t _buddy_alloc_order(int order) { + int found = -1; + for (int o = order; o <= PMM_MAX_ORDER; o++) + if (_fl_first(&g_buddy.orders[o])) { found = o; break; } + if (found < 0) return 0; + + pmm_block_t *b = _fl_first(&g_buddy.orders[found]); + _fl_del(&g_buddy.orders[found], b); + uintptr_t phys = _block_phys(b); + + while (found > order) { + found--; + uintptr_t buddy_phys = phys + ((uintptr_t)PAGE_SIZE << found); + _fl_push(&g_buddy.orders[found], _phys_to_block(buddy_phys), found); + } + + g_buddy.free_pages -= (size_t)1 << order; + return phys; +} + +static void _buddy_free_order(uintptr_t phys, int order) { + if (phys < PMM_FREE_MIN_PHYS) return; + while (order < PMM_MAX_ORDER) { + uintptr_t buddy_phys = phys ^ ((uintptr_t)PAGE_SIZE << order); + + if (buddy_phys < PMM_FREE_MIN_PHYS) break; + if (buddy_phys < g_buddy.mem_start || buddy_phys >= g_buddy.mem_end) + break; + + pmm_block_t *buddy_b = _fl_find(&g_buddy.orders[order], buddy_phys); + if (!buddy_b) break; + + if (buddy_b->order != order) break; + + _fl_del(&g_buddy.orders[order], buddy_b); + if (buddy_phys < phys) phys = buddy_phys; + order++; + } + _fl_push(&g_buddy.orders[order], _phys_to_block(phys), order); + g_buddy.free_pages += (size_t)1 << order; +} + +static void _buddy_free_nocoalesce(uintptr_t phys) { + _fl_push(&g_buddy.orders[0], _phys_to_block(phys), 0); + g_buddy.free_pages += 1; +} + +void pmm_init(struct limine_memmap_response *memmap, + struct limine_hhdm_response *hhdm) { + g_buddy.hhdm_offset = hhdm->offset; + g_buddy.free_pages = 0; + + uintptr_t max_phys = 0; + size_t usable_pages = 0; + for (uint64_t i = 0; i < memmap->entry_count; i++) { + struct limine_memmap_entry *e = memmap->entries[i]; + if (e->type == LIMINE_MEMMAP_USABLE) { + uintptr_t end = e->base + e->length; + if (end > max_phys) max_phys = end; + usable_pages += e->length / PAGE_SIZE; + } + } + max_phys = _align_up(max_phys, PAGE_SIZE); + + g_buddy.mem_start = 0; + g_buddy.mem_end = max_phys; + g_buddy.total_pages = max_phys >> PAGE_SHIFT; + g_buddy.usable_pages = usable_pages; + + for (int o = 0; o < PMM_MAX_ORDER_NR; o++) _fl_init(&g_buddy.orders[o]); + + for (uint64_t i = 0; i < memmap->entry_count; i++) { + struct limine_memmap_entry *e = memmap->entries[i]; + if (e->type != LIMINE_MEMMAP_USABLE) continue; + + uintptr_t base = _align_up(e->base, PAGE_SIZE); + uintptr_t end = (e->base + e->length) & ~(PAGE_SIZE - 1); + + if (base < PMM_FREE_MIN_PHYS) { + base = PMM_FREE_MIN_PHYS; + if (base >= end) continue; + } + + while (base < end) { + size_t rem = (end - base) >> PAGE_SHIFT; + int order = PMM_MAX_ORDER; + while (order > 0) { + size_t bpages = (size_t)1 << order; + if ((base & (bpages * PAGE_SIZE - 1)) == 0 && rem >= bpages) + break; + order--; + } + _fl_push(&g_buddy.orders[order], _phys_to_block(base), order); + g_buddy.free_pages += (size_t)1 << order; + base += (uintptr_t)(PAGE_SIZE << order); + } + } + + serial_printf("[PMM] buddy init: total=%zu free=%zu\n", + g_buddy.total_pages, g_buddy.free_pages); +} + +static volatile uint64_t g_pmm_alloc_count = 0; +static volatile uint64_t g_pmm_free_count = 0; + +void *pmm_alloc(size_t pages) { + if (!pages) return NULL; + int order = _pages_to_order(pages); + if (order < 0) return NULL; + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + spinlock_acquire(&g_pmm_lock); + uintptr_t phys = _buddy_alloc_order(order); + size_t free_after = g_buddy.free_pages; + spinlock_release(&g_pmm_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); + if (phys) { + if (phys < PMM_FREE_MIN_PHYS) { + serial_printf("[PMM_BUG] alloc returned low phys=0x%llx — discarding (should not happen after pmm_init fix)\n", + (unsigned long long)phys); + phys = 0; + } else { + __atomic_fetch_add(&g_pmm_alloc_count, (size_t)1 << order, __ATOMIC_RELAXED); + } + } + if (!phys) { + serial_printf("[PMM_OOM] alloc FAILED pages=%zu order=%d free=%zu allocs=%llu frees=%llu\n", + pages, order, free_after, + (unsigned long long)g_pmm_alloc_count, + (unsigned long long)g_pmm_free_count); + } + return phys ? (void *)(phys + g_buddy.hhdm_offset) : NULL; +} + +void *pmm_alloc_zero(size_t pages) { + if (!pages) return NULL; + int order = _pages_to_order(pages); + if (order < 0) return NULL; + void *p = pmm_alloc(pages); + if (p) memset(p, 0, pages * PAGE_SIZE); + return p; +} + +void *pmm_alloc_aligned(size_t pages, size_t alignment) { + if (!pages) return NULL; + if (alignment < PAGE_SIZE) alignment = PAGE_SIZE; + + if (alignment & (alignment - 1)) { + size_t a = 1; + while (a < alignment) a <<= 1; + alignment = a; + } + + size_t align_pages = alignment / PAGE_SIZE; + size_t req = pages > align_pages ? pages : align_pages; + int order = _pages_to_order(req); + if (order < 0) return NULL; + + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + spinlock_acquire(&g_pmm_lock); + uintptr_t phys = _buddy_alloc_order(order); + if (!phys) { spinlock_release(&g_pmm_lock); asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); return NULL; } + + if (phys & (alignment - 1)) { + _buddy_free_order(phys, order); + spinlock_release(&g_pmm_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); + return NULL; + } + spinlock_release(&g_pmm_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); + + return (void *)(phys + g_buddy.hhdm_offset); +} + +void pmm_free(void *addr, size_t pages) { + if (!addr || !pages) return; + uintptr_t phys = (uintptr_t)addr - g_buddy.hhdm_offset; + if (phys < g_buddy.mem_start || phys >= g_buddy.mem_end) { + serial_printf("[PMM_FREE_BUG] out-of-range addr=%p phys=0x%llx pages=%zu\n", + addr, (unsigned long long)phys, pages); + return; + } + if (phys < 0x100000ULL) { + serial_printf("[PMM_FREE_BUG] low-phys addr=%p phys=0x%llx pages=%zu\n", + addr, (unsigned long long)phys, pages); + return; + } + int order = _pages_to_order(pages); + if (order < 0) { serial_printf("[PMM_FREE] bad order pages=%zu\n", pages); return; } + + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + spinlock_acquire(&g_pmm_lock); + + pmm_block_t *existing = _fl_find(&g_buddy.orders[order], phys); + if (existing) { + serial_printf("[PMM_DOUBLE_FREE] addr=%p phys=0x%llx pages=%zu order=%d ALREADY FREE!\n", + addr, (unsigned long long)phys, pages, order); + spinlock_release(&g_pmm_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); + return; + } + + size_t free_before = g_buddy.free_pages; + memset(addr, 0, 64); + _buddy_free_order(phys, order); + size_t free_after = g_buddy.free_pages; + __atomic_fetch_add(&g_pmm_free_count, (size_t)1 << order, __ATOMIC_RELAXED); + + if (free_after <= free_before) { + serial_printf("[PMM_FREE_BUG] free_pages didn't grow: before=%zu after=%zu phys=0x%llx\n", + free_before, free_after, (unsigned long long)phys); + } + + spinlock_release(&g_pmm_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); +} + +void pmm_free_single(void *addr) { + if (!addr) return; + uintptr_t phys = (uintptr_t)addr - g_buddy.hhdm_offset; + if (phys < g_buddy.mem_start || phys >= g_buddy.mem_end) return; + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + spinlock_acquire(&g_pmm_lock); + _buddy_free_nocoalesce(phys); + spinlock_release(&g_pmm_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); +} + +void *pmm_phys_to_virt(uintptr_t phys) { return (void *)(phys + g_buddy.hhdm_offset); } +uintptr_t pmm_virt_to_phys(void *vaddr) { return (uintptr_t)vaddr - g_buddy.hhdm_offset; } +uint64_t pmm_get_hhdm_offset(void) { return g_buddy.hhdm_offset; } +size_t pmm_get_total_pages(void) { return g_buddy.total_pages; } +size_t pmm_get_usable_pages(void) { return g_buddy.usable_pages; } +size_t pmm_get_free_pages(void) { return g_buddy.free_pages; } +size_t pmm_get_used_pages(void) { return g_buddy.usable_pages > g_buddy.free_pages + ? g_buddy.usable_pages - g_buddy.free_pages : 0; } + +static void _print_size(size_t bytes, const char *label) { + uint64_t v = (uint64_t)bytes; + const char *unit; + uint64_t whole, frac; + + if (v >= 1024ULL * 1024 * 1024) { + whole = v / (1024ULL * 1024 * 1024); + frac = (v % (1024ULL * 1024 * 1024)) * 100 / (1024ULL * 1024 * 1024); + unit = "GiB"; + } else if (v >= 1024ULL * 1024) { + whole = v / (1024ULL * 1024); + frac = (v % (1024ULL * 1024)) * 100 / (1024ULL * 1024); + unit = "MiB"; + } else if (v >= 1024ULL) { + whole = v / 1024; + frac = (v % 1024) * 100 / 1024; + unit = "KiB"; + } else { + whole = v; frac = 0; unit = "B"; + } + printf(" %-16s %llu.%02llu %s\n", label, + (unsigned long long)whole, (unsigned long long)frac, unit); + serial_printf(" %-16s %llu.%02llu %s\n", label, + (unsigned long long)whole, (unsigned long long)frac, unit); +} + +void pmm_print_stats(void) { + size_t usable_bytes = g_buddy.usable_pages * PAGE_SIZE; + size_t free_bytes = g_buddy.free_pages * PAGE_SIZE; + size_t total_bytes = g_buddy.total_pages * PAGE_SIZE; + size_t used_bytes = usable_bytes > free_bytes ? usable_bytes - free_bytes : 0; + size_t reserved = total_bytes > usable_bytes ? total_bytes - usable_bytes : 0; + + serial_printf("\n=== Physical Memory ===\n"); + printf("\n=== Physical Memory ===\n"); + _print_size(usable_bytes, "Usable RAM:"); + _print_size(free_bytes, "Free RAM:"); + _print_size(used_bytes, "Used (kernel):"); + _print_size(reserved, "Reserved/MMIO:"); + serial_printf(" %-16s %u bytes\n", "Page size:", (unsigned)PAGE_SIZE); + printf(" %-16s %u bytes\n", "Page size:", (unsigned)PAGE_SIZE); + serial_printf("=======================\n"); + printf("=======================\n"); + + serial_printf("[PMM] buddy free-list:\n"); + for (int o = 0; o < PMM_MAX_ORDER_NR; o++) { + if (g_buddy.orders[o].count) + serial_printf(" order %2d (%4zu KiB): %zu blocks\n", + o, (PAGE_SIZE << o) / 1024, + g_buddy.orders[o].count); + } +} + +#define SLAB_PAGE_ALLOC(n) pmm_alloc_zero(n) +#define SLAB_PAGE_FREE(p, n) pmm_free(p, n) + +static const size_t g_size_classes[SLAB_NUM_CACHES] = { + 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 +}; + +slab_cache_t g_caches[SLAB_NUM_CACHES]; + +static inline uintptr_t _slab_obj_start(slab_t *s) { + return _align_up((uintptr_t)s + sizeof(slab_t), 8); +} + +static inline size_t _slab_pages(size_t obj_size) { + uintptr_t hdr_end = _align_up(sizeof(slab_t), 8); + if (obj_size <= PAGE_SIZE - hdr_end) + return 1; + if (obj_size <= PAGE_SIZE) + return 2; + return 0; +} + +static inline uint16_t _slab_capacity(size_t obj_size) { + size_t pages = _slab_pages(obj_size); + if (pages == 0) return 0; + uintptr_t obj_start = _align_up(sizeof(slab_t), 8); + size_t avail = pages * PAGE_SIZE - obj_start; + uint16_t cap = (uint16_t)(avail / obj_size); + return cap > 0 ? cap : 0; +} + +static void _slab_list_push(slab_t **head, slab_t *s) { + s->next = *head; s->prev = NULL; + if (*head) (*head)->prev = s; + *head = s; +} + +static void _slab_list_remove(slab_t **head, slab_t *s) { + if (s->prev) s->prev->next = s->next; + else *head = s->next; + if (s->next) s->next->prev = s->prev; + s->next = s->prev = NULL; +} + +static slab_t *_slab_new(slab_cache_t *cache) { + uint16_t cap = _slab_capacity(cache->obj_size); + if (!cap) return NULL; + + size_t pages = _slab_pages(cache->obj_size); + + slab_t *s = (slab_t *)SLAB_PAGE_ALLOC(pages); + if (!s) return NULL; + + s->obj_size = (uint16_t)cache->obj_size; + s->total = cap; + s->used = 0; + s->next = s->prev = NULL; + + uintptr_t start = _slab_obj_start(s); + s->freelist = (void *)start; + for (uint16_t i = 0; i < s->total; i++) { + void **slot = (void **)(start + (uintptr_t)i * cache->obj_size); + *slot = (i + 1 < s->total) + ? (void *)(start + (uintptr_t)(i + 1) * cache->obj_size) + : NULL; + } + return s; +} + +#define LARGE_ALLOC_MAGIC 0xDEADBEEFCAFEBABEULL + +typedef struct { + uint64_t magic; + uint64_t pages; +} large_hdr_t; + +static inline bool _is_large_alloc(void *ptr) { + large_hdr_t *hdr = (large_hdr_t *)ptr - 1; + return hdr->magic == LARGE_ALLOC_MAGIC; +} + +static slab_cache_t *_cache_for(size_t size) { + for (int i = 0; i < SLAB_NUM_CACHES; i++) + if (g_caches[i].obj_size >= size) return &g_caches[i]; + return NULL; +} + +void slab_init(void) { + for (int i = 0; i < SLAB_NUM_CACHES; i++) { + g_caches[i].obj_size = g_size_classes[i]; + g_caches[i].partial = NULL; + g_caches[i].full = NULL; + g_caches[i].total_allocs = 0; + g_caches[i].total_frees = 0; + } + serial_printf("[PMM] slab init: %d caches, sizes 8..4096 bytes\n", + SLAB_NUM_CACHES); +} + +static spinlock_t g_slab_lock = SPINLOCK_INIT; + +void *kmalloc(size_t size) { + if (!size) return NULL; + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + spinlock_acquire(&g_slab_lock); + + void *result; + if (size > SLAB_MAX_SIZE) { + size_t pages = (size + sizeof(large_hdr_t) + PAGE_SIZE - 1) / PAGE_SIZE; + spinlock_release(&g_slab_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); + large_hdr_t *hdr = (large_hdr_t *)SLAB_PAGE_ALLOC(pages); + if (!hdr) return NULL; + hdr->magic = LARGE_ALLOC_MAGIC; + hdr->pages = (uint64_t)pages; + return (void *)(hdr + 1); + } + + slab_cache_t *cache = _cache_for(size); + if (!cache) { spinlock_release(&g_slab_lock); asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); return NULL; } + + if (!cache->partial) { + spinlock_release(&g_slab_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); + slab_t *s = _slab_new(cache); + if (!s) return NULL; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + spinlock_acquire(&g_slab_lock); + _slab_list_push(&cache->partial, s); + } + slab_t *s = cache->partial; + + void *obj = s->freelist; + s->freelist = *(void **)obj; + s->used++; + cache->total_allocs++; + + if (s->used == s->total) { + _slab_list_remove(&cache->partial, s); + _slab_list_push(&cache->full, s); + } + result = obj; + spinlock_release(&g_slab_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); + return result; +} + +void *kzalloc(size_t size) { + void *p = kmalloc(size); + if (p) memset(p, 0, size); + return p; +} + +void kfree(void *ptr) { + if (!ptr) return; + + if (_is_large_alloc(ptr)) { + large_hdr_t *hdr = (large_hdr_t *)ptr - 1; + size_t pages = (size_t)hdr->pages; + hdr->magic = 0; + SLAB_PAGE_FREE(hdr, pages); + return; + } + + uint64_t flags; + asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory"); + spinlock_acquire(&g_slab_lock); + + slab_t *s = (slab_t *)((uintptr_t)ptr & ~((uintptr_t)PAGE_SIZE - 1)); + + slab_cache_t *cache = NULL; + for (int i = 0; i < SLAB_NUM_CACHES; i++) { + if (g_caches[i].obj_size == s->obj_size) { + cache = &g_caches[i]; + break; + } + } + if (!cache) { spinlock_release(&g_slab_lock); asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); return; } + + bool was_full = (s->used == s->total); + *(void **)ptr = s->freelist; + s->freelist = ptr; + s->used--; + cache->total_frees++; + + if (was_full) { + _slab_list_remove(&cache->full, s); + _slab_list_push(&cache->partial, s); + } + if (s->used == 0) { + _slab_list_remove(&cache->partial, s); + size_t pages = _slab_pages(s->obj_size); + spinlock_release(&g_slab_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); + SLAB_PAGE_FREE(s, pages > 0 ? pages : 1); + return; + } + spinlock_release(&g_slab_lock); + asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc"); +} + +void *krealloc(void *ptr, size_t new_size) { + if (!ptr) return kmalloc(new_size); + if (!new_size) { kfree(ptr); return NULL; } + + size_t old_size; + if (_is_large_alloc(ptr)) { + large_hdr_t *hdr = (large_hdr_t *)ptr - 1; + old_size = (size_t)hdr->pages * PAGE_SIZE - sizeof(large_hdr_t); + } else { + slab_t *s = (slab_t *)((uintptr_t)ptr & ~((uintptr_t)PAGE_SIZE - 1)); + old_size = s->obj_size; + } + + void *np = kmalloc(new_size); + if (!np) return NULL; + memcpy(np, ptr, old_size < new_size ? old_size : new_size); + kfree(ptr); + return np; +} + +void slab_print_stats(void) { + serial_printf("[PMM] slab stats:\n"); + for (int i = 0; i < SLAB_NUM_CACHES; i++) { + slab_cache_t *c = &g_caches[i]; + size_t np = 0, nf = 0; + for (slab_t *s = c->partial; s && np < 10000; s = s->next) np++; + for (slab_t *s = c->full; s && nf < 10000; s = s->next) nf++; + serial_printf(" [%4zu B] partial=%zu full=%zu allocs=%zu frees=%zu\n", + c->obj_size, np, nf, c->total_allocs, c->total_frees); + } +} \ No newline at end of file diff --git a/kernel/src/memory/vmm.c b/kernel/src/memory/vmm.c new file mode 100644 index 0000000..988429e --- /dev/null +++ b/kernel/src/memory/vmm.c @@ -0,0 +1,402 @@ +#include "../../include/memory/vmm.h" +#include "../../include/memory/pmm.h" +#include "../../include/smp/smp.h" +#include "../../include/apic/apic.h" +#include "../../include/io/serial.h" +#include +#include + +#define KERNEL_TEST_BASE 0xFFFF800000100000ULL +#define PTE_PHYS_MASK 0x000FFFFFFFFFF000ULL +#define MASK 0x1FF + +static vmm_pagemap_t kernel_pagemap; + +static inline void invlpg(void* addr) { + asm volatile ("invlpg (%0)" :: "r"(addr) : "memory"); +} + +static vmm_pte_t* alloc_table(void) { + void* page = pmm_alloc_zero(1); + if (!page) { + serial_printf("[VMM] alloc_table: OUT OF MEMORY (pmm_alloc_zero(1) returned NULL)!\n"); + serial_printf("[VMM] free_pages=%zu\n", (size_t)pmm_get_free_pages()); + for (;;) asm volatile ("hlt"); + } + return (vmm_pte_t*)page; +} + +static vmm_pte_t* get_table(vmm_pte_t* parent, size_t index, uint64_t flags) { + if (!(parent[index] & VMM_PRESENT)) { + vmm_pte_t* table = alloc_table(); + uintptr_t table_phys = pmm_virt_to_phys(table); + parent[index] = table_phys + | VMM_PRESENT + | VMM_WRITE + | (flags & VMM_USER); + } else if (flags & VMM_USER) { + parent[index] |= VMM_USER; + } + return (vmm_pte_t*)pmm_phys_to_virt(parent[index] & PTE_PHYS_MASK); +} + +bool vmm_map_page(vmm_pagemap_t* map, uintptr_t virt, uintptr_t phys, uint64_t flags) { + if (!map || !map->pml4) { + serial_printf("[VMM_BUG] vmm_map_page: map=%p pml4=%p virt=0x%llx\n", + (void*)map, map ? (void*)map->pml4 : NULL, + (unsigned long long)virt); + return false; + } + size_t pml4_i = (virt >> 39) & MASK; + size_t pdpt_i = (virt >> 30) & MASK; + size_t pd_i = (virt >> 21) & MASK; + size_t pt_i = (virt >> 12) & MASK; + vmm_pte_t* pdpt = get_table(map->pml4, pml4_i, flags); + vmm_pte_t* pd = get_table(pdpt, pdpt_i, flags); + vmm_pte_t* pt = get_table(pd, pd_i, flags); + pt[pt_i] = (phys & PTE_PHYS_MASK) | (flags | VMM_PRESENT); + + asm volatile ("lock addl $0, (%%rsp)" ::: "memory", "cc"); + invlpg((void*)virt); + asm volatile ("lock addl $0, (%%rsp)" ::: "memory", "cc"); + + return true; +} + +void vmm_unmap_page_noflush(vmm_pagemap_t* map, uintptr_t virt) { + size_t pml4_i = (virt >> 39) & MASK; + size_t pdpt_i = (virt >> 30) & MASK; + size_t pd_i = (virt >> 21) & MASK; + size_t pt_i = (virt >> 12) & MASK; + + if (!(map->pml4[pml4_i] & VMM_PRESENT)) return; + vmm_pte_t* pdpt = (vmm_pte_t*)pmm_phys_to_virt(map->pml4[pml4_i] & PTE_PHYS_MASK); + if (!(pdpt[pdpt_i] & VMM_PRESENT)) return; + vmm_pte_t* pd = (vmm_pte_t*)pmm_phys_to_virt(pdpt[pdpt_i] & PTE_PHYS_MASK); + if (!(pd[pd_i] & VMM_PRESENT)) return; + vmm_pte_t* pt = (vmm_pte_t*)pmm_phys_to_virt(pd[pd_i] & PTE_PHYS_MASK); + pt[pt_i] = 0; +} + +void vmm_unmap_page(vmm_pagemap_t* map, uintptr_t virt) { + size_t pml4_i = (virt >> 39) & MASK; + size_t pdpt_i = (virt >> 30) & MASK; + size_t pd_i = (virt >> 21) & MASK; + size_t pt_i = (virt >> 12) & MASK; + + if (!(map->pml4[pml4_i] & VMM_PRESENT)) return; + vmm_pte_t* pdpt = (vmm_pte_t*)pmm_phys_to_virt(map->pml4[pml4_i] & PTE_PHYS_MASK); + if (!(pdpt[pdpt_i] & VMM_PRESENT)) return; + vmm_pte_t* pd = (vmm_pte_t*)pmm_phys_to_virt(pdpt[pdpt_i] & PTE_PHYS_MASK); + if (!(pd[pd_i] & VMM_PRESENT)) return; + vmm_pte_t* pt = (vmm_pte_t*)pmm_phys_to_virt(pd[pd_i] & PTE_PHYS_MASK); + + if (!(pt[pt_i] & VMM_PRESENT)) return; + + uintptr_t phys = pt[pt_i] & PTE_PHYS_MASK; + + pt[pt_i] = 0; + asm volatile ("lock addl $0, (%%rsp)" ::: "memory", "cc"); + invlpg((void*)virt); + if (smp_get_cpu_count() > 1 && (virt >= 0xffff800000000000ULL)) { + ipi_tlb_shootdown_broadcast(&virt, 1); + } + + if (phys >= PMM_FREE_MIN_PHYS) { + pmm_free(pmm_phys_to_virt(phys), 1); + } +} + +vmm_pagemap_t* vmm_create_pagemap(void) { + vmm_pagemap_t* map = pmm_alloc_zero(1); + if (!map) { + serial_printf("[VMM] vmm_create_pagemap: pmm_alloc_zero for map failed\n"); + return NULL; + } + + map->pml4 = alloc_table(); + if (!map->pml4) { + serial_printf("[VMM] vmm_create_pagemap: alloc_table for pml4 failed\n"); + pmm_free(map, 1); + return NULL; + } + + for (size_t i = 256; i < 512; i++) { + map->pml4[i] = kernel_pagemap.pml4[i]; + } + + return map; +} + +void vmm_switch_pagemap(vmm_pagemap_t* map) { + uintptr_t phys = pmm_virt_to_phys(map->pml4); + asm volatile ("mov %0, %%cr3" :: "r"(phys) : "memory"); +} + +bool vmm_virt_to_phys(vmm_pagemap_t* map, uintptr_t virt, uintptr_t* phys_out) { + if (!map || !phys_out) { + serial_printf("VMM_VIRT_TO_PHYS ERROR: null parameters\n"); + return false; + } + + size_t pml4_i = (virt >> 39) & MASK; + size_t pdpt_i = (virt >> 30) & MASK; + size_t pd_i = (virt >> 21) & MASK; + size_t pt_i = (virt >> 12) & MASK; + + if (!(map->pml4[pml4_i] & VMM_PRESENT)) return false; + vmm_pte_t* pdpt = (vmm_pte_t*)pmm_phys_to_virt(map->pml4[pml4_i] & PTE_PHYS_MASK); + if (!(pdpt[pdpt_i] & VMM_PRESENT)) return false; + vmm_pte_t* pd = (vmm_pte_t*)pmm_phys_to_virt(pdpt[pdpt_i] & PTE_PHYS_MASK); + if (!(pd[pd_i] & VMM_PRESENT)) return false; + vmm_pte_t* pt = (vmm_pte_t*)pmm_phys_to_virt(pd[pd_i] & PTE_PHYS_MASK); + if (!(pt[pt_i] & VMM_PRESENT)) return false; + + *phys_out = (pt[pt_i] & PTE_PHYS_MASK) | (virt & 0xFFF); + return true; +} + +bool vmm_get_page_flags(vmm_pagemap_t* map, uintptr_t virt, uint64_t* flags_out) { + if (!map || !flags_out) return false; + + size_t pml4_i = (virt >> 39) & MASK; + size_t pdpt_i = (virt >> 30) & MASK; + size_t pd_i = (virt >> 21) & MASK; + size_t pt_i = (virt >> 12) & MASK; + + if (!(map->pml4[pml4_i] & VMM_PRESENT)) return false; + vmm_pte_t* pdpt = (vmm_pte_t*)pmm_phys_to_virt(map->pml4[pml4_i] & PTE_PHYS_MASK); + if (!(pdpt[pdpt_i] & VMM_PRESENT)) return false; + vmm_pte_t* pd = (vmm_pte_t*)pmm_phys_to_virt(pdpt[pdpt_i] & PTE_PHYS_MASK); + if (!(pd[pd_i] & VMM_PRESENT)) return false; + vmm_pte_t* pt = (vmm_pte_t*)pmm_phys_to_virt(pd[pd_i] & PTE_PHYS_MASK); + if (!(pt[pt_i] & VMM_PRESENT)) return false; + + *flags_out = pt[pt_i] & (0xFFF | (1ULL << 63)); + return true; +} + +vmm_pagemap_t* vmm_clone_pagemap(vmm_pagemap_t* src) { + if (!src) return NULL; + + vmm_pagemap_t* dst = pmm_alloc_zero(1); + if (!dst) return NULL; + dst->pml4 = alloc_table(); + + for (size_t i = 256; i < 512; i++) + dst->pml4[i] = kernel_pagemap.pml4[i]; + + for (size_t pml4_i = 0; pml4_i < 256; pml4_i++) { + if (!(src->pml4[pml4_i] & VMM_PRESENT)) continue; + + vmm_pte_t* src_pdpt = (vmm_pte_t*)pmm_phys_to_virt(src->pml4[pml4_i] & PTE_PHYS_MASK); + vmm_pte_t* dst_pdpt = alloc_table(); + dst->pml4[pml4_i] = pmm_virt_to_phys(dst_pdpt) | (src->pml4[pml4_i] & 0xFFF); + + for (size_t pdpt_i = 0; pdpt_i < 512; pdpt_i++) { + if (!(src_pdpt[pdpt_i] & VMM_PRESENT)) continue; + + vmm_pte_t* src_pd = (vmm_pte_t*)pmm_phys_to_virt(src_pdpt[pdpt_i] & PTE_PHYS_MASK); + vmm_pte_t* dst_pd = alloc_table(); + dst_pdpt[pdpt_i] = pmm_virt_to_phys(dst_pd) | (src_pdpt[pdpt_i] & 0xFFF); + + for (size_t pd_i = 0; pd_i < 512; pd_i++) { + if (!(src_pd[pd_i] & VMM_PRESENT)) continue; + if (src_pd[pd_i] & VMM_PSE) { + void* new_hp = pmm_alloc(512); + if (!new_hp) continue; + void* old_hp = pmm_phys_to_virt(src_pd[pd_i] & PTE_PHYS_MASK & ~0x1FFFFFULL); + memcpy(new_hp, old_hp, 512 * 0x1000); + uint64_t hp_flags = src_pd[pd_i] & ~(PTE_PHYS_MASK & ~0x1FFFFFULL); + dst_pd[pd_i] = (pmm_virt_to_phys(new_hp) & (PTE_PHYS_MASK & ~0x1FFFFFULL)) + | hp_flags; + continue; + } + + vmm_pte_t* src_pt = (vmm_pte_t*)pmm_phys_to_virt(src_pd[pd_i] & PTE_PHYS_MASK); + vmm_pte_t* dst_pt = alloc_table(); + dst_pd[pd_i] = pmm_virt_to_phys(dst_pt) | (src_pd[pd_i] & 0xFFF); + + for (size_t pt_i = 0; pt_i < 512; pt_i++) { + if (!(src_pt[pt_i] & VMM_PRESENT)) continue; + + uintptr_t src_phys = src_pt[pt_i] & PTE_PHYS_MASK; + if (src_phys < PMM_FREE_MIN_PHYS) continue; + + void* new_page = pmm_alloc_zero(1); + if (!new_page) continue; + void* old_page = pmm_phys_to_virt(src_phys); + memcpy(new_page, old_page, 0x1000); + dst_pt[pt_i] = pmm_virt_to_phys(new_page) + | (src_pt[pt_i] & (0xFFF | (1ULL << 63))); + } + } + } + } + + return dst; +} + +void vmm_free_pagemap(vmm_pagemap_t* map) +{ + if (!map || !map->pml4) return; + + for (size_t pml4_i = 0; pml4_i < 256; pml4_i++) { + if (!(map->pml4[pml4_i] & VMM_PRESENT)) continue; + + vmm_pte_t* pdpt = (vmm_pte_t*)pmm_phys_to_virt(map->pml4[pml4_i] & PTE_PHYS_MASK); + + for (size_t pdpt_i = 0; pdpt_i < 512; pdpt_i++) { + if (!(pdpt[pdpt_i] & VMM_PRESENT)) continue; + vmm_pte_t* pd = (vmm_pte_t*)pmm_phys_to_virt(pdpt[pdpt_i] & PTE_PHYS_MASK); + + for (size_t pd_i = 0; pd_i < 512; pd_i++) { + if (!(pd[pd_i] & VMM_PRESENT)) continue; + + if (pd[pd_i] & VMM_PSE) { + uintptr_t hp_phys = pd[pd_i] & PTE_PHYS_MASK & ~0x1FFFFFULL; + if (hp_phys >= PMM_FREE_MIN_PHYS) + pmm_free(pmm_phys_to_virt(hp_phys), 512); + continue; + } + + vmm_pte_t* pt = (vmm_pte_t*)pmm_phys_to_virt(pd[pd_i] & PTE_PHYS_MASK); + + for (size_t pt_i = 0; pt_i < 512; pt_i++) { + if (!(pt[pt_i] & VMM_PRESENT)) continue; + uintptr_t phys = pt[pt_i] & PTE_PHYS_MASK; + if (phys >= PMM_FREE_MIN_PHYS) + pmm_free(pmm_phys_to_virt(phys), 1); + } + + uintptr_t pt_phys = pd[pd_i] & PTE_PHYS_MASK; + if (pt_phys >= PMM_FREE_MIN_PHYS) + pmm_free(pt, 1); + } + + uintptr_t pd_phys = pdpt[pdpt_i] & PTE_PHYS_MASK; + if (pd_phys >= PMM_FREE_MIN_PHYS) + pmm_free(pd, 1); + } + + uintptr_t pdpt_phys = map->pml4[pml4_i] & PTE_PHYS_MASK; + if (pdpt_phys >= PMM_FREE_MIN_PHYS) + pmm_free(pdpt, 1); + } + + pmm_free(map->pml4, 1); + pmm_free(map, 1); +} +uintptr_t kernel_pml4_phys; + +void vmm_init(void) { + uintptr_t cr3; + asm volatile ("mov %%cr3, %0" : "=r"(cr3)); + kernel_pagemap.pml4 = (vmm_pte_t*)pmm_phys_to_virt(cr3); + kernel_pml4_phys = cr3; + serial_printf("VMM: kernel pagemap initialized\n"); + serial_printf("VMM: kernel PML4 phys = 0x%llx\n", kernel_pml4_phys); +} + +vmm_pagemap_t* vmm_get_kernel_pagemap(void) { + return &kernel_pagemap; +} + +void vmm_sync_kernel_mappings(vmm_pagemap_t* map) { + if (!map) return; + for (size_t i = 256; i < 512; i++) { + map->pml4[i] = kernel_pagemap.pml4[i]; + } +} + +void vmm_test(void) { + serial_printf("\n--- VMM EXTENDED 64-BIT TEST ---\n"); + + void* phys1 = pmm_alloc_zero(1); + void* phys2 = pmm_alloc_zero(1); + + uintptr_t paddr1 = pmm_virt_to_phys(phys1); + uintptr_t paddr2 = pmm_virt_to_phys(phys2); + + uintptr_t vaddr1 = KERNEL_TEST_BASE; + uintptr_t vaddr2 = KERNEL_TEST_BASE + 0x1000; + + vmm_map_page(&kernel_pagemap, vaddr1, paddr1, VMM_WRITE); + vmm_map_page(&kernel_pagemap, vaddr2, paddr2, VMM_WRITE); + + uint64_t* ptr1 = (uint64_t*)vaddr1; + uint64_t* ptr2 = (uint64_t*)vaddr2; + + *ptr1 = 0xDEADBEEFCAFEBABE; + *ptr2 = 0xFEEDFACE12345678; + + vmm_pagemap_t* new_map = vmm_create_pagemap(); + + void* phys3 = pmm_alloc_zero(1); + uintptr_t paddr3 = pmm_virt_to_phys(phys3); + uintptr_t vaddr3 = KERNEL_TEST_BASE + 0x2000; + + vmm_map_page(new_map, vaddr3, paddr3, VMM_WRITE); + + uint64_t* ptr3 = (uint64_t*)vaddr3; + *ptr3 = 0xBAADF00DBAADF00D; + + vmm_switch_pagemap(new_map); + serial_printf("Value (new): 0x%llx\n", *ptr3); + + vmm_switch_pagemap(&kernel_pagemap); + serial_printf("Value (kernel): 0x%llx\n", *ptr1); + + serial_printf("--- VMM TEST DONE ---\n"); + + serial_printf("\n--- VMM TRANSLATION TEST ---\n"); + + void* phys_page = pmm_alloc_zero(1); + uintptr_t paddr = pmm_virt_to_phys(phys_page); + uintptr_t vaddr = KERNEL_TEST_BASE + 0x3000; + + vmm_map_page(&kernel_pagemap, vaddr, paddr, VMM_WRITE); + + uintptr_t translated_phys; + if (vmm_virt_to_phys(&kernel_pagemap, vaddr, &translated_phys)) { + serial_printf("Virt 0x%llx -> Phys 0x%llx\n", vaddr, translated_phys); + serial_printf("Original phys: 0x%llx\n", paddr); + serial_printf("Match: %s\n", translated_phys == paddr ? "YES" : "NO"); + } else { + serial_printf("Translation failed!\n"); + } + + uint64_t flags; + if (vmm_get_page_flags(&kernel_pagemap, vaddr, &flags)) { + serial_printf("Page flags: 0x%llx\n", flags); + serial_printf("Present: %s\n", (flags & VMM_PRESENT) ? "YES" : "NO"); + serial_printf("Writable: %s\n", (flags & VMM_WRITE) ? "YES" : "NO"); + } + + uint64_t hhdm = pmm_get_hhdm_offset(); + serial_printf("HHDM offset: 0x%llx\n", hhdm); + + serial_printf("\n--- Memory statistics after tests ---\n"); + size_t free_before = pmm_get_free_pages(); + + serial_printf("\n--- Memory free test ---\n"); + void* test_alloc = pmm_alloc_aligned(2, 4096); + if (test_alloc) { + size_t free_after_alloc = pmm_get_free_pages(); + serial_printf("Allocated 2 pages. Free pages: %zu -> %zu\n", + free_before, free_after_alloc); + + pmm_free(test_alloc, 2); + size_t free_after_free = pmm_get_free_pages(); + serial_printf("Freed 2 pages. Free pages: %zu -> %zu\n", + free_after_alloc, free_after_free); + + if (free_after_free == free_before) { + serial_printf("Memory free test PASSED\n"); + } else { + serial_printf("Memory free test FAILED (possible leak)\n"); + } + } + + serial_printf("--- VMM TRANSLATION TEST DONE ---\n"); +} \ No newline at end of file diff --git a/kernel/src/panic/panic.c b/kernel/src/panic/panic.c new file mode 100644 index 0000000..dc0d6ed --- /dev/null +++ b/kernel/src/panic/panic.c @@ -0,0 +1,211 @@ +#include "../../include/panic/panic.h" +#include "../../include/io/serial.h" +#include "../../include/graphics/fb/fb.h" +#include "../../include/apic/apic.h" +#include "../../include/smp/smp.h" +#include "../../include/smp/percpu.h" +#include "../../include/sched/sched.h" +#include +#include + +extern struct limine_framebuffer *global_framebuffer; + +#define COL_BG 0x000080 +#define COL_WHITE 0xFFFFFF +#define COL_YELLOW 0xFFFF00 +#define COL_RED 0xFF4444 +#define COL_CYAN 0x00FFFF +#define COL_GRAY 0xAAAAAA + +static uint32_t fb_x = 0, fb_y = 0; +static struct limine_framebuffer *g_fb = NULL; + +static void fb_nl(void) { + fb_x = 0; + fb_y += 18; +} + +static void fb_puts_col(const char *s, uint32_t col) { + if (!g_fb) return; + while (*s) { + if (*s == '\n') { fb_nl(); s++; continue; } + fb_draw_char(g_fb, *s, fb_x, fb_y, col); + fb_x += 9; + if (fb_x + 9 > (uint32_t)g_fb->width) fb_nl(); + s++; + } +} + +static void fb_puts(const char *s) { fb_puts_col(s, COL_WHITE); } + +static void fb_puthex(uint64_t v) { + static const char h[] = "0123456789ABCDEF"; + char full[19] = "0x"; + for (int i = 0; i < 16; i++) + full[2 + i] = h[(v >> (60 - i * 4)) & 0xF]; + full[18] = '\0'; + fb_puts_col(full, COL_CYAN); +} + +static void fb_putdec(uint64_t v) { + char buf[22]; int i = 20; buf[21] = '\0'; + if (v == 0) { fb_puts_col("0", COL_CYAN); return; } + while (v && i >= 0) { buf[i--] = '0' + (v % 10); v /= 10; } + fb_puts_col(buf + i + 1, COL_CYAN); +} + +volatile int g_panic_owner = 0; + +static int panic_try_own(void) { + int expected = 0; + return __atomic_compare_exchange_n(&g_panic_owner, &expected, 1, + 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED); +} + +static void halt_other_cpus(void) { + asm volatile("cli"); + lapic_send_nmi_to_all_but_self(); + for (volatile int i = 0; i < 200000; i++) + asm volatile("pause"); +} + +static void draw_panic_screen(const char *msg, struct int_frame_t *regs) { + g_fb = global_framebuffer; + if (!g_fb) return; + + uint32_t W = (uint32_t)g_fb->width; + uint32_t H = (uint32_t)g_fb->height; + + fb_fill_rect(g_fb, 0, 0, W, H, COL_BG); + fb_fill_rect(g_fb, 0, 0, W, 4, COL_WHITE); + fb_fill_rect(g_fb, 0, H - 4, W, 4, COL_WHITE); + + fb_x = 16; fb_y = 16; + + fb_puts_col("*** KERNEL PANIC ***\n", COL_YELLOW); + fb_nl(); + fb_puts_col("Cervus OS has encountered a fatal error and cannot continue.\n", COL_WHITE); + fb_nl(); + + fb_puts_col("Reason: ", COL_GRAY); + fb_puts_col(msg, COL_YELLOW); + fb_nl(); fb_nl(); + + if (regs) { + percpu_t *pc = get_percpu(); + task_t *t = pc ? (task_t *)pc->current_task : NULL; + uint32_t cpu = lapic_get_id(); + if (!t) t = current_task[cpu]; + + fb_puts_col("CPU: ", COL_GRAY); fb_putdec(cpu); fb_puts("\n"); + + if (t) { + fb_puts_col("Task: ", COL_GRAY); + fb_puts_col(t->name, COL_CYAN); + fb_puts(" PID: "); fb_putdec(t->pid); + fb_puts("\n"); + } + fb_nl(); + + fb_puts_col(" Register Dump \n", COL_YELLOW); + + fb_puts_col("RIP: ", COL_GRAY); fb_puthex(regs->rip); + fb_puts(" CS: "); fb_puthex(regs->cs); fb_puts("\n"); + + fb_puts_col("RSP: ", COL_GRAY); fb_puthex(regs->rsp); + fb_puts(" RFL: "); fb_puthex(regs->rflags); fb_puts("\n"); + + fb_puts_col("RAX: ", COL_GRAY); fb_puthex(regs->rax); + fb_puts(" RBX: "); fb_puthex(regs->rbx); fb_puts("\n"); + + fb_puts_col("RCX: ", COL_GRAY); fb_puthex(regs->rcx); + fb_puts(" RDX: "); fb_puthex(regs->rdx); fb_puts("\n"); + + fb_puts_col("RSI: ", COL_GRAY); fb_puthex(regs->rsi); + fb_puts(" RDI: "); fb_puthex(regs->rdi); fb_puts("\n"); + + fb_puts_col("RBP: ", COL_GRAY); fb_puthex(regs->rbp); fb_puts("\n"); + + fb_puts_col("R8: ", COL_GRAY); fb_puthex(regs->r8); + fb_puts(" R9: "); fb_puthex(regs->r9); fb_puts("\n"); + + fb_puts_col("R10: ", COL_GRAY); fb_puthex(regs->r10); + fb_puts(" R11: "); fb_puthex(regs->r11); fb_puts("\n"); + + fb_puts_col("R12: ", COL_GRAY); fb_puthex(regs->r12); + fb_puts(" R13: "); fb_puthex(regs->r13); fb_puts("\n"); + + fb_puts_col("R14: ", COL_GRAY); fb_puthex(regs->r14); + fb_puts(" R15: "); fb_puthex(regs->r15); fb_puts("\n"); + fb_nl(); + + uint64_t cr2 = 0; + asm volatile("mov %%cr2, %0" : "=r"(cr2)); + fb_puts_col("CR2: ", COL_GRAY); fb_puthex(cr2); fb_puts("\n"); + + fb_puts_col("ERR: ", COL_GRAY); fb_puthex(regs->error); + fb_puts(" INT: "); fb_putdec(regs->interrupt); fb_puts("\n"); + } + + fb_nl(); + fb_puts_col("System halted. Check serial output for details.\n", COL_GRAY); +} + +static void serial_panic_dump(const char *msg, struct int_frame_t *regs) { + serial_printf("\n"); + serial_printf(" KERNEL PANIC \n"); + serial_printf("Reason: %s\n", msg); + + uint32_t cpu = lapic_get_id(); + serial_printf("CPU: %u\n", cpu); + + percpu_t *pc = get_percpu(); + task_t *t = pc ? (task_t *)pc->current_task : NULL; + if (!t) t = current_task[cpu]; + if (t) { + serial_printf("Task: %s PID=%u PPID=%u\n", + t->name, t->pid, t->ppid); + } + + if (regs) { + uint64_t cr2 = 0; + asm volatile("mov %%cr2, %0" : "=r"(cr2)); + serial_printf("\nRegisters:\n"); + serial_printf(" RIP=0x%016llx CS=0x%llx\n", regs->rip, regs->cs); + serial_printf(" RSP=0x%016llx SS=0x%llx\n", regs->rsp, regs->ss); + serial_printf(" RFLAGS=0x%016llx\n", regs->rflags); + serial_printf(" RAX=0x%016llx RBX=0x%016llx\n", regs->rax, regs->rbx); + serial_printf(" RCX=0x%016llx RDX=0x%016llx\n", regs->rcx, regs->rdx); + serial_printf(" RSI=0x%016llx RDI=0x%016llx\n", regs->rsi, regs->rdi); + serial_printf(" RBP=0x%016llx\n", regs->rbp); + serial_printf(" R8 =0x%016llx R9 =0x%016llx\n", regs->r8, regs->r9); + serial_printf(" R10=0x%016llx R11=0x%016llx\n", regs->r10, regs->r11); + serial_printf(" R12=0x%016llx R13=0x%016llx\n", regs->r12, regs->r13); + serial_printf(" R14=0x%016llx R15=0x%016llx\n", regs->r14, regs->r15); + serial_printf(" CR2=0x%016llx\n", cr2); + serial_printf(" ERR=0x%016llx INT=%llu\n", regs->error, regs->interrupt); + } + serial_printf("========================================\n"); + serial_printf("System halted.\n\n"); +} + +__attribute__((noreturn)) +void kernel_panic(const char *msg) { + kernel_panic_regs(msg, NULL); +} + +__attribute__((noreturn)) +void kernel_panic_regs(const char *msg, struct int_frame_t *regs) { + asm volatile("cli"); + + if (!panic_try_own()) { + for (;;) asm volatile("cli; hlt"); + } + + serial_force_unlock(); + halt_other_cpus(); + serial_panic_dump(msg, regs); + draw_panic_screen(msg, regs); + + for (;;) asm volatile("cli; hlt"); +} \ No newline at end of file diff --git a/kernel/src/sched/sched.c b/kernel/src/sched/sched.c new file mode 100644 index 0000000..8a3f3f4 --- /dev/null +++ b/kernel/src/sched/sched.c @@ -0,0 +1,669 @@ +#include "../include/sched/capabilities.h" +#include "../include/sched/sched.h" +#include "../include/sched/spinlock.h" +#include "../include/memory/pmm.h" +#include "../include/memory/vmm.h" +#include "../include/io/serial.h" +#include "../include/smp/smp.h" +#include "../include/smp/percpu.h" +#include "../include/apic/apic.h" +#include "../include/gdt/gdt.h" +#include "../include/fs/vfs.h" +#include "../include/panic/panic.h" +#include +#include + +#define KERNEL_STACK_PAGES (KERNEL_STACK_SIZE / 0x1000) +#define MAX_PIDS 4096 + +task_t* ready_queues[MAX_PRIORITY + 1] = {0}; +task_t* current_task[MAX_CPUS] = {0}; + +static task_t idle_tasks[MAX_CPUS]; +static task_t bootstrap_tasks[MAX_CPUS]; +static volatile uint64_t reschedule_calls = 0; +static spinlock_t ready_queue_lock = SPINLOCK_INIT; +static task_t* pid_table[MAX_PIDS] = {0}; +static uint32_t next_pid = 1; +static spinlock_t pid_lock = SPINLOCK_INIT; + +spinlock_t children_lock = SPINLOCK_INIT; + +extern tss_t* tss[MAX_CPUS]; + +static inline void fix_gs_base(percpu_t* pc) { + uint64_t val = (uint64_t)pc; + asm volatile("wrmsr" + :: "c"(0xC0000101U), + "a"((uint32_t)val), + "d"((uint32_t)(val >> 32))); +} + +uint32_t task_alloc_pid(void) { + uint64_t _irqf; + _irqf = spinlock_acquire_irqsave(&pid_lock); + uint32_t found = 0; + for (uint32_t attempt = 0; attempt < MAX_PIDS - 1; attempt++) { + uint32_t i = next_pid; + if (i == 0 || i >= MAX_PIDS) { + next_pid = 1; + i = 1; + } + next_pid = (next_pid + 1 >= MAX_PIDS) ? 1 : next_pid + 1; + if (!pid_table[i]) { found = i; break; } + } + if (!found) { + serial_printf("[PID] FATAL: pid table exhausted (MAX_PIDS=%u)!\n", MAX_PIDS); + } + spinlock_release_irqrestore(&pid_lock, _irqf); + return found; +} + +task_t* task_find_by_pid(uint32_t pid) { + if (pid == 0 || pid >= MAX_PIDS) return NULL; + return pid_table[pid]; +} + +static void pid_register(task_t* t) { + if (t->pid && t->pid < MAX_PIDS) pid_table[t->pid] = t; +} + +static void pid_unregister(task_t* t) { + if (t->pid && t->pid < MAX_PIDS) pid_table[t->pid] = NULL; +} + +static void idle_loop(void* arg); + +#define STACK_CANARY_VALUE 0xDEADC0DEDEADC0DEULL + +static uint64_t alloc_and_init_stack(task_t* t) { + uintptr_t stack_virt = (uintptr_t)pmm_alloc_zero(KERNEL_STACK_PAGES); + if (!stack_virt) return 0; + t->stack_base = stack_virt; + + uint64_t* canary_page = (uint64_t*)stack_virt; + for (size_t i = 0; i < PAGE_SIZE / sizeof(uint64_t); i++) + canary_page[i] = STACK_CANARY_VALUE; + + uintptr_t stack_top = (stack_virt + KERNEL_STACK_SIZE) & ~0xFULL; + uint64_t* sp = (uint64_t*)stack_top; + + if (t->flags & TASK_FLAG_FORK) { + extern void task_trampoline_fork(void); + *--sp = (uint64_t)task_trampoline_fork; + } else if (t->is_userspace) { + extern void task_trampoline_user(void); + *--sp = (uint64_t)task_trampoline_user; + } else { + extern void task_trampoline(void); + *--sp = (uint64_t)task_trampoline; + } + + *--sp = (uint64_t)t; + *--sp = 0; + *--sp = 0; + *--sp = 0; + *--sp = 0; + *--sp = 0; + + return (uint64_t)sp; +} + +static void enqueue_global(task_t* t) { + uint64_t f = spinlock_acquire_irqsave(&ready_queue_lock); + t->next = ready_queues[t->priority]; + ready_queues[t->priority] = t; + spinlock_release_irqrestore(&ready_queue_lock, f); +} + +void __attribute__((used)) ctx_rsp_corruption_detected(task_t* old, uint64_t saved_rsp) { + serial_printf("[CTX-CORRUPT] pid=%u rsp=0x%llx saved but INVALID (stack=0x%llx..0x%llx)!\n", + old ? old->pid : 0, + saved_rsp, + old ? old->stack_base : 0, + old ? (old->stack_base + KERNEL_STACK_SIZE) : 0); + kernel_panic("context_switch: saved invalid RSP into task->rsp"); +} + +static void process_deferred_free(void) { + percpu_t* pc = get_percpu(); + if (!pc) return; + task_t* dead = (task_t*)pc->deferred_free_task; + if (!dead) return; + pc->deferred_free_task = NULL; + task_destroy(dead); +} + +void sched_init(void) { + memset(pid_table, 0, sizeof(pid_table)); + memset(bootstrap_tasks, 0, sizeof(bootstrap_tasks)); + next_pid = 1; + for (uint32_t i = 0; i < smp_get_cpu_count(); i++) { + task_t* idle = &idle_tasks[i]; + memset(idle, 0, sizeof(task_t)); + idle->priority = 0; + idle->runnable = true; + idle->state = TASK_READY; + idle->cpu_id = i; + idle->last_cpu = i; + idle->time_slice = 1; + idle->time_slice_init = 1; + idle->entry = idle_loop; + idle->arg = NULL; + idle->is_userspace = TASK_TYPE_KERNEL; + idle->pid = 0; + idle->uid = UID_ROOT; + idle->gid = GID_ROOT; + idle->capabilities = CAP_ALL; + atomic_init_bool(&idle->on_cpu, false); + idle->name[0]='i'; idle->name[1]='d'; + idle->name[2]='l'; idle->name[3]='e'; + idle->rsp = alloc_and_init_stack(idle); + if (!idle->rsp) { + kernel_panic("SCHED: failed to allocate idle stack"); + } + current_task[i] = NULL; + } + serial_writestring("Scheduler initialized (PREEMPTIVE SMP MODE)\n"); +} + +task_t* task_create(const char* name, void (*entry)(void*), void* arg, int priority) { + task_t* t = calloc(1, sizeof(task_t)); + if (!t) return NULL; + t->pid = task_alloc_pid(); + if (!t->pid) { free(t); return NULL; } + t->ppid = 0; + t->uid = UID_ROOT; + t->gid = GID_ROOT; + t->capabilities = CAP_ALL; + t->entry = entry; + t->arg = arg; + t->priority = priority > MAX_PRIORITY ? MAX_PRIORITY : priority; + t->runnable = true; + t->state = TASK_READY; + t->cpu_id = (uint32_t)-1; + t->time_slice = TASK_DEFAULT_TIMESLICE; + t->time_slice_init = TASK_DEFAULT_TIMESLICE; + t->rip = (uint64_t)entry; + t->is_userspace = TASK_TYPE_KERNEL; + atomic_init_bool(&t->on_cpu, false); + strncpy(t->name, name, sizeof(t->name) - 1); + t->rsp = alloc_and_init_stack(t); + if (!t->rsp) { free(t); return NULL; } + t->fpu_state = (fpu_state_t*)pmm_alloc_zero(1); + pid_register(t); + enqueue_global(t); + serial_printf("[SCHED] task_create: '%s' pid=%u prio=%d\n", t->name, t->pid, t->priority); + return t; +} + +task_t* task_create_user(const char* name, uintptr_t entry, uintptr_t user_rsp, uint64_t cr3, int priority, vmm_pagemap_t* pagemap, uint32_t uid, uint32_t gid) { + task_t* t = calloc(1, sizeof(task_t)); + if (!t) return NULL; + t->pid = task_alloc_pid(); + if (!t->pid) { free(t); return NULL; } + t->ppid = 0; + t->uid = uid; + t->gid = gid; + t->capabilities = cap_initial(uid); + t->entry = (void (*)(void*))entry; + t->arg = NULL; + t->priority = priority > MAX_PRIORITY ? MAX_PRIORITY : priority; + t->runnable = true; + t->state = TASK_READY; + t->cpu_id = (uint32_t)-1; + t->time_slice = TASK_DEFAULT_TIMESLICE; + t->time_slice_init = TASK_DEFAULT_TIMESLICE; + t->rip = entry; + t->is_userspace = TASK_TYPE_USER; + t->user_rsp = user_rsp; + t->cr3 = cr3; + t->pagemap = pagemap; + t->brk_start = 0; + t->brk_current = 0; + t->brk_max = 0x0000700000000000ULL; + atomic_init_bool(&t->on_cpu, false); + strncpy(t->name, name, sizeof(t->name) - 1); + t->rsp = alloc_and_init_stack(t); + if (!t->rsp) { free(t); return NULL; } + t->fpu_state = (fpu_state_t*)pmm_alloc_zero(1); + + t->fd_table = fd_table_create(); + if (t->fd_table) { + int stdio_ret = vfs_init_stdio(t); + if (stdio_ret < 0) + serial_printf("[SCHED] task_create_user: vfs_init_stdio failed: %d\n", + stdio_ret); + } + + t->flags |= TASK_FLAG_OWN_PAGEMAP; + + pid_register(t); + enqueue_global(t); + serial_printf("[SCHED] task_create_user: '%s' pid=%u uid=%u entry=0x%llx user_rsp=0x%llx caps=0x%llx\n", + t->name, t->pid, t->uid, entry, user_rsp, t->capabilities); + return t; +} + +task_t* task_fork(task_t* parent) { + if (!parent) return NULL; + task_t* child = calloc(1, sizeof(task_t)); + if (!child) return NULL; + child->pid = task_alloc_pid(); + if (!child->pid) { free(child); return NULL; } + child->ppid = parent->pid; + child->priority = parent->priority; + child->is_userspace = parent->is_userspace; + strncpy(child->name, parent->name, sizeof(child->name)-1); + child->uid = parent->uid; + child->gid = parent->gid; + child->capabilities = parent->capabilities; + child->time_slice = parent->time_slice_init; + child->time_slice_init = parent->time_slice_init; + child->pagemap = vmm_clone_pagemap(parent->pagemap); + if (!child->pagemap) { free(child); return NULL; } + child->cr3 = (uint64_t)pmm_virt_to_phys(child->pagemap->pml4); + child->brk_start = parent->brk_start; + child->brk_current = parent->brk_current; + child->brk_max = parent->brk_max; + child->user_rsp = parent->user_rsp; + serial_printf("[FORK-DBG2] parent pid=%u user_rsp=0x%llx user_saved_rip=0x%llx\n", + parent->pid, parent->user_rsp, parent->user_saved_rip); + + child->user_saved_rip = parent->user_saved_rip; + child->user_saved_rbp = parent->user_saved_rbp; + child->user_saved_rbx = parent->user_saved_rbx; + child->user_saved_r12 = parent->user_saved_r12; + child->user_saved_r13 = parent->user_saved_r13; + child->user_saved_r14 = parent->user_saved_r14; + child->user_saved_r15 = parent->user_saved_r15; + child->user_saved_r11 = parent->user_saved_r11 | (1ULL << 9); + + child->flags |= TASK_FLAG_FORK; + atomic_init_bool(&child->on_cpu, false); + child->rsp = alloc_and_init_stack(child); + if (!child->rsp) { + vmm_free_pagemap(child->pagemap); + free(child); + return NULL; + } + vmm_sync_kernel_mappings(child->pagemap); + serial_printf("[FORK-DBG] child pid=%u stack_base=0x%llx rsp=0x%llx\n", + child->pid, child->stack_base, child->rsp); + child->fpu_state = (fpu_state_t*)pmm_alloc_zero(1); + if (child->fpu_state && parent->fpu_state) { + memcpy(child->fpu_state, parent->fpu_state, sizeof(fpu_state_t)); + child->fpu_used = parent->fpu_used; + } + + if (parent->fd_table) + child->fd_table = fd_table_clone(parent->fd_table); + + child->state = TASK_READY; + child->runnable = true; + child->parent = parent; + + { + uint64_t _cf = spinlock_acquire_irqsave(&children_lock); + child->sibling = parent->children; + parent->children = child; + spinlock_release_irqrestore(&children_lock, _cf); + } + + pid_register(child); + + serial_printf("[FORK-CHK] child=%p rsp=0x%llx stk=0x%llx rip=0x%llx\n", + (void*)child, child->rsp, child->stack_base, child->user_saved_rip); + + serial_printf("[SCHED] fork: parent='%s' pid=%u -> child pid=%u rip=0x%llx\n", + parent->name, parent->pid, child->pid, child->user_saved_rip); + + enqueue_global(child); + return child; +} + +void task_destroy(task_t* task) { + if (!task) return; + + uint32_t old_flags = __atomic_fetch_or(&task->flags, TASK_FLAG_DESTROYED, __ATOMIC_ACQ_REL); + if (old_flags & TASK_FLAG_DESTROYED) return; + + serial_printf("[DESTROY] pid=%u flags=0x%x on_cpu=%d\n", + task->pid, task->flags, (int)atomic_load_bool_acq(&task->on_cpu)); + + pid_unregister(task); + + if (task->fpu_state) { + pmm_free(task->fpu_state, 1); + task->fpu_state = NULL; + } + + if (task->stack_base) { + pmm_free((void*)task->stack_base, KERNEL_STACK_PAGES); + task->stack_base = 0; + } + + if (task->pagemap && (task->flags & (TASK_FLAG_FORK | TASK_FLAG_OWN_PAGEMAP))) { + vmm_free_pagemap(task->pagemap); + task->pagemap = NULL; + } + + if (task->fd_table) { + fd_table_destroy(task->fd_table); + task->fd_table = NULL; + } + + free(task); +} + +void task_reparent(task_t* child, task_t* new_parent) { + if (!child || !new_parent) return; + child->parent = new_parent; + child->ppid = new_parent->pid; + child->sibling = new_parent->children; + new_parent->children = child; +} + +void task_wakeup_waiters(uint32_t pid) { + task_t* to_wake[64]; + int wake_count = 0; + + uint64_t _irqf = spinlock_acquire_irqsave(&pid_lock); + for (uint32_t i = 1; i < MAX_PIDS && wake_count < 64; i++) { + task_t* t = pid_table[i]; + if (!t) continue; + if (t->state != TASK_BLOCKED) continue; + if (t->wait_for_pid != pid && t->wait_for_pid != (uint32_t)-1) continue; + + serial_printf("[SCHED] wakeup_waiters: waking pid=%u (waited for pid=%u)\n", t->pid, pid); + + t->wait_for_pid = 0; + t->runnable = true; + t->state = TASK_READY; + + to_wake[wake_count++] = t; + } + spinlock_release_irqrestore(&pid_lock, _irqf); + + for (int i = 0; i < wake_count; i++) + enqueue_global(to_wake[i]); +} + +__attribute__((noreturn)) void task_exit(void) +{ + asm volatile("cli"); + uint32_t cpu = lapic_get_id(); + percpu_t* pc = get_percpu(); + task_t* me = pc ? (task_t*)pc->current_task : current_task[cpu]; + + if (!me) kernel_panic("task_exit: no current task"); + + serial_printf("[EXIT] task_exit called cpu=%u me=%p pid=%u\n", cpu, (void*)me, me->pid); + + task_t* init = task_find_by_pid(1); + if (init && init != me) { + uint64_t _cf = spinlock_acquire_irqsave(&children_lock); + task_t* child = me->children; + me->children = NULL; + while (child) { + task_t* sib = child->sibling; + task_reparent(child, init); + child = sib; + } + spinlock_release_irqrestore(&children_lock, _cf); + } + + vmm_switch_pagemap(vmm_get_kernel_pagemap()); + + me->runnable = false; + me->state = TASK_ZOMBIE; + me->cr3 = 0; + + task_wakeup_waiters(me->pid); + + sched_reschedule(); + + kernel_panic("task_exit: returned from sched_reschedule (should never happen)"); +} + +void task_kill(task_t* target) { + if (!target) return; + + if (target->pid == 0) return; + if (target->is_userspace == TASK_TYPE_KERNEL) return; + + if (target->state == TASK_ZOMBIE || target->state == TASK_DEAD) return; + if (target->pending_kill) return; + + serial_printf("[KILL] task_kill pid=%u state=%d cpu=%u\n", + target->pid, (int)target->state, lapic_get_id()); + target->exit_code = 130; + target->pending_kill = true; + + if (target->state == TASK_BLOCKED) { + target->wakeup_time_ns = 0; + task_unblock(target); + } + + if (!(target->flags & TASK_FLAG_STARTED)) { + return; + } + + for (uint32_t cpu = 0; cpu < smp_get_cpu_count(); cpu++) { + if (current_task[cpu] == target) { + extern uint32_t smp_get_lapic_id_for_cpu(uint32_t); + ipi_reschedule_cpu(smp_get_lapic_id_for_cpu(cpu)); + } + } +} + +volatile uint32_t g_foreground_pid = 0; + +void task_set_foreground(uint32_t pid) { + g_foreground_pid = pid; +} + +task_t* task_find_foreground(void) { + uint32_t fpid = g_foreground_pid; + if (fpid == 0) return NULL; + task_t *t = task_find_by_pid(fpid); + if (!t || t->state == TASK_ZOMBIE || t->state == TASK_DEAD) { + g_foreground_pid = 0; + return NULL; + } + return t; +} + +static task_t* sched_pick_next(uint32_t cpu) { + uint64_t _irqf; + + _irqf = spinlock_acquire_irqsave(&ready_queue_lock); + task_t* found = NULL; + for (int p = MAX_PRIORITY; p >= 0 && !found; p--) { + task_t** head = &ready_queues[p]; + task_t* t = *head; + while (t) { + if (t->runnable && t->state != TASK_ZOMBIE && t->state != TASK_DEAD) { + bool expected = false; + if (atomic_cas_bool(&t->on_cpu, &expected, true)) { + *head = t->next; + t->next = NULL; + found = t; + break; + } + } else { + if (t->state == TASK_ZOMBIE || t->state == TASK_DEAD || !t->runnable) { + *head = t->next; + t->next = NULL; + t = *head; + continue; + } + } + head = &t->next; + t = *head; + } + } + spinlock_release_irqrestore(&ready_queue_lock, _irqf); + return found ? found : &idle_tasks[cpu]; +} + +void sched_reschedule(void) { + asm volatile("cli"); + + process_deferred_free(); + + reschedule_calls++; + uint32_t cpu = lapic_get_id(); + + task_t* old = current_task[cpu]; + task_t* next = sched_pick_next(cpu); + + if (!next) { asm volatile("sti"); return; } + + if (old == next) { + if (old == &idle_tasks[cpu]) { + next = sched_pick_next(cpu); + if (next == &idle_tasks[cpu]) { + asm volatile("sti"); + return; + } + } else { + old->time_slice = old->time_slice_init; + asm volatile("sti"); + return; + } + } + + if (old && old->fpu_state && old->state != TASK_ZOMBIE && old->state != TASK_DEAD) { + fpu_save(old->fpu_state); + old->fpu_used = true; + } + + if (old && old != &idle_tasks[cpu]) { + if (old->state == TASK_ZOMBIE) { + percpu_t* pc = get_percpu(); + if (pc) pc->deferred_free_task = old; + } else if (old->runnable && old->state != TASK_DEAD) { + old->time_slice = old->time_slice_init; + old->last_cpu = cpu; + old->state = TASK_READY; + enqueue_global(old); + } + } + + uint64_t switch_cr3 = 0; + if (next->cr3 && (!old || old->cr3 != next->cr3)) { + if (next->pagemap) + vmm_sync_kernel_mappings(next->pagemap); + asm volatile("lock addl $0, (%%rsp)" ::: "memory", "cc"); + switch_cr3 = next->cr3; + } else if (!next->cr3) { + vmm_pagemap_t* kpm = vmm_get_kernel_pagemap(); + if (kpm && kpm->pml4) { + uint64_t kphys = (uint64_t)pmm_virt_to_phys(kpm->pml4); + if (!old || old->cr3 != kphys) + switch_cr3 = kphys; + } + } + + if (tss[cpu]) { + if (next->is_userspace && next->stack_base == 0) { + kernel_panic("SCHED: userspace task has stack_base=0"); + } + tss[cpu]->rsp0 = next->stack_base + KERNEL_STACK_SIZE; + percpu_t* pc = get_percpu(); + if (pc) { + pc->syscall_kernel_rsp = tss[cpu]->rsp0; + if (next->is_userspace) { + pc->syscall_user_rsp = next->user_rsp; + } + } + } + + next->cpu_id = cpu; + next->state = TASK_RUNNING; + if (next->fpu_state) fpu_restore(next->fpu_state); + + if (!(next->flags & TASK_FLAG_STARTED)) { + next->flags |= TASK_FLAG_STARTED; + current_task[cpu] = next; + if (next->cr3) { + serial_printf("[SCHED] CR3 switch cpu=%u old=0x%llx -> new=0x%llx (pid %u->%u)\n", + cpu, old ? old->cr3 : 0ULL, switch_cr3, + old ? old->pid : 0, next->pid); + asm volatile("mov %0, %%cr3" :: "r"(next->cr3) : "memory"); + switch_cr3 = 0; + } else { + asm volatile("mov %%cr3, %%rax; mov %%rax, %%cr3" ::: "rax", "memory"); + } + if (next->is_userspace) { + serial_printf("[SCHED] CPU %u: first start '%s' pid=%u entry=0x%llx user_rsp=0x%llx\n", + cpu, next->name, next->pid, + (uint64_t)next->entry, next->user_rsp); + } + } + + if (old) context_switch(old, next, ¤t_task[cpu], switch_cr3); + else context_switch(&bootstrap_tasks[cpu], next, ¤t_task[cpu], switch_cr3); + + process_deferred_free(); + + asm volatile("sti"); +} + +void task_yield(void) { + sched_reschedule(); +} + +void sched_print_stats(void) { + uint64_t _irqf; + serial_printf("[SCHED] reschedule_calls=%llu\n", reschedule_calls); + _irqf = spinlock_acquire_irqsave(&ready_queue_lock); + for (int p = MAX_PRIORITY; p >= 0; p--) { + int n = 0; + for (task_t* t = ready_queues[p]; t; t = t->next) n++; + if (n) serial_printf(" prio %d: %d tasks\n", p, n); + } + spinlock_release_irqrestore(&ready_queue_lock, _irqf); +} + +void task_unblock(task_t* t) { + if (!t) return; + t->runnable = true; + t->state = TASK_READY; + enqueue_global(t); +} + +void sched_wakeup_sleepers(uint64_t now_ns) { + task_t* to_wake[64]; + int wake_count = 0; + + uint64_t _irqf = spinlock_acquire_irqsave(&pid_lock); + for (uint32_t i = 1; i < MAX_PIDS && wake_count < 64; i++) { + task_t *t = pid_table[i]; + if (!t) continue; + if (t->state != TASK_BLOCKED) continue; + if (t->wakeup_time_ns == 0) continue; + if (now_ns >= t->wakeup_time_ns) { + t->wakeup_time_ns = 0; + t->runnable = true; + t->state = TASK_READY; + to_wake[wake_count++] = t; + } + } + spinlock_release_irqrestore(&pid_lock, _irqf); + + for (int i = 0; i < wake_count; i++) { + enqueue_global(to_wake[i]); + } +} + +static void idle_loop(void* arg) { + (void)arg; + uint32_t cpu = lapic_get_id(); + serial_printf("[IDLE] CPU %u entering idle loop\n", cpu); + while (1) { + process_deferred_free(); + asm volatile("sti; hlt"); + } +} \ No newline at end of file diff --git a/kernel/src/sched/sched_asm.asm b/kernel/src/sched/sched_asm.asm new file mode 100644 index 0000000..58c5ce7 --- /dev/null +++ b/kernel/src/sched/sched_asm.asm @@ -0,0 +1,157 @@ +section .text +extern task_exit +global context_switch +global first_task_start +global fpu_save +global fpu_restore +global task_trampoline +global task_trampoline_user +global task_trampoline_fork + +TASK_ENTRY_OFFSET equ 120 +TASK_ARG_OFFSET equ 128 +TASK_USER_RSP_OFFSET equ 144 +TASK_CR3_OFFSET equ 24 +TASK_USER_SAVED_RIP_OFFSET equ 272 +TASK_USER_SAVED_RBP_OFFSET equ 280 +TASK_USER_SAVED_RBX_OFFSET equ 288 +TASK_USER_SAVED_R12_OFFSET equ 296 +TASK_USER_SAVED_R13_OFFSET equ 304 +TASK_USER_SAVED_R14_OFFSET equ 312 +TASK_USER_SAVED_R15_OFFSET equ 320 +TASK_USER_SAVED_R11_OFFSET equ 328 + +PERCPU_CURRENT_TASK equ 24 +TASK_ON_CPU_OFFSET equ 0x158 + +context_switch: + push rbp + push rbx + push r12 + push r13 + push r14 + push r15 + + mov [rdi], rsp + + mov [rdx], rsi + mov [gs:PERCPU_CURRENT_TASK], rsi + + mov rsp, [rsi] + + test rcx, rcx + jz .skip_cr3 + mov cr3, rcx +.skip_cr3: + + lock add dword [rsp], 0 + mov byte [rdi + TASK_ON_CPU_OFFSET], 0 + + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + pop rbp + + ret + +first_task_start: + mov [gs:PERCPU_CURRENT_TASK], rdi + + mov rsi, [rdi + TASK_CR3_OFFSET] + mov rsp, [rdi] + + test rsi, rsi + jz .skip_cr3_fts + mov cr3, rsi +.skip_cr3_fts: + + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + pop rbp + + ret + +fpu_save: + fxsave [rdi] + ret + +fpu_restore: + fxrstor [rdi] + ret + +task_trampoline: + mov rdi, [rbp + TASK_ARG_OFFSET] + mov rax, [rbp + TASK_ENTRY_OFFSET] + xor rbp, rbp + sti + call rax + call task_exit +.hang: + cli + hlt + jmp .hang + +task_trampoline_user: + mov rax, [rbp + TASK_ENTRY_OFFSET] + mov rcx, [rbp + TASK_USER_RSP_OFFSET] + + xor rbp, rbp + + push qword 0x1B + push rcx + pushfq + pop rdx + or rdx, (1 << 9) + and rdx, ~(3 << 12) + push rdx + push qword 0x23 + push rax + + xor rax, rax + xor rbx, rbx + xor rcx, rcx + xor rdx, rdx + xor rdi, rdi + xor rsi, rsi + xor r8, r8 + xor r9, r9 + xor r10, r10 + xor r11, r11 + xor r12, r12 + xor r13, r13 + xor r14, r14 + xor r15, r15 + + swapgs + iretq + +task_trampoline_fork: + cli + + mov rax, [rbp + TASK_USER_SAVED_RIP_OFFSET] + mov rcx, [rbp + TASK_USER_RSP_OFFSET] + mov r11, [rbp + TASK_USER_SAVED_R11_OFFSET] + mov rbx, [rbp + TASK_USER_SAVED_RBX_OFFSET] + mov r12, [rbp + TASK_USER_SAVED_R12_OFFSET] + mov r13, [rbp + TASK_USER_SAVED_R13_OFFSET] + mov r14, [rbp + TASK_USER_SAVED_R14_OFFSET] + mov r15, [rbp + TASK_USER_SAVED_R15_OFFSET] + mov rbp, [rbp + TASK_USER_SAVED_RBP_OFFSET] + + or r11, (1 << 9) + + push qword 0x1B + push rcx + push r11 + push qword 0x23 + push rax + + xor rax, rax + + swapgs + iretq \ No newline at end of file diff --git a/kernel/src/smp/percpu.c b/kernel/src/smp/percpu.c new file mode 100644 index 0000000..aacc7bb --- /dev/null +++ b/kernel/src/smp/percpu.c @@ -0,0 +1,88 @@ +#include "../../include/smp/percpu.h" +#include "../../include/smp/smp.h" +#include "../../include/memory/pmm.h" +#include "../../include/io/serial.h" +#include +#include + +extern uintptr_t __percpu_start; +extern uintptr_t __percpu_end; + +PERCPU_SECTION percpu_t percpu = {0}; +PERCPU_SECTION int dummy_percpu = 0xDEADBEEF; + +percpu_t* percpu_regions[MAX_CPUS] = {0}; + +bool g_has_fsgsbase = false; + +#define MSR_GS_BASE 0xC0000101 +#define MSR_KERNEL_GS_BASE 0xC0000102 + +static inline uint64_t rdmsr_local(uint32_t msr) { + uint32_t lo, hi; + asm volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr)); + return ((uint64_t)hi << 32) | lo; +} + +static inline void wrmsr_local(uint32_t msr, uint64_t val) { + asm volatile("wrmsr" :: "c"(msr), "a"((uint32_t)val), "d"((uint32_t)(val >> 32))); +} + +static bool detect_fsgsbase(void) { + uint32_t eax = 7, ebx, ecx = 0, edx; + asm volatile("cpuid" + : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) + : "0"(eax), "2"(ecx)); + return (ebx & (1u << 0)) != 0; +} + +void init_percpu_regions(void) { + g_has_fsgsbase = detect_fsgsbase(); + serial_printf("[PerCPU] FSGSBASE: %s\n", g_has_fsgsbase ? "YES" : "NO (using MSR fallback)"); + + size_t percpu_size = &__percpu_end - &__percpu_start; + serial_printf("PerCPU size: %zu bytes\n", percpu_size); + + smp_info_t* info = smp_get_info(); + for (uint32_t i = 0; i < info->cpu_count; i++) { + void* region = malloc(percpu_size); + if (!region) { + serial_printf("PerCPU: Alloc failed for CPU %u\n", i); + continue; + } + memset(region, 0, percpu_size); + memcpy(region, &__percpu_start, percpu_size); + + percpu_regions[i] = (percpu_t*)region; + percpu_regions[i]->cpu_id = info->cpus[i].lapic_id; + percpu_regions[i]->syscall_kernel_rsp = 0; + percpu_regions[i]->syscall_user_rsp = 0; + + serial_printf("PerCPU region for CPU %u at 0x%llx\n", i, (uint64_t)region); + } +} + +percpu_t* get_percpu(void) { + uint64_t gs_base; + if (g_has_fsgsbase) { + asm volatile("rdgsbase %0" : "=r"(gs_base)); + } else { + gs_base = rdmsr_local(MSR_GS_BASE); + } + if (gs_base == 0) return NULL; + return (percpu_t*)gs_base; +} + +percpu_t* get_percpu_mut(void) { + return get_percpu(); +} + +void set_percpu_base(percpu_t* base) { + uint64_t val = (uint64_t)base; + if (g_has_fsgsbase) { + asm volatile("wrgsbase %0" :: "r"(val) : "memory"); + } else { + wrmsr_local(MSR_GS_BASE, val); + } + wrmsr_local(MSR_KERNEL_GS_BASE, val); +} diff --git a/kernel/src/smp/smp.c b/kernel/src/smp/smp.c new file mode 100644 index 0000000..731d310 --- /dev/null +++ b/kernel/src/smp/smp.c @@ -0,0 +1,327 @@ +#include "../../include/smp/smp.h" +#include "../../include/smp/percpu.h" +#include "../../include/acpi/acpi.h" +#include "../../include/apic/apic.h" +#include "../../include/io/serial.h" +#include "../../include/memory/pmm.h" +#include "../../include/memory/vmm.h" +#include "../../include/gdt/gdt.h" +#include "../../include/interrupts/idt.h" +#include "../../include/sse/fpu.h" +#include "../../include/sse/sse.h" +#include "../../include/sched/sched.h" +#include "../include/syscall/syscall.h" +#include +#include +#include +#include + +extern tss_t *tss[MAX_CPUS]; +extern struct { + gdt_entry_t gdt_entries[5 + (MAX_CPUS * 2)]; +} __attribute__((packed)) gdt; + +static smp_info_t smp_info = {0}; +static volatile uint32_t ap_online_count = 0; +tlb_shootdown_t tlb_shootdown_queue[MAX_CPUS] = {0}; + +volatile uint32_t sched_ready_flag = 0; + +void sched_notify_ready(void) { + __sync_synchronize(); + sched_ready_flag = 1; + __sync_synchronize(); + serial_writestring("[SCHED] Scheduler ready, notifying all APs\n"); +} + +__attribute__((used)) +void ap_entry_init(struct limine_mp_info* cpu_info) { + (void)cpu_info; + asm volatile ("cli"); + + lapic_write(0xF0, 0); + + gdt_load(); + idt_load(); + + uint32_t lapic_id = lapic_get_id(); + smp_info_t* info = smp_get_info(); + uint32_t my_index = 0; + for (uint32_t i = 0; i < info->cpu_count; i++) { + if (info->cpus[i].lapic_id == lapic_id && !info->cpus[i].is_bsp) { + my_index = i; + info->cpus[i].state = CPU_ONLINE; + break; + } + } + load_tss(info->cpus[my_index].tss_selector); + serial_printf("TSS Loaded (selector 0x%x)\n", info->cpus[my_index].tss_selector); + + fpu_init(); + sse_init(); + enable_fsgsbase(); + lapic_enable(); + apic_timer_calibrate(); + serial_printf("[SMP] AP %u LAPIC timer started\n", lapic_id); + + cpu_info_t* cpu = smp_get_current_cpu(); + percpu_t* region = percpu_regions[cpu->cpu_index]; + set_percpu_base(region); + serial_printf("PerCPU base set for AP %u: 0x%llx\n", + lapic_id, (uint64_t)region); + syscall_init(); + __sync_fetch_and_add(&ap_online_count, 1); + lapic_eoi(); + + serial_printf("[SMP] AP (LAPIC ID %u) initialized and online!\n", lapic_id); + + while (!sched_ready_flag) + asm volatile ("pause"); + + serial_printf("[SMP] AP %u entering scheduler loop\n", lapic_id); + + asm volatile ("sti"); + + sched_reschedule(); + + while (1) + asm volatile ("hlt"); +} + +void ap_entry_point(struct limine_mp_info* cpu_info) { + uint64_t stack_top; + asm volatile ( + "mov 24(%%rdi), %0" + : "=r"(stack_top) + : "D"(cpu_info) + ); + asm volatile ( + "mov %0, %%rsp\n" + "cli\n" + "jmp ap_entry_init\n" + : + : "r"(stack_top), "D"(cpu_info) + : "memory" + ); +} + +static uint64_t smp_allocate_stack(uint32_t cpu_index, size_t stack_size) { + size_t pages = (stack_size + PAGE_SIZE - 1) / PAGE_SIZE; + void* stack_pages = pmm_alloc(pages); + if (!stack_pages) { + serial_printf("[SMP WARNING] Failed to allocate stack for CPU %u\n", cpu_index); + return 0; + } + uint64_t stack_virt = (uint64_t)stack_pages + stack_size; + serial_printf("[SMP] Allocated stack for CPU %u at 0x%llx (size %zu)\n", + cpu_index, stack_virt, stack_size); + return stack_virt; +} + +void smp_boot_aps(struct limine_mp_response* mp_response) { + if (!mp_response) { + serial_writestring("[SMP ERROR] MP response is NULL\n"); + return; + } + + serial_writestring("\n[SMP] Booting Application Processors \n"); + + smp_info_t* info = smp_get_info(); + uint32_t bsp_lapic_id = info->bsp_lapic_id; + uint32_t ap_count = 0; + + for (uint64_t i = 0; i < mp_response->cpu_count; i++) { + struct limine_mp_info* cpu = mp_response->cpus[i]; + if (cpu->lapic_id == bsp_lapic_id) continue; + + uint64_t stack_top = smp_allocate_stack(i, AP_STACK_SIZE); + if (stack_top == 0) { + serial_printf("[SMP] Skipping CPU %u (stack alloc failed)\n", i); + info->cpus[i].state = CPU_FAULTED; + continue; + } + + info->cpus[i].stack_top = stack_top; + info->cpus[i].state = CPU_BOOTED; + cpu->extra_argument = stack_top; + cpu->goto_address = (void*)ap_entry_point; + + serial_printf("[SMP] Configured AP %lu (LAPIC ID %u) to boot at 0x%llx\n", + i, cpu->lapic_id, (uint64_t)ap_entry_point); + ap_count++; + } + + __sync_synchronize(); + + if (ap_count > 0) { + serial_printf("[SMP] Waiting for %u AP(s) to initialize...\n", ap_count); + uint64_t timeout = 10000000; + while (ap_online_count < ap_count && timeout--) + asm volatile ("pause"); + + uint32_t online = ap_online_count; + if (online == ap_count) + serial_printf("[SMP SUCCESS] All %u AP(s) online!\n", ap_count); + else + serial_printf("[SMP WARNING] Only %u/%u AP(s) online (timeout)\n", + online, ap_count); + info->online_count = 1 + online; + } else { + serial_writestring("[SMP] No APs to boot\n"); + } + + serial_writestring("[SMP] AP Boot Sequence Complete \n\n"); +} + +static void smp_init_limine(struct limine_mp_response* response) { + if (!response) { serial_writestring("[SMP] Limine MP response is NULL\n"); return; } + + serial_printf("[SMP] Initializing via Limine MP (CPU count: %u)\n", + response->cpu_count); + smp_info.cpu_count = response->cpu_count; + smp_info.online_count = 1; + + acpi_madt_t* madt = (acpi_madt_t*)acpi_find_table("APIC", 0); + if (madt) { + smp_info.lapic_base = madt->local_apic_address; + serial_printf("[SMP] LAPIC base from ACPI: 0x%x\n", smp_info.lapic_base); + } else { + smp_info.lapic_base = 0xFEE00000; + } + + for (uint64_t i = 0; i < response->cpu_count; i++) { + struct limine_mp_info* cpu = response->cpus[i]; + smp_info.cpus[i].lapic_id = cpu->lapic_id; + smp_info.cpus[i].processor_id = cpu->lapic_id; + smp_info.cpus[i].acpi_id = 0; + smp_info.cpus[i].state = CPU_UNINITIALIZED; + smp_info.cpus[i].is_bsp = (cpu->lapic_id == response->bsp_lapic_id); + smp_info.cpus[i].cpu_index = i; + + if (smp_info.cpus[i].is_bsp) { + smp_info.bsp_lapic_id = cpu->lapic_id; + smp_info.cpus[i].state = CPU_ONLINE; + serial_printf("[SMP] BSP detected - APIC ID: %u\n", cpu->lapic_id); + } + serial_printf("[SMP] CPU[%lu] - APIC ID: %u, Processor ID: %u, BSP: %s\n", + i, cpu->lapic_id, cpu->lapic_id, + smp_info.cpus[i].is_bsp ? "YES" : "NO"); + } +} + +void smp_init(struct limine_mp_response* mp_response) { + serial_writestring("\n[SMP] Initialization\n"); + smp_init_limine(mp_response); + + uint32_t bsp_index = 0; + for (uint32_t i = 0; i < smp_info.cpu_count; i++) + if (smp_info.cpus[i].is_bsp) { bsp_index = i; break; } + + for (uint32_t i = 0; i < smp_info.cpu_count; i++) { + tss[i] = (tss_t *)calloc(1, sizeof(tss_t)); + if (!tss[i]) { serial_printf("[SMP ERROR] FAILED to allocate TSS for CPU %u\n", i); continue; } + + tss[i]->rsp0 = smp_allocate_stack(i, KERNEL_STACK_SIZE); + tss[i]->ist[0] = smp_allocate_stack(i, KERNEL_STACK_SIZE); + tss[i]->ist[1] = smp_allocate_stack(i, KERNEL_STACK_SIZE); + tss[i]->ist[2] = smp_allocate_stack(i, KERNEL_STACK_SIZE); + tss[i]->ist[3] = smp_allocate_stack(i, KERNEL_STACK_SIZE); + tss[i]->iobase = sizeof(tss_t); + + serial_printf("TSS[%u] base: 0x%llx\n", i, (uint64_t)tss[i]); + + tss_entry_t *entry = (tss_entry_t *)&gdt.gdt_entries[5 + (i * 2)]; + entry->limit_low = sizeof(tss_t) - 1; + uint64_t addr = (uint64_t)tss[i]; + entry->base_low = addr & 0xffff; + entry->base_middle = (addr >> 16) & 0xff; + entry->access = 0x89; + entry->limit_high_and_flags = 0; + entry->base_high = (addr >> 24) & 0xff; + entry->base_higher = addr >> 32; + entry->zero = 0; + + smp_info.cpus[i].tss_selector = TSS_SELECTOR_BASE + (i * 0x10); + } + + gdtr.size = (5 + (smp_info.cpu_count * 2)) * sizeof(gdt_entry_t) - 1; + serial_printf("Reloading extended GDT on BSP...\n"); + gdt_load(); + + load_tss(smp_info.cpus[bsp_index].tss_selector); + serial_printf("BSP TSS loaded (selector 0x%x)\n", + smp_info.cpus[bsp_index].tss_selector); + + uint32_t current_lapic_id = lapic_get_id(); + serial_printf("[SMP] Current LAPIC ID: %u\n", current_lapic_id); + for (uint32_t i = 0; i < smp_info.cpu_count; i++) { + if (smp_info.cpus[i].lapic_id == current_lapic_id) { + smp_info.cpus[i].is_bsp = true; + smp_info.cpus[i].state = CPU_ONLINE; + smp_info.bsp_lapic_id = current_lapic_id; + break; + } + } + + smp_print_info(); + init_percpu_regions(); + smp_boot_aps(mp_response); + set_percpu_base(percpu_regions[bsp_index]); + serial_printf("PerCPU base set for BSP %u: 0x%llx\n", + smp_info.bsp_lapic_id, (uint64_t)percpu_regions[bsp_index]); + serial_writestring("[SMP] Initialization Complete \n\n"); +} + +smp_info_t* smp_get_info(void) { return &smp_info; } +uint32_t smp_get_cpu_count(void) { return smp_info.cpu_count; } +uint32_t smp_get_online_count(void){ return smp_info.online_count; } +bool smp_is_bsp(void) { return lapic_get_id() == smp_info.bsp_lapic_id; } + +cpu_info_t* smp_get_current_cpu(void) { + uint32_t id = lapic_get_id(); + for (uint32_t i = 0; i < smp_info.cpu_count; i++) + if (smp_info.cpus[i].lapic_id == id) return &smp_info.cpus[i]; + for (uint32_t i = 0; i < smp_info.cpu_count; i++) + if (smp_info.cpus[i].is_bsp) return &smp_info.cpus[i]; + return NULL; +} + +void smp_wait_for_ready(void) { + serial_writestring("Waiting until all APs are fully ready...\n"); + while (smp_get_online_count() < smp_get_cpu_count()) + asm volatile ("pause"); + serial_writestring("All APs ready.\n"); +} + +uint32_t smp_get_lapic_id_for_cpu(uint32_t cpu_index) { + smp_info_t* info = smp_get_info(); + if (cpu_index >= info->cpu_count) return 0xFFFFFFFF; + return info->cpus[cpu_index].lapic_id; +} + +void smp_print_info(void) { + serial_printf("\n[SMP] CPU Information \n"); + serial_printf("Total CPUs: %u\n", smp_info.cpu_count); + serial_printf("Online CPUs: %u\n", smp_info.online_count); + serial_printf("BSP APIC ID: %u\n", smp_info.bsp_lapic_id); + serial_printf("LAPIC Base: 0x%llx\n",smp_info.lapic_base); + const char* states[] = {"UNINITIALIZED","BOOTED","ONLINE","OFFLINE","FAULTED"}; + for (uint32_t i = 0; i < smp_info.cpu_count; i++) + serial_printf("CPU[%u]: APIC ID: %u, Processor ID: %u, ACPI ID: %u, State: %s, BSP: %s\n", + i, smp_info.cpus[i].lapic_id, smp_info.cpus[i].processor_id, + smp_info.cpus[i].acpi_id, states[smp_info.cpus[i].state], + smp_info.cpus[i].is_bsp ? "YES" : "NO"); + serial_printf("[SMP] End CPU Information \n"); +} + +void smp_print_info_fb(void) { + printf("[SMP] CPU Information \n"); + printf("Total CPUs: %u\n", smp_info.cpu_count); + printf("Online CPUs: %u\n", smp_info.online_count); + printf("BSP APIC ID: %u\n", smp_info.bsp_lapic_id); + const char* states[] = {"UNINITIALIZED","BOOTED","ONLINE","OFFLINE","FAULTED"}; + for (uint32_t i = 0; i < smp_info.cpu_count; i++) + printf("CPU[%u]: APIC ID: %u, State: %s, BSP: %s\n", + i, smp_info.cpus[i].lapic_id, states[smp_info.cpus[i].state], + smp_info.cpus[i].is_bsp ? "YES" : "NO"); +} \ No newline at end of file diff --git a/kernel/src/sse/fpu.c b/kernel/src/sse/fpu.c new file mode 100644 index 0000000..a70acfe --- /dev/null +++ b/kernel/src/sse/fpu.c @@ -0,0 +1,96 @@ +#include "../../include/sse/fpu.h" +#include "../../include/io/serial.h" + +#define COM1 0x3F8 + +void fpu_init(void) { + serial_writestring("[FPU] Initializing x87 FPU...\n"); + + if (!fpu_detect()) { + serial_writestring("[FPU] No FPU detected!\n"); + return; + } + + uint64_t cr0; + asm volatile("mov %%cr0, %0" : "=r"(cr0)); + + cr0 &= ~(1 << 2); + cr0 |= (1 << 1); + cr0 &= ~(1 << 3); + cr0 &= ~(1 << 5); + + asm volatile("mov %0, %%cr0" : : "r"(cr0)); + + asm volatile("finit"); + + fpu_set_control_word(0x037F); + + uint64_t cr4; + asm volatile("mov %%cr4, %0" : "=r"(cr4)); + cr4 |= (1ULL << 9); + cr4 |= (1ULL << 10); + asm volatile("mov %0, %%cr4" : : "r"(cr4)); + + uint32_t mxcsr = 0x1F80; + asm volatile("ldmxcsr %0" : : "m"(mxcsr)); + + serial_writestring("[FPU] SSE/SSE2 enabled (CR4.OSFXSR|OSXMMEXCPT)\n"); + serial_writestring("[FPU] FPU initialized successfully\n"); +} + +bool fpu_detect(void) { + uint32_t edx; + asm volatile( + "mov $1, %%eax\n" + "cpuid\n" + "mov %%edx, %0\n" + : "=r"(edx) + : + : "eax", "ebx", "ecx", "edx" + ); + return (edx & (1 << 0)) != 0; +} + +void fpu_reset(void) { + asm volatile("finit"); +} + +void fpu_set_control_word(uint16_t cw) { + asm volatile("fldcw %0" : : "m"(cw)); +} + +uint16_t fpu_get_control_word(void) { + uint16_t cw; + asm volatile("fnstcw %0" : "=m"(cw)); + return cw; +} + +void fpu_set_status_word(uint16_t sw) { + (void)sw; +} + +uint16_t fpu_get_status_word(void) { + uint16_t sw; + asm volatile("fnstsw %0" : "=m"(sw)); + return sw; +} + +void fpu_set_tag_word(uint16_t tw) { + (void)tw; +} + +uint16_t fpu_get_tag_word(void) { + struct { + uint16_t control_word; + uint16_t status_word; + uint16_t tag_word; + uint16_t fpu_ip; + uint16_t fpu_cs; + uint16_t fpu_opcode; + uint16_t fpu_dp; + uint16_t fpu_ds; + } __attribute__((packed)) fpu_env; + + asm volatile("fstenv %0" : "=m"(fpu_env)); + return fpu_env.tag_word; +} \ No newline at end of file diff --git a/kernel/src/sse/sse.c b/kernel/src/sse/sse.c new file mode 100644 index 0000000..3651272 --- /dev/null +++ b/kernel/src/sse/sse.c @@ -0,0 +1,238 @@ +#include "../../include/sse/sse.h" +#include "../../include/io/serial.h" +#include "../../include/apic/apic.h" +#include +#include + +static uint32_t cpuid_edx = 0; +static uint32_t cpuid_ecx = 0; +static uint32_t cpuid_ebx_ext = 0; +static bool features_cached = false; + +static void cpuid_cache_features(void) { + if (features_cached) return; + + uint32_t eax, ebx, ecx, edx; + asm volatile( + "mov $1, %%eax\n" + "cpuid\n" + : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) + : + : "memory" + ); + cpuid_edx = edx; + cpuid_ecx = ecx; + + uint32_t max_leaf; + asm volatile("cpuid" : "=a"(max_leaf) : "0"(0) : "ebx", "ecx", "edx"); + if (max_leaf >= 7) { + asm volatile( + "mov $7, %%eax\n" + "xor %%ecx, %%ecx\n" + "cpuid\n" + "mov %%ebx, %0\n" + : "=r"(cpuid_ebx_ext) + : + : "eax", "ecx", "edx" + ); + } + + features_cached = true; +} + +bool sse_supported(void) { cpuid_cache_features(); return (cpuid_edx & (1 << 25)) != 0; } +bool sse2_supported(void) { cpuid_cache_features(); return (cpuid_edx & (1 << 26)) != 0; } +bool sse3_supported(void) { cpuid_cache_features(); return (cpuid_ecx & (1 << 0)) != 0; } +bool ssse3_supported(void) { cpuid_cache_features(); return (cpuid_ecx & (1 << 9)) != 0; } +bool sse4_1_supported(void){ cpuid_cache_features(); return (cpuid_ecx & (1 << 19)) != 0; } +bool sse4_2_supported(void){ cpuid_cache_features(); return (cpuid_ecx & (1 << 20)) != 0; } +bool avx_supported(void) { cpuid_cache_features(); return (cpuid_ecx & (1 << 28)) != 0; } +bool avx2_supported(void) { cpuid_cache_features(); return (cpuid_ebx_ext & (1 << 5)) != 0; } +bool mmx_supported(void) { cpuid_cache_features(); return (cpuid_edx & (1 << 23)) != 0; } + +void sse_init(void) { + serial_writestring("[SSE] Initializing SSE/AVX...\n"); + + cpuid_cache_features(); + + if (!sse_supported()) { + serial_writestring("[SSE] SSE not supported — skipping SSE/AVX init\n"); + return; + } + + uint64_t cr4; + asm volatile("mov %%cr4, %0" : "=r"(cr4)); + cr4 |= (1 << 9); + cr4 |= (1 << 10); + + if (avx_supported()) { + uint32_t ecx; + asm volatile( + "mov $1, %%eax\n" + "cpuid\n" + "mov %%ecx, %0\n" + : "=r"(ecx) + : + : "eax", "ebx", "edx" + ); + if (ecx & (1 << 27)) { + serial_writestring("[SSE] AVX supported, enabling...\n"); + cr4 |= (1 << 18); + uint64_t xcr0; + asm volatile("xgetbv" : "=a"(xcr0) : "c"(0) : "edx"); + xcr0 |= (1 << 1) | (1 << 2); + asm volatile("xsetbv" : : "c"(0), "a"(xcr0), "d"(xcr0 >> 32)); + } + } + + asm volatile("mov %0, %%cr4" : : "r"(cr4)); + + sse_set_mxcsr(MXCSR_DEFAULT); + + serial_writestring("[SSE] SSE initialized successfully\n"); + if (sse_supported()) serial_writestring("[SSE] SSE: YES\n"); + if (sse2_supported()) serial_writestring("[SSE] SSE2: YES\n"); + if (sse3_supported()) serial_writestring("[SSE] SSE3: YES\n"); + if (sse4_1_supported())serial_writestring("[SSE] SSE4.1: YES\n"); + if (sse4_2_supported())serial_writestring("[SSE] SSE4.2: YES\n"); + if (avx_supported()) serial_writestring("[SSE] AVX: YES\n"); + if (mmx_supported()) serial_writestring("[SSE] MMX: YES\n"); +} + +void sse_set_mxcsr(uint32_t mxcsr) { + if (!sse_supported()) return; + asm volatile("ldmxcsr %0" : : "m"(mxcsr)); +} + +uint32_t sse_get_mxcsr(void) { + if (!sse_supported()) return 0; + uint32_t mxcsr; + asm volatile("stmxcsr %0" : "=m"(mxcsr)); + return mxcsr; +} + +void mmx_enter(void) { + if (!mmx_supported()) return; +} + +void mmx_exit(void) { + if (!mmx_supported()) return; + asm volatile("emms"); +} + +void sse_memcpy_fast(void *dest, const void *src, size_t n) { + if (!sse_supported() || n < 64) { + memcpy(dest, src, n); + return; + } + + uint8_t *d = (uint8_t *)dest; + const uint8_t *s = (const uint8_t *)src; + + size_t align_offset = (16 - ((uintptr_t)d & 0xF)) & 0xF; + if (align_offset > n) align_offset = n; + for (size_t i = 0; i < align_offset; i++) d[i] = s[i]; + d += align_offset; s += align_offset; n -= align_offset; + + size_t i; + for (i = 0; i + 64 <= n; i += 64) { + asm volatile( + "movdqu (%0), %%xmm0\n" + "movdqu 16(%0), %%xmm1\n" + "movdqu 32(%0), %%xmm2\n" + "movdqu 48(%0), %%xmm3\n" + "movdqu %%xmm0, (%1)\n" + "movdqu %%xmm1, 16(%1)\n" + "movdqu %%xmm2, 32(%1)\n" + "movdqu %%xmm3, 48(%1)\n" + : + : "r"(s + i), "r"(d + i) + : "xmm0", "xmm1", "xmm2", "xmm3", "memory" + ); + } + for (; i < n; i++) d[i] = s[i]; +} + +void sse_memset_fast(void *dest, int value, size_t n) { + if (!sse_supported() || n < 64) { + memset(dest, value, n); + return; + } + + uint8_t *d = (uint8_t *)dest; + uint8_t v = (uint8_t)value; + uint64_t pattern64 = + (uint64_t)v << 56 | (uint64_t)v << 48 | (uint64_t)v << 40 | (uint64_t)v << 32 | + (uint64_t)v << 24 | (uint64_t)v << 16 | (uint64_t)v << 8 | (uint64_t)v; + + size_t align_offset = (16 - ((uintptr_t)d & 0xF)) & 0xF; + if (align_offset > n) align_offset = n; + for (size_t i = 0; i < align_offset; i++) d[i] = v; + d += align_offset; n -= align_offset; + + asm volatile( + "movq %0, %%xmm0\n" + "punpcklqdq %%xmm0, %%xmm0\n" + : : "r"(pattern64) : "xmm0" + ); + + size_t i; + for (i = 0; i + 64 <= n; i += 64) { + asm volatile( + "movdqu %%xmm0, (%0)\n" + "movdqu %%xmm0, 16(%0)\n" + "movdqu %%xmm0, 32(%0)\n" + "movdqu %%xmm0, 48(%0)\n" + : + : "r"(d + i) + : "memory" + ); + } + for (; i < n; i++) d[i] = v; +} + +void print_simd_cpuid(void) { + printf("\n=== CPUID/SIMD INFORMATION ===\n"); + + uint32_t eax, ebx, ecx, edx; + char vendor[13] = {0}; + asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(0)); + *(uint32_t *)vendor = ebx; + *(uint32_t *)(vendor + 4) = edx; + *(uint32_t *)(vendor + 8) = ecx; + + printf("CPU Vendor: %s\n", vendor); + + asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1)); + printf("Processor Signature: 0x%08x\n", eax); + printf("Stepping: %d Model: %d Family: %d\n", + eax & 0xF, (eax >> 4) & 0xF, (eax >> 8) & 0xF); + + printf("\nSIMD Extensions:\n"); + printf("MMX: %s\n", (edx & (1 << 23)) ? "YES" : "NO"); + printf("SSE: %s\n", (edx & (1 << 25)) ? "YES" : "NO"); + printf("SSE2: %s\n", (edx & (1 << 26)) ? "YES" : "NO"); + printf("SSE3: %s\n", (ecx & (1 << 0)) ? "YES" : "NO"); + printf("SSSE3: %s\n", (ecx & (1 << 9)) ? "YES" : "NO"); + printf("SSE4.1: %s\n", (ecx & (1 << 19)) ? "YES" : "NO"); + printf("SSE4.2: %s\n", (ecx & (1 << 20)) ? "YES" : "NO"); + printf("AVX: %s\n", (ecx & (1 << 28)) ? "YES" : "NO"); + + printf("=== END OF CPUID/SIMD INFO ===\n\n"); +} + +void enable_fsgsbase(void) { + uint32_t eax = 7, ebx, ecx = 0, edx; + asm volatile("cpuid" + : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) + : "0"(eax), "2"(ecx)); + if (ebx & (1 << 0)) { + uint64_t cr4; + asm volatile("mov %%cr4, %0" : "=r"(cr4)); + cr4 |= (1ULL << 16); + asm volatile("mov %0, %%cr4" :: "r"(cr4)); + serial_printf("[FSGSBASE] Enabled on CPU %u\n", lapic_get_id()); + } else { + serial_writestring("[FSGSBASE] Not supported — using MSR fallback\n"); + } +} \ No newline at end of file diff --git a/kernel/src/syscall/disk_syscalls.c b/kernel/src/syscall/disk_syscalls.c new file mode 100644 index 0000000..b037bb0 --- /dev/null +++ b/kernel/src/syscall/disk_syscalls.c @@ -0,0 +1,431 @@ +#include "../../include/syscall/syscall.h" +#include "../../include/syscall/syscall_nums.h" +#include "../../include/syscall/errno.h" +#include "../../include/drivers/disk.h" +#include "../../include/drivers/blkdev.h" +#include "../../include/drivers/ata.h" +#include "../../include/drivers/partition.h" +#include "../../include/sched/sched.h" +#include "../../include/sched/capabilities.h" +#include "../../include/smp/percpu.h" +#include "../../include/io/serial.h" +#include "../../include/memory/pmm.h" +#include "../../include/fs/vfs.h" +#include "../../include/fs/ext2.h" +#include "../../include/fs/fat32.h" +#include +#include + +static inline task_t* disk_cur_task(void) { + percpu_t* pc = get_percpu(); + return pc ? (task_t*)pc->current_task : NULL; +} + +static int disk_strncpy_from_user(char *dst, const char *src, size_t max) { + uintptr_t addr = (uintptr_t)src; + if (addr < 0x1000ULL || addr >= 0x0000800000000000ULL) return -EFAULT; + for (size_t i = 0; i < max - 1; i++) { + dst[i] = src[i]; + if (!dst[i]) return (int)i; + } + dst[max-1] = '\0'; + return (int)(max-1); +} + +static int user_ptr_ok(uint64_t p) { + return p >= 0x1000ULL && p < 0x0000800000000000ULL; +} + +int64_t sys_disk_mount(uint64_t devname_ptr, uint64_t path_ptr, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) { + (void)a3; (void)a4; (void)a5; (void)a6; + task_t *t = disk_cur_task(); + if (!t) return -ESRCH; + if (t->uid != 0 && !(t->capabilities & (1ULL << 1))) return -EPERM; + + char devname[64], path[256]; + if (disk_strncpy_from_user(devname, (const char *)devname_ptr, sizeof(devname)) < 0) return -EFAULT; + if (disk_strncpy_from_user(path, (const char *)path_ptr, sizeof(path)) < 0) return -EFAULT; + serial_printf("[SYSCALL] disk_mount('%s', '%s') by pid=%u\n", devname, path, t->pid); + return disk_mount(devname, path); +} + +int64_t sys_disk_umount(uint64_t path_ptr, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) { + (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; + task_t *t = disk_cur_task(); + if (!t) return -ESRCH; + if (t->uid != 0 && !(t->capabilities & (1ULL << 1))) return -EPERM; + char path[256]; + if (disk_strncpy_from_user(path, (const char *)path_ptr, sizeof(path)) < 0) return -EFAULT; + return disk_umount(path); +} + +int64_t sys_disk_format(uint64_t devname_ptr, uint64_t label_ptr, + uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) +{ + (void)a3; (void)a4; (void)a5; (void)a6; + task_t *t = disk_cur_task(); + if (!t) return -ESRCH; + if (t->uid != 0 && !(t->capabilities & (1ULL << 1))) return -EPERM; + + char devname[64], label[64]; + if (disk_strncpy_from_user(devname, (const char *)devname_ptr, sizeof(devname)) < 0) return -EFAULT; + if (label_ptr) { + if (disk_strncpy_from_user(label, (const char *)label_ptr, sizeof(label)) < 0) return -EFAULT; + } else { + strncpy(label, devname, sizeof(label) - 1); + } + return disk_format(devname, label); +} + +int64_t sys_disk_info(uint64_t index, uint64_t buf_ptr, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) { + (void)a3; (void)a4; (void)a5; (void)a6; + if (!buf_ptr) return -EINVAL; + blkdev_t *dev = blkdev_get((int)index); + if (!dev || !dev->present) return -ENODEV; + struct { + char name[32]; + uint64_t sectors; + uint64_t size_bytes; + char model[41]; + uint8_t present; + uint8_t _pad[6]; + } info; + memset(&info, 0, sizeof(info)); + strncpy(info.name, dev->name, 31); + info.sectors = dev->sector_count; + info.size_bytes = dev->size_bytes; + info.present = 1; + ata_drive_t *ata = (ata_drive_t *)dev->priv; + if (ata) strncpy(info.model, ata->model, 40); + if (!user_ptr_ok(buf_ptr)) return -EFAULT; + memcpy((void *)buf_ptr, &info, sizeof(info)); + return 0; +} + +int64_t sys_disk_read_raw(uint64_t devname_ptr, uint64_t lba, uint64_t count, + uint64_t buf_ptr, uint64_t a5, uint64_t a6) +{ + (void)a5; (void)a6; + task_t *t = disk_cur_task(); + if (!t) return -ESRCH; + if (t->uid != 0 && !(t->capabilities & (1ULL << 1))) return -EPERM; + + char devname[64]; + if (disk_strncpy_from_user(devname, (const char *)devname_ptr, sizeof(devname)) < 0) return -EFAULT; + if (!user_ptr_ok(buf_ptr)) return -EFAULT; + if (count == 0 || count > 256) return -EINVAL; + + const char *name = devname; + if (strncmp(name, "/dev/", 5) == 0) name += 5; + blkdev_t *dev = blkdev_get_by_name(name); + if (!dev) return -ENODEV; + if (lba + count > dev->sector_count) return -EINVAL; + + int r = dev->ops->read_sectors(dev, lba, (uint32_t)count, (void *)buf_ptr); + if (r < 0) return r; + return (int64_t)(count * dev->sector_size); +} + +int64_t sys_disk_write_raw(uint64_t devname_ptr, uint64_t lba, uint64_t count, + uint64_t buf_ptr, uint64_t a5, uint64_t a6) +{ + (void)a5; (void)a6; + task_t *t = disk_cur_task(); + if (!t) return -ESRCH; + if (t->uid != 0 && !(t->capabilities & (1ULL << 1))) return -EPERM; + + char devname[64]; + if (disk_strncpy_from_user(devname, (const char *)devname_ptr, sizeof(devname)) < 0) return -EFAULT; + if (!user_ptr_ok(buf_ptr)) return -EFAULT; + if (count == 0 || count > 256) return -EINVAL; + + const char *name = devname; + if (strncmp(name, "/dev/", 5) == 0) name += 5; + blkdev_t *dev = blkdev_get_by_name(name); + if (!dev) return -ENODEV; + if (lba + count > dev->sector_count) return -EINVAL; + + int r = dev->ops->write_sectors(dev, lba, (uint32_t)count, (const void *)buf_ptr); + if (r < 0) return r; + if (dev->ops->flush) dev->ops->flush(dev); + return (int64_t)(count * dev->sector_size); +} + +int64_t sys_disk_partition(uint64_t devname_ptr, uint64_t specs_ptr, uint64_t nparts, + uint64_t a4, uint64_t a5, uint64_t a6) +{ + (void)a4; (void)a5; (void)a6; + task_t *t = disk_cur_task(); + if (!t) return -ESRCH; + if (t->uid != 0 && !(t->capabilities & (1ULL << 1))) return -EPERM; + + char devname[64]; + if (disk_strncpy_from_user(devname, (const char *)devname_ptr, sizeof(devname)) < 0) return -EFAULT; + if (!user_ptr_ok(specs_ptr)) return -EFAULT; + if (nparts == 0 || nparts > 4) return -EINVAL; + + const char *name = devname; + if (strncmp(name, "/dev/", 5) == 0) name += 5; + blkdev_t *dev = blkdev_get_by_name(name); + if (!dev) return -ENODEV; + + cervus_mbr_part_t specs[4]; + memset(specs, 0, sizeof(specs)); + memcpy(specs, (const void *)specs_ptr, sizeof(cervus_mbr_part_t) * nparts); + + mbr_partition_t parts[4]; + memset(parts, 0, sizeof(parts)); + for (uint64_t i = 0; i < nparts; i++) { + parts[i].boot_flag = specs[i].boot_flag ? 0x80 : 0x00; + parts[i].type = specs[i].type; + parts[i].lba_start = specs[i].lba_start; + parts[i].sector_count = specs[i].sector_count; + parts[i].chs_start[0] = 0xFE; + parts[i].chs_start[1] = 0xFF; + parts[i].chs_start[2] = 0xFF; + parts[i].chs_end[0] = 0xFE; + parts[i].chs_end[1] = 0xFF; + parts[i].chs_end[2] = 0xFF; + } + + uint32_t sig = 0xCE705CE7; + int r = partition_write_mbr(dev, parts, sig); + if (r < 0) return r; + if (dev->ops->flush) dev->ops->flush(dev); + + partition_scan(dev); + return 0; +} + +int64_t sys_disk_mkfs_fat32(uint64_t devname_ptr, uint64_t label_ptr, + uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) +{ + (void)a3; (void)a4; (void)a5; (void)a6; + task_t *t = disk_cur_task(); + if (!t) return -ESRCH; + if (t->uid != 0 && !(t->capabilities & (1ULL << 1))) return -EPERM; + + char devname[64], label[16]; + if (disk_strncpy_from_user(devname, (const char *)devname_ptr, sizeof(devname)) < 0) return -EFAULT; + if (label_ptr) { + if (disk_strncpy_from_user(label, (const char *)label_ptr, sizeof(label)) < 0) return -EFAULT; + } else { + strncpy(label, "CERVUS", sizeof(label) - 1); + label[sizeof(label) - 1] = '\0'; + } + + const char *name = devname; + if (strncmp(name, "/dev/", 5) == 0) name += 5; + blkdev_t *dev = blkdev_get_by_name(name); + if (!dev) return -ENODEV; + + return fat32_format(dev, label); +} + +int64_t sys_disk_bios_install(uint64_t a1, uint64_t a2, uint64_t a3, + uint64_t a4, uint64_t a5, uint64_t a6) { + (void)a4; (void)a5; (void)a6; + const char *disk_name = (const char *)a1; + const void *sys_data = (const void *)a2; + uint32_t sys_size = (uint32_t)a3; + + if (!disk_name || !sys_data || sys_size < 512) return -EINVAL; + + blkdev_t *dev = blkdev_get_by_name(disk_name); + if (!dev) return -ENOENT; + if (dev->sector_size != 512) return -EINVAL; + + uint8_t sector0[512]; + int r = dev->ops->read_sectors(dev, 0, 1, sector0); + if (r < 0) return r; + + uint8_t saved_timestamp[6]; + uint8_t saved_parttable[70]; + memcpy(saved_timestamp, sector0 + 218, 6); + memcpy(saved_parttable, sector0 + 440, 70); + + const uint8_t *src = (const uint8_t *)sys_data; + + memcpy(sector0, src, 512); + + memcpy(sector0 + 218, saved_timestamp, 6); + memcpy(sector0 + 440, saved_parttable, 70); + + uint64_t stage2_loc = 512; + memcpy(sector0 + 0x1A4, &stage2_loc, 8); + + uint32_t stage2_bytes = sys_size - 512; + uint32_t stage2_sectors = (stage2_bytes + 511) / 512; + + if (1 + stage2_sectors >= 2048) return -ENOSPC; + + uint8_t sector_buf[512]; + for (uint32_t i = 0; i < stage2_sectors; i++) { + uint32_t off = i * 512; + uint32_t take = (stage2_bytes - off >= 512) ? 512 : (stage2_bytes - off); + memset(sector_buf, 0, 512); + memcpy(sector_buf, src + 512 + off, take); + r = dev->ops->write_sectors(dev, 1 + i, 1, sector_buf); + if (r < 0) return r; + } + + r = dev->ops->write_sectors(dev, 0, 1, sector0); + if (r < 0) return r; + + if (dev->ops->flush) dev->ops->flush(dev); + + serial_printf("[bios-install] deployed: stage1=512B at LBA 0, stage2=%uB at LBA 1..%u\n", + stage2_bytes, stage2_sectors); + return 0; +} + +int64_t sys_disk_list_parts(uint64_t out_ptr, uint64_t max, + uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) +{ + (void)a3; (void)a4; (void)a5; (void)a6; + if (!user_ptr_ok(out_ptr)) return -EFAULT; + if (max == 0) return -EINVAL; + + cervus_part_info_t *out = (cervus_part_info_t *)out_ptr; + int total = blkdev_count(); + uint64_t written = 0; + + for (int i = 0; i < total && written < max; i++) { + blkdev_t *d = blkdev_get(i); + if (!d || !d->present) continue; + + size_t nlen = strlen(d->name); + bool is_part = false; + if (nlen >= 2) { + for (size_t k = 0; k < nlen; k++) { + if (d->name[k] >= '0' && d->name[k] <= '9') { is_part = true; break; } + } + } + cervus_part_info_t info; + memset(&info, 0, sizeof(info)); + strncpy(info.part_name, d->name, sizeof(info.part_name) - 1); + if (is_part) { + char base[32]; int bi = 0; + for (size_t k = 0; k < nlen && bi < 31; k++) { + if (d->name[k] >= '0' && d->name[k] <= '9') break; + base[bi++] = d->name[k]; + } + base[bi] = '\0'; + strncpy(info.disk_name, base, sizeof(info.disk_name) - 1); + info.part_num = (uint32_t)atoi(d->name + bi); + } else { + strncpy(info.disk_name, d->name, sizeof(info.disk_name) - 1); + info.part_num = 0; + } + info.size_bytes = d->size_bytes; + info.sector_count = d->sector_count; + info.lba_start = 0; + info.type = 0; + info.bootable = 0; + memcpy(&out[written], &info, sizeof(info)); + written++; + } + return (int64_t)written; +} + +int64_t sys_unlink(uint64_t path_ptr, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) { + (void)a2;(void)a3;(void)a4;(void)a5;(void)a6; + char path[256]; + if (disk_strncpy_from_user(path, (const char *)path_ptr, sizeof(path)) < 0) return -EFAULT; + char dirpath[256]; strncpy(dirpath, path, 255); + char *slash = NULL; + for (int i = (int)strlen(dirpath)-1; i >= 0; i--) { if (dirpath[i]=='/') { slash=&dirpath[i]; break; } } + if (!slash) return -EINVAL; + char name[256]; strncpy(name, slash+1, 255); + if (slash==dirpath) dirpath[1]='\0'; else *slash='\0'; + vnode_t *dir = NULL; + int r = vfs_lookup(dirpath, &dir); + if (r<0) return r; + if (!dir->ops || !dir->ops->unlink) { vnode_unref(dir); return -ENOSYS; } + r = dir->ops->unlink(dir, name); + vnode_unref(dir); + if (r == 0) vfs_sync_all(); + return r; +} + +int64_t sys_rmdir(uint64_t p, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) { + return sys_unlink(p,a2,a3,a4,a5,a6); +} + +int64_t sys_mkdir(uint64_t path_ptr, uint64_t mode, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) { + (void)a3;(void)a4;(void)a5;(void)a6; + char path[256]; + if (disk_strncpy_from_user(path, (const char *)path_ptr, sizeof(path)) < 0) return -EFAULT; + int r = vfs_mkdir(path, (uint32_t)mode); + if (r == 0) vfs_sync_all(); + return r; +} + +int64_t sys_rename(uint64_t old_ptr, uint64_t new_ptr, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) { + (void)a3;(void)a4;(void)a5;(void)a6; + char oldp[256], newp[256]; + if (disk_strncpy_from_user(oldp, (const char *)old_ptr, 256) < 0) return -EFAULT; + if (disk_strncpy_from_user(newp, (const char *)new_ptr, 256) < 0) return -EFAULT; + + vnode_t *src_node = NULL; + int r = vfs_lookup(oldp, &src_node); + if (r < 0) return r; + + vnode_t *dst_node = NULL; + if (vfs_lookup(newp, &dst_node) == 0) { + if (dst_node->type == VFS_NODE_DIR) { + const char *base = oldp; + for (const char *p = oldp; *p; p++) if (*p == '/') base = p + 1; + size_t dlen = strlen(newp); + if (dlen + 1 + strlen(base) < 255) { + if (newp[dlen-1] != '/') { newp[dlen] = '/'; newp[dlen+1] = '\0'; dlen++; } + strncat(newp, base, 254 - dlen); + } + } + vnode_unref(dst_node); + } + + vfs_file_t *src_f = NULL, *dst_f = NULL; + r = vfs_open(oldp, O_RDONLY, 0, &src_f); + if (r < 0) { vnode_unref(src_node); return r; } + r = vfs_open(newp, O_WRONLY | O_CREAT | O_TRUNC, src_node->mode, &dst_f); + if (r < 0) { vfs_close(src_f); vnode_unref(src_node); return r; } + char buf[512]; int64_t n; + while ((n = vfs_read(src_f, buf, sizeof(buf))) > 0) vfs_write(dst_f, buf, (size_t)n); + vfs_close(src_f); + vfs_close(dst_f); + vnode_unref(src_node); + + char dirp[256]; strncpy(dirp, oldp, 255); dirp[255] = '\0'; + char *sl = NULL; + for (int i = (int)strlen(dirp)-1; i >= 0; i--) if (dirp[i] == '/') { sl = &dirp[i]; break; } + if (sl) { + char nm[256]; strncpy(nm, sl+1, 255); + if (sl == dirp) dirp[1] = '\0'; else *sl = '\0'; + vnode_t *dir = NULL; + if (vfs_lookup(dirp, &dir) == 0) { + if (dir->ops && dir->ops->unlink) dir->ops->unlink(dir, nm); + vnode_unref(dir); + } + } + vfs_sync_all(); + return 0; +} + +int64_t sys_list_mounts(uint64_t a1, uint64_t a2, uint64_t a3, + uint64_t a4, uint64_t a5, uint64_t a6) { + (void)a3; (void)a4; (void)a5; (void)a6; + vfs_mount_info_t *out = (vfs_mount_info_t *)a1; + int max = (int)a2; + if (!out || max <= 0) return -EINVAL; + return vfs_list_mounts(out, max); +} + +int64_t sys_statvfs(uint64_t a1, uint64_t a2, uint64_t a3, + uint64_t a4, uint64_t a5, uint64_t a6) { + (void)a3; (void)a4; (void)a5; (void)a6; + const char *path = (const char *)a1; + vfs_statvfs_t *out = (vfs_statvfs_t *)a2; + if (!path || !out) return -EINVAL; + return vfs_statvfs(path, out); +} \ No newline at end of file diff --git a/kernel/src/syscall/syscall.c b/kernel/src/syscall/syscall.c new file mode 100644 index 0000000..bae9b21 --- /dev/null +++ b/kernel/src/syscall/syscall.c @@ -0,0 +1,1313 @@ +#include "../../include/syscall/syscall.h" +#include "../../include/syscall/syscall_nums.h" +#include "../../include/syscall/errno.h" +#include "../../include/acpi/acpi.h" +#include "../../include/sched/sched.h" +#include "../../include/sched/capabilities.h" +#include "../../include/smp/smp.h" +#include "../../include/smp/percpu.h" +#include "../../include/apic/apic.h" +#include "../../include/gdt/gdt.h" +#include "../../include/memory/vmm.h" +#include "../../include/memory/pmm.h" +#include "../../include/io/serial.h" +#include "../../include/fs/vfs.h" +#include "../../include/elf/elf.h" +#include "../../include/drivers/disk.h" +#include "../../include/drivers/blkdev.h" +#include "../../include/drivers/ata.h" +#include "../../include/panic/panic.h" +#include "../include/io/ports.h" +#include +#include +#include +#include + +#define MSR_EFER 0xC0000080 +#define MSR_STAR 0xC0000081 +#define MSR_LSTAR 0xC0000082 +#define MSR_SFMASK 0xC0000084 +#define EFER_SCE (1ULL << 0) +#define EFER_NXE (1ULL << 11) + +static inline uint64_t rdmsr(uint32_t msr) { + uint32_t lo, hi; + asm volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr)); + return ((uint64_t)hi << 32) | lo; +} +static inline void wrmsr(uint32_t msr, uint64_t val) { + asm volatile("wrmsr" :: "c"(msr), "a"((uint32_t)val), + "d"((uint32_t)(val >> 32))); +} + +static inline task_t* cur_task(void) { + percpu_t* pc = get_percpu(); + return pc ? (task_t*)pc->current_task : NULL; +} + +static void save_user_regs(task_t* t) { + if (!t) return; + percpu_t* pc = get_percpu(); + if (!pc) return; + t->user_rsp = pc->syscall_user_rsp; + t->user_saved_rip = pc->user_saved_rip; + t->user_saved_rbp = pc->user_saved_rbp; + t->user_saved_rbx = pc->user_saved_rbx; + t->user_saved_r12 = pc->user_saved_r12; + t->user_saved_r13 = pc->user_saved_r13; + t->user_saved_r14 = pc->user_saved_r14; + t->user_saved_r15 = pc->user_saved_r15; + t->user_saved_r11 = pc->user_saved_r11; +} + +static bool uptr_validate(const void* ptr, size_t len) { + uintptr_t addr = (uintptr_t)ptr; + if (addr < 0x1000ULL) return false; + if (addr >= 0x0000800000000000ULL) return false; + if (len > 0x0000800000000000ULL) return false; + if (len && addr + len - 1 < addr) return false; + return true; +} + +static int copy_from_user(void* dst, const void* src, size_t n) { + if (!uptr_validate(src, n)) return -EFAULT; + memcpy(dst, src, n); return 0; +} +static int copy_to_user(void* dst, const void* src, size_t n) { + if (!uptr_validate(dst, n)) return -EFAULT; + memcpy(dst, src, n); return 0; +} +static int strncpy_from_user(char* dst, const char* src, size_t max) { + if (!uptr_validate(src, 1)) return -EFAULT; + for (size_t i = 0; i < max - 1; i++) { + if ((i == 0) || (!((uintptr_t)(src+i) & 0xFFF))) + if (!uptr_validate(src+i, 1)) return -EFAULT; + dst[i] = src[i]; + if (!dst[i]) return (int)i; + } + dst[max-1] = '\0'; + return (int)(max-1); +} + +static int64_t sys_exit(uint64_t code) { + task_t* t = cur_task(); + if (t) t->exit_code = (int)(uint8_t)code; + serial_printf("[SYSCALL] exit(%llu) task='%s' pid=%u\n", + code, t?t->name:"?", t?t->pid:0); + vmm_switch_pagemap(vmm_get_kernel_pagemap()); + task_exit(); +} +static int64_t sys_exit_group(uint64_t code) { return sys_exit(code); } + +static int64_t sys_getpid(void) { task_t*t=cur_task(); return t?(int64_t)t->pid:-ESRCH; } +static int64_t sys_getppid(void) { task_t*t=cur_task(); return t?(int64_t)t->ppid:-ESRCH; } +static int64_t sys_getuid(void) { task_t*t=cur_task(); return t?(int64_t)t->uid:-ESRCH; } +static int64_t sys_getgid(void) { task_t*t=cur_task(); return t?(int64_t)t->gid:-ESRCH; } + +static int64_t sys_setuid(uint64_t u) { + task_t*t=cur_task(); if(!t) return -ESRCH; + if(t->uid!=UID_ROOT && !cap_has(t->capabilities,CAP_SETUID)) return -EPERM; + if(u>65535) return -EINVAL; + t->uid=(uint32_t)u; return 0; +} +static int64_t sys_setgid(uint64_t g) { + task_t*t=cur_task(); if(!t) return -ESRCH; + if(t->uid!=UID_ROOT && !cap_has(t->capabilities,CAP_SETUID)) return -EPERM; + if(g>65535) return -EINVAL; + t->gid=(uint32_t)g; return 0; +} + +static int64_t sys_cap_get(void) { + task_t*t=cur_task(); return t?(int64_t)t->capabilities:-ESRCH; +} +static int64_t sys_cap_drop(uint64_t mask) { + task_t*t=cur_task(); if(!t) return -ESRCH; + t->capabilities=cap_drop(t->capabilities,mask); + serial_printf("[SYSCALL] cap_drop: pid=%u caps=0x%llx\n",t->pid,t->capabilities); + return 0; +} + +static int64_t sys_task_info(uint64_t pid_arg, uint64_t buf_ptr) { + if (!buf_ptr) return -EINVAL; + task_t* target = (pid_arg==0)?cur_task():task_find_by_pid((uint32_t)pid_arg); + if (!target) return -ESRCH; + task_t* me = cur_task(); + if (me && me!=target && !cap_has(me->capabilities,CAP_TASK_INFO)) return -EPERM; + cervus_task_info_t info; memset(&info,0,sizeof(info)); + info.pid=target->pid; info.ppid=target->ppid; + info.uid=target->uid; info.gid=target->gid; + info.capabilities=target->capabilities; + info.state=(uint32_t)target->state; info.priority=(uint32_t)target->priority; + info.total_runtime_ns=target->total_runtime; + strncpy(info.name,target->name,sizeof(info.name)-1); + return copy_to_user((void*)buf_ptr,&info,sizeof(info)); +} + +static int64_t sys_task_kill(uint64_t pid_arg) { + task_t*me=cur_task(); + task_t*target=task_find_by_pid((uint32_t)pid_arg); + if (!target) return -ESRCH; + bool own=(target->ppid==(me?me->pid:0)); + if (!own && !cap_has(me?me->capabilities:0,CAP_KILL_ANY)) return -EPERM; + task_kill(target); return 0; +} + +static int64_t sys_fork(void) { + task_t*parent=cur_task(); if(!parent) return -ESRCH; + save_user_regs(parent); + task_t*child=task_fork(parent); if(!child) return -ENOMEM; + serial_printf("[SYSCALL] fork: parent pid=%u → child pid=%u\n", + parent->pid,child->pid); + return (int64_t)child->pid; +} + +static int64_t sys_yield(void) { task_yield(); return 0; } + +static int64_t sys_wait(uint64_t pid_arg, uint64_t status_ptr, uint64_t flags) { + task_t*parent=cur_task(); if(!parent) return -ESRCH; +retry:; + task_t*zombie=NULL; + { + uint64_t _cf = spinlock_acquire_irqsave(&children_lock); + task_t*child=parent->children; + bool has_children = (child != NULL); + while (child) { + bool match=(pid_arg==(uint64_t)-1)||(child->pid==(uint32_t)pid_arg); + if (match && child->state==TASK_ZOMBIE) { zombie=child; break; } + child=child->sibling; + } + spinlock_release_irqrestore(&children_lock, _cf); + + (void)has_children; + } + + if (!zombie) { + if (flags & WNOHANG) return 0; + save_user_regs(parent); + parent->wait_for_pid=(pid_arg==(uint64_t)-1)?(uint32_t)-1:(uint32_t)pid_arg; + parent->runnable=false; parent->state=TASK_BLOCKED; + if (pid_arg != (uint64_t)-1) + task_set_foreground((uint32_t)pid_arg); + + serial_printf("[WAIT] pid=%u blocking: user_rsp=0x%llx task_rsp=0x%llx\n", + parent->pid,parent->user_rsp,parent->rsp); + sched_reschedule(); goto retry; + } + + if (status_ptr) { + int status=(zombie->exit_code&0xFF)<<8; + if (copy_to_user((void*)status_ptr,&status,sizeof(int))<0) return -EFAULT; + } + uint32_t zpid=zombie->pid; + + { + uint64_t _cf = spinlock_acquire_irqsave(&children_lock); + if (parent->children == zombie) { + parent->children = zombie->sibling; + } else { + task_t *prev = parent->children; + while (prev && prev->sibling != zombie) prev = prev->sibling; + if (prev) prev->sibling = zombie->sibling; + } + zombie->sibling = NULL; + zombie->parent = NULL; + spinlock_release_irqrestore(&children_lock, _cf); + } + + serial_printf("[SYSCALL] wait: parent pid=%u reaped child pid=%u\n", + parent->pid,zpid); + + if (g_foreground_pid == zpid) + task_set_foreground(0); + task_destroy(zombie); + serial_printf("[SYSCALL] wait: task_destroy done, returning %u\n", zpid); + serial_printf("[WAIT-RET] parent pid=%u user_saved_rip=0x%llx user_rsp=0x%llx\n", + parent->pid, parent->user_saved_rip, parent->user_rsp); + return (int64_t)zpid; +} + +#define EXECVE_MAX_PATH 512 +#define EXECVE_MAX_ARGS 128 +#define EXECVE_MAX_ARGLEN 4096 +#define AT_NULL 0 +#define AT_PHDR 3 +#define AT_PHENT 4 +#define AT_PHNUM 5 +#define AT_PAGESZ 6 +#define AT_ENTRY 9 + +static uintptr_t execve_build_stack(vmm_pagemap_t *map, uintptr_t stack_top, const char *argv[], int argc, const elf_load_result_t *elf) { + size_t str_total = 0; + for (int i = 0; i < argc; i++) str_total += strlen(argv[i]) + 1; + + size_t n_auxv = 6; + size_t ptr_count = 1 + (size_t)argc + 1 + 1 + (n_auxv * 2); + size_t frame_bytes = ptr_count * 8; + + uintptr_t aligned_top = stack_top & ~(uintptr_t)0xF; + uintptr_t strings_base = (aligned_top - str_total) & ~(uintptr_t)0xF; + + uintptr_t candidate = strings_base - frame_bytes; + uintptr_t new_rsp = ((candidate - 8) & ~(uintptr_t)0xF) + 8; + + if (new_rsp + frame_bytes > strings_base) { + new_rsp -= 16; + } + + uintptr_t page_base = new_rsp & ~(uintptr_t)0xFFF; + uintptr_t page_end = (stack_top + 0xFFFULL) & ~(uintptr_t)0xFFF; + size_t total_pages = (page_end - page_base) >> 12; + size_t kbuf_size = total_pages * 0x1000; + + if (new_rsp + frame_bytes > strings_base || + strings_base + str_total > stack_top) { + return 0; + } + + uint8_t *kbuf = (uint8_t*)malloc(kbuf_size); + if (!kbuf) return 0; + memset(kbuf, 0, kbuf_size); + + uint64_t argv_user[EXECVE_MAX_ARGS + 1]; + size_t str_off = 0; + for (int i = 0; i < argc; i++) { + size_t slen = strlen(argv[i]) + 1; + memcpy(kbuf + (strings_base + str_off - page_base), argv[i], slen); + argv_user[i] = strings_base + str_off; + str_off += slen; + } + + uint64_t frame[256]; + size_t fi = 0; + frame[fi++] = (uint64_t)argc; + for (int i = 0; i < argc; i++) frame[fi++] = argv_user[i]; + frame[fi++] = 0; + frame[fi++] = 0; + frame[fi++] = AT_PHDR; frame[fi++] = elf->load_base + 0x40; + frame[fi++] = AT_PHENT; frame[fi++] = 56; + frame[fi++] = AT_PHNUM; frame[fi++] = 0; + frame[fi++] = AT_ENTRY; frame[fi++] = elf->entry; + frame[fi++] = AT_PAGESZ; frame[fi++] = 4096; + frame[fi++] = AT_NULL; frame[fi++] = 0; + + memcpy(kbuf + (new_rsp - page_base), frame, fi * 8); + + for (size_t pi = 0; pi < total_pages; pi++) { + uintptr_t virt = page_base + pi * 0x1000; + uintptr_t phys = 0; + uint64_t pf = 0; + + if (!vmm_get_page_flags(map, virt, &pf) || !(pf & VMM_PRESENT)) { + void *pg = pmm_alloc_zero(1); + if (!pg) { free(kbuf); return 0; } + phys = pmm_virt_to_phys(pg); + if (!vmm_map_page(map, virt, phys, + VMM_PRESENT | VMM_WRITE | VMM_USER | VMM_NOEXEC)) { + pmm_free(pg, 1); + free(kbuf); + return 0; + } + } else { + if (!vmm_virt_to_phys(map, virt, &phys)) + { free(kbuf); return 0; } + phys &= ~(uintptr_t)0xFFF; + } + memcpy(pmm_phys_to_virt(phys), kbuf + pi * 0x1000, 0x1000); + } + + serial_printf("[EXECVE] stack built: page_base=0x%llx rsp=0x%llx argc=%d envc=0\n", + (unsigned long long)page_base, (unsigned long long)new_rsp, argc); + free(kbuf); + return new_rsp; +} + +static int64_t sys_execve(uint64_t path_ptr, uint64_t argv_ptr, uint64_t envp_ptr) { + (void)envp_ptr; + task_t *t = cur_task(); + if (!t || !t->is_userspace) return -EPERM; + + char kpath[EXECVE_MAX_PATH]; + if (strncpy_from_user(kpath, (const char*)path_ptr, sizeof(kpath)) < 0) return -EFAULT; + if (!kpath[0]) return -ENOENT; + serial_printf("[EXECVE] pid=%u execve(\"%s\")\n", t->pid, kpath); + + const char *kargv_ptrs[EXECVE_MAX_ARGS + 1]; + char (*kargv_store)[EXECVE_MAX_ARGLEN] = malloc(EXECVE_MAX_ARGS * EXECVE_MAX_ARGLEN); + if (!kargv_store) return -ENOMEM; + int argc = 0; + + if (argv_ptr) { + for (;;) { + if (argc >= EXECVE_MAX_ARGS) { free(kargv_store); return -E2BIG; } + uint64_t uslot = argv_ptr + (uint64_t)argc * 8; + uint64_t aptr = 0; + if (copy_from_user(&aptr, (const void*)uslot, 8) < 0) + { free(kargv_store); return -EFAULT; } + if (!aptr) break; + if (strncpy_from_user(kargv_store[argc], (const char*)aptr, EXECVE_MAX_ARGLEN) < 0) + { free(kargv_store); return -EFAULT; } + kargv_ptrs[argc] = kargv_store[argc]; argc++; + } + } + kargv_ptrs[argc] = NULL; + if (argc == 0) { + strncpy(kargv_store[0], kpath, EXECVE_MAX_ARGLEN-1); + kargv_store[0][EXECVE_MAX_ARGLEN-1] = '\0'; + kargv_ptrs[0] = kargv_store[0]; kargv_ptrs[1] = NULL; argc = 1; + } + + vfs_file_t *vfile = NULL; + int vret = vfs_open(kpath, O_RDONLY, 0, &vfile); + if (vret < 0) { serial_printf("[EXECVE] open failed: %d\n",vret); free(kargv_store); return (int64_t)vret; } + vfs_stat_t st; + if (vfs_fstat(vfile,&st)<0 || st.st_size==0) { serial_printf("[EXECVE] fstat/size failed: path='%s' size=%llu\n", kpath, (unsigned long long)st.st_size); vfs_close(vfile); free(kargv_store); return -EIO; } + size_t fsize = (size_t)st.st_size; + uint8_t *elf_data = malloc(fsize); + if (!elf_data) { serial_printf("[EXECVE] malloc(%zu) failed for path='%s'\n", fsize, kpath); vfs_close(vfile); free(kargv_store); return -ENOMEM; } + int64_t nr = vfs_read(vfile, elf_data, fsize); vfs_close(vfile); + if (nr<0 || (size_t)nr!=fsize) { serial_printf("[EXECVE] read failed: path='%s' expected=%zu got=%lld\n", kpath, fsize, (long long)nr); free(elf_data); free(kargv_store); return -EIO; } + if (fsize < 4 || elf_data[0] != 0x7F || elf_data[1] != 'E' || elf_data[2] != 'L' || elf_data[3] != 'F') { + serial_printf("[EXECVE] not an ELF: path='%s' magic=%02x%02x%02x%02x\n", + kpath, + fsize > 0 ? elf_data[0] : 0, + fsize > 1 ? elf_data[1] : 0, + fsize > 2 ? elf_data[2] : 0, + fsize > 3 ? elf_data[3] : 0); + free(elf_data); free(kargv_store); return -ENOEXEC; + } + + elf_load_result_t elf = elf_load(elf_data, fsize, 0); free(elf_data); + if (elf.error != ELF_OK) { + serial_printf("[EXECVE] elf_load: %s\n",elf_strerror(elf.error)); + if (elf.pagemap) vmm_free_pagemap(elf.pagemap); + free(kargv_store); return -ENOEXEC; + } + + uintptr_t new_rsp = execve_build_stack(elf.pagemap, elf.stack_top, kargv_ptrs, argc, &elf); + free(kargv_store); + if (!new_rsp) { vmm_free_pagemap(elf.pagemap); return -ENOMEM; } + + if (t->fd_table) fd_table_cloexec(t->fd_table); + + vmm_switch_pagemap(vmm_get_kernel_pagemap()); + + vmm_pagemap_t* old_pagemap = t->pagemap; + uint32_t old_flags = t->flags; + + t->pagemap = elf.pagemap; + t->cr3 = (uint64_t)pmm_virt_to_phys(elf.pagemap->pml4); + t->flags |= TASK_FLAG_OWN_PAGEMAP; + t->flags &= ~TASK_FLAG_FORK; + t->brk_start = t->brk_current = elf.load_end; + t->brk_max = 0x0000700000000000ULL; + + t->user_rsp = new_rsp; + t->user_saved_rip = elf.entry; + t->user_saved_rbp = t->user_saved_rbx = 0; + t->user_saved_r12 = t->user_saved_r13 = t->user_saved_r14 = 0; + t->user_saved_r15 = t->user_saved_r11 = 0; + + const char *bn = kpath; + for (const char *p=kpath;*p;p++) if (*p=='/') bn=p+1; + strncpy(t->name, bn, sizeof(t->name)-1); t->name[sizeof(t->name)-1]='\0'; + + percpu_t *pc = get_percpu(); + if (pc) { + pc->syscall_user_rsp = new_rsp; + pc->user_saved_rip = elf.entry; + pc->user_saved_rbp = pc->user_saved_rbx = 0; + pc->user_saved_r12 = pc->user_saved_r13 = pc->user_saved_r14 = 0; + pc->user_saved_r15 = 0; + pc->user_saved_r11 = 0x200; + } + + if (old_pagemap && (old_flags & (TASK_FLAG_OWN_PAGEMAP|TASK_FLAG_FORK))) + vmm_free_pagemap(old_pagemap); + + asm volatile("lock addl $0, (%%rsp)" ::: "memory", "cc"); + vmm_switch_pagemap(t->pagemap); + serial_printf("[EXECVE] exec ok: entry=0x%llx rsp=0x%llx name='%s'\n", + elf.entry, new_rsp, t->name); + return 0; +} + +static int64_t sys_write(uint64_t fd, uint64_t buf_ptr, uint64_t count) { + if (count == 0) return 0; + if (count > 4096) count = 4096; + + char kbuf[4097]; + if (copy_from_user(kbuf, (const void*)buf_ptr, count) < 0) return -EFAULT; + kbuf[count] = '\0'; + + task_t *t = cur_task(); + if (t && t->fd_table) { + vfs_file_t *file = fd_get(t->fd_table, (int)fd); + if (file) + return vfs_write(file, kbuf, count); + } + + if (fd != 1 && fd != 2) return -EBADF; + + { + static bool at_line_start = true; + uint64_t i = 0; + while (i < count) { + uint64_t j = i; + while (j < count && kbuf[j] != '\n') j++; + bool has_newline = (j < count && kbuf[j] == '\n'); + + char chunk[4096 + 8]; + size_t clen = 0; + if (at_line_start && j > i) { + chunk[clen++] = '['; chunk[clen++] = 'U'; + chunk[clen++] = 'S'; chunk[clen++] = 'E'; + chunk[clen++] = 'R'; chunk[clen++] = ']'; + chunk[clen++] = ' '; + } + size_t seg = j - i; + if (seg > 0) { + __builtin_memcpy(chunk + clen, kbuf + i, seg); + clen += seg; + } + if (has_newline) { + chunk[clen++] = '\n'; + at_line_start = true; + i = j + 1; + } else { + if (seg > 0) at_line_start = false; + i = j; + } + if (clen > 0) { + serial_writebuf(chunk, clen); + printf("%.*s", (int)clen, chunk); + } + if (!has_newline) break; + } + } + return (int64_t)count; +} + +static int64_t sys_read(uint64_t fd, uint64_t buf_ptr, uint64_t count) { + if (count == 0) return 0; + if (count > 65536) count = 65536; + + task_t *t = cur_task(); + if (!t) return -ESRCH; + if (!uptr_validate((void*)buf_ptr, count)) return -EFAULT; + + vfs_file_t *file = NULL; + if (t->fd_table) file = fd_get(t->fd_table, (int)fd); + if (!file) return -EBADF; + + char kbuf[4096]; + size_t chunk = count > 4096 ? 4096 : count; + int64_t r = vfs_read(file, kbuf, chunk); + if (r <= 0) return r; + memcpy((void*)buf_ptr, kbuf, (size_t)r); + return r; +} + +static int64_t sys_open(uint64_t path_ptr, uint64_t flags, uint64_t mode) { + task_t *t = cur_task(); + if (!t) return -ESRCH; + if (!t->fd_table) return -ENOMEM; + + char kpath[VFS_MAX_PATH]; + if (strncpy_from_user(kpath, (const char*)path_ptr, sizeof(kpath)) < 0) return -EFAULT; + if (!kpath[0]) return -ENOENT; + + vfs_file_t *file = NULL; + int ret = vfs_open(kpath, (int)flags, (uint32_t)mode, &file); + if (ret < 0) return (int64_t)ret; + + int newfd = fd_alloc(t->fd_table, file, 0); + if (newfd < 0) { vfs_close(file); return -EMFILE; } + return (int64_t)newfd; +} + +static int64_t sys_close(uint64_t fd) { + task_t *t = cur_task(); + if (!t || !t->fd_table) return -EBADF; + return (int64_t)fd_close(t->fd_table, (int)fd); +} + +static int64_t sys_seek(uint64_t fd, uint64_t offset, uint64_t whence) { + task_t *t = cur_task(); + if (!t || !t->fd_table) return -EBADF; + vfs_file_t *f = fd_get(t->fd_table, (int)fd); + if (!f) return -EBADF; + return vfs_seek(f, (int64_t)offset, (int)whence); +} + +static int64_t sys_stat(uint64_t path_ptr, uint64_t stat_ptr) { + if (!stat_ptr) return -EINVAL; + char kpath[VFS_MAX_PATH]; + if (strncpy_from_user(kpath, (const char*)path_ptr, sizeof(kpath)) < 0) return -EFAULT; + vfs_stat_t st; + int r = vfs_stat(kpath, &st); + if (r < 0) return (int64_t)r; + return copy_to_user((void*)stat_ptr, &st, sizeof(st)); +} + +static int64_t sys_fstat(uint64_t fd, uint64_t stat_ptr) { + if (!stat_ptr) return -EINVAL; + task_t *t = cur_task(); + if (!t || !t->fd_table) return -EBADF; + vfs_file_t *f = fd_get(t->fd_table, (int)fd); + if (!f) return -EBADF; + vfs_stat_t st; + int r = vfs_fstat(f, &st); + if (r < 0) return (int64_t)r; + return copy_to_user((void*)stat_ptr, &st, sizeof(st)); +} + +#define IOCTL_KBUF_MAX 128 + +#define TIOCGWINSZ 0x5413 +#define TIOCGCURSOR 0x5480 +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 + +#define IOCTL_TERMIOS_SIZE 48 + +static size_t ioctl_out_size(uint64_t request) { + switch (request) { + case TIOCGWINSZ: return 8; + case TIOCGCURSOR: return 8; + case TCGETS: return IOCTL_TERMIOS_SIZE; + default: return 0; + } +} + +static size_t ioctl_in_size(uint64_t request) { + switch (request) { + case TCSETS: + case TCSETSW: + case TCSETSF: return IOCTL_TERMIOS_SIZE; + default: return 0; + } +} + +static int64_t sys_ioctl(uint64_t fd, uint64_t request, uint64_t arg_ptr) { + task_t *t = cur_task(); + if (!t || !t->fd_table) return -EBADF; + vfs_file_t *f = fd_get(t->fd_table, (int)fd); + if (!f) return -EBADF; + + size_t out_sz = ioctl_out_size(request); + size_t in_sz = ioctl_in_size(request); + + if (arg_ptr) { + size_t validate_sz = out_sz > in_sz ? out_sz : in_sz; + if (validate_sz == 0) validate_sz = IOCTL_KBUF_MAX; + if (!uptr_validate((void *)arg_ptr, validate_sz)) + return -EFAULT; + } + + char kbuf[IOCTL_KBUF_MAX]; + memset(kbuf, 0, sizeof(kbuf)); + + if (arg_ptr && in_sz > 0) { + if (copy_from_user(kbuf, (const void *)arg_ptr, in_sz) < 0) + return -EFAULT; + } + + int64_t r = vfs_ioctl(f, request, arg_ptr ? (void *)kbuf : (void *)0); + if (r < 0) return r; + + if (arg_ptr && out_sz > 0) { + if (copy_to_user((void *)arg_ptr, kbuf, out_sz) < 0) + return -EFAULT; + } + return r; +} + +static int64_t sys_readdir(uint64_t fd, uint64_t dirent_ptr) { + if (!dirent_ptr) return -EINVAL; + task_t *t = cur_task(); + if (!t || !t->fd_table) return -EBADF; + vfs_file_t *f = fd_get(t->fd_table, (int)fd); + if (!f) return -EBADF; + vfs_dirent_t kd; + int r = vfs_readdir(f, &kd); + if (r < 0) return (int64_t)r; + return copy_to_user((void*)dirent_ptr, &kd, sizeof(kd)); +} + +static int64_t sys_dup(uint64_t fd) { + task_t *t = cur_task(); + if (!t || !t->fd_table) return -EBADF; + vfs_file_t *f = fd_get(t->fd_table, (int)fd); + if (!f) return -EBADF; + if (f->vnode && f->vnode->ops && f->vnode->ops->ref) + f->vnode->ops->ref(f->vnode); + int nfd = fd_alloc(t->fd_table, f, 0); + if (nfd < 0) { + if (f->vnode && f->vnode->ops && f->vnode->ops->unref) + f->vnode->ops->unref(f->vnode); + return -EMFILE; + } + return (int64_t)nfd; +} + +static int64_t sys_dup2(uint64_t oldfd, uint64_t newfd) { + task_t *t = cur_task(); + if (!t || !t->fd_table) return -EBADF; + int r = fd_dup2(t->fd_table, (int)oldfd, (int)newfd); + return r < 0 ? (int64_t)r : (int64_t)newfd; +} + +#define PIPE_BUFSZ 4096 + +typedef struct { + char buf[PIPE_BUFSZ]; + uint32_t head, tail; + int readers, writers; + uint32_t reader_waiting_pid; + spinlock_t lock; +} pipe_shared_t; + +typedef struct { + pipe_shared_t *shared; + int end; +} pipe_vdata_t; + +static int64_t pipe_read_op(vnode_t *n, void *buf, size_t len, uint64_t off) { + (void)off; + pipe_vdata_t *vd = (pipe_vdata_t*)n->fs_data; + pipe_shared_t *ps = vd->shared; + size_t got = 0; + char *dst = (char*)buf; + while (got < len) { + if (ps->head == ps->tail) { + if (ps->writers == 0) break; + if (got > 0) break; + + task_t *me = cur_task(); + if (me) { + save_user_regs(me); + ps->reader_waiting_pid = me->pid; + me->runnable = false; + me->state = TASK_BLOCKED; + } + sched_reschedule(); + if (me) ps->reader_waiting_pid = 0; + if (me && me->pending_kill) return got > 0 ? (int64_t)got : -EINTR; + continue; + } + dst[got++] = ps->buf[ps->head]; + ps->head = (ps->head + 1) % PIPE_BUFSZ; + } + return (int64_t)got; +} + +static int64_t pipe_write_op(vnode_t *n, const void *buf, size_t len, uint64_t off) { + (void)off; + pipe_vdata_t *vd = (pipe_vdata_t*)n->fs_data; + pipe_shared_t *ps = vd->shared; + if (ps->readers == 0) return -EPIPE; + const char *src = (const char*)buf; + for (size_t i = 0; i < len; i++) { + uint32_t next = (ps->tail + 1) % PIPE_BUFSZ; + int spins = 0; + while (next == ps->head) { + if (ps->readers == 0) return (i > 0) ? (int64_t)i : -EPIPE; + task_t *me = cur_task(); + if (me) save_user_regs(me); + task_yield(); + if (me && me->pending_kill) return (i > 0) ? (int64_t)i : -EINTR; + next = (ps->tail + 1) % PIPE_BUFSZ; + spins++; + if (spins > 10000) break; + } + if (next == ps->head) { + return (i > 0) ? (int64_t)i : -EAGAIN; + } + ps->buf[ps->tail] = src[i]; + ps->tail = next; + if (ps->reader_waiting_pid) { + task_t *reader = task_find_by_pid(ps->reader_waiting_pid); + if (reader && !reader->runnable) { + task_unblock(reader); + } + } + } + return (int64_t)len; +} + +static int pipe_stat_op(vnode_t *n, vfs_stat_t *out) { + memset(out,0,sizeof(*out)); + out->st_ino = n->ino; + out->st_type = VFS_NODE_PIPE; + return 0; +} + +static void pipe_ref_op(vnode_t *n) { (void)n; } + +static void pipe_unref_op(vnode_t *n) { + pipe_vdata_t *vd = (pipe_vdata_t*)n->fs_data; + pipe_shared_t *ps = vd->shared; + if (vd->end == 0) ps->readers--; + else { + ps->writers--; + if (ps->reader_waiting_pid) { + task_t *reader = task_find_by_pid(ps->reader_waiting_pid); + if (reader && !reader->runnable) { + task_unblock(reader); + } + ps->reader_waiting_pid = 0; + } + } + + int r = ps->readers; + int w = ps->writers; + + free(vd); free(n); + + if (r <= 0 && w <= 0) + free(ps); +} + +static const vnode_ops_t pipe_read_ops = { + .read = pipe_read_op, + .stat = pipe_stat_op, + .ref = pipe_ref_op, + .unref = pipe_unref_op, +}; +static const vnode_ops_t pipe_write_ops = { + .write = pipe_write_op, + .stat = pipe_stat_op, + .ref = pipe_ref_op, + .unref = pipe_unref_op, +}; + +static int64_t sys_pipe(uint64_t fds_ptr) { + if (!uptr_validate((void*)fds_ptr, 2*sizeof(int))) return -EFAULT; + + task_t *t = cur_task(); + if (!t || !t->fd_table) return -ENOMEM; + + pipe_shared_t *ps = (pipe_shared_t*)malloc(sizeof(pipe_shared_t)); + if (!ps) return -ENOMEM; + memset(ps, 0, sizeof(*ps)); + ps->readers = 1; ps->writers = 1; + + vnode_t *rv = (vnode_t*) malloc(sizeof(vnode_t)); + vnode_t *wv = (vnode_t*) malloc(sizeof(vnode_t)); + pipe_vdata_t*rd = (pipe_vdata_t*)malloc(sizeof(pipe_vdata_t)); + pipe_vdata_t*wd = (pipe_vdata_t*)malloc(sizeof(pipe_vdata_t)); + if (!rv||!wv||!rd||!wd) { + free(ps);free(rv);free(wv);free(rd);free(wd); return -ENOMEM; + } + memset(rv,0,sizeof(*rv)); memset(wv,0,sizeof(*wv)); + rd->shared=ps; rd->end=0; + wd->shared=ps; wd->end=1; + + static uint64_t pipe_ino = 0x10000; + rv->type=VFS_NODE_PIPE; rv->mode=0600; rv->ino=pipe_ino++; + rv->ops=&pipe_read_ops; rv->fs_data=rd; rv->refcount=1; + wv->type=VFS_NODE_PIPE; wv->mode=0600; wv->ino=pipe_ino++; + wv->ops=&pipe_write_ops; wv->fs_data=wd; wv->refcount=1; + + vfs_file_t *rf = vfs_file_alloc(); + vfs_file_t *wf = vfs_file_alloc(); + if (!rf||!wf) { + free(ps);free(rv);free(wv);free(rd);free(wd); + if(rf) vfs_file_free(rf); + if(wf) vfs_file_free(wf); + return -ENOMEM; + } + rf->vnode=rv; rf->flags=O_RDONLY; rf->offset=0; rf->refcount=1; + wf->vnode=wv; wf->flags=O_WRONLY; wf->offset=0; wf->refcount=1; + + int rfd = fd_alloc(t->fd_table, rf, 0); + int wfd = fd_alloc(t->fd_table, wf, 0); + if (rfd<0||wfd<0) { + fd_close(t->fd_table,rfd); fd_close(t->fd_table,wfd); return -EMFILE; + } + + int fds[2] = {rfd, wfd}; + memcpy((void*)fds_ptr, fds, sizeof(fds)); + return 0; +} + +#define F_GETFD 1 +#define F_SETFD 2 +#define F_GETFL 3 +#define F_SETFL 4 + +static int64_t sys_fcntl(uint64_t fd, uint64_t cmd, uint64_t arg) { + task_t *t = cur_task(); + if (!t || !t->fd_table) return -EBADF; + vfs_file_t *f = fd_get(t->fd_table, (int)fd); + if (!f) return -EBADF; + switch (cmd) { + case F_GETFD: return (int64_t)fd_get_flags(t->fd_table,(int)fd); + case F_SETFD: return (int64_t)fd_set_flags(t->fd_table,(int)fd,(int)arg); + case F_GETFL: return (int64_t)f->flags; + case F_SETFL: f->flags=(f->flags & O_ACCMODE)|((int)arg & ~O_ACCMODE); return 0; + default: return -EINVAL; + } +} + +static int64_t sys_brk(uint64_t new_brk) { + task_t *t = cur_task(); + if (!t || !t->is_userspace) return -EINVAL; + if (!new_brk) return (int64_t)t->brk_current; + if (new_brk < t->brk_start || new_brk > t->brk_max) return (int64_t)t->brk_current; + + uintptr_t old_brk = t->brk_current; + uintptr_t old_page = (old_brk + 0xFFFULL) & ~0xFFFULL; + uintptr_t new_page = (new_brk + 0xFFFULL) & ~0xFFFULL; + + if (new_brk > old_brk) { + for (uintptr_t p = old_page; p < new_page; p += 0x1000) { + void *ph = pmm_alloc_zero(1); + if (!ph) return (int64_t)t->brk_current; + if (!vmm_map_page(t->pagemap, p, pmm_virt_to_phys(ph), + VMM_PRESENT|VMM_WRITE|VMM_USER|VMM_NOEXEC)) + { pmm_free(ph,1); return (int64_t)t->brk_current; } + } + } else { + for (uintptr_t p = new_page; p < old_page; p += 0x1000) + vmm_unmap_page(t->pagemap, p); + } + t->brk_current = new_brk; + return (int64_t)new_brk; +} + +static int64_t sys_mmap(uint64_t hint, uint64_t length, uint64_t prot, uint64_t flags, uint64_t fd, uint64_t offset) { + (void)offset; + task_t *t = cur_task(); + if (!t || !t->is_userspace) return (int64_t)MAP_FAILED; + if (!(flags & MAP_ANONYMOUS)) return (int64_t)MAP_FAILED; + if (fd!=(uint64_t)-1 && fd!=0) return (int64_t)MAP_FAILED; + if (!length) return (int64_t)MAP_FAILED; + + size_t pages = (length + 0xFFFULL) >> 12; + uintptr_t addr; + if (flags & MAP_FIXED) addr = hint & ~0xFFFULL; + else if (hint) addr = hint & ~0xFFFULL; + else { addr = (t->brk_max - (uint64_t)pages*0x1000) & ~0xFFFULL; t->brk_max = addr; } + + uint64_t vf = VMM_PRESENT|VMM_USER; + if (prot & PROT_WRITE) vf |= VMM_WRITE; + if (!(prot & PROT_EXEC)) vf |= VMM_NOEXEC; + + for (size_t i = 0; i < pages; i++) { + void *ph = pmm_alloc_zero(1); + if (!ph) { for (size_t j=0;jpagemap,addr+j*0x1000); return (int64_t)MAP_FAILED; } + if (!vmm_map_page(t->pagemap, addr+i*0x1000, pmm_virt_to_phys(ph), vf)) { + pmm_free(ph,1); for(size_t j=0;jpagemap,addr+j*0x1000); return (int64_t)MAP_FAILED; + } + } + serial_printf("[SYSCALL] mmap: addr=0x%llx pages=%zu prot=0x%llx\n", addr, pages, prot); + return (int64_t)addr; +} + +static int64_t sys_munmap(uint64_t addr, uint64_t length) { + task_t *t = cur_task(); + if (!t||!t->is_userspace||addr&0xFFF||!length) return -EINVAL; + size_t pages = (length+0xFFFULL)>>12; + for (size_t i=0;ipagemap, addr+i*0x1000); + return 0; +} + +static int64_t sys_uptime(void) { return (int64_t)hpet_elapsed_ns(); } + +static int64_t sys_meminfo(uint64_t buf_ptr) { + if (!buf_ptr) return -EINVAL; + cervus_meminfo_t info; + + uint64_t usable = (uint64_t)pmm_get_usable_pages() * PAGE_SIZE; + uint64_t free = (uint64_t)pmm_get_free_pages() * PAGE_SIZE; + uint64_t used = (uint64_t)pmm_get_used_pages() * PAGE_SIZE; + + if (free > usable) free = usable; + if (used > usable) used = usable; + + info.total_bytes = usable; + info.free_bytes = free; + info.used_bytes = used; + info.usable_bytes = usable; + info.page_size = PAGE_SIZE; + return copy_to_user((void*)buf_ptr, &info, sizeof(info)); +} + +static int64_t sys_sleep_ns(uint64_t ns) { + if (ns == 0) return 0; + if (!hpet_is_available()) { + task_yield(); + return 0; + } + task_t *me = cur_task(); + if (!me) return -ESRCH; + + save_user_regs(me); + + serial_printf("[SLEEP] pid=%u sleeping %llu ns\n", me->pid, ns); + + uint64_t now = hpet_elapsed_ns(); + me->wakeup_time_ns = now + ns; + me->runnable = false; + me->state = TASK_BLOCKED; + + sched_reschedule(); + + serial_printf("[SLEEP] pid=%u woke up\n", me ? me->pid : 0); + return 0; +} + +static int _rtc_bcd2bin(int v) { return (v & 0x0F) + ((v >> 4) * 10); } + +static uint8_t _cmos_read(uint8_t reg) { + outb(0x70, reg & 0x7F); + io_wait(); + return inb(0x71); +} + +static bool _rtc_updating(void) { + outb(0x70, 0x0A); + io_wait(); + return (inb(0x71) & 0x80) != 0; +} + +static int64_t _rtc_read_unix(void) { + for (int i = 0; i < 1000 && _rtc_updating(); i++) + io_wait(); + + uint8_t sec, min, hour, mday, mon, year; + uint8_t sec2, min2; + do { + sec = _cmos_read(0x00); + min = _cmos_read(0x02); + hour = _cmos_read(0x04); + mday = _cmos_read(0x07); + mon = _cmos_read(0x08); + year = _cmos_read(0x09); + sec2 = _cmos_read(0x00); + min2 = _cmos_read(0x02); + } while (sec != sec2 || min != min2); + + uint8_t regb = _cmos_read(0x0B); + int binary_mode = (regb & 0x04); + int hour24 = (regb & 0x02); + + if (!binary_mode) { + sec = (uint8_t)_rtc_bcd2bin(sec); + min = (uint8_t)_rtc_bcd2bin(min); + mday = (uint8_t)_rtc_bcd2bin(mday); + mon = (uint8_t)_rtc_bcd2bin(mon); + year = (uint8_t)_rtc_bcd2bin(year); + if (!hour24 && (hour & 0x80)) + hour = (uint8_t)(_rtc_bcd2bin(hour & 0x7F) + 12); + else + hour = (uint8_t)_rtc_bcd2bin(hour); + } + + int iyear = year + ((year < 70) ? 2000 : 1900); + + if (sec > 59 || min > 59 || hour > 23) return 0; + if (mday < 1 || mday > 31) return 0; + if (mon < 1 || mon > 12) return 0; + if (iyear < 2000) return 0; + + static const int mdays[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + #define IS_LEAP(y) (((y)%4==0 && (y)%100!=0) || (y)%400==0) + + int64_t days = 0; + for (int y = 1970; y < iyear; y++) + days += IS_LEAP(y) ? 366 : 365; + for (int m = 1; m < (int)mon; m++) + days += mdays[m-1] + (m == 2 && IS_LEAP(iyear) ? 1 : 0); + days += mday - 1; + + return days * 86400LL + (int64_t)hour*3600LL + (int64_t)min*60LL + (int64_t)sec; +} + +static volatile int64_t g_rtc_base_sec = 0; +static volatile uint64_t g_rtc_base_ns = 0; +static volatile bool g_rtc_initialized = false; + +static void _ensure_rtc_base(void) { + if (g_rtc_initialized) return; + int64_t t = _rtc_read_unix(); + if (t > 0) { + g_rtc_base_sec = t; + g_rtc_base_ns = hpet_elapsed_ns(); + g_rtc_initialized = true; + } +} + +static int64_t sys_clock_get(uint64_t id, uint64_t ts_ptr) { + (void)id; + if (!ts_ptr) return -EINVAL; + + cervus_timespec_t ts; + + if (id == 1) { + uint64_t ns = hpet_elapsed_ns(); + ts.tv_sec = (int64_t)(ns / 1000000000ULL); + ts.tv_nsec = (int64_t)(ns % 1000000000ULL); + } else { + _ensure_rtc_base(); + + if (g_rtc_initialized) { + uint64_t now_ns = hpet_elapsed_ns(); + uint64_t delta = now_ns - g_rtc_base_ns; + int64_t real_s = g_rtc_base_sec + (int64_t)(delta / 1000000000ULL); + uint64_t real_ns = delta % 1000000000ULL; + ts.tv_sec = real_s; + ts.tv_nsec = (int64_t)real_ns; + } else { + uint64_t ns = hpet_elapsed_ns(); + ts.tv_sec = (int64_t)(ns / 1000000000ULL); + ts.tv_nsec = (int64_t)(ns % 1000000000ULL); + } + } + + return copy_to_user((void*)ts_ptr, &ts, sizeof(ts)); +} + +static int64_t sys_dbg_print(uint64_t str, uint64_t len) { + task_t *t = cur_task(); if (!t) return -ESRCH; + if (t->uid!=UID_ROOT && !cap_has(t->capabilities,CAP_DBG_SERIAL)) return -EPERM; + if (!len) return 0; + if (len>512) len=512; + char kbuf[513]; + if (copy_from_user(kbuf,(const void*)str,len)<0) return -EFAULT; + kbuf[len]='\0'; serial_printf("[DBG pid=%u] %s",t->pid,kbuf); + return (int64_t)len; +} + +static int64_t sys_ioport_read(uint64_t port, uint64_t width) { + task_t *t=cur_task(); if(!t||!cap_has(t->capabilities,CAP_IOPORT)) return -EPERM; + if (port>0xFFFF) return -EINVAL; + uint64_t v=0; + switch(width){ + case 1:{uint8_t x;asm volatile("inb %w1,%b0":"=a"(x):"Nd"((uint16_t)port));v=x;break;} + case 2:{uint16_t x;asm volatile("inw %w1,%w0":"=a"(x):"Nd"((uint16_t)port));v=x;break;} + case 4:{uint32_t x;asm volatile("inl %w1,%k0":"=a"(x):"Nd"((uint16_t)port));v=x;break;} + default:return -EINVAL; + } + return (int64_t)v; +} +static int64_t sys_ioport_write(uint64_t port, uint64_t width, uint64_t val) { + task_t *t=cur_task(); if(!t||!cap_has(t->capabilities,CAP_IOPORT)) return -EPERM; + if (port>0xFFFF) return -EINVAL; + switch(width){ + case 1:asm volatile("outb %b0,%w1"::"a"((uint8_t)val),"Nd"((uint16_t)port));break; + case 2:asm volatile("outw %w0,%w1"::"a"((uint16_t)val),"Nd"((uint16_t)port));break; + case 4:asm volatile("outl %k0,%w1"::"a"((uint32_t)val),"Nd"((uint16_t)port));break; + default:return -EINVAL; + } + return 0; +} + +static int64_t sys_shutdown(void) { + task_t *t = cur_task(); + if (t && t->uid != 0) return -EPERM; + serial_writestring("[SYSCALL] shutdown requested\n"); + vfs_sync_all(); + acpi_shutdown(); + return 0; +} + +static int64_t sys_reboot(void) { + task_t *t = cur_task(); + if (t && t->uid != 0) return -EPERM; + serial_writestring("[SYSCALL] reboot requested\n"); + vfs_sync_all(); + acpi_reboot(); + return 0; +} + +typedef int64_t (*syscall_fn_t)(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); + +#define W0(fn) static int64_t _##fn(uint64_t a,uint64_t b,uint64_t c,uint64_t d,uint64_t e,uint64_t f){(void)a;(void)b;(void)c;(void)d;(void)e;(void)f;return fn();} +#define W1(fn) static int64_t _##fn(uint64_t a,uint64_t b,uint64_t c,uint64_t d,uint64_t e,uint64_t f){(void)b;(void)c;(void)d;(void)e;(void)f;return fn(a);} +#define W2(fn) static int64_t _##fn(uint64_t a,uint64_t b,uint64_t c,uint64_t d,uint64_t e,uint64_t f){(void)c;(void)d;(void)e;(void)f;return fn(a,b);} +#define W3(fn) static int64_t _##fn(uint64_t a,uint64_t b,uint64_t c,uint64_t d,uint64_t e,uint64_t f){(void)d;(void)e;(void)f;return fn(a,b,c);} +#define W6(fn) static int64_t _##fn(uint64_t a,uint64_t b,uint64_t c,uint64_t d,uint64_t e,uint64_t f){return fn(a,b,c,d,e,f);} + +W1(sys_exit) W1(sys_exit_group) +W0(sys_getpid) W0(sys_getppid) +W0(sys_getuid) W0(sys_getgid) +W1(sys_setuid) W1(sys_setgid) +W0(sys_fork) W0(sys_yield) +W0(sys_cap_get) W1(sys_cap_drop) +W2(sys_task_info) W1(sys_task_kill) +W3(sys_read) W3(sys_write) +W3(sys_open) W1(sys_close) +W3(sys_seek) W2(sys_stat) +W2(sys_fstat) W1(sys_dup) +W2(sys_dup2) W1(sys_pipe) +W3(sys_fcntl) +W3(sys_ioctl) +W2(sys_readdir) +W1(sys_brk) W6(sys_mmap) +W2(sys_munmap) +W2(sys_clock_get) W1(sys_sleep_ns) W0(sys_uptime) W1(sys_meminfo) +W2(sys_dbg_print) +W2(sys_ioport_read) W3(sys_ioport_write) +W0(sys_shutdown) W0(sys_reboot) + +extern int64_t sys_disk_mount(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_disk_umount(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_disk_format(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_disk_info(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_disk_read_raw(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_disk_write_raw(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_disk_partition(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_disk_mkfs_fat32(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_disk_list_parts(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_disk_bios_install(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_unlink(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_rmdir(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_mkdir(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_rename(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_list_mounts(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +extern int64_t sys_statvfs(uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); + +static int64_t _sys_execve(uint64_t a,uint64_t b,uint64_t c,uint64_t d,uint64_t e,uint64_t f){(void)d;(void)e;(void)f;return sys_execve(a,b,c);} +static int64_t _sys_wait (uint64_t a,uint64_t b,uint64_t c,uint64_t d,uint64_t e,uint64_t f){(void)d;(void)e;(void)f;return sys_wait(a,b,c);} + +static const syscall_fn_t syscall_table[SYSCALL_TABLE_SIZE] = { + [SYS_EXIT] = _sys_exit, + [SYS_EXIT_GROUP] = _sys_exit_group, + [SYS_GETPID] = _sys_getpid, + [SYS_GETPPID] = _sys_getppid, + [SYS_GETUID] = _sys_getuid, + [SYS_GETGID] = _sys_getgid, + [SYS_SETUID] = _sys_setuid, + [SYS_SETGID] = _sys_setgid, + [SYS_FORK] = _sys_fork, + [SYS_EXECVE] = _sys_execve, + [SYS_WAIT] = _sys_wait, + [SYS_YIELD] = _sys_yield, + [SYS_CAP_GET] = _sys_cap_get, + [SYS_CAP_DROP] = _sys_cap_drop, + [SYS_TASK_INFO] = _sys_task_info, + [SYS_TASK_KILL] = _sys_task_kill, + [SYS_READ] = _sys_read, + [SYS_WRITE] = _sys_write, + [SYS_OPEN] = _sys_open, + [SYS_CLOSE] = _sys_close, + [SYS_SEEK] = _sys_seek, + [SYS_STAT] = _sys_stat, + [SYS_FSTAT] = _sys_fstat, + [SYS_IOCTL] = _sys_ioctl, + [SYS_DUP] = _sys_dup, + [SYS_DUP2] = _sys_dup2, + [SYS_PIPE] = _sys_pipe, + [SYS_FCNTL] = _sys_fcntl, + [SYS_READDIR] = _sys_readdir, + [SYS_BRK] = _sys_brk, + [SYS_MMAP] = _sys_mmap, + [SYS_MUNMAP] = _sys_munmap, + [SYS_CLOCK_GET] = _sys_clock_get, + [SYS_SLEEP_NS] = _sys_sleep_ns, + [SYS_UPTIME] = _sys_uptime, + [SYS_MEMINFO] = _sys_meminfo, + [SYS_DBG_PRINT] = _sys_dbg_print, + [SYS_IOPORT_READ] = _sys_ioport_read, + [SYS_IOPORT_WRITE] = _sys_ioport_write, + [SYS_SHUTDOWN] = _sys_shutdown, + [SYS_REBOOT] = _sys_reboot, + [SYS_DISK_MOUNT] = sys_disk_mount, + [SYS_DISK_UMOUNT] = sys_disk_umount, + [SYS_DISK_FORMAT] = sys_disk_format, + [SYS_DISK_INFO] = sys_disk_info, + [SYS_UNLINK] = sys_unlink, + [SYS_RMDIR] = sys_rmdir, + [SYS_MKDIR] = sys_mkdir, + [SYS_RENAME] = sys_rename, + [SYS_DISK_READ_RAW] = sys_disk_read_raw, + [SYS_DISK_WRITE_RAW] = sys_disk_write_raw, + [SYS_DISK_PARTITION] = sys_disk_partition, + [SYS_DISK_MKFS_FAT32] = sys_disk_mkfs_fat32, + [SYS_DISK_LIST_PARTS] = sys_disk_list_parts, + [SYS_DISK_BIOS_INSTALL] = sys_disk_bios_install, + [SYS_LIST_MOUNTS] = sys_list_mounts, + [SYS_STATVFS] = sys_statvfs, +}; + +__attribute__((noreturn)) void sysret_bad_rip_panic(uint64_t bad_rip, uint64_t retval) { + task_t *t = cur_task(); + serial_printf("[SYSRET-PANIC] Non-canonical user RIP=0x%llx before SYSRET!\n" + " syscall retval=0x%llx task=%s pid=%u\n" + " user_saved_rip=0x%llx user_rsp=0x%llx cr3=0x%llx\n", + bad_rip, retval, + t ? t->name : "?", t ? t->pid : 0, + t ? t->user_saved_rip : 0, + t ? t->user_rsp : 0, + t ? t->cr3 : 0); + kernel_panic("SYSRET: non-canonical user RIP — would have caused triple fault"); +} + +__attribute__((noreturn)) void sysret_bad_rsp_panic(uint64_t bad_rsp, uint64_t user_rip) { + task_t *t = cur_task(); + serial_printf("[SYSRET-PANIC] Non-canonical user RSP=0x%llx before SYSRET!\n" + " user_rip=0x%llx task=%s pid=%u\n" + " user_saved_rip=0x%llx user_rsp=0x%llx cr3=0x%llx\n", + bad_rsp, user_rip, + t ? t->name : "?", t ? t->pid : 0, + t ? t->user_saved_rip : 0, + t ? t->user_rsp : 0, + t ? t->cr3 : 0); + kernel_panic("SYSRET: non-canonical user RSP — would have caused triple fault"); +} + +int64_t syscall_handler_c(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t user_rip) { + (void)user_rip; + task_t *t = cur_task(); + if (t) { + save_user_regs(t); + } + if (nr >= SYSCALL_TABLE_SIZE || !syscall_table[nr]) { + serial_printf("[SYSCALL] unknown nr=%llu\n", nr); + return -ENOSYS; + } + + int64_t ret = syscall_table[nr](a1, a2, a3, a4, a5, 0); + + task_t *me = cur_task(); + if (me && me->pending_kill) { + me->pending_kill = false; + me->exit_code = 130; + vmm_switch_pagemap(vmm_get_kernel_pagemap()); + task_exit(); + } + return ret; +} + +void syscall_init(void) { + extern void syscall_entry(void); + + wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SCE | EFER_NXE); + + uint64_t star = ((uint64_t)GDT_STAR_SYSRET_BASE << 48) + | ((uint64_t)GDT_STAR_SYSCALL_CS << 32); + wrmsr(MSR_STAR, star); + wrmsr(MSR_LSTAR, (uint64_t)syscall_entry); + wrmsr(MSR_SFMASK, (1U << 9) | (1U << 10) | (1U << 8) | (1U << 18)); + + percpu_t *pc = get_percpu(); + if (!pc) { + serial_printf("[SYSCALL] WARNING: no percpu, skipping kernel_rsp\n"); + return; + } + + extern tss_t *tss[MAX_CPUS]; + cpu_info_t *cpu_info = smp_get_current_cpu(); + if (!cpu_info) return; + + uint32_t idx = cpu_info->cpu_index; + if (idx < MAX_CPUS && tss[idx]) { + pc->syscall_kernel_rsp = tss[idx]->rsp0; + serial_printf("[SYSCALL] CPU %u (index %u): kernel_rsp=0x%llx\n", + pc->cpu_id, idx, pc->syscall_kernel_rsp); + } +} \ No newline at end of file diff --git a/kernel/src/syscall/syscall_asm.asm b/kernel/src/syscall/syscall_asm.asm new file mode 100644 index 0000000..883602f --- /dev/null +++ b/kernel/src/syscall/syscall_asm.asm @@ -0,0 +1,145 @@ +section .text +global syscall_entry +extern syscall_handler_c +extern sched_reschedule + +PERCPU_KERNEL_RSP equ 0 +PERCPU_USER_RSP equ 8 +PERCPU_SAVED_RBP equ 48 +PERCPU_SAVED_RBX equ 56 +PERCPU_SAVED_R12 equ 64 +PERCPU_SAVED_R13 equ 72 +PERCPU_SAVED_R14 equ 80 +PERCPU_SAVED_R15 equ 88 +PERCPU_SAVED_R11 equ 96 +PERCPU_SAVED_RIP equ 104 +PERCPU_NEED_RESCHED equ 40 +PERCPU_CURRENT_TASK equ 24 + +TASK_USER_RSP equ 144 +TASK_USER_SAVED_RIP equ 272 +TASK_USER_SAVED_RBP equ 280 +TASK_USER_SAVED_RBX equ 288 +TASK_USER_SAVED_R12 equ 296 +TASK_USER_SAVED_R13 equ 304 +TASK_USER_SAVED_R14 equ 312 +TASK_USER_SAVED_R15 equ 320 +TASK_USER_SAVED_R11 equ 328 + +syscall_entry: + swapgs + mov [gs:PERCPU_USER_RSP], rsp + mov [gs:PERCPU_SAVED_RBP], rbp + mov [gs:PERCPU_SAVED_RBX], rbx + mov [gs:PERCPU_SAVED_R12], r12 + mov [gs:PERCPU_SAVED_R13], r13 + mov [gs:PERCPU_SAVED_R14], r14 + mov [gs:PERCPU_SAVED_R15], r15 + mov [gs:PERCPU_SAVED_R11], r11 + mov [gs:PERCPU_SAVED_RIP], rcx + mov rsp, [gs:PERCPU_KERNEL_RSP] + + push r11 + push rcx + push rbx + push r12 + push r13 + push r14 + push r15 + push rbp + + push rcx + mov rcx, rdx + mov r9, r8 + mov r8, r10 + mov rdx, rsi + mov rsi, rdi + mov rdi, rax + call syscall_handler_c + + add rsp, 8 + pop rbp + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + pop rcx + pop r11 + +.check_resched: + cmp byte [gs:PERCPU_NEED_RESCHED], 0 + je .no_resched + mov byte [gs:PERCPU_NEED_RESCHED], 0 + push rax + call sched_reschedule + pop rax + jmp .check_resched + +.no_resched: + cli + + mov r10, rax + mov rax, [gs:PERCPU_CURRENT_TASK] + + mov rcx, [rax + TASK_USER_SAVED_RIP] + test rcx, rcx + jnz .rip_ok + push rax + push rcx + extern serial_printf + mov rdi, rax + mov rsi, [rax + 168] + mov esi, esi + mov rdx, [rax + 272] + mov rcx, [rax + 144] + lea rdi, [rel .fmt_zero_rip] + call serial_printf + lea rdi, [rel .msg_zero_rip] + extern kernel_panic + call kernel_panic +.fmt_zero_rip: db "[NO_RESCHED-BUG] task=0x%llx pid=%u user_saved_rip=0x%llx user_rsp=0x%llx", 10, 0 +.msg_zero_rip: db "sysret: user_saved_rip=0 — would fault at NULL", 0 +.rip_ok: + mov rsp, [rax + TASK_USER_RSP] + mov rcx, [rax + TASK_USER_SAVED_RIP] + mov r11, [rax + TASK_USER_SAVED_R11] + mov rbp, [rax + TASK_USER_SAVED_RBP] + mov rbx, [rax + TASK_USER_SAVED_RBX] + mov r12, [rax + TASK_USER_SAVED_R12] + mov r13, [rax + TASK_USER_SAVED_R13] + mov r14, [rax + TASK_USER_SAVED_R14] + mov r15, [rax + TASK_USER_SAVED_R15] + mov rax, r10 + + and r11, 0x00000000003C0FFF + or r11, 0x0000000000000202 + + mov r9, rcx + shr r9, 47 + jnz .sysret_bad_rip + + mov r9, rsp + shr r9, 47 + jnz .sysret_bad_rsp + + swapgs + o64 sysret + +.sysret_bad_rip: + extern sysret_bad_rip_panic + sti + mov rdi, rcx + mov rsi, rax + call sysret_bad_rip_panic + cli + hlt + +.sysret_bad_rsp: + extern sysret_bad_rsp_panic + sti + mov rdi, rsp + mov rsi, rcx + call sysret_bad_rsp_panic + cli + hlt \ No newline at end of file diff --git a/libc/include/ctype.h b/libc/include/ctype.h new file mode 100644 index 0000000..7a8304a --- /dev/null +++ b/libc/include/ctype.h @@ -0,0 +1,19 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +int isalnum(int c); +int isalpha(int c); +int isblank(int c); +int iscntrl(int c); +int isdigit(int c); +int isgraph(int c); +int islower(int c); +int isupper(int c); +int isprint(int c); +int ispunct(int c); +int isspace(int c); +int isxdigit(int c); +int tolower(int c); +int toupper(int c); + +#endif \ No newline at end of file diff --git a/libc/include/math.h b/libc/include/math.h new file mode 100644 index 0000000..60b7e3e --- /dev/null +++ b/libc/include/math.h @@ -0,0 +1,62 @@ +#ifndef _MATH_H +#define _MATH_H + +#include + +int abs(int x); +double fabs(double x); +double pow(double base, double exp); +double pow10(int n); +int isinf(double x); +int isnan(double x); + +static inline double floor(double x) { + int64_t i = (int64_t)x; + return (double)(i - (x < (double)i)); +} + +static inline double ceil(double x) { + int64_t i = (int64_t)x; + return (double)(i + (x > (double)i)); +} + +static inline double round(double x) { + return (x >= 0.0) ? floor(x + 0.5) : ceil(x - 0.5); +} + +static inline double sqrt(double x) { + double result; + asm volatile ("sqrtsd %1, %0" : "=x"(result) : "x"(x)); + return result; +} + +static inline float sqrtf(float x) { + float result; + asm volatile ("sqrtss %1, %0" : "=x"(result) : "x"(x)); + return result; +} + +static inline double log2(double x) { + double result; + asm volatile ( + "fld1\n\t" + "fld %1\n\t" + "fyl2x\n\t" + "fstp %0\n\t" + : "=m"(result) : "m"(x) + ); + return result; +} + +#define MIN(a, b) ({ __typeof__(a) _a = (a); __typeof__(b) _b = (b); _a < _b ? _a : _b; }) +#define MAX(a, b) ({ __typeof__(a) _a = (a); __typeof__(b) _b = (b); _a > _b ? _a : _b; }) + +#define ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1)) +#define ALIGN_DOWN(x, align) ((x) & ~((align) - 1)) + +#define IS_POWER_OF_TWO(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) + +#define INFINITY (1.0/0.0) +#define NAN (0.0/0.0) + +#endif \ No newline at end of file diff --git a/libc/include/stdio.h b/libc/include/stdio.h new file mode 100644 index 0000000..e2f5310 --- /dev/null +++ b/libc/include/stdio.h @@ -0,0 +1,44 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#include +#include +#include +#include + +#define EOF (-1) +#define MAX_SCROLL_LINES 1000 + +int putchar(int c); +int puts(const char *str); +int printf(const char *format, ...); + +int sprintf (char* restrict buf, const char* restrict fmt, ...); +int snprintf(char* restrict buf, size_t size, const char* restrict fmt, ...); +int vsprintf (char* restrict buf, const char* restrict fmt, va_list ap); +int vsnprintf(char* restrict buf, size_t size, const char* restrict fmt, va_list ap); +int vprintf(const char* restrict fmt, va_list ap); + +int getchar(void); +int scanf (const char * restrict fmt, ...); +int vscanf(const char * restrict fmt, va_list ap); +int sscanf (const char * restrict str, const char * restrict fmt, ...); +int vsscanf(const char *str, const char *fmt, va_list ap); + +extern uint32_t cursor_x; +extern uint32_t cursor_y; + +extern uint32_t text_color; +extern uint32_t bg_color; + +void scroll_screen(int lines); +uint32_t get_screen_width(void); +uint32_t get_screen_height(void); + +void set_cursor_position(uint32_t x, uint32_t y); +void get_cursor_position(uint32_t *x, uint32_t *y); +void set_text_color(uint32_t color); +void clear_screen(void); +void scroll_up(int lines); + +#endif \ No newline at end of file diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h new file mode 100644 index 0000000..906be8f --- /dev/null +++ b/libc/include/stdlib.h @@ -0,0 +1,30 @@ +#ifndef _STDLIB_H +#define _STDLIB_H + +#include +#include + +char* itoa(int val, char* restrict str, int base); + +long strtol (const char * restrict s, char ** restrict end, int base); +unsigned long strtoul (const char * restrict s, char ** restrict end, int base); + +long long strtoll (const char * restrict s, char ** restrict end, int base); +unsigned long long strtoull(const char * restrict s, char ** restrict end, int base); + +static inline int atoi(const char* s) { return (int)strtol (s, (char**)0, 10); } +static inline long atol(const char* s) { return strtol (s, (char**)0, 10); } + +void* malloc (size_t size); +void* calloc (size_t nmemb, size_t size); +void* realloc(void* ptr, size_t size); +void free (void* ptr); +void* aligned_alloc(size_t alignment, size_t size); +void aligned_free (void* ptr); + +static inline void abort(void) { + __asm__ volatile ("cli; hlt"); + __builtin_unreachable(); +} + +#endif \ No newline at end of file diff --git a/libc/include/string.h b/libc/include/string.h new file mode 100644 index 0000000..36da3a7 --- /dev/null +++ b/libc/include/string.h @@ -0,0 +1,45 @@ +#ifndef _STRING_H +#define _STRING_H + +#include +#include + +void* memcpy (void* restrict dst, const void* restrict src, size_t n); +void* memmove(void* dst, const void* src, size_t n); +void* memset (void* dst, int c, size_t n); +int memcmp (const void* a, const void* b, size_t n); +void *memchr(void *p, int val, size_t n); +void *rawmemchr(void *p, int c); + +void* memset_explicit(void* dst, int c, size_t n); + +size_t strlen (const char* s); +size_t strnlen(const char* s, size_t maxlen); + +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); + +char *strcat(char *dest, const char *src); +char* strncat(char* restrict dst, const char* restrict src, size_t n); + +int strcmp (const char* a, const char* b); +int strncmp(const char* a, const char* b, size_t n); + +char* strchr (const char* s, int c); +char* strrchr(const char* s, int c); +char* strstr (const char* haystack, const char* needle); +char* strpbrk(const char* s, const char* accept); +size_t strspn (const char* s, const char* accept); +size_t strcspn(const char* s, const char* reject); +char *strtok(char *str, const char *delim); + +long strtol (const char* restrict s, char** restrict end, int base); +unsigned long strtoul(const char* restrict s, char** restrict end, int base); + +char* strdup(const char* s); + +static inline void bzero(void* s, size_t n) { + memset(s, 0, n); +} + +#endif \ No newline at end of file diff --git a/libc/src/ctype/isalnum.c b/libc/src/ctype/isalnum.c new file mode 100644 index 0000000..b922331 --- /dev/null +++ b/libc/src/ctype/isalnum.c @@ -0,0 +1,7 @@ +#include + +int isalnum(int c) { + return (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z'); +} diff --git a/libc/src/ctype/isalpha.c b/libc/src/ctype/isalpha.c new file mode 100644 index 0000000..e749e2f --- /dev/null +++ b/libc/src/ctype/isalpha.c @@ -0,0 +1,6 @@ +#include + +int isalpha(int c) { + return (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z'); +} diff --git a/libc/src/ctype/isblank.c b/libc/src/ctype/isblank.c new file mode 100644 index 0000000..66d99e0 --- /dev/null +++ b/libc/src/ctype/isblank.c @@ -0,0 +1,5 @@ +#include + +int isblank(int c) { + return c == ' ' || c == '\t'; +} diff --git a/libc/src/ctype/iscntrl.c b/libc/src/ctype/iscntrl.c new file mode 100644 index 0000000..8542795 --- /dev/null +++ b/libc/src/ctype/iscntrl.c @@ -0,0 +1,8 @@ +#include + +int iscntrl(int c) { + return c == '\n' || c == '\t' || + c == '\r' || c == '\b' || + c == '\f' || c == '\a' || + c == '\0'; +} diff --git a/libc/src/ctype/isdigit.c b/libc/src/ctype/isdigit.c new file mode 100644 index 0000000..c7c45ee --- /dev/null +++ b/libc/src/ctype/isdigit.c @@ -0,0 +1,5 @@ +#include + +int isdigit(int c) { + return c >= '0' && c <= '9'; +} \ No newline at end of file diff --git a/libc/src/ctype/isgraph.c b/libc/src/ctype/isgraph.c new file mode 100644 index 0000000..fc4963e --- /dev/null +++ b/libc/src/ctype/isgraph.c @@ -0,0 +1,5 @@ +#include + +int isgraph(int c) { + return c >= 33 && c <= 126; +} diff --git a/libc/src/ctype/islower.c b/libc/src/ctype/islower.c new file mode 100644 index 0000000..85d6b3a --- /dev/null +++ b/libc/src/ctype/islower.c @@ -0,0 +1,5 @@ +#include + +int islower(int c) { + return c >= 'a' && c <= 'z'; +} \ No newline at end of file diff --git a/libc/src/ctype/isprint.c b/libc/src/ctype/isprint.c new file mode 100644 index 0000000..fd68c3e --- /dev/null +++ b/libc/src/ctype/isprint.c @@ -0,0 +1,5 @@ +#include + +int isprint(int c) { + return c >= 32 && c <= 126; +} \ No newline at end of file diff --git a/libc/src/ctype/ispunct.c b/libc/src/ctype/ispunct.c new file mode 100644 index 0000000..f1b3c2e --- /dev/null +++ b/libc/src/ctype/ispunct.c @@ -0,0 +1,8 @@ +#include + +int ispunct(int c) { + return (c >= 33 && c <= 47) || + (c >= 58 && c <= 64) || + (c >= 91 && c <= 96) || + (c >= 123 && c <= 126); +} diff --git a/libc/src/ctype/isspace.c b/libc/src/ctype/isspace.c new file mode 100644 index 0000000..9edad9b --- /dev/null +++ b/libc/src/ctype/isspace.c @@ -0,0 +1,6 @@ +#include + +int isspace(int c) { + return c == ' ' || c == '\t' || c == '\n' || + c == '\v' || c == '\f' || c == '\r'; +} diff --git a/libc/src/ctype/isupper.c b/libc/src/ctype/isupper.c new file mode 100644 index 0000000..26839de --- /dev/null +++ b/libc/src/ctype/isupper.c @@ -0,0 +1,5 @@ +#include + +int isupper(int c) { + return c >= 'A' && c <= 'Z'; +} diff --git a/libc/src/ctype/isxdigit.c b/libc/src/ctype/isxdigit.c new file mode 100644 index 0000000..6d9c960 --- /dev/null +++ b/libc/src/ctype/isxdigit.c @@ -0,0 +1,7 @@ +#include + +int isxdigit(int c) { + return (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'F') || + (c >= 'a' && c <= 'f'); +} diff --git a/libc/src/ctype/tolower.c b/libc/src/ctype/tolower.c new file mode 100644 index 0000000..0621ac0 --- /dev/null +++ b/libc/src/ctype/tolower.c @@ -0,0 +1,8 @@ +#include + +int tolower(int c) { + if (!isalpha(c)) + return c; + + return c + ('a' - 'A'); +} diff --git a/libc/src/ctype/toupper.c b/libc/src/ctype/toupper.c new file mode 100644 index 0000000..7b122ca --- /dev/null +++ b/libc/src/ctype/toupper.c @@ -0,0 +1,8 @@ +#include + +int toupper(int c) { + if (!isalpha(c)) + return c; + + return c - ('a' - 'A'); +} diff --git a/libc/src/math/abs.c b/libc/src/math/abs.c new file mode 100644 index 0000000..a499d2c --- /dev/null +++ b/libc/src/math/abs.c @@ -0,0 +1,5 @@ +#include + +int abs(int n) { + return n >= 0 ? n : -n; +} diff --git a/libc/src/math/fabs.c b/libc/src/math/fabs.c new file mode 100644 index 0000000..16e12de --- /dev/null +++ b/libc/src/math/fabs.c @@ -0,0 +1,12 @@ +#include +#include + +double fabs(double x) { + union { + double d; + uint64_t i; + } u = { .d = x }; + + u.i &= 0x7FFFFFFFFFFFFFFFULL; + return u.d; +} \ No newline at end of file diff --git a/libc/src/math/isinf.c b/libc/src/math/isinf.c new file mode 100644 index 0000000..12a6a00 --- /dev/null +++ b/libc/src/math/isinf.c @@ -0,0 +1,14 @@ +#include +#include + +int isinf(double x) { + union { + double f; + uint64_t i; + } u = { .f = x }; + + uint64_t exp = (u.i >> 52) & 0x7FF; + uint64_t mantissa = u.i & 0xFFFFFFFFFFFFFULL; + + return (exp == 0x7FF) && (mantissa == 0); +} \ No newline at end of file diff --git a/libc/src/math/isnan.c b/libc/src/math/isnan.c new file mode 100644 index 0000000..66afe95 --- /dev/null +++ b/libc/src/math/isnan.c @@ -0,0 +1,14 @@ +#include +#include + +int isnan(double x) { + union { + double f; + uint64_t i; + } u = { .f = x }; + + uint64_t exp = (u.i >> 52) & 0x7FF; + uint64_t mantissa = u.i & 0xFFFFFFFFFFFFFULL; + + return (exp == 0x7FF) && (mantissa != 0); +} \ No newline at end of file diff --git a/libc/src/math/pow.c b/libc/src/math/pow.c new file mode 100644 index 0000000..2f0acc7 --- /dev/null +++ b/libc/src/math/pow.c @@ -0,0 +1,37 @@ +#include + +double pow(double x, double y) { + if (y == 0.0) return 1.0; + + if (y == (int)y) { + int n = (int)y; + double result = 1.0; + + if (n > 0) { + for (int i = 0; i < n; i++) { + result *= x; + } + } else { + for (int i = 0; i < -n; i++) { + result /= x; + } + } + + return result; + } + + if (x > 0.0) { + int int_part = (int)y; + double frac_part = y - int_part; + + double int_pow = pow(x, int_part); + + if (frac_part > 0.0) { + return int_pow * (1.0 + frac_part * (x - 1.0)); + } else { + return int_pow / (1.0 - frac_part * (x - 1.0)); + } + } + + return NAN; +} \ No newline at end of file diff --git a/libc/src/math/pow10.c b/libc/src/math/pow10.c new file mode 100644 index 0000000..389fd43 --- /dev/null +++ b/libc/src/math/pow10.c @@ -0,0 +1,17 @@ +#include + +double pow10(int n) { + double result = 1.0; + + if (n >= 0) { + for (int i = 0; i < n; i++) { + result *= 10.0; + } + } else { + for (int i = 0; i < -n; i++) { + result /= 10.0; + } + } + + return result; +} \ No newline at end of file diff --git a/libc/src/stdio/getchar.c b/libc/src/stdio/getchar.c new file mode 100644 index 0000000..b230a78 --- /dev/null +++ b/libc/src/stdio/getchar.c @@ -0,0 +1,6 @@ +#include +#include "../../../kernel/include/drivers/ps2.h" + +int getchar(void) { + return (unsigned char)kb_buf_getc(); +} \ No newline at end of file diff --git a/libc/src/stdio/printf.c b/libc/src/stdio/printf.c new file mode 100644 index 0000000..a283f14 --- /dev/null +++ b/libc/src/stdio/printf.c @@ -0,0 +1,9 @@ +#include +#include + +int printf(const char *format, ...) { + va_list args; + va_start(args, format); + int n = vprintf(format, args); + return n; +} \ No newline at end of file diff --git a/libc/src/stdio/putchar.c b/libc/src/stdio/putchar.c new file mode 100644 index 0000000..2b6b89a --- /dev/null +++ b/libc/src/stdio/putchar.c @@ -0,0 +1,360 @@ +#include +#include +#include "../../../kernel/include/graphics/fb/fb.h" + +uint32_t cursor_x = 0; +uint32_t cursor_y = 0; +uint32_t text_color = COLOR_WHITE; +uint32_t bg_color = COLOR_BLACK; + +extern struct limine_framebuffer *global_framebuffer; + +static int cursor_visible = 1; +static int scroll_buffer_index = 0; +static int total_scroll_lines = 0; +static int flush_inhibit = 0; +static int autowrap = 1; + +uint32_t get_screen_width(void) { + if (!global_framebuffer) return 1024; + return global_framebuffer->width; +} +uint32_t get_screen_height(void) { + if (!global_framebuffer) return 768; + return global_framebuffer->height; +} + +uint32_t get_cursor_row(void) { return cursor_y / 16; } +uint32_t get_cursor_col(void) { return cursor_x / 8; } + +static void flush_all(void) { + if (!flush_inhibit && global_framebuffer) + fb_flush(global_framebuffer); +} + +static void flush_region(uint32_t y_start, uint32_t h) { + if (!flush_inhibit && global_framebuffer) + fb_flush_lines(global_framebuffer, y_start, y_start + h); +} + +void scroll_screen(int lines) { + if (!global_framebuffer || lines <= 0) return; + uint32_t sh = get_screen_height(); + uint32_t sp = (uint32_t)(lines * 16); + if (sp >= sh) { fb_clear(global_framebuffer, bg_color); flush_all(); return; } + + uint32_t *buf = (uint32_t *)global_framebuffer->address; + extern uint32_t *g_backbuf; + extern uint32_t g_bb_pitch; + uint32_t pitch; + uint32_t *target; + if (g_backbuf) { + target = g_backbuf; + pitch = g_bb_pitch; + } else { + target = buf; + pitch = global_framebuffer->pitch / 4; + } + + uint32_t rows_to_move = sh - sp; + memmove(target, target + sp * pitch, rows_to_move * pitch * sizeof(uint32_t)); + memset(target + rows_to_move * pitch, 0, sp * pitch * sizeof(uint32_t)); + + if (bg_color != 0) { + uint32_t sw = get_screen_width(); + uint32_t *clear_start = target + rows_to_move * pitch; + for (uint32_t y = 0; y < sp; y++) { + uint32_t *row = clear_start + y * pitch; + for (uint32_t x = 0; x < sw; x++) + row[x] = bg_color; + } + } + + flush_all(); +} + +static void draw_cursor_at(uint32_t x, uint32_t y) { + if (!global_framebuffer || !cursor_visible) return; + if (x + 8 > global_framebuffer->width || y + 16 > global_framebuffer->height) return; + for (uint32_t col = 0; col < 8; col++) { + fb_draw_pixel(global_framebuffer, x + col, y + 14, text_color); + fb_draw_pixel(global_framebuffer, x + col, y + 15, text_color); + } + flush_region(y + 14, 2); +} + +static void erase_cursor_at(uint32_t x, uint32_t y) { + if (!global_framebuffer) return; + if (x + 8 > global_framebuffer->width || y + 16 > global_framebuffer->height) return; + for (uint32_t col = 0; col < 8; col++) { + fb_draw_pixel(global_framebuffer, x + col, y + 14, bg_color); + fb_draw_pixel(global_framebuffer, x + col, y + 15, bg_color); + } + flush_region(y + 14, 2); +} + +void draw_cursor(void) { draw_cursor_at(cursor_x, cursor_y); } +void erase_cursor(void) { erase_cursor_at(cursor_x, cursor_y); } + +static uint32_t ansi_color(int code, int bright) { + static const uint32_t base[8] = { + 0x000000, 0xAA0000, 0x00AA00, 0xAA5500, + 0x0000AA, 0xAA00AA, 0x00AAAA, 0xAAAAAA, + }; + static const uint32_t bright8[8] = { + 0x555555, 0xFF5555, 0x55FF55, 0xFFFF55, + 0x5555FF, 0xFF55FF, 0x55FFFF, 0xFFFFFF, + }; + return bright ? bright8[code & 7] : base[code & 7]; +} + +#define ESC_MAX_PARAMS 8 + +typedef enum { + PS_NORMAL, + PS_ESC, + PS_CSI, + PS_CSI_PRIV, + PS_ESC_SP, +} parse_state_t; + +static parse_state_t ps_state = PS_NORMAL; +static int ps_params[ESC_MAX_PARAMS]; +static int ps_nparams = 0; +static int ps_cur = 0; +static int ps_bold = 0; + +static void ps_reset_params(void) { + for (int i = 0; i < ESC_MAX_PARAMS; i++) ps_params[i] = -1; + ps_nparams = 0; ps_cur = 0; +} +static void ps_push_param(void) { + if (ps_nparams < ESC_MAX_PARAMS) ps_params[ps_nparams++] = ps_cur; + ps_cur = 0; +} +static int ps_get(int i, int def) { + if (i >= ps_nparams || ps_params[i] < 0) return def; + return ps_params[i]; +} + +static int ps_reverse = 0; + +static void handle_sgr(void) { + if (ps_nparams == 0) { + text_color = COLOR_WHITE; bg_color = COLOR_BLACK; + ps_bold = 0; ps_reverse = 0; + return; + } + for (int i = 0; i < ps_nparams; i++) { + int p = ps_params[i]; if (p < 0) p = 0; + if (p == 0) { text_color = COLOR_WHITE; bg_color = COLOR_BLACK; ps_bold = 0; ps_reverse = 0; } + else if (p == 1) { ps_bold = 1; } + else if (p == 22) { ps_bold = 0; } + else if (p == 7) { + if (!ps_reverse) { + uint32_t tmp = text_color; text_color = bg_color; bg_color = tmp; + ps_reverse = 1; + } + } + else if (p == 27) { + if (ps_reverse) { + uint32_t tmp = text_color; text_color = bg_color; bg_color = tmp; + ps_reverse = 0; + } + } + else if (p >= 30 && p <= 37) { + uint32_t c = ansi_color(p-30, ps_bold); + if (ps_reverse) bg_color = c; else text_color = c; + } + else if (p >= 90 && p <= 97) { + uint32_t c = ansi_color(p-90, 1); + if (ps_reverse) bg_color = c; else text_color = c; + } + else if (p >= 40 && p <= 47) { + uint32_t c = ansi_color(p-40, 0); + if (ps_reverse) text_color = c; else bg_color = c; + } + } +} + +static void erase_to_eol(void) { + if (!global_framebuffer) return; + uint32_t sw = get_screen_width(); + if (cursor_x >= sw) return; + fb_fill_rect(global_framebuffer, cursor_x, cursor_y, sw - cursor_x, 16, bg_color); + flush_region(cursor_y, 16); +} + +static void cursor_move_right(int n) { + uint32_t sw = get_screen_width(); + cursor_x += (uint32_t)(n * 8); + if (cursor_x + 8 > sw) cursor_x = sw - 8; +} +static void cursor_move_left(int n) { + uint32_t delta = (uint32_t)(n * 8); + if (cursor_x >= delta) cursor_x -= delta; + else cursor_x = 0; +} + +static uint32_t saved_cx = 0, saved_cy = 0; + +static void clear_cell(uint32_t x, uint32_t y) { + if (!global_framebuffer) return; + fb_fill_rect(global_framebuffer, x, y, 8, 16, bg_color); +} + +static void draw_and_advance(char c) { + if (!global_framebuffer) return; + uint32_t sh = get_screen_height(); + uint32_t sw = get_screen_width(); + if (!autowrap && cursor_x + 8 >= sw) { + clear_cell(cursor_x, cursor_y); + fb_draw_char(global_framebuffer, c, cursor_x, cursor_y, text_color); + flush_region(cursor_y, 16); + return; + } + clear_cell(cursor_x, cursor_y); + fb_draw_char(global_framebuffer, c, cursor_x, cursor_y, text_color); + flush_region(cursor_y, 16); + cursor_x += 8; + if (cursor_x + 8 > sw) { cursor_x = 0; cursor_y += 16; } + if (cursor_y + 16 > sh) { scroll_screen(1); cursor_y = sh - 16; } +} + +int putchar(int c) { + if (!global_framebuffer) return EOF; + uint8_t ch = (uint8_t)c; + + switch (ps_state) { + + case PS_NORMAL: + if (ch == 0x1B) { ps_state = PS_ESC; return c; } + switch (ch) { + case '\n': + cursor_x = 0; cursor_y += 16; + if (cursor_y + 16 > get_screen_height()) { + scroll_screen(1); cursor_y = get_screen_height() - 16; + } + break; + case '\r': cursor_x = 0; break; + case '\t': cursor_x = (cursor_x + 32) & ~31u; break; + case '\b': + if (cursor_x >= 8) { + cursor_x -= 8; + clear_cell(cursor_x, cursor_y); + flush_region(cursor_y, 16); + } + break; + default: + if (ch >= 32 && ch <= 126) draw_and_advance((char)ch); + break; + } + break; + + case PS_ESC: + if (ch == '[') { ps_state = PS_CSI; ps_reset_params(); } + else if (ch == ' ') { ps_state = PS_ESC_SP; } + else { ps_state = PS_NORMAL; } + break; + + case PS_ESC_SP: + ps_state = PS_NORMAL; + break; + + case PS_CSI: + if (ch == '?') { ps_state = PS_CSI_PRIV; break; } + __attribute__((fallthrough)); + case PS_CSI_PRIV: + if (ch >= '0' && ch <= '9') { + ps_cur = ps_cur * 10 + (ch - '0'); + } else if (ch == ';') { + ps_push_param(); + } else { + ps_push_param(); + + if (ps_state == PS_CSI_PRIV) { + int p = ps_get(0, 0); + if (p == 25) { + if (ch == 'l') { + cursor_visible = 0; + flush_inhibit = 1; + } else if (ch == 'h') { + cursor_visible = 1; + flush_inhibit = 0; + if (global_framebuffer) + fb_flush(global_framebuffer); + } + } else if (p == 7) { + if (ch == 'l') autowrap = 0; + else if (ch == 'h') autowrap = 1; + } + ps_state = PS_NORMAL; + break; + } + + switch (ch) { + case 'm': handle_sgr(); break; + case 'J': { + int mode = ps_get(0, 0); + if (mode == 2 || mode == 3) { + fb_clear(global_framebuffer, bg_color); + cursor_x = 0; cursor_y = 0; + flush_all(); + } + break; + } + case 'K': { + int mode = ps_get(0, 0); + if (mode == 0) erase_to_eol(); + break; + } + case 'H': + case 'f': { + int row = ps_get(0, 1); if (row < 1) row = 1; + int col = ps_get(1, 1); if (col < 1) col = 1; + uint32_t cx = (uint32_t)((col - 1) * 8); + uint32_t cy = (uint32_t)((row - 1) * 16); + uint32_t sw = get_screen_width(); + uint32_t sh = get_screen_height(); + if (cx + 8 > sw) cx = (sw >= 8) ? sw - 8 : 0; + if (cy + 16 > sh) cy = (sh >= 16) ? sh - 16 : 0; + cursor_x = cx; + cursor_y = cy; + break; + } + case 'A': { + int n = ps_get(0, 1); if (n < 1) n = 1; + uint32_t d = (uint32_t)(n * 16); + cursor_y = (cursor_y >= d) ? cursor_y - d : 0; + break; + } + case 'B': { + int n = ps_get(0, 1); if (n < 1) n = 1; + cursor_y += (uint32_t)(n * 16); + break; + } + case 'C': cursor_move_right(ps_get(0, 1)); break; + case 'D': cursor_move_left (ps_get(0, 1)); break; + case 's': saved_cx = cursor_x; saved_cy = cursor_y; break; + case 'u': cursor_x = saved_cx; cursor_y = saved_cy; break; + default: break; + } + ps_state = PS_NORMAL; + } + break; + } + return c; +} + +void clear_screen_with_scroll(void) { + if (global_framebuffer) { + fb_clear(global_framebuffer, bg_color); + cursor_x = 0; cursor_y = 0; + scroll_buffer_index = 0; total_scroll_lines = 0; + flush_all(); + } +} +void get_cursor_position(uint32_t *x, uint32_t *y) { + if (x) *x = cursor_x; + if (y) *y = cursor_y; +} \ No newline at end of file diff --git a/libc/src/stdio/puts.c b/libc/src/stdio/puts.c new file mode 100644 index 0000000..781e8b7 --- /dev/null +++ b/libc/src/stdio/puts.c @@ -0,0 +1,27 @@ +#include +#include + +int puts(const char *str) { + int count = 0; + + if (!str) { + const char *null_str = "(null)"; + while (*null_str) { + putchar(*null_str++); + count++; + } + putchar('\n'); + count++; + return count; + } + + while (*str) { + putchar(*str++); + count++; + } + + putchar('\n'); + count++; + + return count; +} \ No newline at end of file diff --git a/libc/src/stdio/scanf.c b/libc/src/stdio/scanf.c new file mode 100644 index 0000000..2280398 --- /dev/null +++ b/libc/src/stdio/scanf.c @@ -0,0 +1,246 @@ +#include +#include +#include +#include +#include +#include +#include +#include "../../kernel/include/drivers/ps2.h" +#include "../../kernel/include/graphics/fb/fb.h" + +extern struct limine_framebuffer *global_framebuffer; +extern uint32_t bg_color; + +static int readline_buf(char *buf, size_t size) { + if (!buf || size == 0) return 0; + + uint32_t prompt_x, prompt_y; + get_cursor_position(&prompt_x, &prompt_y); + + size_t len = 0; + + while (len < size - 1) { + int c = getchar(); + if (c == EOF) break; + + if (c == '\n' || c == '\r') { + putchar('\n'); + break; + } + + if (c == '\b') { + if (len == 0) continue; + + len--; + + if (cursor_x >= 8) { + cursor_x -= 8; + } else if (cursor_y > prompt_y || + (cursor_y == prompt_y && cursor_x > prompt_x)) { + cursor_y -= 16; + cursor_x = (get_screen_width() / 8) * 8 - 8; + } else { + continue; + } + + if (global_framebuffer) + fb_fill_rect(global_framebuffer, + cursor_x, cursor_y, 8, 16, bg_color); + continue; + } + + if ((unsigned char)c < 32 && c != '\t') continue; + + buf[len++] = (char)c; + putchar(c); + } + + buf[len] = '\0'; + return (int)len; +} + +int vsscanf(const char *str, const char *fmt, va_list ap) { + if (!str || !fmt) return EOF; + + const char *s = str; + const char *f = fmt; + int n = 0; + + while (*f) { + if (*f == ' ' || *f == '\t' || *f == '\n' || *f == '\r') { + while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') + s++; + f++; + continue; + } + + if (*f != '%') { + if (*s != *f) break; + s++; f++; + continue; + } + + f++; + + bool suppress = false; + if (*f == '*') { suppress = true; f++; } + + int width = 0; + while (*f >= '0' && *f <= '9') { + width = width * 10 + (*f - '0'); + f++; + } + + enum { LEN_INT, LEN_LONG, LEN_LLONG } len = LEN_INT; + if (*f == 'l') { + f++; + if (*f == 'l') { f++; len = LEN_LLONG; } + else { len = LEN_LONG; } + } else if (*f == 'h') { + f++; + if (*f == 'h') f++; + } + + char spec = *f++; + + if (spec == '%') { + while (*s == ' ' || *s == '\t') s++; + if (*s != '%') break; + s++; + continue; + } + + if (spec == 'n') { + if (!suppress) { + *va_arg(ap, int *) = (int)(s - str); + } + continue; + } + + if (spec == 'c') { + if (!*s) break; + if (!suppress) { + char *out = va_arg(ap, char *); + *out = *s; + n++; + } + s++; + continue; + } + + while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') + s++; + + if (!*s) break; + + if (spec == 's') { + char *out = suppress ? NULL : va_arg(ap, char *); + int cnt = 0; + while (*s && *s != ' ' && *s != '\t' && + *s != '\n' && *s != '\r') { + if (width && cnt >= width) break; + if (out) out[cnt] = *s; + cnt++; + s++; + } + if (cnt == 0) break; + if (out) { out[cnt] = '\0'; n++; } + continue; + } + + int base = 10; + bool is_signed = false; + + switch (spec) { + case 'd': base = 10; is_signed = true; break; + case 'i': base = 0; is_signed = true; break; + case 'u': base = 10; is_signed = false; break; + case 'o': base = 8; is_signed = false; break; + case 'x': + case 'X': base = 16; is_signed = false; break; + default: + goto done; + } + + char tmp[32]; + int tlen = 0; + int maxw = width ? width : (int)sizeof(tmp) - 1; + + if (is_signed && (*s == '-' || *s == '+') && tlen < maxw) + tmp[tlen++] = *s++; + + if ((base == 16 || base == 0) && + *s == '0' && (s[1] == 'x' || s[1] == 'X') && tlen + 2 <= maxw) { + tmp[tlen++] = *s++; tmp[tlen++] = *s++; + if (base == 0) base = 16; + } else if (base == 0 && *s == '0') { + tmp[tlen++] = *s++; + base = 8; + } else if (base == 0) { + base = 10; + } + + while (*s && tlen < maxw) { + char c = *s; + bool ok = false; + if (base == 10 && c >= '0' && c <= '9') ok = true; + if (base == 8 && c >= '0' && c <= '7') ok = true; + if (base == 16 && ((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F'))) ok = true; + if (!ok) break; + tmp[tlen++] = c; + s++; + } + + if (tlen == 0) break; + tmp[tlen] = '\0'; + + if (!suppress) { + char *end = NULL; + if (is_signed) { + long long val = strtoll(tmp, &end, base); + if (end == tmp) break; + switch (len) { + case LEN_INT: *va_arg(ap, int *) = (int)val; break; + case LEN_LONG: *va_arg(ap, long *) = (long)val; break; + case LEN_LLONG: *va_arg(ap, long long *) = val; break; + } + } else { + unsigned long long val = strtoull(tmp, &end, base); + if (end == tmp) break; + switch (len) { + case LEN_INT: *va_arg(ap, unsigned int *) = (unsigned int)val; break; + case LEN_LONG: *va_arg(ap, unsigned long *) = (unsigned long)val; break; + case LEN_LLONG: *va_arg(ap, unsigned long long *) = val; break; + } + } + n++; + } + } + +done: + return n; +} + +int sscanf(const char * restrict str, const char * restrict fmt, ...) { + va_list ap; + va_start(ap, fmt); + int r = vsscanf(str, fmt, ap); + va_end(ap); + return r; +} + +int vscanf(const char * restrict fmt, va_list ap) { + char buf[256]; + readline_buf(buf, sizeof(buf)); + return vsscanf(buf, fmt, ap); +} + +int scanf(const char * restrict fmt, ...) { + va_list ap; + va_start(ap, fmt); + int r = vscanf(fmt, ap); + va_end(ap); + return r; +} \ No newline at end of file diff --git a/libc/src/stdio/screen.c b/libc/src/stdio/screen.c new file mode 100644 index 0000000..d8ee662 --- /dev/null +++ b/libc/src/stdio/screen.c @@ -0,0 +1,38 @@ +#include +#include "../../../kernel/include/graphics/fb/fb.h" + +extern struct limine_framebuffer *global_framebuffer; + +void set_cursor_position(uint32_t x, uint32_t y) { + cursor_x = x; + cursor_y = y; +} + +void set_text_color(uint32_t color) { + text_color = color; +} + +void set_background_color(uint32_t color) { + bg_color = color; +} + +void clear_screen(void) { + if (global_framebuffer) { + fb_clear(global_framebuffer, bg_color); + cursor_x = 0; + cursor_y = 0; + } +} + +void scroll_up(int lines) { + if (lines <= 0) return; + + scroll_screen(lines); + + uint32_t scroll_pixels = (uint32_t)(lines * 16); + if (cursor_y >= scroll_pixels) { + cursor_y -= scroll_pixels; + } else { + cursor_y = 0; + } +} \ No newline at end of file diff --git a/libc/src/stdio/snprintf.c b/libc/src/stdio/snprintf.c new file mode 100644 index 0000000..f3ec1bc --- /dev/null +++ b/libc/src/stdio/snprintf.c @@ -0,0 +1,381 @@ +#include +#include +#include +#include + +typedef struct { + char* buf; + size_t pos; + size_t size; +} snprintf_ctx_t; + +static void ctx_putc(snprintf_ctx_t* ctx, char c) { + if (ctx->pos + 1 < ctx->size) + ctx->buf[ctx->pos] = c; + ctx->pos++; +} + +static void ctx_puts(snprintf_ctx_t* ctx, const char* s, int len) { + for (int i = 0; i < len; i++) ctx_putc(ctx, s[i]); +} + +static void write_uint_full(snprintf_ctx_t* ctx, + unsigned long long val, int base, int upper, + int width, int zero_pad, int left, + int alt, int show_sign, int space_sign, + char forced_sign) { + const char* digs = upper ? "0123456789ABCDEF" : "0123456789abcdef"; + char tmp[72]; int len = 0; + if (val == 0) { tmp[len++] = '0'; } + else { while (val) { tmp[len++] = digs[val % (unsigned)base]; val /= (unsigned)base; } } + + char prefix[4]; int pfx = 0; + if (forced_sign) prefix[pfx++] = forced_sign; + else if (show_sign) prefix[pfx++] = '+'; + else if (space_sign) prefix[pfx++] = ' '; + if (alt && base == 16) { prefix[pfx++] = '0'; prefix[pfx++] = upper ? 'X':'x'; } + else if (alt && base == 8 && !(len==1 && tmp[0]=='0')) { prefix[pfx++] = '0'; } + else if (alt && base == 2) { prefix[pfx++] = '0'; prefix[pfx++] = upper ? 'B':'b'; } + + int total = len + pfx; + int pad = (width > total) ? width - total : 0; + + if (!left && !zero_pad) { for (int i=0;i= 0; i--) ctx_putc(ctx, tmp[i]); + if ( left) { for (int i=0;i= 1.0) { + if (val >= 1e16) { val /= 1e16; e += 16; } + if (val >= 1e8) { val /= 1e8; e += 8; } + if (val >= 1e4) { val /= 1e4; e += 4; } + if (val >= 1e2) { val /= 1e2; e += 2; } + if (val >= 1e1) { val /= 1e1; e += 1; } + } else { + if (val < 1e-15) { val *= 1e16; e -= 16; } + if (val < 1e-7) { val *= 1e8; e -= 8; } + if (val < 1e-3) { val *= 1e4; e -= 4; } + if (val < 1e-1) { val *= 1e2; e -= 2; } + if (val < 1e0) { val *= 1e1; e -= 1; } + } + (void)val; + return e; +} + +static int double_to_str(char* buf, double val, char fmt_char, int precision, + int show_sign, int space_sign, int alt, int is_neg) { + if (precision < 0) precision = 6; + if (precision > 17) precision = 17; + + int upper = (fmt_char == 'F' || fmt_char == 'E' || fmt_char == 'G'); + int i = 0; + + if (is_neg) buf[i++] = '-'; + else if (show_sign) buf[i++] = '+'; + else if (space_sign) buf[i++] = ' '; + + int exp10 = (val != 0.0) ? ilog10(val) : 0; + + int use_exp; + if (fmt_char == 'e' || fmt_char == 'E') { + use_exp = 1; + } else if (fmt_char == 'g' || fmt_char == 'G') { + int eff = (precision == 0) ? 1 : precision; + use_exp = (exp10 < -4 || exp10 >= eff); + precision = use_exp ? (eff - 1) : (eff - 1 - exp10); + if (precision < 0) precision = 0; + if (precision > 17) precision = 17; + } else { + use_exp = (exp10 > 15 || (val != 0.0 && exp10 < -17)); + if (use_exp) { fmt_char = upper ? 'E' : 'e'; upper = (fmt_char == 'E'); } + } + + double src = val; + if (use_exp && val != 0.0) { + int e = exp10; + if (e > 0 && e <= 17) src /= (double)pow10_tbl[e]; + else if (e > 17) { src /= (double)pow10_tbl[17]; src /= (double)pow10_tbl[e - 17 < 17 ? e-17 : 17]; } + else if (e < 0 && -e <= 17) src *= (double)pow10_tbl[-e]; + else if (e < -17) { src *= (double)pow10_tbl[17]; src *= (double)pow10_tbl[-e-17 < 17 ? -e-17 : 17]; } + if (src >= 10.0) { src /= 10.0; exp10++; } + if (src < 1.0 && src != 0.0) { src *= 10.0; exp10--; } + } + + unsigned long long scale = pow10_tbl[precision]; + double scaled_d = src * (double)scale + 0.5; + if (scaled_d >= 1.8e19) scaled_d = 1.8e19 - 1.0; + unsigned long long iscaled = (unsigned long long)scaled_d; + unsigned long long int_part = iscaled / scale; + unsigned long long frac_part = iscaled % scale; + + if (use_exp && int_part >= 10) { int_part = 1; frac_part = 0; exp10++; } + + { + char itmp[24]; int ilen = 0; + unsigned long long ip = int_part; + if (ip == 0) itmp[ilen++] = '0'; + else while (ip) { itmp[ilen++] = '0' + (int)(ip % 10); ip /= 10; } + for (int j = ilen-1; j >= 0; j--) buf[i++] = itmp[j]; + } + + if (precision > 0 || alt) { + char ftmp[20]; + unsigned long long fp2 = frac_part; + for (int k = precision - 1; k >= 0; k--) { + ftmp[k] = '0' + (int)(fp2 % 10); + fp2 /= 10; + } + int fend = precision; + if ((fmt_char == 'g' || fmt_char == 'G') && !alt) { + while (fend > 0 && ftmp[fend-1] == '0') fend--; + } + if (fend > 0 || alt) { + buf[i++] = '.'; + for (int k = 0; k < fend; k++) buf[i++] = ftmp[k]; + } + } + + if (use_exp) { + buf[i++] = upper ? 'E' : 'e'; + int ae = exp10 < 0 ? -exp10 : exp10; + buf[i++] = exp10 < 0 ? '-' : '+'; + if (ae >= 100) buf[i++] = '0' + ae / 100; + buf[i++] = '0' + (ae / 10) % 10; + buf[i++] = '0' + ae % 10; + } + + return i; +} + +static void write_float(snprintf_ctx_t* ctx, double val, char fmt_char, + int precision, int width, int zero_pad, int left, + int show_sign, int space_sign, int alt) { + char tmp[64]; int len; + int upper = (fmt_char == 'F' || fmt_char == 'E' || fmt_char == 'G'); + + if (val != val) { + const char* s = upper ? "NAN" : "nan"; + len = 3; tmp[0]=s[0]; tmp[1]=s[1]; tmp[2]=s[2]; + } else { + int is_neg = 0; + if (val < 0.0) { is_neg = 1; val = -val; } + if (val > 1.7976931348623157e+308) { + len = 0; + if (is_neg) tmp[len++] = '-'; + else if (show_sign) tmp[len++] = '+'; + else if (space_sign) tmp[len++] = ' '; + const char* s = upper ? "INF" : "inf"; + tmp[len++]=s[0]; tmp[len++]=s[1]; tmp[len++]=s[2]; + } else { + len = double_to_str(tmp, val, fmt_char, precision, + show_sign, space_sign, alt, is_neg); + } + } + + int has_sign = (tmp[0]=='-' || tmp[0]=='+' || tmp[0]==' '); + int pad = (width > len) ? width - len : 0; + if (!left && !zero_pad) { for (int j=0;j= '0' && *fmt <= '9') width = width*10 + (*fmt++ - '0'); + } + + int precision=-1, has_prec=0; + if (*fmt == '.') { + has_prec=1; precision=0; fmt++; + if (*fmt == '*') { + precision = va_arg(ap, int); + if (precision < 0) { has_prec=0; precision=-1; } + fmt++; + } else { + while (*fmt >= '0' && *fmt <= '9') + precision = precision*10 + (*fmt++ - '0'); + } + } + + int is_hh=0,is_h=0,is_l=0,is_ll=0,is_z=0; + if (*fmt=='h') { + fmt++; + if (*fmt=='h') { is_hh=1; fmt++; } else is_h=1; + } else if (*fmt=='l') { + is_l=1; fmt++; + if (*fmt=='l') { is_ll=1; fmt++; } + } else if (*fmt=='z') { is_z=1; fmt++; } + else if (*fmt=='t') { is_l=1; fmt++; } + else if (*fmt=='L') { fmt++; } + + if (!*fmt) break; + + switch (*fmt) { + case 'd': case 'i': { + long long v; + if (is_ll) v = va_arg(ap, long long); + else if (is_l) v = va_arg(ap, long); + else if (is_hh) v = (signed char) va_arg(ap, int); + else if (is_h) v = (short) va_arg(ap, int); + else if (is_z) v = (long long) va_arg(ap, size_t); + else v = va_arg(ap, int); + write_sint(&ctx, v, width, zero_pad, left, show_sign, space_sign); + break; + } + case 'u': { + unsigned long long v; + if (is_ll) v = va_arg(ap, unsigned long long); + else if (is_l) v = va_arg(ap, unsigned long); + else if (is_hh) v = (unsigned char) va_arg(ap, unsigned int); + else if (is_h) v = (unsigned short)va_arg(ap, unsigned int); + else if (is_z) v = va_arg(ap, size_t); + else v = va_arg(ap, unsigned int); + write_uint_full(&ctx,v,10,0,width,zero_pad,left,0,show_sign,space_sign,0); + break; + } + case 'o': { + unsigned long long v; + if (is_ll) v = va_arg(ap, unsigned long long); + else if (is_l) v = va_arg(ap, unsigned long); + else v = va_arg(ap, unsigned int); + write_uint_full(&ctx,v,8,0,width,zero_pad,left,alt,0,0,0); + break; + } + case 'x': case 'X': { + unsigned long long v; + if (is_ll) v = va_arg(ap, unsigned long long); + else if (is_l) v = va_arg(ap, unsigned long); + else v = va_arg(ap, unsigned int); + write_uint_full(&ctx,v,16,(*fmt=='X'),width,zero_pad,left,alt,0,0,0); + break; + } + case 'b': case 'B': { + unsigned long long v; + if (is_ll) v = va_arg(ap, unsigned long long); + else if (is_l) v = va_arg(ap, unsigned long); + else v = va_arg(ap, unsigned int); + write_uint_full(&ctx,v,2,(*fmt=='B'),width,zero_pad,left,alt,0,0,0); + break; + } + case 'p': { + uintptr_t v = (uintptr_t)va_arg(ap, void*); + ctx_putc(&ctx,'0'); ctx_putc(&ctx,'x'); + write_uint_full(&ctx,(unsigned long long)v,16,0,width,1,left,0,0,0,0); + break; + } + case 'f': case 'F': + case 'e': case 'E': + case 'g': case 'G': { + double v = va_arg(ap, double); + write_float(&ctx, v, *fmt, + has_prec ? precision : 6, + width, zero_pad, left, show_sign, space_sign, alt); + break; + } + case 's': { + const char* s = va_arg(ap, const char*); + if (!s) s = "(null)"; + int slen = (int)strlen(s); + if (has_prec && precision < slen) slen = precision; + int pad = (width > slen) ? width - slen : 0; + if (!left) { for (int j=0;j 1) ? width - 1 : 0; + if (!left) { for (int j=0;j 0) buf[ctx.pos < size ? ctx.pos : size-1] = '\0'; + return (int)ctx.pos; +} + +int vprintf(const char* restrict fmt, va_list ap) { + char buf[1024]; + int n = vsnprintf(buf, sizeof(buf), fmt, ap); + for (int i = 0; i < n && buf[i]; i++) putchar(buf[i]); + return n; +} + +int vsprintf(char* restrict buf, const char* restrict fmt, va_list ap) { + return vsnprintf(buf, (size_t)-1, fmt, ap); +} + +int snprintf(char* restrict buf, size_t size, const char* restrict fmt, ...) { + va_list ap; va_start(ap, fmt); + int n = vsnprintf(buf, size, fmt, ap); + va_end(ap); return n; +} + +int sprintf(char* restrict buf, const char* restrict fmt, ...) { + va_list ap; va_start(ap, fmt); + int n = vsnprintf(buf, (size_t)-1, fmt, ap); + va_end(ap); return n; +} \ No newline at end of file diff --git a/libc/src/stdlib/aligned_alloc.c b/libc/src/stdlib/aligned_alloc.c new file mode 100644 index 0000000..d691e99 --- /dev/null +++ b/libc/src/stdlib/aligned_alloc.c @@ -0,0 +1,14 @@ +#include +#include "../../../kernel/include/memory/pmm.h" + +void *aligned_alloc(size_t alignment, size_t size) { + if (size == 0) return NULL; + if (alignment == 0 || (alignment & (alignment - 1))) return NULL; + if (alignment < 16) alignment = 16; + void *raw = kmalloc(size + alignment + sizeof(void *)); + if (!raw) return NULL; + uintptr_t addr = (uintptr_t)raw + sizeof(void *); + uintptr_t aligned = (addr + alignment - 1) & ~(alignment - 1); + ((void **)aligned)[-1] = raw; + return (void *)aligned; +} diff --git a/libc/src/stdlib/aligned_free.c b/libc/src/stdlib/aligned_free.c new file mode 100644 index 0000000..3496579 --- /dev/null +++ b/libc/src/stdlib/aligned_free.c @@ -0,0 +1,8 @@ +#include +#include "../../../kernel/include/memory/pmm.h" + +void aligned_free(void* ptr) { + if (!ptr) return; + void* raw = ((void**)ptr)[-1]; + kfree(raw); +} diff --git a/libc/src/stdlib/calloc.c b/libc/src/stdlib/calloc.c new file mode 100644 index 0000000..ac4f2d1 --- /dev/null +++ b/libc/src/stdlib/calloc.c @@ -0,0 +1,11 @@ +#include +#include +#include "../../../kernel/include/memory/pmm.h" + +void *calloc(size_t nmemb, size_t size) { + if (nmemb == 0 || size == 0) return NULL; + if (nmemb > (size_t)-1 / size) return NULL; + void *ptr = kmalloc(nmemb * size); + if (ptr) memset(ptr, 0, nmemb * size); + return ptr; +} diff --git a/libc/src/stdlib/free.c b/libc/src/stdlib/free.c new file mode 100644 index 0000000..a469d8d --- /dev/null +++ b/libc/src/stdlib/free.c @@ -0,0 +1,6 @@ +#include +#include "../../../kernel/include/memory/pmm.h" + +void free(void *ptr) { + kfree(ptr); +} \ No newline at end of file diff --git a/libc/src/stdlib/itoa.c b/libc/src/stdlib/itoa.c new file mode 100644 index 0000000..2ca12b9 --- /dev/null +++ b/libc/src/stdlib/itoa.c @@ -0,0 +1,41 @@ +#include +#include +#include + +char *itoa(int val, char *restrict str, int base) { + int i = 0; + bool negative = false; + + if (val == 0) { + str[i++] = '0'; + str[i] = '\0'; + return str; + } + + if (val < 0 && base == 10) { + negative = true; + val = -val; + } + + while (val != 0) { + int rem = val % base; + str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0'; + val = val / base; + } + + if (negative) + str[i++] = '-'; + + str[i] = '\0'; + + int start = 0, end = strlen(str) - 1; + while (start < end) { + char temp = str[start]; + str[start] = str[end]; + str[end] = temp; + end--; + start++; + } + + return str; +} diff --git a/libc/src/stdlib/malloc.c b/libc/src/stdlib/malloc.c new file mode 100644 index 0000000..7463a04 --- /dev/null +++ b/libc/src/stdlib/malloc.c @@ -0,0 +1,7 @@ +#include +#include "../../../kernel/include/memory/pmm.h" + +void *malloc(size_t size) { + if (size == 0) return NULL; + return kmalloc(size); +} diff --git a/libc/src/stdlib/realloc.c b/libc/src/stdlib/realloc.c new file mode 100644 index 0000000..913b263 --- /dev/null +++ b/libc/src/stdlib/realloc.c @@ -0,0 +1,7 @@ +#include +#include +#include "../../../kernel/include/memory/pmm.h" + +void *realloc(void *ptr, size_t size) { + return krealloc(ptr, size); +} \ No newline at end of file diff --git a/libc/src/stdlib/strtoll.c b/libc/src/stdlib/strtoll.c new file mode 100644 index 0000000..95861cf --- /dev/null +++ b/libc/src/stdlib/strtoll.c @@ -0,0 +1,40 @@ +#include +#include +#include + +long long strtoll(const char * restrict s, char ** restrict end, int base) { + while (*s == ' ' || *s == '\t') s++; + + bool neg = false; + if (*s == '-') { neg = true; s++; } + else if (*s == '+') { s++; } + + if (base == 0) { + if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) { base = 16; s += 2; } + else if (*s == '0') { base = 8; s++; } + else { base = 10; } + } else if (base == 16 && *s == '0' && (s[1] == 'x' || s[1] == 'X')) { + s += 2; + } + + unsigned long long acc = 0; + const char *start = s; + + while (*s) { + int digit; + char c = *s; + if (c >= '0' && c <= '9') digit = c - '0'; + else if (c >= 'a' && c <= 'z') digit = c - 'a' + 10; + else if (c >= 'A' && c <= 'Z') digit = c - 'A' + 10; + else break; + + if (digit >= base) break; + acc = acc * (unsigned)base + (unsigned)digit; + s++; + } + + if (end) *end = (s == start) ? (char *)start : (char *)s; + + if (neg) return -(long long)acc; + return (long long)acc; +} \ No newline at end of file diff --git a/libc/src/stdlib/strtoull.c b/libc/src/stdlib/strtoull.c new file mode 100644 index 0000000..b8d67de --- /dev/null +++ b/libc/src/stdlib/strtoull.c @@ -0,0 +1,36 @@ +#include +#include +#include + +unsigned long long strtoull(const char * restrict s, char ** restrict end, int base) { + while (*s == ' ' || *s == '\t') s++; + + if (*s == '+') s++; + + if (base == 0) { + if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) { base = 16; s += 2; } + else if (*s == '0') { base = 8; s++; } + else { base = 10; } + } else if (base == 16 && *s == '0' && (s[1] == 'x' || s[1] == 'X')) { + s += 2; + } + + unsigned long long acc = 0; + const char *start = s; + + while (*s) { + int digit; + char c = *s; + if (c >= '0' && c <= '9') digit = c - '0'; + else if (c >= 'a' && c <= 'z') digit = c - 'a' + 10; + else if (c >= 'A' && c <= 'Z') digit = c - 'A' + 10; + else break; + + if (digit >= base) break; + acc = acc * (unsigned)base + (unsigned)digit; + s++; + } + + if (end) *end = (s == start) ? (char *)start : (char *)s; + return acc; +} \ No newline at end of file diff --git a/libc/src/string/memchr.c b/libc/src/string/memchr.c new file mode 100644 index 0000000..74362e3 --- /dev/null +++ b/libc/src/string/memchr.c @@ -0,0 +1,12 @@ +#include + +void *memchr(void *ptr, int val, size_t n) { + const unsigned char *p = (const unsigned char*)ptr; + unsigned char c = (unsigned char)val; + for (size_t i = 0; i < n; i++) { + if (p[i] == c) + return (void*)(p + i); + } + + return NULL; +} diff --git a/libc/src/string/memcmp.c b/libc/src/string/memcmp.c new file mode 100644 index 0000000..2b1d2f1 --- /dev/null +++ b/libc/src/string/memcmp.c @@ -0,0 +1,14 @@ +#include + +int memcmp(const void *s1, const void *s2, size_t n) { + const uint8_t *p1 = (const uint8_t *)s1; + const uint8_t *p2 = (const uint8_t *)s2; + + for (size_t i = 0; i < n; i++) { + if (p1[i] != p2[i]) { + return p1[i] < p2[i] ? -1 : 1; + } + } + + return 0; +} \ No newline at end of file diff --git a/libc/src/string/memcpy.c b/libc/src/string/memcpy.c new file mode 100644 index 0000000..fc86ad2 --- /dev/null +++ b/libc/src/string/memcpy.c @@ -0,0 +1,12 @@ +#include + +void *memcpy(void *restrict dest, const void *restrict src, size_t n) { + uint8_t *restrict pdest = (uint8_t *restrict)dest; + const uint8_t *restrict psrc = (const uint8_t *restrict)src; + + for (size_t i = 0; i < n; i++) { + pdest[i] = psrc[i]; + } + + return dest; +} \ No newline at end of file diff --git a/libc/src/string/memmove.c b/libc/src/string/memmove.c new file mode 100644 index 0000000..5b9d943 --- /dev/null +++ b/libc/src/string/memmove.c @@ -0,0 +1,18 @@ +#include + +void *memmove(void *dest, const void *src, size_t n) { + uint8_t *pdest = (uint8_t *)dest; + const uint8_t *psrc = (const uint8_t *)src; + + if (src > dest) { + for (size_t i = 0; i < n; i++) { + pdest[i] = psrc[i]; + } + } else if (src < dest) { + for (size_t i = n; i > 0; i--) { + pdest[i-1] = psrc[i-1]; + } + } + + return dest; +} \ No newline at end of file diff --git a/libc/src/string/memset.c b/libc/src/string/memset.c new file mode 100644 index 0000000..45d2f56 --- /dev/null +++ b/libc/src/string/memset.c @@ -0,0 +1,11 @@ +#include + +void *memset(void *s, int c, size_t n) { + uint8_t *p = (uint8_t *)s; + + for (size_t i = 0; i < n; i++) { + p[i] = (uint8_t)c; + } + + return s; +} \ No newline at end of file diff --git a/libc/src/string/memset_explicit.c b/libc/src/string/memset_explicit.c new file mode 100644 index 0000000..306c102 --- /dev/null +++ b/libc/src/string/memset_explicit.c @@ -0,0 +1,7 @@ +#include + +void* memset_explicit(void* dst, int c, size_t n) { + volatile unsigned char* p = (volatile unsigned char*)dst; + while (n--) *p++ = (unsigned char)c; + return dst; +} \ No newline at end of file diff --git a/libc/src/string/rawmemchr.c b/libc/src/string/rawmemchr.c new file mode 100644 index 0000000..a54ac24 --- /dev/null +++ b/libc/src/string/rawmemchr.c @@ -0,0 +1,11 @@ +#include + +void *rawmemchr(void *ptr, int val) { + const unsigned char *p = (const unsigned char*)ptr; + unsigned char c = (unsigned char)val; + for (;;) { + if (*p == c) + return (void*)p; + p++; + } +} diff --git a/libc/src/string/strcat.c b/libc/src/string/strcat.c new file mode 100644 index 0000000..c09e93d --- /dev/null +++ b/libc/src/string/strcat.c @@ -0,0 +1,17 @@ +#include + +char *strcat(char *dest, const char *src) { + char *ptr = dest; + + while (*ptr != '\0') { + ptr++; + } + + while (*src != '\0') { + *ptr++ = *src++; + } + + *ptr = '\0'; + + return dest; +} \ No newline at end of file diff --git a/libc/src/string/strchr.c b/libc/src/string/strchr.c new file mode 100644 index 0000000..5323015 --- /dev/null +++ b/libc/src/string/strchr.c @@ -0,0 +1,16 @@ +#include + +char *strchr(const char *str, int c) { + char ch = (char)c; + while (*str) { + if (*str == ch) + return (char*)str; + + str++; + } + + if (ch == '\0') + return (char*)str; + + return NULL; +} diff --git a/libc/src/string/strcmp.c b/libc/src/string/strcmp.c new file mode 100644 index 0000000..56500bc --- /dev/null +++ b/libc/src/string/strcmp.c @@ -0,0 +1,13 @@ +#include + +int strcmp(const char *str1, const char *str2) { + size_t i = 0; + while (str1[i] != '\0' && str2[i] != '\0') { + if (str1[i] != str2[i]) + goto ret; + + i++; + } +ret: + return (unsigned char)str1[i] - (unsigned char)str2[i]; +} diff --git a/libc/src/string/strcpy.c b/libc/src/string/strcpy.c new file mode 100644 index 0000000..4313542 --- /dev/null +++ b/libc/src/string/strcpy.c @@ -0,0 +1,7 @@ +#include + +char *strcpy(char *dest, const char *src) { + char *p = dest; + while ((*p++ = *src++) != '\0') { } + return dest; +} diff --git a/libc/src/string/strcspn.c b/libc/src/string/strcspn.c new file mode 100644 index 0000000..5418ec9 --- /dev/null +++ b/libc/src/string/strcspn.c @@ -0,0 +1,11 @@ +#include + +size_t strcspn(const char* s, const char* reject) { + size_t n = 0; + while (s[n]) { + for (const char* r = reject; *r; r++) + if (s[n] == *r) return n; + n++; + } + return n; +} \ No newline at end of file diff --git a/libc/src/string/strdup.c b/libc/src/string/strdup.c new file mode 100644 index 0000000..e65f65b --- /dev/null +++ b/libc/src/string/strdup.c @@ -0,0 +1,9 @@ +#include +#include + +char* strdup(const char* s) { + size_t len = strlen(s) + 1; + char* copy = malloc(len); + if (copy) memcpy(copy, s, len); + return copy; +} \ No newline at end of file diff --git a/libc/src/string/strlen.c b/libc/src/string/strlen.c new file mode 100644 index 0000000..58dc618 --- /dev/null +++ b/libc/src/string/strlen.c @@ -0,0 +1,11 @@ +#include + +size_t strlen(const char *str) { + size_t len = 0; + while (*str != '\0') { + len++; + str++; + } + + return len; +} diff --git a/libc/src/string/strncat.c b/libc/src/string/strncat.c new file mode 100644 index 0000000..a1a5a88 --- /dev/null +++ b/libc/src/string/strncat.c @@ -0,0 +1,9 @@ +#include + +char* strncat(char* restrict dst, const char* restrict src, size_t n) { + char* d = dst + strlen(dst); + while (n-- && *src) + *d++ = *src++; + *d = '\0'; + return dst; +} \ No newline at end of file diff --git a/libc/src/string/strncmp.c b/libc/src/string/strncmp.c new file mode 100644 index 0000000..96d56c0 --- /dev/null +++ b/libc/src/string/strncmp.c @@ -0,0 +1,18 @@ +#include + +int strncmp(const char *str1, const char *str2, size_t n) { + size_t i = 0; + while (i < n) { + unsigned char c1 = (unsigned char)str1[i], + c2 = (unsigned char)str2[i]; + if (c1 != c2) + return c1 - c2; + + if (c1 == '\0') + return 0; + + i++; + } + + return 0; +} diff --git a/libc/src/string/strncpy.c b/libc/src/string/strncpy.c new file mode 100644 index 0000000..08a86eb --- /dev/null +++ b/libc/src/string/strncpy.c @@ -0,0 +1,11 @@ +#include + +char *strncpy(char *dest, const char *src, size_t n) { + size_t i = 0; + for (; i < n && src[i] != '\0'; i++) + dest[i] = src[i]; + for (; i < n; i++) + dest[i] = '\0'; + + return dest; +} diff --git a/libc/src/string/strnlen.c b/libc/src/string/strnlen.c new file mode 100644 index 0000000..3b542d6 --- /dev/null +++ b/libc/src/string/strnlen.c @@ -0,0 +1,7 @@ +#include + +size_t strnlen(const char* s, size_t maxlen) { + size_t n = 0; + while (n < maxlen && s[n]) n++; + return n; +} \ No newline at end of file diff --git a/libc/src/string/strpbrk.c b/libc/src/string/strpbrk.c new file mode 100644 index 0000000..c55a880 --- /dev/null +++ b/libc/src/string/strpbrk.c @@ -0,0 +1,11 @@ +#include + +char *strpbrk(const char *str1, const char *str2) { + for (; *str1 != '\0'; str1++) { + for (const char *p = str2; *p != '\0'; p++) { + if (*str1 == *p) + return (char*)str1; + } + } + return NULL; +} diff --git a/libc/src/string/strrchr.c b/libc/src/string/strrchr.c new file mode 100644 index 0000000..55962f7 --- /dev/null +++ b/libc/src/string/strrchr.c @@ -0,0 +1,9 @@ +#include + +char* strrchr(const char* s, int c) { + const char* last = NULL; + do { + if (*s == (char)c) last = s; + } while (*s++); + return (char*)last; +} \ No newline at end of file diff --git a/libc/src/string/strspn.c b/libc/src/string/strspn.c new file mode 100644 index 0000000..49c7474 --- /dev/null +++ b/libc/src/string/strspn.c @@ -0,0 +1,24 @@ +#include + +size_t strspn(const char *str1, const char *str2) { + size_t count = 0; + while (*str1) { + const char *p = str2; + int found = 0; + while (*p) { + if (*str1 == *p) { + found = 1; + break; + } + p++; + } + + if (!found) + break; + + count++; + str1++; + } + + return count; +} diff --git a/libc/src/string/strstr.c b/libc/src/string/strstr.c new file mode 100644 index 0000000..a3d3f6d --- /dev/null +++ b/libc/src/string/strstr.c @@ -0,0 +1,17 @@ +#include + +char *strstr(const char *haystack, const char *needle) { + if (*needle == '\0') + return (char*)haystack; + + for (size_t i = 0; haystack[i] != '\0'; i++) { + size_t j = 0; + while (needle[j] != '\0' && haystack[j + i] == needle[j]) + j++; + + if (needle[j] == '\0') + return (char*)&haystack[i]; + } + + return NULL; +} diff --git a/libc/src/string/strtok.c b/libc/src/string/strtok.c new file mode 100644 index 0000000..0c92bf0 --- /dev/null +++ b/libc/src/string/strtok.c @@ -0,0 +1,22 @@ +#include + +static char *old_string = NULL; + +char *strtok(char *str, const char *delim) { + if (str == NULL) str = old_string; + str += strspn(str, delim); + if (*str == '\0') { + old_string = str; + return NULL; + } + + char *token = str; + str = strpbrk(token, delim); + if (str == NULL) + old_string = rawmemchr(token, '\0'); + else { + *str = '\0'; + old_string = str + 1; + } + return token; +} diff --git a/libc/src/string/strtol.c b/libc/src/string/strtol.c new file mode 100644 index 0000000..5100921 --- /dev/null +++ b/libc/src/string/strtol.c @@ -0,0 +1,39 @@ +#include +#include + +long strtol(const char* restrict s, char** restrict end, int base) { + while (isspace((unsigned char)*s)) s++; + + int neg = 0; + if (*s == '-') { neg = 1; s++; } + else if (*s == '+') { s++; } + + if ((base == 0 || base == 16) && s[0] == '0' && + (s[1] == 'x' || s[1] == 'X')) { + base = 16; + s += 2; + } else if (base == 0 && s[0] == '0') { + base = 8; + s++; + } else if (base == 0) { + base = 10; + } + + long result = 0; + int any = 0; + for (; *s; s++) { + int digit; + unsigned char c = (unsigned char)*s; + if (isdigit(c)) digit = c - '0'; + else if (isupper(c)) digit = c - 'A' + 10; + else if (islower(c)) digit = c - 'a' + 10; + else break; + + if (digit >= base) break; + result = result * base + digit; + any = 1; + } + + if (end) *end = (char*)(any ? s : (const char*)s); + return neg ? -result : result; +} \ No newline at end of file diff --git a/libc/src/string/strtoul.c b/libc/src/string/strtoul.c new file mode 100644 index 0000000..4a293e2 --- /dev/null +++ b/libc/src/string/strtoul.c @@ -0,0 +1,37 @@ +#include +#include + +unsigned long strtoul(const char* restrict s, char** restrict end, int base) { + while (isspace((unsigned char)*s)) s++; + + if (*s == '+') s++; + + if ((base == 0 || base == 16) && s[0] == '0' && + (s[1] == 'x' || s[1] == 'X')) { + base = 16; + s += 2; + } else if (base == 0 && s[0] == '0') { + base = 8; + s++; + } else if (base == 0) { + base = 10; + } + + unsigned long result = 0; + int any = 0; + for (; *s; s++) { + int digit; + unsigned char c = (unsigned char)*s; + if (isdigit(c)) digit = c - '0'; + else if (isupper(c)) digit = c - 'A' + 10; + else if (islower(c)) digit = c - 'a' + 10; + else break; + + if (digit >= base) break; + result = result * (unsigned long)base + (unsigned long)digit; + any = 1; + } + + if (end) *end = (char*)(any ? s : (const char*)s); + return result; +} \ No newline at end of file diff --git a/usr/apps/cal.c b/usr/apps/cal.c new file mode 100644 index 0000000..0389cca --- /dev/null +++ b/usr/apps/cal.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include +#include + +#define A_INVERT "\x1b[7m" +#define A_BOLD "\x1b[1m" +#define A_RESET "\x1b[0m" + +static const char *MNAME[12] = { + "January","February","March","April","May","June", + "July","August","September","October","November","December" +}; +static int MDAYS[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + +static int is_leap(int y) +{ + return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); +} + +static int days_in_month(int y, int m) +{ + if (m == 2 && is_leap(y)) return 29; + return MDAYS[m - 1]; +} + +static int first_dow(int y, int m) +{ + int64_t days = 0; + for (int yr = 1970; yr < y; yr++) days += is_leap(yr) ? 366 : 365; + int md[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + md[1] = is_leap(y) ? 29 : 28; + for (int mo = 0; mo < m - 1; mo++) days += md[mo]; + return (int)((days + 4) % 7); +} + +static void get_today(int *out_y, int *out_m, int *out_d) +{ + *out_y = 0; *out_m = 0; *out_d = 0; + + cervus_timespec_t ts; + if (cervus_clock_gettime(CLOCK_REALTIME, &ts) != 0 || ts.tv_sec <= 0) + return; + + int64_t t = ts.tv_sec; + int64_t days = t / 86400; + + int y = 1970; + while (1) { + int dy = is_leap(y) ? 366 : 365; + if (days < dy) break; + days -= dy; + y++; + } + + int md[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + md[1] = is_leap(y) ? 29 : 28; + + int mo = 0; + while (mo < 12) { if (days < md[mo]) break; days -= md[mo]; mo++; } + + *out_y = y; + *out_m = mo + 1; + *out_d = (int)(days + 1); +} + +static void print_header(int y, int m, int today_y, int today_m) +{ + char title[64]; + snprintf(title, sizeof(title), "%s %d", MNAME[m - 1], y); + int tlen = (int)strlen(title); + int pad = (20 - tlen) / 2; + + for (int i = 0; i < pad; i++) putchar(' '); + + if (y == today_y && m == today_m) { + fputs(A_INVERT A_BOLD, stdout); + fputs(title, stdout); + fputs(A_RESET, stdout); + } else { + fputs(A_BOLD, stdout); + fputs(title, stdout); + fputs(A_RESET, stdout); + } + putchar('\n'); + fputs(C_GRAY " Su Mo Tu We Th Fr Sa" A_RESET "\n", stdout); +} + +static void print_month(int y, int m, int today_y, int today_m, int today_d) +{ + print_header(y, m, today_y, today_m); + + int mdays = days_in_month(y, m); + int dow = first_dow(y, m); + + for (int i = 0; i < dow; i++) fputs(" ", stdout); + + for (int d = 1; d <= mdays; d++) { + int is_today = (y == today_y && m == today_m && d == today_d); + + if (is_today) { + fprintf(stdout, " " A_INVERT A_BOLD "%2d" A_RESET, d); + } else { + fprintf(stdout, " %2d", d); + } + + if (++dow == 7) { + putchar('\n'); + dow = 0; + } + } + if (dow != 0) putchar('\n'); +} + +static void print_help(void) +{ + fputs( + "Usage: cal [OPTION] [[MONTH] YEAR]\n" + "Display a calendar.\n" + "\n" + " (no args) current month\n" + " YEAR all 12 months of YEAR\n" + " MONTH YEAR specific month (MONTH = 1-12)\n" + " --help display this help and exit\n" + "\n" + "Today's day is highlighted with " A_INVERT "inverted colours" A_RESET ".\n" + "The current month header is also " A_INVERT "inverted" A_RESET ".\n", + stdout + ); +} + +int main(int argc, char **argv) +{ + int today_y, today_m, today_d; + get_today(&today_y, &today_m, &today_d); + + int year = today_y ? today_y : 2025; + int month = today_m ? today_m : 1; + + const char *args[2] = {NULL, NULL}; + int real_argc = 0; + int flag_help = 0; + + for (int i = 1; i < argc; i++) { + if (is_shell_flag(argv[i])) continue; + if (strcmp(argv[i], "--help") == 0) { flag_help = 1; continue; } + if (real_argc < 2) args[real_argc] = argv[i]; + real_argc++; + } + + if (flag_help) { print_help(); return 0; } + + if (real_argc == 2) { + month = atoi(args[0]); + year = atoi(args[1]); + } else if (real_argc == 1) { + year = atoi(args[0]); + putchar('\n'); + fprintf(stdout, " " A_BOLD "%d" A_RESET "\n\n", year); + for (int m = 1; m <= 12; m++) { + print_month(year, m, today_y, today_m, today_d); + putchar('\n'); + } + return 0; + } + + if (month < 1 || month > 12) { + fputs("cal: invalid month (must be 1-12)\n", stderr); + return 1; + } + + putchar('\n'); + print_month(year, month, today_y, today_m, today_d); + putchar('\n'); + return 0; +} \ No newline at end of file diff --git a/usr/apps/calc.c b/usr/apps/calc.c new file mode 100644 index 0000000..67ef4e9 --- /dev/null +++ b/usr/apps/calc.c @@ -0,0 +1,206 @@ +#include +#include +#include +#include +#include +#include + +#define SCALE 1000000LL + +typedef long long fx; + +static const char *p; + +static void skip_ws(void) { while (*p && isspace((unsigned char)*p)) p++; } + +static fx parse_number(int *err) +{ + skip_ws(); + long long intpart = 0, frac = 0, fscale = 1; + int had_digit = 0; + while (isdigit((unsigned char)*p)) { + intpart = intpart * 10 + (*p - '0'); + had_digit = 1; p++; + } + if (*p == '.') { + p++; + while (isdigit((unsigned char)*p)) { + if (fscale < SCALE) { frac = frac * 10 + (*p - '0'); fscale *= 10; } + had_digit = 1; p++; + } + } + if (!had_digit) { *err = 1; return 0; } + return intpart * SCALE + (frac * SCALE) / fscale; +} + +static fx parse_expr(int *err); + +static fx parse_primary(int *err) +{ + skip_ws(); + if (*p == '(') { + p++; + fx v = parse_expr(err); + skip_ws(); + if (*p == ')') p++; + else *err = 1; + return v; + } + if (*p == '-') { p++; return -parse_primary(err); } + if (*p == '+') { p++; return parse_primary(err); } + return parse_number(err); +} + +static fx parse_term(int *err) +{ + fx v = parse_primary(err); + while (!*err) { + skip_ws(); + if (*p == '*') { + p++; + fx r = parse_primary(err); + v = (v * r) / SCALE; + } else if (*p == '/') { + p++; + fx r = parse_primary(err); + if (r == 0) { *err = 2; return 0; } + v = (v * SCALE) / r; + } else break; + } + return v; +} + +static fx parse_expr(int *err) +{ + fx v = parse_term(err); + while (!*err) { + skip_ws(); + if (*p == '+') { p++; v += parse_term(err); } + else if (*p == '-') { p++; v -= parse_term(err); } + else break; + } + return v; +} + +static void print_fx(fx v) +{ + if (v < 0) { putchar('-'); v = -v; } + long long ip = v / SCALE; + long long fp = v % SCALE; + + char ibuf[32]; + int ilen = 0; + if (ip == 0) { + ibuf[ilen++] = '0'; + } else { + long long tmp = ip; + while (tmp > 0) { ibuf[ilen++] = '0' + (int)(tmp % 10); tmp /= 10; } + for (int a = 0, b = ilen - 1; a < b; a++, b--) { + char t = ibuf[a]; ibuf[a] = ibuf[b]; ibuf[b] = t; + } + } + ibuf[ilen] = '\0'; + fputs(ibuf, stdout); + + if (fp != 0) { + char fbuf[8]; + int flen = 0; + long long tmp = fp; + long long scale = SCALE; + fbuf[flen++] = '.'; + while (scale > 1) { + scale /= 10; + fbuf[flen++] = '0' + (int)(tmp / scale); + tmp %= scale; + } + fbuf[flen] = '\0'; + while (flen > 1 && fbuf[flen - 1] == '0') { fbuf[--flen] = '\0'; } + fputs(fbuf, stdout); + } + putchar('\n'); +} + +static void calc_help(void) +{ + putchar('\n'); + fputs(C_CYAN "Cervus calc" C_RESET " - fixed-point calculator (6 decimal digits)\n", stdout); + fputs(C_GRAY "-------------------------------------------" C_RESET "\n", stdout); + fputs(C_BOLD "Operators:" C_RESET " + - * / ( )\n", stdout); + fputs(C_GRAY "-------------------------------------------" C_RESET "\n", stdout); + fputs(C_BOLD "Examples:" C_RESET "\n", stdout); + fputs(" calc> " C_YELLOW "3.14 + 5" C_RESET " = 8.14\n", stdout); + fputs(" calc> " C_YELLOW "10 / 3" C_RESET " = 3.333333\n", stdout); + fputs(" calc> " C_YELLOW "2 * (3 + 4)" C_RESET " = 14\n", stdout); + fputs(" calc> " C_YELLOW "(1.5 + 2.5) * 4" C_RESET " = 16\n", stdout); + fputs(" calc> " C_YELLOW "100 / 7" C_RESET " = 14.285714\n", stdout); + fputs(" calc> " C_YELLOW "-5 + 3" C_RESET " = -2\n", stdout); + fputs(C_GRAY "-------------------------------------------" C_RESET "\n", stdout); + fputs(" Type " C_BOLD "q" C_RESET " or " C_BOLD "exit" C_RESET " to quit.\n", stdout); + putchar('\n'); +} + +static int readline_calc(char *buf, int maxlen) +{ + int i = 0; + for (;;) { + char c; + ssize_t r = read(0, &c, 1); + if (r <= 0) { + buf[i] = '\0'; + return (i > 0) ? i : -1; + } + if (c == '\r') continue; + if (c == '\n') { + write(1, "\n", 1); + buf[i] = '\0'; + return i; + } + if (c == '\b' || c == 0x7F) { + if (i > 0) { + i--; + write(1, "\b \b", 3); + } + continue; + } + if (c == 0x03) { + write(1, "^C\n", 3); + buf[0] = '\0'; + return 0; + } + if (c >= 0x20 && c < 0x7F && i < maxlen - 1) { + buf[i++] = c; + write(1, &c, 1); + } + } +} + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + fputs(C_CYAN "Cervus calc" C_RESET " - fixed-point (6 digits). " + "Type " C_BOLD "help" C_RESET " for examples, " C_BOLD "q" C_RESET " to exit.\n", stdout); + + char line[256]; + for (;;) { + fputs("calc> ", stdout); + int n = readline_calc(line, sizeof(line)); + if (n < 0) { putchar('\n'); break; } + while (n > 0 && isspace((unsigned char)line[n - 1])) line[--n] = '\0'; + if (n == 0) continue; + if (strcmp(line, "q") == 0 || strcmp(line, "quit") == 0 || + strcmp(line, "exit") == 0) break; + if (strcmp(line, "help") == 0) { calc_help(); continue; } + + p = line; + int err = 0; + fx v = parse_expr(&err); + skip_ws(); + if (*p != '\0') err = 1; + + if (err == 1) fputs(C_RED " parse error\n" C_RESET, stdout); + else if (err == 2) fputs(C_RED " division by zero\n" C_RESET, stdout); + else { fputs(" = ", stdout); print_fx(v); } + } + putchar('\n'); + return 0; +} \ No newline at end of file diff --git a/usr/apps/date.c b/usr/apps/date.c new file mode 100644 index 0000000..ed02fd9 --- /dev/null +++ b/usr/apps/date.c @@ -0,0 +1,98 @@ +#include +#include +#include + +static const int MDAYS[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; +static const char *MNAME[12] = { + "Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec" +}; +static const char *WDAY[7] = {"Thu","Fri","Sat","Sun","Mon","Tue","Wed"}; + +static int is_leap(int y) { return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); } +static int bcd2bin(int v) { return (v & 0x0F) + ((v >> 4) * 10); } + +static int cmos_read(int reg) +{ + if (cervus_ioport_write(0x70, 1, (uint32_t)(reg & 0x7F)) < 0) return -1; + return (int)(cervus_ioport_read(0x71, 1) & 0xFF); +} +static void cmos_wait_ready(void) +{ + for (int i = 0; i < 2000; i++) { + cervus_ioport_write(0x70, 1, 0x0A); + uint32_t sta = cervus_ioport_read(0x71, 1); + if (!(sta & 0x80)) return; + } +} + +static int64_t rtc_read_unix(void) +{ + cmos_wait_ready(); + int sec = cmos_read(0x00); + int min = cmos_read(0x02); + int hour = cmos_read(0x04); + int mday = cmos_read(0x07); + int mon = cmos_read(0x08); + int year = cmos_read(0x09); + if (sec < 0 || min < 0 || hour < 0 || mday < 0 || mon < 0 || year < 0) return 0; + + cervus_ioport_write(0x70, 1, 0x0B); + int regb = (int)cervus_ioport_read(0x71, 1); + int binary_mode = (regb >= 0) && (regb & 0x04); + int hour24 = (regb >= 0) && (regb & 0x02); + + if (!binary_mode) { + sec = bcd2bin(sec); + min = bcd2bin(min); + mday = bcd2bin(mday); + mon = bcd2bin(mon); + year = bcd2bin(year); + if (!hour24 && (hour & 0x80)) hour = bcd2bin(hour & 0x7F) + 12; + else hour = bcd2bin(hour); + } + year += (year < 70) ? 2000 : 1900; + if (sec < 0 || sec > 59 || min < 0 || min > 59) return 0; + if (hour < 0 || hour > 23) return 0; + if (mday < 1 || mday > 31) return 0; + if (mon < 1 || mon > 12) return 0; + if (year < 2000) return 0; + + int64_t days = 0; + for (int y = 1970; y < year; y++) days += is_leap(y) ? 366 : 365; + for (int m = 1; m < mon; m++) days += MDAYS[m-1] + (m == 2 && is_leap(year) ? 1 : 0); + days += mday - 1; + return days * 86400LL + (int64_t)hour * 3600LL + (int64_t)min * 60LL + (int64_t)sec; +} + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + int64_t t = rtc_read_unix(); + if (t <= 0) { + uint64_t up = cervus_uptime_ns() / 1000000000ULL; + fputs(" RTC not available.\n", stdout); + printf(" Uptime: %lus\n", (unsigned long)up); + return 0; + } + int wday = (int)((t / 86400 + 4) % 7); + int64_t days = t / 86400; + int64_t rem = t % 86400; + if (rem < 0) { rem += 86400; days--; } + int hour = (int)(rem / 3600); + int min = (int)((rem % 3600) / 60); + int sec = (int)(rem % 60); + + int year = 1970; + while (1) { int dy = is_leap(year) ? 366 : 365; if (days < dy) break; days -= dy; year++; } + int mon = 0; + while (mon < 12) { + int dm = MDAYS[mon] + (mon == 1 && is_leap(year) ? 1 : 0); + if (days < dm) break; + days -= dm; mon++; + } + int mday = (int)days + 1; + printf(" %s %s %2d %02d:%02d:%02d UTC %04d\n", + WDAY[wday], MNAME[mon], mday, hour, min, sec, year); + return 0; +} diff --git a/usr/apps/execve_target.c b/usr/apps/execve_target.c new file mode 100644 index 0000000..13b9bc5 --- /dev/null +++ b/usr/apps/execve_target.c @@ -0,0 +1,15 @@ +#include +#include +#include + +int main(int argc, char **argv) +{ + puts("=== execve_target: STARTED ==="); + printf(" PID: %d\n", (int)getpid()); + printf(" PPID: %d\n", (int)getppid()); + printf(" argc: %d\n", argc); + for (int i = 0; i < argc; i++) + printf(" argv[%d] = %s\n", i, argv[i]); + puts("=== execve_target: DONE, exit(99) ==="); + return 99; +} diff --git a/usr/apps/fetch.c b/usr/apps/fetch.c new file mode 100644 index 0000000..865e1f7 --- /dev/null +++ b/usr/apps/fetch.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include + +static const char *logo[] = { + " L ", + " 'k.i , ", + " \";\"+U., ", + " \\_' -. ", + " .f ,_.;.", + " I ,f ", + " ' ", + NULL +}; + +static void cpuid_leaf(uint32_t leaf, uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d) +{ + asm volatile ("cpuid" + : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) + : "0"(leaf), "2"(0)); +} + +static void print_uptime(void) +{ + uint64_t ns = cervus_uptime_ns(); + uint64_t total_s = ns / 1000000000ULL; + uint64_t ms = (ns / 1000000ULL) % 1000ULL; + uint64_t secs = total_s % 60; + uint64_t mins = (total_s / 60) % 60; + uint64_t hours = (total_s / 3600) % 24; + uint64_t days = total_s / 86400; + fputs("uptime: ", stdout); + if (days > 0) printf("%lud, ", (unsigned long)days); + printf("%02lu:%02lu:%02lu (%lus %lums)", + (unsigned long)hours, (unsigned long)mins, (unsigned long)secs, + (unsigned long)total_s, (unsigned long)ms); +} + +static void print_cpu(void) +{ + uint32_t a, b, c, d; + cpuid_leaf(0x80000000, &a, &b, &c, &d); + if (a >= 0x80000004) { + char brand[49]; + uint32_t *p = (uint32_t *)brand; + cpuid_leaf(0x80000002, &p[0], &p[1], &p[2], &p[3]); + cpuid_leaf(0x80000003, &p[4], &p[5], &p[6], &p[7]); + cpuid_leaf(0x80000004, &p[8], &p[9], &p[10], &p[11]); + brand[48] = '\0'; + const char *br = brand; + while (*br == ' ') br++; + printf("cpu: %s", br); + } +} + +static void print_mem(void) +{ + cervus_meminfo_t mi; + if (cervus_meminfo(&mi) != 0) return; + uint64_t used = mi.used_bytes; + uint64_t total = mi.total_bytes; + const uint64_t MiB = 1024ULL * 1024; + const uint64_t GiB = 1024ULL * 1024 * 1024; + fputs("mem: ", stdout); + if (total >= GiB) + printf("%lu.%02lu / %lu.%02lu GiB", + (unsigned long)(used / GiB), (unsigned long)((used % GiB) * 100 / GiB), + (unsigned long)(total / GiB), (unsigned long)((total % GiB) * 100 / GiB)); + else + printf("%lu / %lu MiB", + (unsigned long)(used / MiB), (unsigned long)(total / MiB)); +} + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + putchar('\n'); + for (int i = 0; logo[i]; i++) { + printf(" %s ", logo[i]); + switch (i) { + case 1: fputs("os: Cervus OS", stdout); break; + case 2: print_uptime(); break; + case 3: print_cpu(); break; + case 4: fputs(C_RESET "shell: CSH", stdout); break; + case 5: print_mem(); break; + } + putchar('\n'); + } + putchar('\n'); + return 0; +} diff --git a/usr/apps/hello.c b/usr/apps/hello.c new file mode 100644 index 0000000..31756a5 --- /dev/null +++ b/usr/apps/hello.c @@ -0,0 +1,10 @@ +#include +#include + +int main(int argc, char **argv) +{ + (void)argv; + printf("Hello, Cervus world!\n"); + printf("argc = %d\n", argc); + return 0; +} diff --git a/usr/apps/neo.c b/usr/apps/neo.c new file mode 100644 index 0000000..17ed48f --- /dev/null +++ b/usr/apps/neo.c @@ -0,0 +1,908 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NEO_VERSION "0.1" +#define NEO_TABSTOP 4 +#define NEO_QUIT_CONFIRM 1 + +#define KEY_NONE 0 +#define KEY_ESC 0x1B +#define KEY_BACKSPACE 127 +#define KEY_CTRL(k) ((k) & 0x1f) + +#define KEY_ARROW_UP 1000 +#define KEY_ARROW_DOWN 1001 +#define KEY_ARROW_LEFT 1002 +#define KEY_ARROW_RIGHT 1003 +#define KEY_HOME 1004 +#define KEY_END 1005 +#define KEY_DEL 1006 +#define KEY_PAGE_UP 1007 +#define KEY_PAGE_DOWN 1008 + +#define TIOCGWINSZ 0x5413 + +typedef struct { uint16_t ws_row, ws_col, ws_xpixel, ws_ypixel; } neo_winsize_t; + +typedef struct { + int size; + int cap; + char *chars; + int rsize; + char *render; +} neo_row_t; + +typedef struct { + int cx, cy; + int rx; + int rowoff; + int coloff; + int screenrows; + int screencols; + int numrows; + int rowscap; + neo_row_t *row; + int dirty; + char *filename; + char statusmsg[256]; + int statusmsg_visible; + int quit_pending; + long disk_size; + struct termios orig_termios; +} neo_t; + +static neo_t E; +static const char *g_cwd = "/"; + +static void die(const char *msg) +{ + write(1, "\x1b[2J", 4); + write(1, "\x1b[H", 3); + if (msg) { + write(2, "neo: ", 5); + write(2, msg, strlen(msg)); + write(2, "\n", 1); + } + exit(1); +} + +static void disable_raw_mode(void) +{ + tcsetattr(0, TCSAFLUSH, &E.orig_termios); + write(1, "\x1b[?7h\x1b[?25h", 11); +} + +static void enable_raw_mode(void) +{ + if (tcgetattr(0, &E.orig_termios) < 0) die("tcgetattr"); + atexit(disable_raw_mode); + + struct termios raw = E.orig_termios; + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + raw.c_oflag &= ~(OPOST); + raw.c_cflag |= (CS8); + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + raw.c_cc[VMIN] = 1; + raw.c_cc[VTIME] = 0; + if (tcsetattr(0, TCSAFLUSH, &raw) < 0) die("tcsetattr"); + write(1, "\x1b[?7l", 5); +} + +static int read_key(void) +{ + char c; + ssize_t n; + while ((n = read(0, &c, 1)) == 0) { } + if (n < 0) return KEY_NONE; + + if (c != 0x1B) return (unsigned char)c; + + char seq[4]; + if (read(0, &seq[0], 1) != 1) return KEY_ESC; + if (read(0, &seq[1], 1) != 1) return KEY_ESC; + + if (seq[0] == '[') { + if (seq[1] >= '0' && seq[1] <= '9') { + if (read(0, &seq[2], 1) != 1) return KEY_ESC; + if (seq[2] == '~') { + switch (seq[1]) { + case '1': + case '7': return KEY_HOME; + case '3': return KEY_DEL; + case '4': + case '8': return KEY_END; + case '5': return KEY_PAGE_UP; + case '6': return KEY_PAGE_DOWN; + } + } + } else { + switch (seq[1]) { + case 'A': return KEY_ARROW_UP; + case 'B': return KEY_ARROW_DOWN; + case 'C': return KEY_ARROW_RIGHT; + case 'D': return KEY_ARROW_LEFT; + case 'H': return KEY_HOME; + case 'F': return KEY_END; + } + } + } else if (seq[0] == 'O') { + switch (seq[1]) { + case 'H': return KEY_HOME; + case 'F': return KEY_END; + } + } + return KEY_ESC; +} + +static void get_window_size(void) +{ + neo_winsize_t ws; + if (syscall3(SYS_IOCTL, 1, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0 && ws.ws_row > 0) { + E.screencols = ws.ws_col; + E.screenrows = ws.ws_row; + } else { + E.screencols = 80; + E.screenrows = 24; + } + E.screenrows -= 2; + if (E.screenrows < 1) E.screenrows = 1; +} + +static int row_cx_to_rx(neo_row_t *row, int cx) +{ + int rx = 0; + for (int j = 0; j < cx && j < row->size; j++) { + if (row->chars[j] == '\t') rx += (NEO_TABSTOP - (rx % NEO_TABSTOP)); + else rx++; + } + return rx; +} + +static int row_rx_to_cx(neo_row_t *row, int rx) +{ + int cur_rx = 0; + int cx; + for (cx = 0; cx < row->size; cx++) { + if (row->chars[cx] == '\t') cur_rx += (NEO_TABSTOP - (cur_rx % NEO_TABSTOP)); + else cur_rx++; + if (cur_rx > rx) return cx; + } + return cx; +} + +static void row_update(neo_row_t *row) +{ + int tabs = 0; + for (int j = 0; j < row->size; j++) if (row->chars[j] == '\t') tabs++; + free(row->render); + row->render = malloc(row->size + tabs * (NEO_TABSTOP - 1) + 1); + int idx = 0; + for (int j = 0; j < row->size; j++) { + if (row->chars[j] == '\t') { + row->render[idx++] = ' '; + while (idx % NEO_TABSTOP != 0) row->render[idx++] = ' '; + } else { + row->render[idx++] = row->chars[j]; + } + } + row->render[idx] = '\0'; + row->rsize = idx; +} + +static void rows_reserve(int want) +{ + if (want <= E.rowscap) return; + int nc = E.rowscap ? E.rowscap * 2 : 32; + while (nc < want) nc *= 2; + neo_row_t *nr = malloc(sizeof(neo_row_t) * nc); + if (!nr) die("out of memory"); + if (E.row) { + memcpy(nr, E.row, sizeof(neo_row_t) * E.numrows); + } + for (int i = E.numrows; i < nc; i++) { + nr[i].size = 0; nr[i].cap = 0; nr[i].chars = NULL; + nr[i].rsize = 0; nr[i].render = NULL; + } + E.row = nr; + E.rowscap = nc; +} + +static void row_insert_at(int at, const char *s, int len) +{ + if (at < 0 || at > E.numrows) return; + rows_reserve(E.numrows + 1); + for (int i = E.numrows; i > at; i--) E.row[i] = E.row[i - 1]; + + neo_row_t *r = &E.row[at]; + r->size = len; + r->cap = len + 1; + r->chars = malloc(r->cap); + if (!r->chars) die("out of memory"); + if (len > 0) memcpy(r->chars, s, len); + r->chars[len] = '\0'; + r->render = NULL; + r->rsize = 0; + row_update(r); + E.numrows++; + E.dirty = 1; +} + +static void row_free(neo_row_t *r) +{ + free(r->chars); + free(r->render); + r->chars = NULL; r->render = NULL; + r->size = 0; r->cap = 0; r->rsize = 0; +} + +static void row_delete_at(int at) +{ + if (at < 0 || at >= E.numrows) return; + row_free(&E.row[at]); + for (int i = at; i < E.numrows - 1; i++) E.row[i] = E.row[i + 1]; + E.numrows--; + E.dirty = 1; +} + +static void row_reserve(neo_row_t *r, int want) +{ + if (want <= r->cap) return; + int nc = r->cap ? r->cap * 2 : 16; + while (nc < want) nc *= 2; + char *nb = malloc(nc); + if (!nb) die("out of memory"); + if (r->chars) memcpy(nb, r->chars, r->size); + nb[r->size] = '\0'; + free(r->chars); + r->chars = nb; + r->cap = nc; +} + +static void row_insert_char(neo_row_t *r, int at, int ch) +{ + if (at < 0 || at > r->size) at = r->size; + row_reserve(r, r->size + 2); + memmove(&r->chars[at + 1], &r->chars[at], r->size - at + 1); + r->chars[at] = (char)ch; + r->size++; + row_update(r); + E.dirty = 1; +} + +static void row_append_string(neo_row_t *r, const char *s, int len) +{ + row_reserve(r, r->size + len + 1); + memcpy(&r->chars[r->size], s, len); + r->size += len; + r->chars[r->size] = '\0'; + row_update(r); + E.dirty = 1; +} + +static void row_delete_char(neo_row_t *r, int at) +{ + if (at < 0 || at >= r->size) return; + memmove(&r->chars[at], &r->chars[at + 1], r->size - at); + r->size--; + row_update(r); + E.dirty = 1; +} + +static void editor_insert_char(int ch) +{ + if (E.cy == E.numrows) row_insert_at(E.numrows, "", 0); + row_insert_char(&E.row[E.cy], E.cx, ch); + E.cx++; +} + +static void editor_insert_newline(void) +{ + if (E.cx == 0) { + row_insert_at(E.cy, "", 0); + } else { + neo_row_t *r = &E.row[E.cy]; + row_insert_at(E.cy + 1, &r->chars[E.cx], r->size - E.cx); + r = &E.row[E.cy]; + r->size = E.cx; + r->chars[r->size] = '\0'; + row_update(r); + } + E.cy++; + E.cx = 0; +} + +static void editor_delete_char(void) +{ + if (E.cy == E.numrows) return; + if (E.cx == 0 && E.cy == 0) return; + + neo_row_t *r = &E.row[E.cy]; + if (E.cx > 0) { + row_delete_char(r, E.cx - 1); + E.cx--; + } else { + E.cx = E.row[E.cy - 1].size; + row_append_string(&E.row[E.cy - 1], r->chars, r->size); + row_delete_at(E.cy); + E.cy--; + } +} + +static char *rows_to_string(int *len) +{ + int total = 0; + for (int j = 0; j < E.numrows; j++) total += E.row[j].size + 1; + char *buf = malloc(total + 1); + if (!buf) die("out of memory"); + char *p = buf; + for (int j = 0; j < E.numrows; j++) { + memcpy(p, E.row[j].chars, E.row[j].size); + p += E.row[j].size; + *p++ = '\n'; + } + *p = '\0'; + *len = total; + return buf; +} + +static void set_status(const char *fmt, ...); + +static void editor_open(const char *filename) +{ + free(E.filename); + size_t fl = strlen(filename); + E.filename = malloc(fl + 1); + memcpy(E.filename, filename, fl + 1); + + char full[512]; + resolve_path(g_cwd, filename, full, sizeof(full)); + + int fd = open(full, O_RDONLY, 0); + if (fd < 0) { + E.disk_size = -1; + set_status("New file: %s", filename); + return; + } + + struct stat st; + if (fstat(fd, &st) < 0) { close(fd); E.disk_size = -1; return; } + size_t sz = (size_t)st.st_size; + E.disk_size = (long)sz; + char *buf = malloc(sz + 1); + if (!buf) { close(fd); die("out of memory"); } + + size_t total = 0; + while (total < sz) { + ssize_t r = read(fd, buf + total, sz - total); + if (r <= 0) break; + total += (size_t)r; + } + close(fd); + buf[total] = '\0'; + + size_t i = 0; + while (i < total) { + size_t start = i; + while (i < total && buf[i] != '\n' && buf[i] != '\r') i++; + int len = (int)(i - start); + row_insert_at(E.numrows, buf + start, len); + if (i < total && buf[i] == '\r') i++; + if (i < total && buf[i] == '\n') i++; + } + free(buf); + E.dirty = 0; +} + +static char *prompt(const char *prompt_fmt); + +static int editor_save(void) +{ + if (!E.filename) { + char *name = prompt("Save as (ESC to cancel): %s"); + if (!name) { + set_status("Save cancelled"); + return -1; + } + if (name[0] == '\0') { + free(name); + set_status("Save cancelled (empty filename)"); + return -1; + } + E.filename = name; + E.disk_size = -1; + } + + char full[512]; + resolve_path(g_cwd, E.filename, full, sizeof(full)); + + if (E.disk_size >= 0) { + struct stat st; + if (stat(full, &st) == 0 && (long)st.st_size != E.disk_size) { + char *ans = prompt("File changed on disk! Overwrite? [y/N]: %s"); + if (!ans) { set_status("Save cancelled"); return -1; } + int yes = (ans[0] == 'y' || ans[0] == 'Y'); + free(ans); + if (!yes) { set_status("Save cancelled"); return -1; } + } + } + + int len = 0; + char *buf = rows_to_string(&len); + + int fd = open(full, O_RDWR | O_CREAT | O_TRUNC, 0644); + if (fd < 0) { + free(buf); + set_status("Save failed: errno=%d (%s)", errno, full); + return -1; + } + ssize_t written = 0; + while (written < len) { + ssize_t w = write(fd, buf + written, len - written); + if (w <= 0) { close(fd); free(buf); set_status("Save failed (write err)"); return -1; } + written += w; + } + close(fd); + free(buf); + E.dirty = 0; + E.disk_size = len; + set_status("Saved %d bytes to %s", len, E.filename); + return 0; +} + +typedef struct { char *b; int len; int cap; } abuf_t; + +static void ab_append(abuf_t *ab, const char *s, int len) +{ + if (ab->len + len > ab->cap) { + int nc = ab->cap ? ab->cap * 2 : 1024; + while (nc < ab->len + len) nc *= 2; + char *nb = malloc(nc); + if (!nb) die("out of memory"); + if (ab->b) memcpy(nb, ab->b, ab->len); + free(ab->b); + ab->b = nb; + ab->cap = nc; + } + memcpy(ab->b + ab->len, s, len); + ab->len += len; +} +static void ab_free(abuf_t *ab) { free(ab->b); ab->b = NULL; ab->len = 0; ab->cap = 0; } + +static void scroll(void) +{ + E.rx = 0; + if (E.cy < E.numrows) E.rx = row_cx_to_rx(&E.row[E.cy], E.cx); + + if (E.cy < E.rowoff) E.rowoff = E.cy; + if (E.cy >= E.rowoff + E.screenrows) E.rowoff = E.cy - E.screenrows + 1; + if (E.rx < E.coloff) E.coloff = E.rx; + if (E.rx >= E.coloff + E.screencols) E.coloff = E.rx - E.screencols + 1; +} + +static void draw_rows(abuf_t *ab) +{ + char pos[16]; + int limit = E.screencols - 1; + if (limit < 1) limit = 1; + for (int y = 0; y < E.screenrows; y++) { + int n = snprintf(pos, sizeof(pos), "\x1b[%d;1H", y + 1); + ab_append(ab, pos, n); + + int filerow = y + E.rowoff; + if (filerow >= E.numrows) { + if (E.numrows == 0 && y == E.screenrows / 3) { + char welcome[80]; + int wl = snprintf(welcome, sizeof(welcome), + "neo editor -- version %s -- press ESC to exit", NEO_VERSION); + if (wl > limit) wl = limit; + int padding = (limit - wl) / 2; + if (padding > 0) { ab_append(ab, "~", 1); padding--; } + while (padding-- > 0) ab_append(ab, " ", 1); + ab_append(ab, welcome, wl); + } else { + ab_append(ab, "~", 1); + } + } else { + int len = E.row[filerow].rsize - E.coloff; + if (len < 0) len = 0; + if (len > limit) len = limit; + ab_append(ab, E.row[filerow].render + E.coloff, len); + } + ab_append(ab, "\x1b[K", 3); + } +} + +static void draw_status(abuf_t *ab) +{ + char pos[16]; + int n = snprintf(pos, sizeof(pos), "\x1b[%d;1H", E.screenrows + 1); + ab_append(ab, pos, n); + ab_append(ab, "\x1b[7m", 4); + char status[256], rstatus[80]; + int len = snprintf(status, sizeof(status), " %.40s%s ", + E.filename ? E.filename : "[No Name]", + E.dirty ? " [modified]" : ""); + int rlen = snprintf(rstatus, sizeof(rstatus), "%d/%d ", + E.cy + 1, E.numrows); + + int limit = E.screencols - 1; + if (limit < 1) limit = 1; + + if (len > limit) len = limit; + ab_append(ab, status, len); + while (len < limit) { + if (limit - len == rlen) { ab_append(ab, rstatus, rlen); break; } + ab_append(ab, " ", 1); + len++; + } + ab_append(ab, "\x1b[m", 3); + ab_append(ab, "\x1b[K", 3); +} + +static void draw_message(abuf_t *ab) +{ + char pos[16]; + int n = snprintf(pos, sizeof(pos), "\x1b[%d;1H", E.screenrows + 2); + ab_append(ab, pos, n); + ab_append(ab, "\x1b[K", 3); + if (E.statusmsg_visible) { + int mlen = strlen(E.statusmsg); + if (mlen > E.screencols) mlen = E.screencols; + ab_append(ab, E.statusmsg, mlen); + } else { + const char *hint = " ^S=save ^Q=quit ^F=find ^G=goto ^B=top ^E=end ESC=exit"; + int mlen = strlen(hint); + if (mlen > E.screencols) mlen = E.screencols; + ab_append(ab, hint, mlen); + } +} + +static void refresh_screen(void) +{ + scroll(); + abuf_t ab = {0}; + ab_append(&ab, "\x1b[?25l", 6); + draw_rows(&ab); + draw_status(&ab); + draw_message(&ab); + + int cursor_row = (E.cy - E.rowoff) + 1; + int cursor_col = (E.rx - E.coloff) + 1; + + char curbuf[32]; + int n = snprintf(curbuf, sizeof(curbuf), "\x1b[%d;%dH", cursor_row, cursor_col); + ab_append(&ab, curbuf, n); + + ab_append(&ab, "\x1b[?25h", 6); + + write(1, ab.b, ab.len); + ab_free(&ab); +} + +static void set_status(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vsnprintf(E.statusmsg, sizeof(E.statusmsg), fmt, ap); + va_end(ap); + E.statusmsg_visible = 1; +} + +static char *prompt_cb(const char *prompt_fmt, void (*callback)(char *, int)) +{ + size_t bufcap = 128; + size_t buflen = 0; + char *buf = malloc(bufcap); + buf[0] = '\0'; + + for (;;) { + set_status(prompt_fmt, buf); + refresh_screen(); + int c = read_key(); + if (c == KEY_DEL || c == KEY_CTRL('h') || c == KEY_BACKSPACE) { + if (buflen > 0) buf[--buflen] = '\0'; + } else if (c == KEY_ESC) { + set_status(""); + E.statusmsg_visible = 0; + if (callback) callback(buf, c); + free(buf); + return NULL; + } else if (c == '\r' || c == '\n') { + if (buflen != 0 || callback) { + set_status(""); + E.statusmsg_visible = 0; + if (callback) callback(buf, c); + return buf; + } + } else if (!iscntrl(c) && c < 128) { + if (buflen + 1 >= bufcap) { + bufcap *= 2; + char *nb = malloc(bufcap); + memcpy(nb, buf, buflen); + free(buf); + buf = nb; + } + buf[buflen++] = (char)c; + buf[buflen] = '\0'; + } + if (callback) callback(buf, c); + } +} + +static char *prompt(const char *prompt_fmt) +{ + return prompt_cb(prompt_fmt, NULL); +} + +static void move_cursor(int key) +{ + neo_row_t *row = (E.cy >= E.numrows) ? NULL : &E.row[E.cy]; + switch (key) { + case KEY_ARROW_LEFT: + if (E.cx > 0) E.cx--; + else if (E.cy > 0) { E.cy--; E.cx = E.row[E.cy].size; } + break; + case KEY_ARROW_RIGHT: + if (row && E.cx < row->size) E.cx++; + else if (row && E.cx == row->size) { E.cy++; E.cx = 0; } + break; + case KEY_ARROW_UP: + if (E.cy > 0) E.cy--; + break; + case KEY_ARROW_DOWN: + if (E.cy < E.numrows) E.cy++; + break; + } + row = (E.cy >= E.numrows) ? NULL : &E.row[E.cy]; + int rowlen = row ? row->size : 0; + if (E.cx > rowlen) E.cx = rowlen; +} + +static void goto_line(void) +{ + char *p = prompt("Go to line: %s (ESC cancels)"); + if (!p) return; + int n = atoi(p); + free(p); + if (n < 1) n = 1; + if (n > E.numrows) n = E.numrows == 0 ? 1 : E.numrows; + E.cy = n - 1; + E.cx = 0; +} + +static int __find_last_match = -1; +static int __find_direction = 1; +static int __find_saved_cx, __find_saved_cy; +static int __find_saved_rowoff, __find_saved_coloff; +static char *__find_last_query = NULL; + +static void editor_find_callback(char *query, int key) +{ + if (key == '\r' || key == '\n' || key == KEY_ESC) { + __find_last_match = -1; + __find_direction = 1; + return; + } + if (key == KEY_ARROW_DOWN || key == KEY_ARROW_RIGHT) { + __find_direction = 1; + } else if (key == KEY_ARROW_UP || key == KEY_ARROW_LEFT) { + __find_direction = -1; + } else { + __find_last_match = -1; + __find_direction = 1; + } + if (!query || !query[0]) return; + + int current = __find_last_match; + if (current == -1) current = E.cy; + int qlen = (int)strlen(query); + + for (int i = 0; i < E.numrows; i++) { + current += __find_direction; + if (current == -1) current = E.numrows - 1; + else if (current == E.numrows) current = 0; + + neo_row_t *row = &E.row[current]; + char *match = strstr(row->render, query); + if (match) { + __find_last_match = current; + E.cy = current; + int rx = (int)(match - row->render); + E.cx = row_rx_to_cx(row, rx); + E.rowoff = E.numrows; + (void)qlen; + return; + } + } +} + +static void editor_find(void) +{ + __find_saved_cx = E.cx; + __find_saved_cy = E.cy; + __find_saved_rowoff = E.rowoff; + __find_saved_coloff = E.coloff; + __find_last_match = -1; + __find_direction = 1; + + char *query = prompt_cb( + "Search: %s (Up/Down=prev/next, Enter=keep, ESC=cancel)", + editor_find_callback); + + if (query) { + if (query[0] == '\0' && __find_last_query) { + free(query); + query = strdup(__find_last_query); + if (query) { + editor_find_callback(query, 0); + } + } + if (query && query[0]) { + free(__find_last_query); + __find_last_query = strdup(query); + } + if (query) free(query); + } else { + E.cx = __find_saved_cx; + E.cy = __find_saved_cy; + E.rowoff = __find_saved_rowoff; + E.coloff = __find_saved_coloff; + } +} + +static int process_key(void) +{ + int c = read_key(); + + switch (c) { + case '\r': + case '\n': + editor_insert_newline(); + break; + + case KEY_ESC: + if (E.dirty && NEO_QUIT_CONFIRM && !E.quit_pending) { + set_status("Unsaved changes. ESC again to exit without saving, Ctrl-S to save."); + E.quit_pending = 1; + return 1; + } + return 0; + + case KEY_CTRL('s'): + editor_save(); + E.quit_pending = 0; + break; + + case KEY_CTRL('q'): + if (E.dirty && NEO_QUIT_CONFIRM && !E.quit_pending) { + set_status("Unsaved changes. Ctrl-Q again to force quit."); + E.quit_pending = 1; + return 1; + } + return 0; + + case KEY_CTRL('g'): + goto_line(); + break; + + case KEY_CTRL('f'): + editor_find(); + break; + + case KEY_CTRL('b'): + E.cy = 0; + E.cx = 0; + E.rowoff = 0; + E.coloff = 0; + break; + + case KEY_CTRL('e'): + E.cy = E.numrows == 0 ? 0 : E.numrows - 1; + if (E.cy < E.numrows) E.cx = E.row[E.cy].size; + else E.cx = 0; + break; + + case KEY_HOME: + E.cx = 0; + break; + + case KEY_END: + if (E.cy < E.numrows) E.cx = E.row[E.cy].size; + break; + + case KEY_BACKSPACE: + case KEY_CTRL('h'): + editor_delete_char(); + break; + + case KEY_DEL: + move_cursor(KEY_ARROW_RIGHT); + editor_delete_char(); + break; + + case KEY_PAGE_UP: + case KEY_PAGE_DOWN: { + if (c == KEY_PAGE_UP) { + E.cy = E.rowoff; + } else { + E.cy = E.rowoff + E.screenrows - 1; + if (E.cy > E.numrows) E.cy = E.numrows; + } + int times = E.screenrows; + while (times--) move_cursor(c == KEY_PAGE_UP ? KEY_ARROW_UP : KEY_ARROW_DOWN); + break; + } + + case KEY_ARROW_UP: + case KEY_ARROW_DOWN: + case KEY_ARROW_LEFT: + case KEY_ARROW_RIGHT: + move_cursor(c); + break; + + case KEY_CTRL('l'): + case 0: + break; + + default: + if (c >= 32 && c < 127) editor_insert_char(c); + else if (c == '\t') editor_insert_char('\t'); + break; + } + E.quit_pending = 0; + return 1; +} + +static void init_editor(void) +{ + E.cx = 0; E.cy = 0; E.rx = 0; + E.rowoff = 0; E.coloff = 0; + E.numrows = 0; E.rowscap = 0; E.row = NULL; + E.dirty = 0; + E.filename = NULL; + E.statusmsg[0] = '\0'; + E.statusmsg_visible = 0; + E.quit_pending = 0; + E.disk_size = -1; + get_window_size(); +} + +int main(int argc, char **argv) +{ + g_cwd = get_cwd_flag(argc, argv); + + init_editor(); + enable_raw_mode(); + + const char *file_to_open = NULL; + for (int i = 1; i < argc; i++) { + if (is_shell_flag(argv[i])) continue; + file_to_open = argv[i]; + break; + } + + if (file_to_open) editor_open(file_to_open); + + write(1, "\x1b[2J", 4); + write(1, "\x1b[H", 3); + + refresh_screen(); + while (process_key()) { + refresh_screen(); + } + + write(1, "\x1b[2J", 4); + write(1, "\x1b[H", 3); + disable_raw_mode(); + return 0; +} \ No newline at end of file diff --git a/usr/apps/shell.c b/usr/apps/shell.c new file mode 100644 index 0000000..192e006 --- /dev/null +++ b/usr/apps/shell.c @@ -0,0 +1,975 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef VFS_MAX_PATH +#define VFS_MAX_PATH 1024 +#endif + +#define TIOCGWINSZ 0x5413 +#define TIOCGCURSOR 0x5480 + +typedef struct { uint16_t ws_row, ws_col, ws_xpixel, ws_ypixel; } cervus_winsize_t; +typedef struct { uint32_t row, col; } cervus_cursor_pos_t; + +static inline int sh_ioctl(int fd, unsigned long req, void *arg) { + return (int)syscall3(SYS_IOCTL, fd, req, arg); +} + +static int g_cols = 80; +static int g_rows = 25; + +static void term_update_size(void) { + cervus_winsize_t ws; + if (sh_ioctl(1, TIOCGWINSZ, &ws) == 0 && ws.ws_col >= 8 && ws.ws_row >= 2) { + g_cols = (int)ws.ws_col; + g_rows = (int)ws.ws_row; + } +} + +static int term_get_cursor_row(void) { + cervus_cursor_pos_t cp; + if (sh_ioctl(1, TIOCGCURSOR, &cp) == 0) return (int)cp.row; + return 0; +} + +static void vt_goto(int row, int col) { + char b[24]; + snprintf(b, sizeof(b), "\x1b[%d;%dH", row + 1, col + 1); + fputs(b, stdout); +} + +static void vt_eol(void) { fputs("\x1b[K", stdout); } + +#define HIST_MAX 1024 +#define LINE_MAX 1024 + +static char history[HIST_MAX][LINE_MAX]; +static int hist_count = 0, hist_head = 0; + +static const char *g_hist_file = NULL; + +static void hist_load(const char *path) { + int fd = open(path, O_RDONLY, 0); + if (fd < 0) return; + char line[LINE_MAX]; + int li = 0; + char ch; + while (read(fd, &ch, 1) > 0) { + if (ch == '\n' || li >= LINE_MAX - 1) { + line[li] = '\0'; + if (li > 0) { + int idx = (hist_head + hist_count) % HIST_MAX; + strncpy(history[idx], line, LINE_MAX - 1); + history[idx][LINE_MAX - 1] = '\0'; + if (hist_count < HIST_MAX) hist_count++; + else hist_head = (hist_head + 1) % HIST_MAX; + } + li = 0; + } else { + line[li++] = ch; + } + } + close(fd); +} + +static void hist_save_entry(const char *path, const char *l) { + int fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0600); + if (fd < 0) return; + int n = 0; + while (l[n]) n++; + write(fd, l, n); + write(fd, "\n", 1); + close(fd); +} + +static void hist_push(const char *l) { + if (!l[0]) return; + if (hist_count > 0) { + int last = (hist_head + hist_count - 1) % HIST_MAX; + if (strcmp(history[last], l) == 0) return; + } + int idx = (hist_head + hist_count) % HIST_MAX; + strncpy(history[idx], l, LINE_MAX - 1); + history[idx][LINE_MAX - 1] = '\0'; + if (hist_count < HIST_MAX) hist_count++; + else hist_head = (hist_head + 1) % HIST_MAX; + if (g_hist_file) hist_save_entry(g_hist_file, l); +} + +static const char *hist_get(int n) { + if (n < 1 || n > hist_count) return NULL; + return history[(hist_head + hist_count - n) % HIST_MAX]; +} + +#define ENV_MAX_VARS 128 +#define ENV_NAME_MAX 64 +#define ENV_VAL_MAX 512 + +typedef struct { char name[ENV_NAME_MAX]; char value[ENV_VAL_MAX]; } env_var_t; + +static env_var_t g_env[ENV_MAX_VARS]; +static int g_env_count = 0; + +static int env_find(const char *name) { + for (int i = 0; i < g_env_count; i++) + if (strcmp(g_env[i].name, name) == 0) return i; + return -1; +} +static const char *env_get(const char *name) { + int i = env_find(name); + return i >= 0 ? g_env[i].value : ""; +} +static void env_set(const char *name, const char *value) { + int i = env_find(name); + if (i >= 0) { strncpy(g_env[i].value, value, ENV_VAL_MAX - 1); return; } + if (g_env_count >= ENV_MAX_VARS) return; + strncpy(g_env[g_env_count].name, name, ENV_NAME_MAX - 1); + strncpy(g_env[g_env_count].value, value, ENV_VAL_MAX - 1); + g_env_count++; +} +static void env_unset(const char *name) { + int i = env_find(name); + if (i < 0) return; + g_env[i] = g_env[--g_env_count]; +} + +static int g_last_rc = 0; + +static void expand_vars(const char *src, char *dst, size_t dsz) { + size_t di = 0; + for (const char *p = src; *p && di + 1 < dsz; ) { + if (*p != '$') { dst[di++] = *p++; continue; } + p++; + if (*p == '?') { + char tmp[12]; + int len = snprintf(tmp, sizeof(tmp), "%d", g_last_rc); + for (int x = 0; x < len && di + 1 < dsz; x++) dst[di++] = tmp[x]; + p++; continue; + } + int braced = (*p == '{'); + if (braced) p++; + char name[ENV_NAME_MAX]; int ni = 0; + while (*p && ni + 1 < (int)ENV_NAME_MAX) { + char c = *p; + if (braced) { if (c == '}') { p++; break; } } + else if (!isalnum((unsigned char)c) && c != '_') break; + name[ni++] = c; p++; + } + name[ni] = '\0'; + if (ni == 0) { dst[di++] = '$'; continue; } + const char *val = env_get(name); + for (; *val && di + 1 < dsz; val++) dst[di++] = *val; + } + dst[di] = '\0'; +} + +static char cwd[VFS_MAX_PATH]; +static int prompt_len = 0; + +static const char *display_path(void) { + static char dpbuf[VFS_MAX_PATH]; + const char *home = env_get("HOME"); + size_t hlen = home ? strlen(home) : 0; + if (hlen > 1 && strncmp(cwd, home, hlen) == 0 && + (cwd[hlen] == '/' || cwd[hlen] == '\0')) { + dpbuf[0] = '~'; + strncpy(dpbuf + 1, cwd + hlen, sizeof(dpbuf) - 2); + dpbuf[sizeof(dpbuf) - 1] = '\0'; + if (dpbuf[1] == '\0') { dpbuf[0] = '~'; dpbuf[1] = '\0'; } + return dpbuf; + } + return cwd; +} + +static void print_prompt(void) { + const char *dp = display_path(); + fputs(C_GREEN "cervus" C_RESET ":" C_BLUE, stdout); + fputs(dp, stdout); + fputs(C_RESET "$ ", stdout); + prompt_len = 9 + (int)strlen(dp); +} + +static int g_start_row = 0; + +static void sync_start_row(int cur_logical_pos) { + int real_row = term_get_cursor_row(); + int row_offset = (prompt_len + cur_logical_pos) / g_cols; + g_start_row = real_row - row_offset; + if (g_start_row < 0) g_start_row = 0; +} + +static void input_pos_to_screen(int pos, int *row, int *col) { + int abs = prompt_len + pos; + *row = g_start_row + abs / g_cols; + *col = abs % g_cols; +} + +static void cursor_to(int pos) { + int row, col; + input_pos_to_screen(pos, &row, &col); + if (row >= g_rows) row = g_rows - 1; + if (row < 0) row = 0; + vt_goto(row, col); +} + +static int last_row_of(int len) { + int abs = prompt_len + len; + return g_start_row + (abs > 0 ? (abs - 1) : 0) / g_cols; +} + +static void redraw(const char *buf, int from, int new_len, int old_len, int pos) { + cursor_to(from); + if (new_len > from) write(1, buf + from, new_len - from); + sync_start_row(new_len); + if (old_len > new_len) { + int old_last = last_row_of(old_len); + int new_last = last_row_of(new_len); + cursor_to(new_len); vt_eol(); + for (int r = new_last + 1; r <= old_last; r++) { + if (r >= g_rows) break; + vt_goto(r, 0); vt_eol(); + } + } + cursor_to(pos); +} + +static void replace_line(char *buf, int *len, int *pos, const char *newtext, int newlen) { + int old_len = *len; + for (int i = 0; i < newlen; i++) buf[i] = newtext[i]; + buf[newlen] = '\0'; + *len = newlen; + *pos = newlen; + redraw(buf, 0, newlen, old_len, newlen); +} + +static void insert_str(char *buf, int *len, int *pos, int maxlen, const char *s, int slen) { + if (*len + slen >= maxlen) return; + int old_len = *len; + for (int i = *len; i >= *pos; i--) buf[i + slen] = buf[i]; + for (int i = 0; i < slen; i++) buf[*pos + i] = s[i]; + *len += slen; + buf[*len] = '\0'; + cursor_to(*pos); + write(1, buf + *pos, *len - *pos); + sync_start_row(*len); + *pos += slen; + cursor_to(*pos); +} + +static int find_word_start(const char *buf, int pos) { + int p = pos; + while (p > 0 && buf[p - 1] != ' ') p--; + return p; +} + +static void list_dir_matches(const char *dir, const char *prefix, int plen, + char matches[][256], int *nmatch, int max) { + DIR *d = opendir(dir); + if (!d) return; + struct dirent *de; + while (*nmatch < max && (de = readdir(d)) != NULL) { + if (strncmp(de->d_name, prefix, plen) == 0) { + strncpy(matches[*nmatch], de->d_name, 255); + matches[*nmatch][255] = '\0'; + (*nmatch)++; + } + } + closedir(d); +} + +static void do_tab_complete(char *buf, int *len, int *pos, int maxlen) { + int ws_start = find_word_start(buf, *pos); + int wlen = *pos - ws_start; + if (wlen <= 0) { + insert_str(buf, len, pos, maxlen, " ", 4); + return; + } + char word[256]; + if (wlen > 255) wlen = 255; + memcpy(word, buf + ws_start, wlen); + word[wlen] = '\0'; + + int is_first_word = 1; + for (int i = 0; i < ws_start; i++) { + if (buf[i] != ' ') { is_first_word = 0; break; } + } + + char matches[32][256]; + int nmatch = 0; + + if (is_first_word) { + const char *pathvar = env_get("PATH"); + char ptmp[ENV_VAL_MAX]; + strncpy(ptmp, pathvar, sizeof(ptmp) - 1); + char *p = ptmp; + while (*p && nmatch < 32) { + char *seg = p; + while (*p && *p != ':') p++; + if (*p == ':') *p++ = '\0'; + if (seg[0]) list_dir_matches(seg, word, wlen, matches, &nmatch, 32); + } + const char *builtins[] = {"help","exit","cd","export","unset",NULL}; + for (int i = 0; builtins[i] && nmatch < 32; i++) { + if (strncmp(builtins[i], word, wlen) == 0) { + strncpy(matches[nmatch], builtins[i], 255); + nmatch++; + } + } + } else { + char dirp[VFS_MAX_PATH]; + const char *prefix = word; + char *last_slash = NULL; + for (int i = 0; word[i]; i++) if (word[i] == '/') last_slash = &word[i]; + if (last_slash) { + int dlen = (int)(last_slash - word); + char raw_dir[256]; + memcpy(raw_dir, word, dlen); + raw_dir[dlen] = '\0'; + if (raw_dir[0] == '\0') strcpy(raw_dir, "/"); + resolve_path(cwd, raw_dir, dirp, sizeof(dirp)); + prefix = last_slash + 1; + } else { + strncpy(dirp, cwd, sizeof(dirp) - 1); + } + int plen = (int)strlen(prefix); + list_dir_matches(dirp, prefix, plen, matches, &nmatch, 32); + } + + if (nmatch == 0) { + insert_str(buf, len, pos, maxlen, " ", 4); + return; + } + if (nmatch == 1) { + const char *m = matches[0]; + int mlen = (int)strlen(m); + int tail = mlen - wlen; + if (tail > 0) { + const char *suffix = m + wlen; + if (is_first_word) { + int need = tail; + if (*len + need >= maxlen) return; + int old_len = *len; + for (int i = *len; i >= *pos; i--) buf[i + need] = buf[i]; + for (int i = 0; i < tail; i++) buf[*pos + i] = suffix[i]; + *len += need; + buf[*len] = '\0'; + cursor_to(*pos); + write(1, buf + *pos, *len - *pos); + sync_start_row(*len); + *pos += need; + cursor_to(*pos); + } else { + insert_str(buf, len, pos, maxlen, suffix, tail); + } + } + return; + } + int common = (int)strlen(matches[0]); + for (int i = 1; i < nmatch; i++) { + int j = 0; + while (j < common && matches[0][j] == matches[i][j]) j++; + common = j; + } + int extra = common - wlen; + if (extra > 0) { + insert_str(buf, len, pos, maxlen, matches[0] + wlen, extra); + return; + } + putchar(10); + for (int i = 0; i < nmatch; i++) { + fputs(" ", stdout); fputs(matches[i], stdout); + } + putchar(10); + print_prompt(); + write(1, buf, *len); + sync_start_row(*len); + cursor_to(*pos); +} + +static int readline_edit(char *buf, int maxlen) { + term_update_size(); + { + int real_row = term_get_cursor_row(); + g_start_row = real_row - prompt_len / g_cols; + if (g_start_row < 0) g_start_row = 0; + } + int len = 0, pos = 0, hidx = 0; + static char saved[LINE_MAX]; + saved[0] = '\0'; buf[0] = '\0'; + + for (;;) { + char c; + if (read(0, &c, 1) <= 0) return -1; + + if (c == '\x1b') { + char s[4]; + if (read(0, &s[0], 1) <= 0) continue; + if (s[0] != '[') continue; + if (read(0, &s[1], 1) <= 0) continue; + if (s[1] == 'A') { + if (hidx == 0) strncpy(saved, buf, LINE_MAX - 1); + if (hidx < hist_count) { + hidx++; + const char *h = hist_get(hidx); + if (h) { + int hl = (int)strlen(h); + if (hl > maxlen - 1) hl = maxlen - 1; + replace_line(buf, &len, &pos, h, hl); + } + } + continue; + } + if (s[1] == 'B') { + if (hidx > 0) { + hidx--; + const char *h = hidx == 0 ? saved : hist_get(hidx); + if (!h) h = ""; + int hl = (int)strlen(h); + if (hl > maxlen - 1) hl = maxlen - 1; + replace_line(buf, &len, &pos, h, hl); + } + continue; + } + if (s[1] == 'C') { if (pos < len) { pos++; cursor_to(pos); } continue; } + if (s[1] == 'D') { if (pos > 0) { pos--; cursor_to(pos); } continue; } + if (s[1] == 'H') { pos = 0; cursor_to(0); continue; } + if (s[1] == 'F') { pos = len; cursor_to(len); continue; } + if (s[1] >= '1' && s[1] <= '6') { + char tilde; read(0, &tilde, 1); + if (tilde != '~') continue; + if (s[1] == '3' && pos < len) { + for (int i = pos; i < len - 1; i++) buf[i] = buf[i + 1]; + len--; buf[len] = '\0'; + redraw(buf, pos, len, len + 1, pos); + } else if (s[1] == '1') { pos = 0; cursor_to(0); } + else if (s[1] == '4') { pos = len; cursor_to(len); } + } + continue; + } + + if (c == '\n' || c == '\r') { buf[len] = '\0'; cursor_to(len); putchar(10); return len; } + if (c == 3) { fputs("^C", stdout); putchar(10); buf[0] = '\0'; return 0; } + if (c == 4) { if (len == 0) return -1; continue; } + if (c == 1) { pos = 0; cursor_to(0); continue; } + if (c == 5) { pos = len; cursor_to(len); continue; } + if (c == '\t') { + do_tab_complete(buf, &len, &pos, maxlen); + continue; + } + if (c == 11) { + if (pos < len) { int old_len = len; len = pos; buf[len] = '\0'; redraw(buf, pos, len, old_len, pos); } + continue; + } + if (c == 21) { + if (pos > 0) { + int old_len = len, del = pos; + for (int i = 0; i < len - del; i++) buf[i] = buf[i + del]; + len -= del; pos = 0; buf[len] = '\0'; + redraw(buf, 0, len, old_len, 0); + } + continue; + } + if (c == 23) { + if (pos > 0) { + int p = pos; + while (p > 0 && buf[p - 1] == ' ') p--; + while (p > 0 && buf[p - 1] != ' ') p--; + int old_len = len, del = pos - p; + for (int i = p; i < len - del; i++) buf[i] = buf[i + del]; + len -= del; pos = p; buf[len] = '\0'; + redraw(buf, p, len, old_len, p); + } + continue; + } + if (c == '\b' || c == 0x7F) { + if (pos > 0) { + int old_len = len; + for (int i = pos - 1; i < len - 1; i++) buf[i] = buf[i + 1]; + len--; pos--; buf[len] = '\0'; + redraw(buf, pos, len, old_len, pos); + } + continue; + } + if (c >= 0x20 && c < 0x7F) { + if (len >= maxlen - 1) continue; + for (int i = len; i > pos; i--) buf[i] = buf[i - 1]; + buf[pos] = c; len++; buf[len] = '\0'; + cursor_to(pos); write(1, buf + pos, len - pos); + sync_start_row(len); pos++; + cursor_to(pos); + } + } +} + +#define MAX_ARGS 32 + +static int tokenize(char *line, char *argv[], int maxargs) { + int argc = 0; + char *p = line; + while (*p) { + while (isspace((unsigned char)*p)) p++; + if (!*p) break; + if (argc >= maxargs - 1) break; + char *out = p; + argv[argc++] = out; + int in_dquote = 0, in_squote = 0; + while (*p) { + if (in_dquote) { + if (*p == '"') { in_dquote = 0; p++; } + else { *out++ = *p++; } + } else if (in_squote) { + if (*p == '\'') { in_squote = 0; p++; } + else { *out++ = *p++; } + } else { + if (*p == '"') { in_dquote = 1; p++; } + else if (*p == '\'') { in_squote = 1; p++; } + else if (isspace((unsigned char)*p)) { p++; break; } + else { *out++ = *p++; } + } + } + *out = '\0'; + if (in_dquote || in_squote) { argv[argc] = NULL; return -1; } + } + argv[argc] = NULL; + return argc; +} + +static void cmd_help(void) { + putchar(10); + fputs(" " C_CYAN "Cervus Shell" C_RESET " - commands\n", stdout); + fputs(" " C_GRAY "-----------------------------------" C_RESET "\n", stdout); + fputs(" " C_BOLD "help" C_RESET " show this message\n", stdout); + fputs(" " C_BOLD "cd" C_RESET "

change directory\n", stdout); + fputs(" " C_BOLD "export" C_RESET " N=V set variable N to value V\n", stdout); + fputs(" " C_BOLD "unset" C_RESET " N delete variable N\n", stdout); + fputs(" " C_BOLD "env" C_RESET " list variables\n", stdout); + fputs(" " C_BOLD "exit" C_RESET " quit shell\n", stdout); + fputs(" " C_GRAY "-----------------------------------" C_RESET "\n", stdout); + fputs(" " C_BOLD "Programs:" C_RESET " ls, cat, echo, pwd, clear, uname\n", stdout); + fputs(" meminfo, cpuinfo, ps, kill, find, stat, wc, yes, sleep\n", stdout); + fputs(" mount, umount, mkfs, lsblk, mv, rm, mkdir, touch\n", stdout); + fputs(" " C_RED "shutdown" C_RESET ", " C_CYAN "reboot" C_RESET "\n", stdout); + fputs(" " C_GRAY "-----------------------------------" C_RESET "\n", stdout); + fputs(" " C_BOLD "Operators:" C_RESET " cmd1 " C_YELLOW ";" C_RESET + " cmd2 " C_YELLOW "&&" C_RESET " " C_YELLOW "||" C_RESET "\n", stdout); + fputs(" " C_BOLD "Tab" C_RESET " auto-complete / 4 spaces\n", stdout); + fputs(" " C_BOLD "Ctrl+C" C_RESET " interrupt\n", stdout); + fputs(" " C_BOLD "Ctrl+A/E" C_RESET " beginning/end of line\n", stdout); + fputs(" " C_BOLD "Ctrl+K/U" C_RESET " delete to end/beginning\n", stdout); + fputs(" " C_BOLD "Ctrl+W" C_RESET " delete word\n", stdout); + fputs(" " C_BOLD "Arrows" C_RESET " cursor / history\n", stdout); + fputs(" " C_GRAY "-----------------------------------" C_RESET "\n", stdout); + putchar(10); +} + +static int cmd_cd(const char *path) { + if (!path || !path[0] || strcmp(path, "~") == 0) { + const char *home = env_get("HOME"); + path = (home && home[0]) ? home : "/"; + } + char np[VFS_MAX_PATH]; + resolve_path(cwd, path, np, sizeof(np)); + struct stat st; + if (stat(np, &st) < 0) { fputs(C_RED "cd: not found: " C_RESET, stdout); fputs(path, stdout); putchar(10); return 1; } + if (st.st_type != 1) { fputs(C_RED "cd: not a dir: " C_RESET, stdout); fputs(path, stdout); putchar(10); return 1; } + strncpy(cwd, np, sizeof(cwd) - 1); + cwd[sizeof(cwd) - 1] = '\0'; + chdir(np); + return 0; +} + +static int valid_varname(const char *s) { + if (!s || !*s) return 0; + if (!isalpha((unsigned char)*s) && *s != '_') return 0; + for (s++; *s; s++) + if (!isalnum((unsigned char)*s) && *s != '_') return 0; + return 1; +} + +static int cmd_export(int argc, char *argv[]) { + if (argc < 2) { fputs(C_RED "export: usage: export NAME=VALUE\n" C_RESET, stdout); return 1; } + if (argc > 2) { fputs(C_RED "export: invalid syntax\n" C_RESET, stdout); return 1; } + char *arg = argv[1]; + char *eq_pos = strchr(arg, '='); + if (!eq_pos) { + if (!valid_varname(arg)) { fputs(C_RED "export: not a valid identifier\n" C_RESET, stdout); return 1; } + env_set(arg, ""); return 0; + } + *eq_pos = '\0'; + const char *name = arg, *val = eq_pos + 1; + if (!valid_varname(name)) { *eq_pos = '='; fputs(C_RED "export: not a valid identifier\n" C_RESET, stdout); return 1; } + env_set(name, val); + *eq_pos = '='; + return 0; +} + +static int cmd_unset(int argc, char *argv[]) { + if (argc < 2) { fputs(C_RED "unset: usage: unset NAME\n" C_RESET, stdout); return 1; } + for (int i = 1; i < argc; i++) env_unset(argv[i]); + return 0; +} + +static int find_in_path(const char *cmd, char *out, size_t outsz) { + const char *pathvar = env_get("PATH"); + if (!pathvar || !pathvar[0]) { + path_join("/bin", cmd, out, outsz); + struct stat st; + return stat(out, &st) == 0 && st.st_type != 1; + } + char tmp[ENV_VAL_MAX]; + strncpy(tmp, pathvar, sizeof(tmp) - 1); + char *p = tmp; + while (*p) { + char *seg = p; + while (*p && *p != ':') p++; + if (*p == ':') *p++ = '\0'; + if (!seg[0]) continue; + char candidate[VFS_MAX_PATH]; + path_join(seg, cmd, candidate, sizeof(candidate)); + struct stat st; + if (stat(candidate, &st) == 0 && st.st_type != 1) { strncpy(out, candidate, outsz - 1); return 1; } + } + return 0; +} + +typedef enum { REDIR_NONE = 0, REDIR_OUT, REDIR_APPEND, REDIR_IN } redir_type_t; + +typedef struct { + redir_type_t type; + char path[VFS_MAX_PATH]; +} redir_t; + +static int parse_redirects(char *argv[], int *argc, redir_t redirs[], int max_redirs, int *nredirs) { + *nredirs = 0; + int new_argc = 0; + for (int i = 0; i < *argc; i++) { + const char *a = argv[i]; + redir_type_t rt = REDIR_NONE; + const char *target = NULL; + + if (strcmp(a, ">>") == 0) { + rt = REDIR_APPEND; + if (i + 1 < *argc) target = argv[++i]; + } else if (strcmp(a, ">") == 0) { + rt = REDIR_OUT; + if (i + 1 < *argc) target = argv[++i]; + } else if (strcmp(a, "<") == 0) { + rt = REDIR_IN; + if (i + 1 < *argc) target = argv[++i]; + } else if (a[0] == '>' && a[1] == '>' && a[2] != '\0') { + rt = REDIR_APPEND; target = a + 2; + } else if (a[0] == '>' && a[1] != '>' && a[1] != '\0') { + rt = REDIR_OUT; target = a + 1; + } else if (a[0] == '<' && a[1] != '\0') { + rt = REDIR_IN; target = a + 1; + } else { + argv[new_argc++] = argv[i]; + continue; + } + + if (!target || !target[0]) { + fputs(C_RED "syntax error: missing redirection target\n" C_RESET, stdout); + return -1; + } + if (*nredirs < max_redirs) { + redirs[*nredirs].type = rt; + char resolved[VFS_MAX_PATH]; + resolve_path(cwd, target, resolved, sizeof(resolved)); + strncpy(redirs[*nredirs].path, resolved, VFS_MAX_PATH - 1); + redirs[*nredirs].path[VFS_MAX_PATH - 1] = '\0'; + (*nredirs)++; + } + } + argv[new_argc] = NULL; + *argc = new_argc; + return 0; +} + +static int run_single(char *line) { + char expanded[LINE_MAX]; + expand_vars(line, expanded, sizeof(expanded)); + char buf[LINE_MAX]; + strncpy(buf, expanded, LINE_MAX - 1); + char *argv[MAX_ARGS]; + int argc = tokenize(buf, argv, MAX_ARGS); + if (argc < 0) { fputs(C_RED "syntax error: unclosed quote\n" C_RESET, stdout); return 1; } + if (!argc) return 0; + + redir_t redirs[8]; + int nredirs = 0; + if (parse_redirects(argv, &argc, redirs, 8, &nredirs) < 0) return 1; + if (!argc) return 0; + + const char *cmd = argv[0]; + + if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; } + if (strcmp(cmd, "exit") == 0) { fputs("Goodbye!\n", stdout); exit(0); } + if (strcmp(cmd, "cd") == 0) return cmd_cd(argc > 1 ? argv[1] : NULL); + if (strcmp(cmd, "export") == 0) return cmd_export(argc, argv); + if (strcmp(cmd, "unset") == 0) return cmd_unset(argc, argv); + + char binpath[VFS_MAX_PATH]; + if (cmd[0] == '/') { + strncpy(binpath, cmd, sizeof(binpath) - 1); + binpath[sizeof(binpath) - 1] = '\0'; + } else if (cmd[0] == '.') { + resolve_path(cwd, cmd, binpath, sizeof(binpath)); + } else { + if (!find_in_path(cmd, binpath, sizeof(binpath))) { + char t_cwd[VFS_MAX_PATH]; + resolve_path(cwd, cmd, t_cwd, sizeof(t_cwd)); + struct stat st; + if (stat(t_cwd, &st) == 0 && st.st_type != 1) { + strncpy(binpath, t_cwd, sizeof(binpath) - 1); + binpath[sizeof(binpath) - 1] = '\0'; + } else { + fputs(C_RED "not found: " C_RESET, stdout); fputs(cmd, stdout); putchar(10); return 127; + } + } + } + +#define REAL_ARGV_MAX (MAX_ARGS + ENV_MAX_VARS + 4) + char *real_argv_buf[REAL_ARGV_MAX]; + static char _cwd_flag[VFS_MAX_PATH + 8]; + static char _env_flags[ENV_MAX_VARS][ENV_NAME_MAX + ENV_VAL_MAX + 8]; + + int ri = 0; + real_argv_buf[ri++] = binpath; + for (int i = 1; i < argc; i++) real_argv_buf[ri++] = argv[i]; + snprintf(_cwd_flag, sizeof(_cwd_flag), "--cwd=%s", cwd); + real_argv_buf[ri++] = _cwd_flag; + for (int ei = 0; ei < g_env_count && ri < REAL_ARGV_MAX - 1; ei++) { + snprintf(_env_flags[ei], sizeof(_env_flags[ei]), "--env:%s=%s", + g_env[ei].name, g_env[ei].value); + real_argv_buf[ri++] = _env_flags[ei]; + } + real_argv_buf[ri] = NULL; + + pid_t child = fork(); + if (child < 0) { fputs(C_RED "fork failed" C_RESET "\n", stdout); return 1; } + if (child == 0) { + for (int i = 0; i < nredirs; i++) { + int fd = -1; + int target_fd = -1; + if (redirs[i].type == REDIR_OUT) { + fd = open(redirs[i].path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + target_fd = 1; + } else if (redirs[i].type == REDIR_APPEND) { + fd = open(redirs[i].path, O_WRONLY | O_CREAT | O_APPEND, 0644); + target_fd = 1; + } else if (redirs[i].type == REDIR_IN) { + fd = open(redirs[i].path, O_RDONLY, 0); + target_fd = 0; + } + if (fd < 0) { + fputs(C_RED "redirect: cannot open: " C_RESET, stdout); + fputs(redirs[i].path, stdout); + putchar('\n'); + exit(1); + } + dup2(fd, target_fd); + close(fd); + } + execve(binpath, (char *const *)real_argv_buf, NULL); + fputs(C_RED "exec failed: " C_RESET, stdout); fputs(binpath, stdout); putchar(10); exit(127); + } + int status = 0; + waitpid(child, &status, 0); + return (status >> 8) & 0xFF; +} + +typedef enum { CH_NONE = 0, CH_SEQ, CH_AND, CH_OR } chain_t; + +static void run_command(char *line) { + char work[LINE_MAX]; + strncpy(work, line, LINE_MAX - 1); + char *segs[64]; chain_t ops[64]; int ns = 1; + segs[0] = work; ops[0] = CH_NONE; + char *p = work; + while (*p) { + if (*p == '"') { p++; while (*p && *p != '"') p++; if (*p) p++; continue; } + if (*p == '\'') { p++; while (*p && *p != '\'') p++; if (*p) p++; continue; } + if (*p == '&' && *(p+1) == '&') { *p='\0'; p+=2; while(isspace((unsigned char)*p))p++; ops[ns]=CH_AND; segs[ns]=p; ns++; continue; } + if (*p == '|' && *(p+1) == '|') { *p='\0'; p+=2; while(isspace((unsigned char)*p))p++; ops[ns]=CH_OR; segs[ns]=p; ns++; continue; } + if (*p == ';') { *p='\0'; p++; while(isspace((unsigned char)*p))p++; ops[ns]=CH_SEQ; segs[ns]=p; ns++; continue; } + p++; + } + int rc = 0; + for (int i = 0; i < ns; i++) { + char *s = segs[i]; + while (isspace((unsigned char)*s)) s++; + size_t sl = strlen(s); + while (sl > 0 && isspace((unsigned char)s[sl - 1])) s[--sl] = '\0'; + if (!s[0]) continue; + if (i > 0) { + if (ops[i] == CH_AND && rc != 0) continue; + if (ops[i] == CH_OR && rc == 0) continue; + } + rc = run_single(s); + } + g_last_rc = rc; +} + +static void print_motd(void) { + int fd = open("/mnt/etc/motd", O_RDONLY, 0); + if (fd < 0) fd = open("/etc/motd", O_RDONLY, 0); + if (fd < 0) { putchar(10); fputs(" Cervus OS v0.0.2\n Type 'help' for commands.\n", stdout); putchar(10); return; } + char buf[1024]; + ssize_t n = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (n > 0) { buf[n] = '\0'; write(1, buf, n); } +} + + +static int g_installed = 0; + +static int sys_disk_mount(const char *dev, const char *path) { + return (int)syscall2(SYS_DISK_MOUNT, dev, path); +} + +static int launch_installer(void) { + const char *path = "/bin/install-on-disk"; + struct stat st; + if (stat(path, &st) != 0) { + fputs(C_RED " install-on-disk not found on system.\n" C_RESET, stdout); + return -1; + } + + const char *argv[4]; + argv[0] = path; + argv[1] = "--env:MODE=live"; + argv[2] = "--cwd=/"; + argv[3] = NULL; + + pid_t child = fork(); + if (child < 0) { + fputs(C_RED " fork failed\n" C_RESET, stdout); + return -1; + } + if (child == 0) { + execve(path, (char *const *)argv, NULL); + fputs(C_RED " exec install-on-disk failed\n" C_RESET, stdout); + exit(127); + } + int status = 0; + waitpid(child, &status, 0); + return (status >> 8) & 0xFF; +} + +static int ask_install_or_live(void) { + fputs("\x1b[2J\x1b[H", stdout); + fputs("\n", stdout); + fputs(C_CYAN " Cervus OS" C_RESET " - Live ISO\n", stdout); + fputs(C_GRAY " -----------------------------------" C_RESET "\n\n", stdout); + fputs(" A disk has been detected on this machine.\n", stdout); + fputs(" What would you like to do?\n\n", stdout); + fputs(" [" C_BOLD "1" C_RESET "] Install Cervus to disk\n", stdout); + fputs(" [" C_BOLD "2" C_RESET "] Continue in Live mode\n\n", stdout); + fputs(" Choice [1-2]: ", stdout); + + char c = 0; + while (1) { + if (read(0, &c, 1) <= 0) continue; + if (c == '1' || c == '2') { putchar(c); putchar(10); break; } + } + return (c == '1') ? 1 : 0; +} + +int main(int argc, char **argv) { + (void)argc; (void)argv; + + struct stat dev_st; + int has_disk = (stat("/dev/hda", &dev_st) == 0); + int has_hda2 = (stat("/dev/hda2", &dev_st) == 0); + int has_hda_legacy = 0; + + int disk_mounted = 0; + + if (has_hda2) { + int mr = sys_disk_mount("hda2", "/mnt"); + if (mr == 0) { + disk_mounted = 1; + g_installed = 1; + } + } else if (has_disk) { + int mr = sys_disk_mount("hda", "/mnt"); + if (mr == 0) { + disk_mounted = 1; + g_installed = 1; + has_hda_legacy = 1; + } + } + (void)has_hda_legacy; + + if (!disk_mounted && has_disk) { + if (ask_install_or_live() == 1) { + launch_installer(); + struct stat retry_st; + if (stat("/dev/hda2", &retry_st) == 0) { + if (sys_disk_mount("hda2", "/mnt") == 0) { + disk_mounted = 1; + g_installed = 1; + } + } + } + } + + if (disk_mounted) { + strncpy(cwd, "/mnt/home", sizeof(cwd)); + env_set("HOME", "/mnt/home"); + env_set("PATH", "/mnt/bin:/mnt/apps:/mnt/usr/bin"); + env_set("SHELL", "/mnt/bin/shell"); + } else { + strncpy(cwd, "/", sizeof(cwd)); + env_set("HOME", "/"); + env_set("PATH", "/bin:/apps:/usr/bin"); + env_set("SHELL", "/bin/shell"); + } + + if (!disk_mounted && has_disk) env_set("MODE", "live"); + else if (!has_disk) env_set("MODE", "live"); + else env_set("MODE", "installed"); + + print_motd(); + + { + static char hist_path[VFS_MAX_PATH]; + const char *h = env_get("HOME"); + if (h && h[0]) { + path_join(h, ".history", hist_path, sizeof(hist_path)); + g_hist_file = hist_path; + hist_load(hist_path); + } + } + + if (!has_disk) { + fputs(C_YELLOW " [Live Mode]" C_RESET " No disk detected. All changes are in RAM.\n\n", stdout); + } else if (!disk_mounted) { + fputs(C_YELLOW " [Live Mode]" C_RESET " Disk not mounted.\n\n", stdout); + } + + char line[LINE_MAX]; + for (;;) { + print_prompt(); + int n = readline_edit(line, LINE_MAX); + if (n < 0) { + fputs("\nSession ended. Restarting shell...\n", stdout); + const char *h = env_get("HOME"); + strncpy(cwd, (h && h[0]) ? h : "/", sizeof(cwd)); + print_motd(); + continue; + } + int len = (int)strlen(line); + while (len > 0 && isspace((unsigned char)line[len - 1])) line[--len] = '\0'; + if (len > 0) { hist_push(line); run_command(line); } + } +} \ No newline at end of file diff --git a/usr/apps/test_execve.c b/usr/apps/test_execve.c new file mode 100644 index 0000000..079908b --- /dev/null +++ b/usr/apps/test_execve.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include + +static int failed = 0; +static void ok(const char *s) { printf(" [OK] %s\n", s); } +static void fail(const char *s) { printf(" [FAIL] %s\n", s); failed = 1; } + +static int file_exists(const char *path) +{ + struct stat st; + return stat(path, &st) == 0; +} + +static const char *resolve_app(const char *name, char *buf, size_t bufsz) +{ + const char *prefixes[] = { "/mnt/apps/", "/apps/", "/mnt/bin/", "/bin/", NULL }; + for (int i = 0; prefixes[i]; i++) { + size_t pl = strlen(prefixes[i]); + size_t nl = strlen(name); + if (pl + nl + 1 > bufsz) continue; + memcpy(buf, prefixes[i], pl); + memcpy(buf + pl, name, nl + 1); + if (file_exists(buf)) return buf; + } + return NULL; +} + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + puts("--- test_execve ---"); + + char target[256]; + if (!resolve_app("execve_target", target, sizeof(target))) { + printf(" [SKIP] execve_target not found\n"); + puts("--- test_execve done ---"); + return 0; + } + + { + char *const cargv[] = { target, (char *)"hello", (char *)"from", (char *)"execve", NULL }; + pid_t child = fork(); + if (child < 0) { fail("fork"); return 1; } + if (child == 0) { + execve(target, cargv, NULL); + printf(" [FATAL] execve failed\n"); + return 127; + } + int status = 0; + waitpid(child, &status, 0); + if (WIFEXITED(status) && WEXITSTATUS(status) == 99) ok("execve target exits 99"); + else { + printf(" exit status = %d\n", WEXITSTATUS(status)); + fail("execve exit code"); + } + } + + { + pid_t child = fork(); + if (child < 0) { fail("fork"); return 1; } + if (child == 0) { + char *const cargv[] = { (char *)"/no/such/binary", NULL }; + int r = execve("/no/such/binary", cargv, NULL); + return (r < 0) ? 0 : 1; + } + int status = 0; + waitpid(child, &status, 0); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) ok("execve nonexistent returns error"); + else fail("execve nonexistent should return error"); + } + + { + pid_t child = fork(); + if (child < 0) { fail("fork"); return 1; } + if (child == 0) { + execve(target, NULL, NULL); + return 127; + } + int status = 0; + waitpid(child, &status, 0); + if (WIFEXITED(status) && WEXITSTATUS(status) == 99) ok("execve with NULL argv"); + else fail("execve NULL argv"); + } + + puts("--- test_execve done ---"); + return failed ? 1 : 0; +} diff --git a/usr/apps/test_files.c b/usr/apps/test_files.c new file mode 100644 index 0000000..793cc56 --- /dev/null +++ b/usr/apps/test_files.c @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include +#include + +static int failed = 0; +static void ok(const char *s) { printf(" [OK] %s\n", s); } +static void fail(const char *s) { printf(" [FAIL] %s\n", s); failed = 1; } + +static int file_exists(const char *path) +{ + struct stat st; + return stat(path, &st) == 0; +} + +static const char *resolve_etc(const char *name, char *buf, size_t bufsz) +{ + const char *prefixes[] = { "/mnt/etc/", "/etc/", NULL }; + for (int i = 0; prefixes[i]; i++) { + size_t pl = strlen(prefixes[i]); + size_t nl = strlen(name); + if (pl + nl + 1 > bufsz) continue; + memcpy(buf, prefixes[i], pl); + memcpy(buf + pl, name, nl + 1); + if (file_exists(buf)) return buf; + } + return NULL; +} + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + puts("--- test_files ---"); + + char hostname_path[256], passwd_path[256]; + const char *hostname = resolve_etc("hostname", hostname_path, sizeof(hostname_path)); + const char *passwd = resolve_etc("passwd", passwd_path, sizeof(passwd_path)); + + if (!hostname) printf(" [WARN] hostname not found in /etc or /mnt/etc\n"); + if (!passwd) printf(" [WARN] passwd not found in /etc or /mnt/etc\n"); + + { + const char *msg = "hello from test_files\n"; + ssize_t w = write(1, msg, strlen(msg)); + if (w == (ssize_t)strlen(msg)) ok("write to stdout"); + else fail("write to stdout"); + } + { + const char *msg = "stderr line\n"; + ssize_t w = write(2, msg, strlen(msg)); + if (w == (ssize_t)strlen(msg)) ok("write to stderr"); + else fail("write to stderr"); + } + + if (hostname) { + int fd = open(hostname, O_RDONLY); + if (fd >= 0) { + ok("open hostname"); + char buf[64]; + memset(buf, 0, sizeof(buf)); + ssize_t r = read(fd, buf, sizeof(buf) - 1); + if (r > 0) { printf(" hostname = '%s'\n", buf); ok("read hostname"); } + else fail("read hostname"); + struct stat st; + if (fstat(fd, &st) == 0) { + printf(" fstat: size=%lu\n", (unsigned long)st.st_size); + ok("fstat"); + } else fail("fstat"); + close(fd); + ok("close"); + } else fail("open hostname"); + } + + if (passwd) { + struct stat st; + if (stat(passwd, &st) == 0) { + printf(" stat: ino=%lu size=%lu\n", + (unsigned long)st.st_ino, (unsigned long)st.st_size); + ok("stat passwd"); + } else fail("stat passwd"); + } + + { + int fd = open("/no/such/file", O_RDONLY); + if (fd < 0) ok("open nonexistent returns error"); + else { close(fd); fail("open nonexistent should fail"); } + } + + if (hostname) { + int fd = open(hostname, O_RDONLY); + if (fd >= 0) { + char buf[4]; memset(buf, 0, sizeof(buf)); + read(fd, buf, 2); + off_t pos = lseek(fd, 0, SEEK_CUR); + if (pos == 2) ok("lseek SEEK_CUR"); + else fail("lseek SEEK_CUR"); + lseek(fd, 0, SEEK_SET); + char buf2[4]; memset(buf2, 0, sizeof(buf2)); + read(fd, buf2, 2); + if (buf[0] == buf2[0] && buf[1] == buf2[1]) ok("lseek SEEK_SET re-read"); + else fail("lseek SEEK_SET re-read"); + close(fd); + } else fail("open for lseek test"); + } + + if (hostname) { + int fd = open(hostname, O_RDONLY); + if (fd >= 0) { + int fd2 = dup(fd); + if (fd2 >= 0 && fd2 != fd) { + ok("dup"); + char buf[32]; memset(buf, 0, sizeof(buf)); + ssize_t r = read(fd2, buf, sizeof(buf) - 1); + if (r > 0) ok("read from dup'd fd"); + else fail("read from dup'd fd"); + close(fd2); + } else fail("dup"); + close(fd); + } else fail("open for dup test"); + } + + if (hostname) { + int fd = open(hostname, O_RDONLY); + if (fd >= 0) { + int r = dup2(fd, 10); + if (r == 10) { + ok("dup2"); + char buf[32]; memset(buf, 0, sizeof(buf)); + ssize_t n = read(10, buf, sizeof(buf) - 1); + if (n > 0) ok("read from dup2 fd"); + else fail("read from dup2 fd"); + close(10); + } else fail("dup2"); + close(fd); + } else fail("open for dup2 test"); + } + + { + int fd = open("/dev/null", O_WRONLY); + if (fd >= 0) { + ssize_t w = write(fd, "garbage", 7); + if (w == 7) ok("write to /dev/null"); + else fail("write to /dev/null"); + close(fd); + } else fail("open /dev/null"); + } + { + int fd = open("/dev/zero", O_RDONLY); + if (fd >= 0) { + char buf[8]; memset(buf, 0xFF, 8); + ssize_t r = read(fd, buf, 8); + int all_zero = 1; + for (int i = 0; i < 8; i++) if (buf[i]) all_zero = 0; + if (r == 8 && all_zero) ok("read from /dev/zero"); + else fail("read from /dev/zero"); + close(fd); + } else fail("open /dev/zero"); + } + + puts("--- test_files done ---"); + return failed ? 1 : 0; +} diff --git a/usr/apps/test_mem.c b/usr/apps/test_mem.c new file mode 100644 index 0000000..98ed382 --- /dev/null +++ b/usr/apps/test_mem.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include + +static int failed = 0; +static void ok(const char *s) { printf(" [OK] %s\n", s); } +static void fail(const char *s) { printf(" [FAIL] %s\n", s); failed = 1; } + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + puts("--- test_mem ---"); + + void *brk0 = sbrk(0); + printf(" initial brk = %p\n", brk0); + if ((uintptr_t)brk0 > 0) ok("sbrk(0) returns valid address"); + else fail("sbrk(0)"); + + void *old = sbrk(4096); + if (old == brk0) ok("sbrk(4096) returns old brk"); + else fail("sbrk(4096)"); + + volatile uint8_t *heap = (volatile uint8_t *)brk0; + heap[0] = 0xAB; heap[4095] = 0xCD; + if (heap[0] == 0xAB && heap[4095] == 0xCD) ok("write/read heap page"); + else fail("write/read heap page"); + + void *cur = sbrk(0); + sbrk(-4096); + void *after = sbrk(0); + if ((uintptr_t)after == (uintptr_t)cur - 4096) ok("sbrk shrink"); + else fail("sbrk shrink"); + + void *m = mmap(NULL, 8192, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (m != MAP_FAILED) { + ok("mmap anonymous 8 KiB"); + volatile uint8_t *p = (volatile uint8_t *)m; + p[0] = 0x11; p[8191] = 0x22; + if (p[0] == 0x11 && p[8191] == 0x22) ok("write/read mmap pages"); + else fail("write/read mmap pages"); + if (munmap(m, 8192) == 0) ok("munmap"); + else fail("munmap"); + } else fail("mmap anonymous"); + + void *big = mmap(NULL, 1024 * 1024, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (big != MAP_FAILED) { + ok("mmap 1 MiB"); + volatile uint8_t *bp = (volatile uint8_t *)big; + int ok_all = 1; + for (int i = 0; i < 256; i++) { + bp[i * 4096] = (uint8_t)i; + if (bp[i * 4096] != (uint8_t)i) ok_all = 0; + } + if (ok_all) ok("touch 256 pages of 1 MiB mmap"); + else fail("touch mmap pages"); + munmap(big, 1024 * 1024); + } else fail("mmap 1 MiB"); + + { + void *addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (addr != MAP_FAILED) { + munmap(addr, 4096); + void *fixed = mmap(addr, 4096, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + if (fixed == addr) ok("MAP_FIXED at specific address"); + else fail("MAP_FIXED"); + if (fixed != MAP_FAILED) munmap(fixed, 4096); + } + } + + puts("--- test_mem done ---"); + return failed ? 1 : 0; +} diff --git a/usr/apps/test_pipe.c b/usr/apps/test_pipe.c new file mode 100644 index 0000000..7d4364a --- /dev/null +++ b/usr/apps/test_pipe.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include + +static int failed = 0; +static void ok(const char *s) { printf(" [OK] %s\n", s); } +static void fail(const char *s) { printf(" [FAIL] %s\n", s); failed = 1; } + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + puts("--- test_pipe ---"); + + int fds[2] = { -1, -1 }; + if (pipe(fds) == 0 && fds[0] >= 0 && fds[1] >= 0) ok("pipe() creates two fds"); + else { fail("pipe() failed"); return 1; } + printf(" read_fd=%d write_fd=%d\n", fds[0], fds[1]); + + { + const char *msg = "hello pipe"; + ssize_t w = write(fds[1], msg, strlen(msg)); + if (w == (ssize_t)strlen(msg)) ok("write to pipe"); + else fail("write to pipe"); + + char buf[32]; + memset(buf, 0, sizeof(buf)); + ssize_t r = read(fds[0], buf, sizeof(buf) - 1); + if (r == (ssize_t)strlen(msg) && strcmp(buf, msg) == 0) + ok("read from pipe matches written data"); + else fail("read from pipe"); + } + close(fds[0]); close(fds[1]); + + { + int p[2]; + if (pipe(p) != 0) { fail("pipe for fork test"); return 1; } + pid_t child = fork(); + if (child < 0) { fail("fork"); return 1; } + if (child == 0) { + close(p[0]); + const char *s = "world"; + write(p[1], s, strlen(s)); + close(p[1]); + return 0; + } + close(p[1]); + char buf[32]; memset(buf, 0, sizeof(buf)); + ssize_t r = read(p[0], buf, sizeof(buf) - 1); + close(p[0]); + int status = 0; waitpid(child, &status, 0); + if (r > 0 && strcmp(buf, "world") == 0) ok("pipe IPC parent<-child"); + else fail("pipe IPC"); + } + + { + int p[2]; + if (pipe(p) != 0) { fail("pipe for dup2 test"); return 1; } + pid_t child = fork(); + if (child < 0) { fail("fork for dup2"); return 1; } + if (child == 0) { + close(p[0]); + dup2(p[1], 1); + close(p[1]); + const char *s = "from child stdout\n"; + write(1, s, strlen(s)); + return 0; + } + close(p[1]); + char buf[64]; memset(buf, 0, sizeof(buf)); + ssize_t r = read(p[0], buf, sizeof(buf) - 1); + close(p[0]); + int status = 0; waitpid(child, &status, 0); + if (r > 0 && strncmp(buf, "from child stdout", 17) == 0) + ok("dup2 redirects child stdout through pipe"); + else fail("dup2 redirect"); + } + + puts("--- test_pipe done ---"); + return failed ? 1 : 0; +} diff --git a/usr/apps/test_process.c b/usr/apps/test_process.c new file mode 100644 index 0000000..e375ec9 --- /dev/null +++ b/usr/apps/test_process.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +static int failed = 0; +static void ok(const char *s) { printf(" [OK] %s\n", s); } +static void fail(const char *s) { printf(" [FAIL] %s\n", s); failed = 1; } + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + puts("--- test_process ---"); + + pid_t my_pid = getpid(); + if (my_pid > 0) ok("getpid > 0"); else fail("getpid > 0"); + + pid_t my_ppid = getppid(); + if (my_ppid > 0) ok("getppid > 0"); else fail("getppid > 0"); + + pid_t child = fork(); + if (child < 0) { fail("fork"); return 1; } + + if (child == 0) { + if (getppid() == my_pid) ok("child: ppid == parent pid"); + else fail("child: ppid == parent pid"); + return 42; + } + + int status = 0; + pid_t reaped = waitpid(child, &status, 0); + if (reaped == child) ok("waitpid returns child pid"); + else fail("waitpid returns child pid"); + if (WIFEXITED(status)) ok("WIFEXITED"); + else fail("WIFEXITED"); + if (WEXITSTATUS(status) == 42) ok("exit code 42"); + else { printf(" exit code = %d\n", WEXITSTATUS(status)); fail("exit code 42"); } + + pid_t r = waitpid(-1, &status, WNOHANG); + if (r == 0) ok("WNOHANG returns 0 when no zombie"); + else fail("WNOHANG returns 0 when no zombie"); + + if (getuid() == 0) ok("getuid == 0 (root)"); + else fail("getuid == 0"); + + puts("--- test_process done ---"); + return failed ? 1 : 0; +} diff --git a/usr/apps/uptime.c b/usr/apps/uptime.c new file mode 100644 index 0000000..174f8df --- /dev/null +++ b/usr/apps/uptime.c @@ -0,0 +1,22 @@ +#include +#include + +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + uint64_t ns = cervus_uptime_ns(); + uint64_t total_s = ns / 1000000000ULL; + uint64_t ms = (ns / 1000000ULL) % 1000ULL; + uint64_t secs = total_s % 60; + uint64_t mins = (total_s / 60) % 60; + uint64_t hours = (total_s / 3600) % 24; + uint64_t days = total_s / 86400; + + fputs(" Uptime: ", stdout); + if (days > 0) + printf("%lu day%s, ", (unsigned long)days, days != 1 ? "s" : ""); + printf("%02lu:%02lu:%02lu (%lus %lums)\n", + (unsigned long)hours, (unsigned long)mins, (unsigned long)secs, + (unsigned long)total_s, (unsigned long)ms); + return 0; +} diff --git a/usr/installer/install-on-disk.c b/usr/installer/install-on-disk.c new file mode 100644 index 0000000..d5753eb --- /dev/null +++ b/usr/installer/install-on-disk.c @@ -0,0 +1,592 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_ENTRIES 128 + +#define MBR_TYPE_FAT32_LBA 0x0C +#define MBR_TYPE_LINUX 0x83 +#define MBR_TYPE_LINUX_SWAP 0x82 + +typedef struct { + char name[32]; + char model[41]; + uint64_t sectors; + uint64_t size_bytes; +} disk_summary_t; + +typedef struct { + char name[64]; + uint8_t type; +} dir_entry_t; + +static void safe_strcpy(char *dst, size_t dsz, const char *src) +{ + if (!dst || dsz == 0) return; + if (!src) { dst[0] = '\0'; return; } + size_t i = 0; + while (i + 1 < dsz && src[i]) { dst[i] = src[i]; i++; } + dst[i] = '\0'; +} + +static void clear_screen(void) +{ + fputs("\x1b[2J\x1b[H", stdout); +} + +static int ensure_dir(const char *path) +{ + struct stat st; + if (stat(path, &st) == 0) return 0; + return mkdir(path, 0755); +} + +static int ensure_parent_dir(const char *path) +{ + char tmp[512]; + size_t len = strlen(path); + if (len >= sizeof(tmp)) return -1; + int last_slash = -1; + for (int i = (int)len - 1; i >= 0; i--) { + if (path[i] == '/') { last_slash = i; break; } + } + if (last_slash <= 0) return 0; + for (int i = 0; i < last_slash; i++) tmp[i] = path[i]; + tmp[last_slash] = '\0'; + int depth = 0; + int starts[32]; + starts[depth++] = 0; + for (int i = 1; i < last_slash && depth < 32; i++) { + if (tmp[i] == '/') starts[depth++] = i; + } + for (int d = 0; d < depth; d++) { + int end = (d + 1 < depth) ? starts[d + 1] : last_slash; + char part[512]; + for (int i = 0; i < end; i++) part[i] = tmp[i]; + part[end] = '\0'; + if (part[0] == '\0') continue; + struct stat st; + if (stat(part, &st) != 0) syscall2(SYS_MKDIR, part, 0755); + } + return 0; +} + +static int copy_one_file_progress(const char *src, const char *dst, const char *display_name) +{ + int sfd = open(src, O_RDONLY, 0); + if (sfd < 0) return sfd; + ensure_parent_dir(dst); + int dfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0755); + if (dfd < 0) { close(sfd); return dfd; } + + struct stat st; + uint64_t total = 0; + if (stat(src, &st) == 0) total = st.st_size; + + static char fbuf[4096]; + ssize_t n; + int rc = 0; + uint64_t written = 0; + int last_pct = -1; + int spinner = 0; + + while ((n = read(sfd, fbuf, sizeof(fbuf))) > 0) { + ssize_t w = write(dfd, fbuf, (size_t)n); + if (w < 0) { rc = (int)w; break; } + written += (uint64_t)w; + if (total > 0 && display_name) { + int pct = (int)((written * 100) / total); + if (pct != last_pct) { + static const char glyphs[4] = { '|', '/', '-', '\\' }; + fputs("\r\033[K ", stdout); + putchar(glyphs[spinner & 3]); + fputs(" ", stdout); + fputs(display_name, stdout); + fputs(" ", stdout); + char pb[8]; + int bi = 0; + if (pct >= 100) { pb[bi++]='1'; pb[bi++]='0'; pb[bi++]='0'; } + else if (pct >= 10) { pb[bi++]=(char)('0'+pct/10); pb[bi++]=(char)('0'+pct%10); } + else { pb[bi++]=(char)('0'+pct); } + pb[bi++]='%'; + pb[bi]='\0'; + fputs(pb, stdout); + spinner++; + last_pct = pct; + } + } + } + close(sfd); + close(dfd); + + if (display_name) { + fputs("\r\033[K ", stdout); + fputs(display_name, stdout); + fputs(rc < 0 ? " FAILED\n" : " done\n", stdout); + } + return rc; +} + +static int copy_one_file(const char *src, const char *dst) +{ + return copy_one_file_progress(src, dst, NULL); +} + +static int read_dir_entries(const char *path, dir_entry_t *out, int max) +{ + DIR *d = opendir(path); + if (!d) return 0; + int count = 0; + struct dirent *de; + while (count < max && (de = readdir(d)) != NULL) { + if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || + (de->d_name[1] == '.' && de->d_name[2] == '\0'))) continue; + safe_strcpy(out[count].name, sizeof(out[count].name), de->d_name); + out[count].type = de->d_type; + count++; + } + closedir(d); + return count; +} + +static int should_exclude_from_copy(const char *name) +{ + if (strcmp(name, "install-on-disk") == 0) return 1; + return 0; +} + +static void copy_tree(const char *src_dir, const char *dst_dir) +{ + dir_entry_t entries[MAX_ENTRIES]; + int n = read_dir_entries(src_dir, entries, MAX_ENTRIES); + if (n == 0) return; + ensure_dir(dst_dir); + for (int i = 0; i < n; i++) { + if (should_exclude_from_copy(entries[i].name)) { + fputs(C_GRAY " skip (installer): " C_RESET, stdout); + fputs(entries[i].name, stdout); + putchar(10); + continue; + } + char sp[256], dp[256]; + path_join(src_dir, entries[i].name, sp, sizeof(sp)); + path_join(dst_dir, entries[i].name, dp, sizeof(dp)); + if (entries[i].type == 1) { + ensure_dir(dp); + copy_tree(sp, dp); + } else { + copy_one_file_progress(sp, dp, sp); + } + } +} + +static int list_disks(disk_summary_t out[4]) +{ + int found = 0; + for (int i = 0; i < 4; i++) { + struct { + char name[32]; + uint64_t sectors; + uint64_t size_bytes; + char model[41]; + uint8_t present; + uint8_t _pad[6]; + } info; + memset(&info, 0, sizeof(info)); + int r = (int)syscall2(SYS_DISK_INFO, (uint64_t)i, (uint64_t)&info); + if (r < 0 || !info.present) continue; + size_t nlen = strlen(info.name); + int is_part = 0; + for (size_t k = 0; k < nlen; k++) { + if (info.name[k] >= '0' && info.name[k] <= '9') { is_part = 1; break; } + } + if (is_part) continue; + safe_strcpy(out[found].name, sizeof(out[found].name), info.name); + safe_strcpy(out[found].model, sizeof(out[found].model), info.model); + out[found].sectors = info.sectors; + out[found].size_bytes = info.size_bytes; + found++; + if (found >= 4) break; + } + return found; +} + +static int ask_choose_disk(char *out_name, size_t out_cap) +{ + disk_summary_t disks[4]; + int n = list_disks(disks); + if (n == 0) { + fputs(C_RED " No disks detected!" C_RESET "\n", stdout); + return -1; + } + fputs("\n", stdout); + fputs(C_CYAN " Available disks:" C_RESET "\n", stdout); + for (int i = 0; i < n; i++) { + fputs(" ", stdout); + putchar((char)('1' + i)); + fputs(") ", stdout); + fputs(C_BOLD, stdout); + fputs(disks[i].name, stdout); + fputs(C_RESET, stdout); + fputs(" ", stdout); + uint64_t mb = disks[i].size_bytes / (1024 * 1024); + char buf[32]; + int bi = 0; + if (mb == 0) { + buf[bi++] = '0'; + } else { + char rev[32]; + int ri = 0; + uint64_t v = mb; + while (v) { rev[ri++] = (char)('0' + (v % 10)); v /= 10; } + while (ri) buf[bi++] = rev[--ri]; + } + buf[bi] = '\0'; + fputs(buf, stdout); + fputs(" MB ", stdout); + fputs(disks[i].model, stdout); + fputs("\n", stdout); + } + fputs("\n Select disk [1-", stdout); + putchar((char)('0' + n)); + fputs("] (q to cancel): ", stdout); + char c = 0; + while (1) { + if (read(0, &c, 1) <= 0) continue; + if (c >= '1' && c <= (char)('0' + n)) { putchar(c); putchar(10); break; } + if (c == 'q' || c == 'Q') { putchar(c); putchar(10); return -1; } + } + int idx = c - '1'; + safe_strcpy(out_name, out_cap, disks[idx].name); + return 0; +} + +static void progress_done(const char *msg) +{ + putchar('\r'); + fputs(C_GREEN " ", stdout); + fputs(msg, stdout); + fputs(C_RESET " \n", stdout); +} + +static void progress_fail(const char *msg) +{ + putchar('\r'); + fputs(C_RED " ", stdout); + fputs(msg, stdout); + fputs(C_RESET " \n", stdout); +} + +static int write_limine_conf(const char *path) +{ + int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) return fd; + const char *conf = + "timeout: 5\n" + "default_entry: 1\n" + "interface_branding: Cervus\n" + "wallpaper: boot():/boot/wallpaper.png\n" + "\n" + "/Cervus v0.0.2 Alpha\n" + " protocol: limine\n" + " path: boot():/kernel\n" + " module_path: boot():/shell.elf\n" + " module_cmdline: init\n"; + write(fd, conf, strlen(conf)); + close(fd); + return 0; +} + +static int do_install(void) +{ + clear_screen(); + + fputs(C_CYAN " Cervus OS Installer" C_RESET "\n", stdout); + fputs(C_GRAY " -----------------------------------" C_RESET "\n", stdout); + + char chosen_disk_name[32]; + if (ask_choose_disk(chosen_disk_name, sizeof(chosen_disk_name)) < 0) { + fputs("\n Cancelled.\n\n", stdout); + return 1; + } + + fputs("\n Target disk: " C_BOLD, stdout); + fputs(chosen_disk_name, stdout); + fputs(C_RESET "\n", stdout); + fputs(" Layout: ESP (FAT32, 64 MB) + root (ext2) + swap (16 MB)\n", stdout); + fputs("\n", stdout); + fputs(C_RED " WARNING: This will erase ALL data on " C_RESET, stdout); + fputs(C_BOLD, stdout); + fputs(chosen_disk_name, stdout); + fputs(C_RESET C_RED "!" C_RESET "\n\n", stdout); + fputs(" Continue? [y/n]: ", stdout); + + char c = 0; + while (1) { + if (read(0, &c, 1) <= 0) continue; + if (c == 'y' || c == 'Y' || c == 'n' || c == 'N') { putchar(c); putchar(10); break; } + } + + if (c == 'n' || c == 'N') { + fputs("\n Cancelled.\n\n", stdout); + return 1; + } + + disk_summary_t disks[4]; + int n_disks = list_disks(disks); + uint64_t total_sectors = 0; + for (int i = 0; i < n_disks; i++) { + if (strcmp(disks[i].name, chosen_disk_name) == 0) { + total_sectors = disks[i].sectors; + break; + } + } + if (total_sectors < 300000) { + fputs(C_RED " Disk too small (need at least 150 MB)" C_RESET "\n\n", stdout); + return 1; + } + + uint32_t esp_start = 2048; + uint32_t esp_size = 131072; + uint32_t swap_size = 32768; + uint32_t root_start = esp_start + esp_size; + uint32_t avail = (uint32_t)total_sectors - root_start - swap_size; + uint32_t root_size = avail; + uint32_t swap_start = root_start + root_size; + + fputs("\n [1/8] Writing partition table...\n", stdout); + cervus_mbr_part_t specs[4]; + memset(specs, 0, sizeof(specs)); + specs[0].boot_flag = 1; + specs[0].type = MBR_TYPE_FAT32_LBA; + specs[0].lba_start = esp_start; + specs[0].sector_count = esp_size; + specs[1].boot_flag = 0; + specs[1].type = MBR_TYPE_LINUX; + specs[1].lba_start = root_start; + specs[1].sector_count = root_size; + specs[2].boot_flag = 0; + specs[2].type = MBR_TYPE_LINUX_SWAP; + specs[2].lba_start = swap_start; + specs[2].sector_count = swap_size; + if (cervus_disk_partition(chosen_disk_name, specs, 3) < 0) { + progress_fail("Failed to write partition table!"); + return 1; + } + progress_done("partition table written"); + + char part1[32], part2[32]; + snprintf(part1, sizeof(part1), "%s1", chosen_disk_name); + snprintf(part2, sizeof(part2), "%s2", chosen_disk_name); + + fputs(" [2/8] Formatting ", stdout); + fputs(part1, stdout); + fputs(" as FAT32 (ESP)...\n", stdout); + if (cervus_disk_mkfs_fat32(part1, "CERVUS-ESP") < 0) { + progress_fail("mkfs.fat32 failed!"); + return 1; + } + progress_done("FAT32 ESP created"); + + fputs(" [3/8] Formatting ", stdout); + fputs(part2, stdout); + fputs(" as ext2 (root)...\n", stdout); + if (cervus_disk_format(part2, "cervus-root") < 0) { + progress_fail("mkfs.ext2 failed!"); + return 1; + } + progress_done("ext2 root created"); + + fputs(" [4/8] Mounting partitions...\n", stdout); + ensure_dir("/mnt/esp"); + ensure_dir("/mnt/root"); + if (cervus_disk_mount(part1, "/mnt/esp") < 0) { + progress_fail("mount ESP failed"); + return 1; + } + if (cervus_disk_mount(part2, "/mnt/root") < 0) { + progress_fail("mount root failed"); + cervus_disk_umount("/mnt/esp"); + return 1; + } + progress_done("mounted"); + + fputs(" [5/8] Copying boot files to ESP...\n", stdout); + ensure_dir("/mnt/esp/boot"); + ensure_dir("/mnt/esp/boot/limine"); + ensure_dir("/mnt/esp/EFI"); + ensure_dir("/mnt/esp/EFI/BOOT"); + + struct { const char *src; const char *dst; int required; } boot_files[] = { + { "/boot/kernel", "/mnt/esp/boot/kernel", 1 }, + { "/boot/kernel", "/mnt/esp/kernel", 0 }, + { "/boot/shell.elf", "/mnt/esp/boot/shell.elf", 1 }, + { "/boot/shell.elf", "/mnt/esp/shell.elf", 0 }, + { "/boot/limine-bios.sys", "/mnt/esp/boot/limine/limine-bios.sys", 0 }, + { "/boot/limine-bios-hdd.bin", "/mnt/esp/boot/limine/limine-bios-hdd.bin", 0 }, + { "/boot/BOOTX64.EFI", "/mnt/esp/EFI/BOOT/BOOTX64.EFI", 0 }, + { "/boot/BOOTIA32.EFI", "/mnt/esp/EFI/BOOT/BOOTIA32.EFI", 0 }, + { "/boot/wallpaper.png", "/mnt/esp/boot/wallpaper.png", 0 }, + { "/boot/wallpaper.png", "/mnt/esp/wallpaper.png", 0 }, + { NULL, NULL, 0 } + }; + for (int i = 0; boot_files[i].src; i++) { + struct stat st; + if (stat(boot_files[i].src, &st) != 0) { + if (boot_files[i].required) { + fputs(C_RED " MISSING required: " C_RESET, stdout); + fputs(boot_files[i].src, stdout); + putchar(10); + } else { + fputs(C_YELLOW " skip (missing): " C_RESET, stdout); + fputs(boot_files[i].src, stdout); + putchar(10); + } + continue; + } + if (copy_one_file_progress(boot_files[i].src, boot_files[i].dst, boot_files[i].src) < 0) { + fputs(C_RED " FAILED: " C_RESET, stdout); + fputs(boot_files[i].dst, stdout); + putchar(10); + } else { + fputs(C_GREEN " " C_RESET, stdout); + fputs(boot_files[i].dst, stdout); + putchar(10); + } + } + + fputs(" [6/8] Writing limine.conf...\n", stdout); + int ok1 = write_limine_conf("/mnt/esp/boot/limine/limine.conf"); + int ok2 = write_limine_conf("/mnt/esp/EFI/BOOT/limine.conf"); + int ok3 = write_limine_conf("/mnt/esp/limine.conf"); + if (ok1 < 0 && ok2 < 0 && ok3 < 0) + progress_fail("failed to write limine.conf"); + else + progress_done("limine.conf written (3 locations)"); + + fputs(" [7/8] Populating root filesystem...\n", stdout); + const char *rdirs[] = { + "/mnt/root/bin", "/mnt/root/apps", "/mnt/root/etc", + "/mnt/root/home", "/mnt/root/tmp", "/mnt/root/var", + "/mnt/root/usr", + NULL + }; + for (int i = 0; rdirs[i]; i++) ensure_dir(rdirs[i]); + + fputs(" copying /bin...\n", stdout); + copy_tree("/bin", "/mnt/root/bin"); + fputs(" copying /apps...\n", stdout); + copy_tree("/apps", "/mnt/root/apps"); + + struct stat ust; + if (stat("/usr", &ust) == 0) { + fputs(" copying /usr (sysroot)...\n", stdout); + copy_tree("/usr", "/mnt/root/usr"); + } else { + fputs(" /usr not present in live image — sysroot skipped\n", stdout); + } + + struct stat est; + if (stat("/etc", &est) == 0) { + fputs(" copying /etc...\n", stdout); + static dir_entry_t etc_entries[MAX_ENTRIES]; + int nn = read_dir_entries("/etc", etc_entries, MAX_ENTRIES); + for (int i = 0; i < nn; i++) { + const char *nm = etc_entries[i].name; + size_t nl = strlen(nm); + int is_txt = (nl >= 5 && strcmp(nm + nl - 4, ".txt") == 0); + if (etc_entries[i].type == 0) { + char sp[256], dp[256]; + path_join("/etc", nm, sp, sizeof(sp)); + if (is_txt) path_join("/mnt/root/home", nm, dp, sizeof(dp)); + else path_join("/mnt/root/etc", nm, dp, sizeof(dp)); + copy_one_file(sp, dp); + } else if (etc_entries[i].type == 1) { + char sp[256], dp[256]; + path_join("/etc", nm, sp, sizeof(sp)); + path_join("/mnt/root/etc", nm, dp, sizeof(dp)); + copy_tree(sp, dp); + } + } + } + + struct stat hst; + if (stat("/home", &hst) == 0) { + fputs(" copying /home...\n", stdout); + copy_tree("/home", "/mnt/root/home"); + } + + fputs(" [8/8] Installing BIOS stage1 to MBR...\n", stdout); + { + static uint8_t sys_buf[300 * 1024]; + int fd = open("/mnt/esp/boot/limine/limine-bios-hdd.bin", O_RDONLY, 0); + if (fd < 0) { + progress_fail("limine-bios-hdd.bin not found on ESP"); + } else { + struct stat st; + int sr = stat("/mnt/esp/boot/limine/limine-bios-hdd.bin", &st); + uint32_t sys_size = (sr == 0) ? (uint32_t)st.st_size : 0; + + if (sys_size == 0 || sys_size > sizeof(sys_buf)) { + close(fd); + progress_fail("bad limine-bios-hdd.bin size"); + } else { + uint32_t got = 0; + int ok = 1; + while (got < sys_size) { + ssize_t n = read(fd, sys_buf + got, sys_size - got); + if (n <= 0) { ok = 0; break; } + got += (uint32_t)n; + } + close(fd); + if (!ok || got != sys_size) { + progress_fail("short read on limine-bios-hdd.bin"); + } else { + long r = cervus_disk_bios_install(chosen_disk_name, sys_buf, sys_size); + if (r < 0) progress_fail("BIOS install syscall failed"); + else progress_done("BIOS stage1 installed"); + } + } + } + } + + cervus_disk_umount("/mnt/esp"); + cervus_disk_umount("/mnt/root"); + + clear_screen(); + + fputs("\n" C_GREEN " Installation complete!" C_RESET "\n", stdout); + fputs(" The system will reboot in 3 seconds.\n\n", stdout); + + for (int i = 3; i > 0; i--) { + fputs(" Rebooting in ", stdout); + putchar((char)('0' + i)); + fputs("...\r", stdout); + syscall1(SYS_SLEEP_NS, 1000000000ULL); + } + fputs("\n", stdout); + syscall0(SYS_REBOOT); + return 0; +} + +int main(int argc, char **argv) +{ + const char *mode = getenv_argv(argc, argv, "MODE", ""); + + if (strcmp(mode, "live") != 0) { + fputs(C_RED "install-on-disk: this command is only available in Live mode.\n" C_RESET, stderr); + fputs("The system is already installed on disk.\n", stderr); + return 1; + } + + do_install(); + return 0; +} \ No newline at end of file diff --git a/usr/lib/libcervus/compat.c b/usr/lib/libcervus/compat.c new file mode 100644 index 0000000..cff3e82 --- /dev/null +++ b/usr/lib/libcervus/compat.c @@ -0,0 +1,349 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int __cervus_errno; + +static long __compat_sys_ret(long r) +{ + if (r < 0 && r > -4096) { + __cervus_errno = (int)-r; + return -1; + } + return r; +} + +int access(const char *path, int mode) +{ + struct stat st; + if (!path) { __cervus_errno = EFAULT; return -1; } + long r = syscall2(SYS_STAT, path, &st); + (void)mode; + if (r < 0 && r > -4096) { __cervus_errno = (int)-r; return -1; } + return 0; +} + +static char __cervus_cwd[512] = "/"; + +int fchdir(int fd) +{ + (void)fd; + __cervus_errno = ENOSYS; + return -1; +} + +int symlink(const char *target, const char *linkpath) +{ + (void)target; (void)linkpath; + __cervus_errno = ENOSYS; + return -1; +} + +ssize_t readlink(const char *path, char *buf, size_t bufsiz) +{ + (void)path; (void)buf; (void)bufsiz; + __cervus_errno = ENOSYS; + return -1; +} + +int sched_yield(void) +{ + syscall0(SYS_YIELD); + return 0; +} + +long pathconf(const char *path, int name) +{ + (void)path; + switch (name) { + case 0: return 255; + case 1: return 512; + default: __cervus_errno = EINVAL; return -1; + } +} + +long fpathconf(int fd, int name) +{ + (void)fd; + switch (name) { + case 0: return 255; + case 1: return 512; + default: __cervus_errno = EINVAL; return -1; + } +} + +int mprotect(void *addr, size_t len, int prot) +{ + return (int)__compat_sys_ret(syscall3(SYS_MPROTECT, addr, len, prot)); +} + +char *realpath(const char *path, char *resolved) +{ + if (!path) { __cervus_errno = EINVAL; return NULL; } + static char sbuf[512]; + char *out = resolved ? resolved : sbuf; + + if (path[0] == '/') { + strncpy(out, path, 511); + out[511] = '\0'; + } else { + strncpy(out, __cervus_cwd, 511); + out[511] = '\0'; + size_t bl = strlen(out); + if (bl > 0 && out[bl - 1] != '/' && bl < 510) { + out[bl++] = '/'; + out[bl] = '\0'; + } + strncat(out, path, 511 - strlen(out)); + } + + char tmp[512]; + strncpy(tmp, out, 511); + tmp[511] = '\0'; + char *parts[64]; + int np = 0; + char *p = tmp; + while (*p) { + while (*p == '/') p++; + if (!*p) break; + char *s = p; + while (*p && *p != '/') p++; + if (*p) *p++ = '\0'; + if (strcmp(s, ".") == 0) continue; + if (strcmp(s, "..") == 0) { if (np > 0) np--; continue; } + if (np < 64) parts[np++] = s; + } + size_t ol = 0; + for (int i = 0; i < np; i++) { + out[ol++] = '/'; + size_t pl = strlen(parts[i]); + if (ol + pl >= 511) break; + memcpy(out + ol, parts[i], pl); + ol += pl; + } + out[ol] = '\0'; + if (ol == 0) { out[0] = '/'; out[1] = '\0'; } + return out; +} + +char *mkdtemp(char *tmpl) +{ + if (!tmpl) { __cervus_errno = EINVAL; return NULL; } + size_t len = strlen(tmpl); + if (len < 6 || strcmp(tmpl + len - 6, "XXXXXX") != 0) { + __cervus_errno = EINVAL; + return NULL; + } + static uint64_t seq = 0; + uint64_t pid = (uint64_t)getpid(); + const char *alpha = "0123456789abcdefghijklmnopqrstuvwxyz"; + for (int attempt = 0; attempt < 100; attempt++) { + uint64_t seed = (cervus_uptime_ns() ^ (pid << 32)) + (seq++); + for (int i = 0; i < 6; i++) { + tmpl[len - 6 + i] = alpha[seed % 36]; + seed /= 36; + } + if (mkdir(tmpl, 0700) == 0) return tmpl; + if (__cervus_errno != EEXIST) return NULL; + } + __cervus_errno = EEXIST; + return NULL; +} + +static char **__env_table = NULL; +static int __env_count = 0; +static int __env_cap = 0; + +int putenv(char *str) +{ + if (!str) return -1; + char *eq = strchr(str, '='); + if (!eq) return -1; + size_t nl = (size_t)(eq - str); + for (int i = 0; i < __env_count; i++) { + if (strncmp(__env_table[i], str, nl) == 0 && __env_table[i][nl] == '=') { + __env_table[i] = str; + return 0; + } + } + if (__env_count >= __env_cap) { + int nc = __env_cap ? __env_cap * 2 : 16; + char **nt = (char **)realloc(__env_table, (size_t)nc * sizeof(char *)); + if (!nt) return -1; + __env_table = nt; + __env_cap = nc; + } + __env_table[__env_count++] = str; + return 0; +} + +int setenv(const char *name, const char *value, int overwrite) +{ + if (!name || !value) { __cervus_errno = EINVAL; return -1; } + size_t nl = strlen(name); + size_t vl = strlen(value); + for (int i = 0; i < __env_count; i++) { + if (strncmp(__env_table[i], name, nl) == 0 && __env_table[i][nl] == '=') { + if (!overwrite) return 0; + char *nv = (char *)malloc(nl + vl + 2); + if (!nv) return -1; + memcpy(nv, name, nl); + nv[nl] = '='; + memcpy(nv + nl + 1, value, vl + 1); + __env_table[i] = nv; + return 0; + } + } + char *nv = (char *)malloc(nl + vl + 2); + if (!nv) return -1; + memcpy(nv, name, nl); + nv[nl] = '='; + memcpy(nv + nl + 1, value, vl + 1); + return putenv(nv); +} + +int unsetenv(const char *name) +{ + if (!name) { __cervus_errno = EINVAL; return -1; } + size_t nl = strlen(name); + for (int i = 0; i < __env_count; i++) { + if (strncmp(__env_table[i], name, nl) == 0 && __env_table[i][nl] == '=') { + __env_table[i] = __env_table[--__env_count]; + return 0; + } + } + return 0; +} + +int uname(struct utsname *buf) +{ + if (!buf) { __cervus_errno = EFAULT; return -1; } + strncpy(buf->sysname, "Cervus", _UTSNAME_LENGTH - 1); + strncpy(buf->nodename, "cervus", _UTSNAME_LENGTH - 1); + strncpy(buf->release, "0.0.2", _UTSNAME_LENGTH - 1); + strncpy(buf->version, "#1", _UTSNAME_LENGTH - 1); + strncpy(buf->machine, "x86_64", _UTSNAME_LENGTH - 1); + buf->sysname[_UTSNAME_LENGTH - 1] = '\0'; + buf->nodename[_UTSNAME_LENGTH - 1] = '\0'; + buf->release[_UTSNAME_LENGTH - 1] = '\0'; + buf->version[_UTSNAME_LENGTH - 1] = '\0'; + buf->machine[_UTSNAME_LENGTH - 1] = '\0'; + return 0; +} + +void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, + int (*cmp)(const void *, const void *)) +{ + const unsigned char *lo = (const unsigned char *)base; + const unsigned char *hi = lo + nmemb * size; + while (lo < hi) { + size_t half = (size_t)((hi - lo) / (ptrdiff_t)size) / 2; + const unsigned char *mid = lo + half * size; + int r = cmp(key, mid); + if (r == 0) return (void *)mid; + if (r < 0) hi = mid; + else lo = mid + size; + } + return NULL; +} + +struct __cervus_FILE { + int fd; + int eof; + int err; + int flags; + char *buf; + size_t buf_size; + size_t buf_pos; +}; + +FILE *fdopen(int fd, const char *mode) +{ + (void)mode; + FILE *f = (FILE *)malloc(sizeof(FILE)); + if (!f) { __cervus_errno = ENOMEM; return NULL; } + f->fd = fd; + f->eof = 0; + f->err = 0; + f->flags = 0; + f->buf = NULL; + f->buf_size = 0; + f->buf_pos = 0; + return f; +} + +FILE *popen(const char *cmd, const char *type) +{ + if (!cmd || !type) { __cervus_errno = EINVAL; return NULL; } + int fds[2]; + if (pipe(fds) < 0) return NULL; + pid_t pid = fork(); + if (pid < 0) { + close(fds[0]); + close(fds[1]); + return NULL; + } + if (pid == 0) { + if (type[0] == 'r') { dup2(fds[1], 1); } + else { dup2(fds[0], 0); } + close(fds[0]); + close(fds[1]); + char *argv[] = { "/bin/sh", "-c", (char *)cmd, NULL }; + execve("/bin/sh", argv, NULL); + _exit(127); + } + if (type[0] == 'r') { + close(fds[1]); + return fdopen(fds[0], "r"); + } else { + close(fds[0]); + return fdopen(fds[1], "w"); + } +} + +int pclose(FILE *f) +{ + if (!f) return -1; + int fd = f->fd; + free(f); + close(fd); + int status = 0; + waitpid(-1, &status, 0); + return status; +} + +int ungetc(int c, FILE *f) +{ + (void)c; (void)f; + return EOF; +} + +void rewind(FILE *f) +{ + if (f) { + syscall3(SYS_SEEK, f->fd, 0, 0); + f->eof = 0; + f->err = 0; + } +} + +char *tmpnam(char *buf) +{ + static char sbuf[32]; + static uint64_t seq = 0; + char *out = buf ? buf : sbuf; + uint64_t seed = cervus_uptime_ns() ^ (seq++); + snprintf(out, 32, "/tmp/tmp%llu", (unsigned long long)seed); + return out; +} \ No newline at end of file diff --git a/usr/lib/libcervus/crt0.asm b/usr/lib/libcervus/crt0.asm new file mode 100644 index 0000000..e34ff9c --- /dev/null +++ b/usr/lib/libcervus/crt0.asm @@ -0,0 +1,41 @@ +BITS 64 +DEFAULT REL + +section .text + global _start + extern main + extern __cervus_argc + extern __cervus_argv + extern __cervus_filter_args + extern __cervus_filtered_argv + +_start: + xor rbp, rbp + + mov rdi, [rsp] + lea rsi, [rsp + 8] + + lea rax, [rel __cervus_argc] + mov dword [rax], edi + lea rax, [rel __cervus_argv] + mov qword [rax], rsi + + and rsp, -16 + + movsxd rdi, dword [rel __cervus_argc] + mov rsi, qword [rel __cervus_argv] + call __cervus_filter_args + + movsxd rdi, eax + lea rsi, [rel __cervus_filtered_argv] + call main + + movsxd rdi, eax + xor rax, rax + syscall + +.hang: + hlt + jmp .hang + +section .note.GNU-stack noalloc noexec nowrite progbits \ No newline at end of file diff --git a/usr/lib/libcervus/ctype/ctype.c b/usr/lib/libcervus/ctype/ctype.c new file mode 100644 index 0000000..debf84f --- /dev/null +++ b/usr/lib/libcervus/ctype/ctype.c @@ -0,0 +1,16 @@ +#include + +int isdigit(int c) { return c >= '0' && c <= '9'; } +int isalpha(int c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } +int isalnum(int c) { return isdigit(c) || isalpha(c); } +int isupper(int c) { return c >= 'A' && c <= 'Z'; } +int islower(int c) { return c >= 'a' && c <= 'z'; } +int isspace(int c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'; } +int isprint(int c) { return (unsigned char)c >= 0x20 && (unsigned char)c < 0x7F; } +int isgraph(int c) { return (unsigned char)c > 0x20 && (unsigned char)c < 0x7F; } +int ispunct(int c) { return isgraph(c) && !isalnum(c); } +int isxdigit(int c) { return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } +int iscntrl(int c) { return (unsigned char)c < 0x20 || c == 0x7F; } +int isblank(int c) { return c == ' ' || c == '\t'; } +int toupper(int c) { return islower(c) ? c - 'a' + 'A' : c; } +int tolower(int c) { return isupper(c) ? c - 'A' + 'a' : c; } \ No newline at end of file diff --git a/usr/lib/libcervus/dirent/dirent.c b/usr/lib/libcervus/dirent/dirent.c new file mode 100644 index 0000000..6bbaf50 --- /dev/null +++ b/usr/lib/libcervus/dirent/dirent.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + uint64_t d_ino; + uint8_t d_type; + char d_name[256]; +} __kernel_dirent_t; + +struct __cervus_DIR { + int fd; + struct dirent buf; +}; + +DIR *opendir(const char *path) +{ + int fd = open(path, O_RDONLY | O_DIRECTORY, 0); + if (fd < 0) return NULL; + DIR *d = (DIR *)malloc(sizeof(DIR)); + if (!d) { close(fd); return NULL; } + d->fd = fd; + return d; +} + +struct dirent *readdir(DIR *dirp) +{ + if (!dirp) return NULL; + __kernel_dirent_t kde; + int r = (int)syscall2(SYS_READDIR, dirp->fd, &kde); + if (r != 0) return NULL; + dirp->buf.d_ino = kde.d_ino; + dirp->buf.d_type = kde.d_type; + size_t nl = strlen(kde.d_name); + if (nl >= sizeof(dirp->buf.d_name)) nl = sizeof(dirp->buf.d_name) - 1; + memcpy(dirp->buf.d_name, kde.d_name, nl); + dirp->buf.d_name[nl] = '\0'; + return &dirp->buf; +} + +int closedir(DIR *dirp) +{ + if (!dirp) return -1; + int fd = dirp->fd; + free(dirp); + return close(fd); +} + +void rewinddir(DIR *dirp) +{ + if (!dirp) return; + lseek(dirp->fd, 0, SEEK_SET); +} + +int dirfd(DIR *dirp) { return dirp ? dirp->fd : -1; } \ No newline at end of file diff --git a/usr/lib/libcervus/libcervus.c b/usr/lib/libcervus/libcervus.c new file mode 100644 index 0000000..251ab2a --- /dev/null +++ b/usr/lib/libcervus/libcervus.c @@ -0,0 +1,461 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int __cervus_argc; +char **__cervus_argv; + +int __cervus_errno = 0; + +static long __sys_ret(long r) +{ + if (r < 0 && r > -4096) { + __cervus_errno = (int)-r; + return -1; + } + return r; +} + +#define CERVUS_PATH_MAX 512 + +static char __cervus_cwd[CERVUS_PATH_MAX]; +static int __cervus_cwd_inited = 0; + +static const char *__cervus_get_cwd(void) +{ + if (!__cervus_cwd_inited) { + const char *c = get_cwd_flag(__cervus_argc, __cervus_argv); + if (!c || !*c) c = "/"; + size_t n = strlen(c); + if (n >= sizeof(__cervus_cwd)) n = sizeof(__cervus_cwd) - 1; + memcpy(__cervus_cwd, c, n); + __cervus_cwd[n] = '\0'; + __cervus_cwd_inited = 1; + } + return __cervus_cwd; +} + +static const char *__cervus_resolve(const char *path, char *buf, size_t bufsz) +{ + if (!path) return path; + if (path[0] == '/') return path; + resolve_path(__cervus_get_cwd(), path, buf, bufsz); + return buf; +} + +ssize_t read(int fd, void *buf, size_t n) +{ + return (ssize_t)__sys_ret(syscall3(SYS_READ, fd, buf, n)); +} +ssize_t write(int fd, const void *buf, size_t n) +{ + return (ssize_t)__sys_ret(syscall3(SYS_WRITE, fd, buf, n)); +} +int close(int fd) +{ + return (int)__sys_ret(syscall1(SYS_CLOSE, fd)); +} +off_t lseek(int fd, off_t off, int whence) +{ + return (off_t)__sys_ret(syscall3(SYS_SEEK, fd, (uint64_t)off, whence)); +} +int dup(int fd) +{ + return (int)__sys_ret(syscall1(SYS_DUP, fd)); +} +int dup2(int oldfd, int newfd) +{ + return (int)__sys_ret(syscall2(SYS_DUP2, oldfd, newfd)); +} +int pipe(int fds[2]) +{ + return (int)__sys_ret(syscall1(SYS_PIPE, fds)); +} + +int ioctl(int fd, unsigned long request, ...) +{ + va_list ap; + va_start(ap, request); + void *arg = va_arg(ap, void *); + va_end(ap); + return (int)__sys_ret(syscall3(SYS_IOCTL, fd, request, arg)); +} + +int isatty(int fd) +{ + struct winsize ws; + long r = syscall3(SYS_IOCTL, fd, TIOCGWINSZ, &ws); + if (r < 0) { + __cervus_errno = (int)-r; + return 0; + } + return 1; +} + +int unlink(const char *path) +{ + char abs[CERVUS_PATH_MAX]; + path = __cervus_resolve(path, abs, sizeof(abs)); + return (int)__sys_ret(syscall1(SYS_UNLINK, path)); +} +int rmdir(const char *path) +{ + char abs[CERVUS_PATH_MAX]; + path = __cervus_resolve(path, abs, sizeof(abs)); + return (int)__sys_ret(syscall1(SYS_RMDIR, path)); +} + +pid_t getpid(void) { return (pid_t)syscall0(SYS_GETPID); } +pid_t getppid(void) { return (pid_t)syscall0(SYS_GETPPID); } +uid_t getuid(void) { return (uid_t)syscall0(SYS_GETUID); } +gid_t getgid(void) { return (gid_t)syscall0(SYS_GETGID); } +int setuid(uid_t u) { return (int)__sys_ret(syscall1(SYS_SETUID, u)); } +int setgid(gid_t g) { return (int)__sys_ret(syscall1(SYS_SETGID, g)); } +pid_t fork(void) { return (pid_t)__sys_ret(syscall0(SYS_FORK)); } + +int execve(const char *path, char *const argv[], char *const envp[]) +{ + char abs[CERVUS_PATH_MAX]; + path = __cervus_resolve(path, abs, sizeof(abs)); + return (int)__sys_ret(syscall3(SYS_EXECVE, path, argv, envp)); +} + +int execv(const char *path, char *const argv[]) +{ + char *empty[] = { NULL }; + return execve(path, argv, empty); +} + +int execvp(const char *file, char *const argv[]) +{ + if (!file || !*file) { __cervus_errno = ENOENT; return -1; } + + int has_slash = 0; + for (const char *p = file; *p; p++) if (*p == '/') { has_slash = 1; break; } + if (has_slash) return execve(file, argv, NULL); + + const char *path = getenv("PATH"); + if (!path || !*path) path = "/bin:/apps"; + + char buf[512]; + const char *p = path; + while (*p) { + const char *colon = p; + while (*colon && *colon != ':') colon++; + size_t dlen = (size_t)(colon - p); + size_t flen = strlen(file); + if (dlen + 1 + flen + 1 <= sizeof(buf)) { + memcpy(buf, p, dlen); + buf[dlen] = '/'; + memcpy(buf + dlen + 1, file, flen); + buf[dlen + 1 + flen] = '\0'; + execve(buf, argv, NULL); + } + p = colon; + if (*p == ':') p++; + } + __cervus_errno = ENOENT; + return -1; +} + +void _exit(int status) { syscall1(SYS_EXIT, status); __builtin_unreachable(); } + +unsigned int sleep(unsigned int sec) +{ + cervus_nanosleep((uint64_t)sec * 1000000000ULL); + return 0; +} +int usleep(unsigned int usec) +{ + return cervus_nanosleep((uint64_t)usec * 1000ULL); +} + +void sched_yield_cervus(void) { syscall0(SYS_YIELD); } + +char *getcwd(char *buf, size_t size) +{ + if (!buf || size < 2) { __cervus_errno = EINVAL; return NULL; } + const char *c = __cervus_get_cwd(); + size_t n = strlen(c); + if (n + 1 > size) { __cervus_errno = ERANGE; return NULL; } + memcpy(buf, c, n + 1); + return buf; +} + +int chdir(const char *path) +{ + if (!path || !*path) { __cervus_errno = ENOENT; return -1; } + + char abs[CERVUS_PATH_MAX]; + const char *p = __cervus_resolve(path, abs, sizeof(abs)); + + struct stat st; + if ((int)__sys_ret(syscall2(SYS_STAT, p, &st)) < 0) return -1; + if (!S_ISDIR(st.st_mode)) { __cervus_errno = ENOTDIR; return -1; } + + size_t n = strlen(p); + if (n >= sizeof(__cervus_cwd)) { __cervus_errno = ENAMETOOLONG; return -1; } + memcpy(__cervus_cwd, p, n + 1); + __cervus_cwd_inited = 1; + return 0; +} + +void *sbrk(intptr_t incr) +{ + uintptr_t cur = (uintptr_t)syscall1(SYS_BRK, 0); + if (incr == 0) return (void *)cur; + uintptr_t nw = (uintptr_t)syscall1(SYS_BRK, cur + (uintptr_t)incr); + if (nw != cur + (uintptr_t)incr) { + __cervus_errno = ENOMEM; + return (void *)-1; + } + return (void *)cur; +} +int brk(void *addr) +{ + uintptr_t r = (uintptr_t)syscall1(SYS_BRK, (uintptr_t)addr); + if (r != (uintptr_t)addr) { __cervus_errno = ENOMEM; return -1; } + return 0; +} + +int open(const char *path, int flags, ...) +{ + mode_t mode = 0; + if (flags & O_CREAT) { + va_list ap; + va_start(ap, flags); + mode = va_arg(ap, mode_t); + va_end(ap); + } + char abs[CERVUS_PATH_MAX]; + path = __cervus_resolve(path, abs, sizeof(abs)); + return (int)__sys_ret(syscall3(SYS_OPEN, path, flags, mode)); +} +int creat(const char *path, mode_t mode) +{ + return open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); +} +int fcntl(int fd, int cmd, ...) +{ + va_list ap; + va_start(ap, cmd); + long arg = va_arg(ap, long); + va_end(ap); + return (int)__sys_ret(syscall3(SYS_FCNTL, fd, cmd, arg)); +} + +int stat(const char *path, struct stat *out) +{ + char abs[CERVUS_PATH_MAX]; + path = __cervus_resolve(path, abs, sizeof(abs)); + return (int)__sys_ret(syscall2(SYS_STAT, path, out)); +} +int fstat(int fd, struct stat *out) +{ + return (int)__sys_ret(syscall2(SYS_FSTAT, fd, out)); +} +int mkdir(const char *path, mode_t mode) +{ + char abs[CERVUS_PATH_MAX]; + path = __cervus_resolve(path, abs, sizeof(abs)); + return (int)__sys_ret(syscall2(SYS_MKDIR, path, mode)); +} +int chmod(const char *path, mode_t mode) +{ + (void)path; (void)mode; + return 0; +} +int rename(const char *oldp, const char *newp) +{ + char absa[CERVUS_PATH_MAX], absb[CERVUS_PATH_MAX]; + oldp = __cervus_resolve(oldp, absa, sizeof(absa)); + newp = __cervus_resolve(newp, absb, sizeof(absb)); + return (int)__sys_ret(syscall2(SYS_RENAME, oldp, newp)); +} + +void *mmap(void *a, size_t l, int p, int f, int fd, off_t o) +{ + long r = syscall6(SYS_MMAP, a, l, p, f, fd, (uint64_t)o); + if (r < 0 && r > -4096) { __cervus_errno = (int)-r; return MAP_FAILED; } + return (void *)r; +} +int munmap(void *a, size_t l) { return (int)__sys_ret(syscall2(SYS_MUNMAP, a, l)); } + +pid_t waitpid(pid_t p, int *s, int f) { return (pid_t)__sys_ret(syscall3(SYS_WAIT, p, s, f)); } +pid_t wait(int *s) { return waitpid(-1, s, 0); } + +ssize_t cervus_dbg_print(const char *b, size_t n) { return (ssize_t)syscall2(SYS_DBG_PRINT, b, n); } + +char *optarg = NULL; +int optind = 1; +int optopt = 0; +int opterr = 1; + +static int __opt_subidx = 1; + +int getopt(int argc, char *const argv[], const char *optstring) +{ + if (!optstring) optstring = ""; + int colon_mode = (optstring[0] == ':'); + const char *opts = colon_mode ? optstring + 1 : optstring; + + optarg = NULL; + + if (optind >= argc) return -1; + + char *cur = argv[optind]; + if (!cur || cur[0] != '-' || cur[1] == '\0') return -1; + if (cur[0] == '-' && cur[1] == '-' && cur[2] == '\0') { + optind++; + return -1; + } + + char ch = cur[__opt_subidx]; + if (ch == '\0') { + optind++; + __opt_subidx = 1; + return getopt(argc, argv, optstring); + } + + const char *pp = opts; + while (*pp && *pp != ch) pp++; + if (*pp == '\0' || ch == ':') { + optopt = ch; + if (opterr && !colon_mode) { + const char *prog = argv[0] ? argv[0] : "?"; + fprintf(stderr, "%s: invalid option -- '%c'\n", prog, ch); + } + __opt_subidx++; + if (cur[__opt_subidx] == '\0') { + optind++; + __opt_subidx = 1; + } + return '?'; + } + + if (pp[1] == ':') { + if (cur[__opt_subidx + 1] != '\0') { + optarg = &cur[__opt_subidx + 1]; + optind++; + __opt_subidx = 1; + return ch; + } + if (optind + 1 >= argc) { + optopt = ch; + optind++; + __opt_subidx = 1; + if (opterr && !colon_mode) { + const char *prog = argv[0] ? argv[0] : "?"; + fprintf(stderr, "%s: option requires an argument -- '%c'\n", prog, ch); + } + return colon_mode ? ':' : '?'; + } + optarg = argv[optind + 1]; + optind += 2; + __opt_subidx = 1; + return ch; + } + + __opt_subidx++; + if (cur[__opt_subidx] == '\0') { + optind++; + __opt_subidx = 1; + } + return ch; +} + +int tcgetattr(int fd, struct termios *t) +{ + if (!t) { __cervus_errno = EINVAL; return -1; } + return (int)__sys_ret(syscall3(SYS_IOCTL, fd, TCGETS, t)); +} + +int tcsetattr(int fd, int optional_actions, const struct termios *t) +{ + if (!t) { __cervus_errno = EINVAL; return -1; } + unsigned long req; + switch (optional_actions) { + case TCSADRAIN: req = TCSETSW; break; + case TCSAFLUSH: req = TCSETSF; break; + case TCSANOW: + default: req = TCSETS; break; + } + return (int)__sys_ret(syscall3(SYS_IOCTL, fd, req, t)); +} + +int cervus_task_info(pid_t p, cervus_task_info_t *o) { return (int)__sys_ret(syscall2(SYS_TASK_INFO, p, o)); } +int cervus_task_kill(pid_t p) { return (int)__sys_ret(syscall1(SYS_TASK_KILL, p)); } +uint64_t cervus_cap_get(void) { return (uint64_t)syscall0(SYS_CAP_GET); } +int cervus_cap_drop(uint64_t m) { return (int)__sys_ret(syscall1(SYS_CAP_DROP, m)); } + +int cervus_meminfo(cervus_meminfo_t *m) { return (int)__sys_ret(syscall1(SYS_MEMINFO, m)); } +uint64_t cervus_uptime_ns(void) { return (uint64_t)syscall0(SYS_UPTIME); } +int cervus_clock_gettime(int id, cervus_timespec_t *t){ return (int)__sys_ret(syscall2(SYS_CLOCK_GET, id, t)); } +int cervus_nanosleep(uint64_t ns) { return (int)__sys_ret(syscall1(SYS_SLEEP_NS, ns)); } + +int cervus_shutdown(void) { return (int)__sys_ret(syscall0(SYS_SHUTDOWN)); } +int cervus_reboot(void) { return (int)__sys_ret(syscall0(SYS_REBOOT)); } + +int cervus_disk_info(int i, cervus_disk_info_t *o) { return (int)__sys_ret(syscall2(SYS_DISK_INFO, (uint64_t)i, o)); } +int cervus_disk_mount(const char *d, const char *p) { return (int)__sys_ret(syscall2(SYS_DISK_MOUNT, d, p)); } +int cervus_disk_umount(const char *p) { return (int)__sys_ret(syscall1(SYS_DISK_UMOUNT, p)); } +int cervus_disk_format(const char *d, const char *l) { return (int)__sys_ret(syscall2(SYS_DISK_FORMAT, d, l)); } +int cervus_disk_mkfs_fat32(const char *d, const char *l) { return (int)__sys_ret(syscall2(SYS_DISK_MKFS_FAT32, d, l)); } +int cervus_disk_partition(const char *d, const cervus_mbr_part_t *s, uint64_t n) { return (int)__sys_ret(syscall3(SYS_DISK_PARTITION, d, s, n)); } +int cervus_disk_read_raw(const char *d, uint64_t lba, uint64_t c, void *b) { return (int)__sys_ret(syscall4(SYS_DISK_READ_RAW, d, lba, c, b)); } +int cervus_disk_write_raw(const char *d, uint64_t lba, uint64_t c, const void *b){ return (int)__sys_ret(syscall4(SYS_DISK_WRITE_RAW, d, lba, c, b)); } +long cervus_disk_list_parts(cervus_part_info_t *o, int m) { return __sys_ret(syscall2(SYS_DISK_LIST_PARTS, o, m)); } +long cervus_disk_bios_install(const char *d, const void *sd, uint32_t ss) { return __sys_ret(syscall3(SYS_DISK_BIOS_INSTALL, d, sd, ss)); } + +long cervus_list_mounts(cervus_mount_info_t *o, int m) { return __sys_ret(syscall2(SYS_LIST_MOUNTS, o, m)); } +long cervus_statvfs(const char *p, cervus_statvfs_t *o) { return __sys_ret(syscall2(SYS_STATVFS, p, o)); } + +uint32_t cervus_ioport_read(uint16_t p, int w) { return (uint32_t)syscall2(SYS_IOPORT_READ, p, w); } +int cervus_ioport_write(uint16_t p, int w, uint32_t v) { return (int)__sys_ret(syscall3(SYS_IOPORT_WRITE, p, w, v)); } + +void __cervus_assert_fail(const char *expr, const char *file, int line, const char *func) +{ + printf("assertion failed: %s (%s:%d, %s)\n", + expr ? expr : "(null)", + file ? file : "(null)", + line, + func ? func : "(null)"); + syscall1(SYS_EXIT, 134); + for (;;) { } +} + +#define _CERVUS_FILT_MAX 128 +char *__cervus_filtered_argv[_CERVUS_FILT_MAX + 1]; + +int __cervus_filter_args(int argc, char **argv) +{ + int out = 0; + for (int i = 0; i < argc && out < _CERVUS_FILT_MAX; i++) { + const char *a = argv[i]; + if (i > 0 && a && a[0] == '-' && a[1] == '-' && + ((a[2]=='c' && a[3]=='w' && a[4]=='d' && a[5]=='=') || + (a[2]=='e' && a[3]=='n' && a[4]=='v' && a[5]==':'))) { + continue; + } + __cervus_filtered_argv[out++] = (char *)a; + } + __cervus_filtered_argv[out] = NULL; + return out; +} \ No newline at end of file diff --git a/usr/lib/libcervus/math/abs.c b/usr/lib/libcervus/math/abs.c new file mode 100644 index 0000000..a499d2c --- /dev/null +++ b/usr/lib/libcervus/math/abs.c @@ -0,0 +1,5 @@ +#include + +int abs(int n) { + return n >= 0 ? n : -n; +} diff --git a/usr/lib/libcervus/math/fabs.c b/usr/lib/libcervus/math/fabs.c new file mode 100644 index 0000000..16e12de --- /dev/null +++ b/usr/lib/libcervus/math/fabs.c @@ -0,0 +1,12 @@ +#include +#include + +double fabs(double x) { + union { + double d; + uint64_t i; + } u = { .d = x }; + + u.i &= 0x7FFFFFFFFFFFFFFFULL; + return u.d; +} \ No newline at end of file diff --git a/usr/lib/libcervus/math/isinf.c b/usr/lib/libcervus/math/isinf.c new file mode 100644 index 0000000..12a6a00 --- /dev/null +++ b/usr/lib/libcervus/math/isinf.c @@ -0,0 +1,14 @@ +#include +#include + +int isinf(double x) { + union { + double f; + uint64_t i; + } u = { .f = x }; + + uint64_t exp = (u.i >> 52) & 0x7FF; + uint64_t mantissa = u.i & 0xFFFFFFFFFFFFFULL; + + return (exp == 0x7FF) && (mantissa == 0); +} \ No newline at end of file diff --git a/usr/lib/libcervus/math/isnan.c b/usr/lib/libcervus/math/isnan.c new file mode 100644 index 0000000..66afe95 --- /dev/null +++ b/usr/lib/libcervus/math/isnan.c @@ -0,0 +1,14 @@ +#include +#include + +int isnan(double x) { + union { + double f; + uint64_t i; + } u = { .f = x }; + + uint64_t exp = (u.i >> 52) & 0x7FF; + uint64_t mantissa = u.i & 0xFFFFFFFFFFFFFULL; + + return (exp == 0x7FF) && (mantissa != 0); +} \ No newline at end of file diff --git a/usr/lib/libcervus/math/pow.c b/usr/lib/libcervus/math/pow.c new file mode 100644 index 0000000..2f0acc7 --- /dev/null +++ b/usr/lib/libcervus/math/pow.c @@ -0,0 +1,37 @@ +#include + +double pow(double x, double y) { + if (y == 0.0) return 1.0; + + if (y == (int)y) { + int n = (int)y; + double result = 1.0; + + if (n > 0) { + for (int i = 0; i < n; i++) { + result *= x; + } + } else { + for (int i = 0; i < -n; i++) { + result /= x; + } + } + + return result; + } + + if (x > 0.0) { + int int_part = (int)y; + double frac_part = y - int_part; + + double int_pow = pow(x, int_part); + + if (frac_part > 0.0) { + return int_pow * (1.0 + frac_part * (x - 1.0)); + } else { + return int_pow / (1.0 - frac_part * (x - 1.0)); + } + } + + return NAN; +} \ No newline at end of file diff --git a/usr/lib/libcervus/math/pow10.c b/usr/lib/libcervus/math/pow10.c new file mode 100644 index 0000000..389fd43 --- /dev/null +++ b/usr/lib/libcervus/math/pow10.c @@ -0,0 +1,17 @@ +#include + +double pow10(int n) { + double result = 1.0; + + if (n >= 0) { + for (int i = 0; i < n; i++) { + result *= 10.0; + } + } else { + for (int i = 0; i < -n; i++) { + result /= 10.0; + } + } + + return result; +} \ No newline at end of file diff --git a/usr/lib/libcervus/memory/memory.c b/usr/lib/libcervus/memory/memory.c new file mode 100644 index 0000000..c3cddf7 --- /dev/null +++ b/usr/lib/libcervus/memory/memory.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include + +extern int __cervus_errno; + +typedef struct __mblock { + size_t size; + size_t prev_size; +} __mblock_t; + +#define MB_HDR_SZ (sizeof(__mblock_t)) +#define MB_ALIGN 16 +#define MB_MIN_TOTAL 32 +#define MB_FREE_BIT ((size_t)1) +#define MB_SIZE(b) ((b)->size & ~MB_FREE_BIT) +#define MB_IS_FREE(b) (((b)->size & MB_FREE_BIT) != 0) +#define MB_USER(b) ((void *)((char *)(b) + MB_HDR_SZ)) +#define MB_FROM_USER(p) ((__mblock_t *)((char *)(p) - MB_HDR_SZ)) + +static __mblock_t *__heap_start = NULL; +static __mblock_t *__heap_end = NULL; + +static inline size_t __align_up(size_t n, size_t a) { + return (n + a - 1) & ~(a - 1); +} + +static inline __mblock_t *__mb_next(__mblock_t *b) { + return (__mblock_t *)((char *)b + MB_SIZE(b)); +} + +static inline __mblock_t *__mb_prev(__mblock_t *b) { + if (b->prev_size == 0) return NULL; + return (__mblock_t *)((char *)b - b->prev_size); +} + +static __mblock_t *__heap_grow(size_t need) +{ + size_t chunk = __align_up(need + MB_HDR_SZ, 65536); + + if (!__heap_start) { + void *base = sbrk((intptr_t)chunk); + if (base == (void *)-1) return NULL; + + uintptr_t addr = (uintptr_t)base; + uintptr_t aligned = (addr + MB_ALIGN - 1) & ~(uintptr_t)(MB_ALIGN - 1); + size_t lost = aligned - addr; + if (lost >= chunk - MB_MIN_TOTAL - MB_HDR_SZ) { + __cervus_errno = ENOMEM; + return NULL; + } + + __heap_start = (__mblock_t *)aligned; + size_t usable = chunk - lost; + + __mblock_t *first = __heap_start; + size_t first_sz = usable - MB_HDR_SZ; + first->size = first_sz | MB_FREE_BIT; + first->prev_size = 0; + + __heap_end = (__mblock_t *)((char *)first + first_sz); + __heap_end->size = 0; + __heap_end->prev_size = first_sz; + + return first; + } + + void *p = sbrk((intptr_t)chunk); + if (p == (void *)-1) return NULL; + if ((uintptr_t)p != (uintptr_t)__heap_end + MB_HDR_SZ) { + __cervus_errno = ENOMEM; + return NULL; + } + + __mblock_t *new_block = __heap_end; + new_block->size = chunk | MB_FREE_BIT; + + __mblock_t *new_end = (__mblock_t *)((char *)new_block + MB_SIZE(new_block)); + new_end->size = 0; + new_end->prev_size = MB_SIZE(new_block); + __heap_end = new_end; + + __mblock_t *prev = __mb_prev(new_block); + if (prev && MB_IS_FREE(prev)) { + size_t merged_sz = MB_SIZE(prev) + MB_SIZE(new_block); + prev->size = merged_sz | MB_FREE_BIT; + __heap_end->prev_size = merged_sz; + return prev; + } + return new_block; +} + +static void __mb_split(__mblock_t *b, size_t need) +{ + size_t cur = MB_SIZE(b); + if (cur < need + MB_MIN_TOTAL) { + b->size = cur; + return; + } + b->size = need; + + __mblock_t *rest = (__mblock_t *)((char *)b + need); + rest->size = (cur - need) | MB_FREE_BIT; + rest->prev_size = need; + + __mblock_t *after = __mb_next(rest); + if (after) after->prev_size = MB_SIZE(rest); +} + +void *malloc(size_t n) +{ + if (n == 0) n = 1; + size_t need = __align_up(n + MB_HDR_SZ, MB_ALIGN); + if (need < MB_MIN_TOTAL) need = MB_MIN_TOTAL; + + for (__mblock_t *b = __heap_start; b && b != __heap_end; b = __mb_next(b)) { + if (MB_IS_FREE(b) && MB_SIZE(b) >= need) { + __mb_split(b, need); + return MB_USER(b); + } + } + + __mblock_t *grown = __heap_grow(need); + if (!grown) return NULL; + if (MB_SIZE(grown) < need) { + __cervus_errno = ENOMEM; + return NULL; + } + __mb_split(grown, need); + return MB_USER(grown); +} + +void *calloc(size_t nm, size_t sz) +{ + size_t t = nm * sz; + if (nm && t / nm != sz) { __cervus_errno = ENOMEM; return NULL; } + void *p = malloc(t); + if (p) memset(p, 0, t); + return p; +} + +void free(void *p) +{ + if (!p) return; + __mblock_t *b = MB_FROM_USER(p); + b->size = MB_SIZE(b) | MB_FREE_BIT; + + __mblock_t *next = __mb_next(b); + if (next != __heap_end && MB_IS_FREE(next)) { + size_t merged = MB_SIZE(b) + MB_SIZE(next); + b->size = merged | MB_FREE_BIT; + __mblock_t *after = __mb_next(b); + if (after) after->prev_size = merged; + } + __mblock_t *prev = __mb_prev(b); + if (prev && MB_IS_FREE(prev)) { + size_t merged = MB_SIZE(prev) + MB_SIZE(b); + prev->size = merged | MB_FREE_BIT; + __mblock_t *after = __mb_next(prev); + if (after) after->prev_size = merged; + } +} + +void *realloc(void *p, size_t n) +{ + if (!p) return malloc(n); + if (n == 0) { free(p); return NULL; } + + __mblock_t *b = MB_FROM_USER(p); + size_t cur_total = MB_SIZE(b); + size_t cur_user = cur_total - MB_HDR_SZ; + size_t need = __align_up(n + MB_HDR_SZ, MB_ALIGN); + if (need < MB_MIN_TOTAL) need = MB_MIN_TOTAL; + + if (need <= cur_total) { + if (cur_total >= need + MB_MIN_TOTAL) { + b->size = need; + __mblock_t *rest = (__mblock_t *)((char *)b + need); + rest->size = (cur_total - need) | MB_FREE_BIT; + rest->prev_size = need; + __mblock_t *after = __mb_next(rest); + if (after) after->prev_size = MB_SIZE(rest); + if (after != __heap_end && MB_IS_FREE(after)) { + size_t merged = MB_SIZE(rest) + MB_SIZE(after); + rest->size = merged | MB_FREE_BIT; + __mblock_t *aft2 = __mb_next(rest); + if (aft2) aft2->prev_size = merged; + } + } + return p; + } + + __mblock_t *next = __mb_next(b); + if (next != __heap_end && MB_IS_FREE(next) && + cur_total + MB_SIZE(next) >= need) + { + size_t combined = cur_total + MB_SIZE(next); + b->size = combined; + __mblock_t *after = __mb_next(b); + if (after) after->prev_size = combined; + if (combined >= need + MB_MIN_TOTAL) { + b->size = need; + __mblock_t *rest = (__mblock_t *)((char *)b + need); + rest->size = (combined - need) | MB_FREE_BIT; + rest->prev_size = need; + __mblock_t *aft = __mb_next(rest); + if (aft) aft->prev_size = MB_SIZE(rest); + } + return p; + } + + void *np = malloc(n); + if (!np) return NULL; + memcpy(np, p, cur_user); + free(p); + return np; +} \ No newline at end of file diff --git a/usr/lib/libcervus/setjmp.asm b/usr/lib/libcervus/setjmp.asm new file mode 100644 index 0000000..e47db57 --- /dev/null +++ b/usr/lib/libcervus/setjmp.asm @@ -0,0 +1,38 @@ +BITS 64 +DEFAULT REL + +section .text + +global setjmp +global longjmp + +setjmp: + mov [rdi + 0x00], rbx + mov [rdi + 0x08], rbp + mov [rdi + 0x10], r12 + mov [rdi + 0x18], r13 + mov [rdi + 0x20], r14 + mov [rdi + 0x28], r15 + lea rax, [rsp + 8] + mov [rdi + 0x30], rax + mov rax, [rsp] + mov [rdi + 0x38], rax + xor eax, eax + ret + +longjmp: + mov rbx, [rdi + 0x00] + mov rbp, [rdi + 0x08] + mov r12, [rdi + 0x10] + mov r13, [rdi + 0x18] + mov r14, [rdi + 0x20] + mov r15, [rdi + 0x28] + mov rsp, [rdi + 0x30] + mov eax, esi + test eax, eax + jnz .done + mov eax, 1 +.done: + jmp qword [rdi + 0x38] + +section .note.GNU-stack noalloc noexec nowrite progbits \ No newline at end of file diff --git a/usr/lib/libcervus/signal/signal.c b/usr/lib/libcervus/signal/signal.c new file mode 100644 index 0000000..d114464 --- /dev/null +++ b/usr/lib/libcervus/signal/signal.c @@ -0,0 +1,39 @@ +#include +#include + +sighandler_t signal(int signum, sighandler_t handler) +{ + (void)signum; + (void)handler; + return SIG_DFL; +} + +int raise(int sig) +{ + (void)sig; + return 0; +} + +int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) +{ + (void)sig; (void)act; + if (oldact) { + oldact->sa_handler = SIG_DFL; + memset(&oldact->sa_mask, 0, sizeof(oldact->sa_mask)); + oldact->sa_flags = 0; + } + return 0; +} + +int sigemptyset(sigset_t *set) { if (set) memset(set, 0, sizeof(*set)); return 0; } +int sigfillset(sigset_t *set) { if (set) memset(set, 0xFF, sizeof(*set)); return 0; } +int sigaddset(sigset_t *set, int sig) { (void)set; (void)sig; return 0; } +int sigdelset(sigset_t *set, int sig) { (void)set; (void)sig; return 0; } +int sigismember(const sigset_t *set, int sig) { (void)set; (void)sig; return 0; } + +int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) +{ + (void)how; (void)set; + if (oldset) memset(oldset, 0, sizeof(*oldset)); + return 0; +} \ No newline at end of file diff --git a/usr/lib/libcervus/stdio/scanf.c b/usr/lib/libcervus/stdio/scanf.c new file mode 100644 index 0000000..fdb15de --- /dev/null +++ b/usr/lib/libcervus/stdio/scanf.c @@ -0,0 +1,252 @@ +#include +#include +#include +#include +#include +#include + +extern uint64_t __cervus_strtod_bits(const char *s, char **endptr); + +static int __is_space(int c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'; +} + +int vsscanf(const char *str, const char *fmt, va_list ap) +{ + if (!str || !fmt) return -1; + const char *s = str; + const char *f = fmt; + int matched = 0; + int saw_anything = 0; + + while (*f) { + if (__is_space((unsigned char)*f)) { + while (__is_space((unsigned char)*s)) s++; + f++; + continue; + } + if (*f != '%') { + if (*s != *f) return saw_anything ? matched : (matched ? matched : -1); + s++; f++; + continue; + } + f++; + + int suppress = 0; + if (*f == '*') { suppress = 1; f++; } + + int width = 0; + int has_width = 0; + while (*f >= '0' && *f <= '9') { + width = width * 10 + (*f - '0'); + has_width = 1; + f++; + } + if (!has_width) width = 0; + + int len_mod = 0; + if (*f == 'h') { f++; if (*f == 'h') { f++; len_mod = 2; } else len_mod = 1; } + else if (*f == 'l') { f++; if (*f == 'l') { f++; len_mod = 4; } else len_mod = 3; } + else if (*f == 'z') { f++; len_mod = 5; } + else if (*f == 'j' || *f == 't') { f++; len_mod = 4; } + + char conv = *f; + if (!conv) break; + f++; + + if (conv == '%') { + if (*s != '%') return matched ? matched : -1; + s++; + continue; + } + + if (conv == 'n') { + if (!suppress) { + int read = (int)(s - str); + if (len_mod == 3 || len_mod == 5) *va_arg(ap, long *) = read; + else if (len_mod == 4) *va_arg(ap, long long *) = read; + else *va_arg(ap, int *) = read; + } + continue; + } + + if (conv == 'c') { + int w = has_width ? width : 1; + char *out = suppress ? NULL : va_arg(ap, char *); + for (int i = 0; i < w; i++) { + if (!*s) return matched ? matched : -1; + if (out) out[i] = *s; + s++; + } + if (!suppress) matched++; + saw_anything = 1; + continue; + } + + if (conv != '[') { + while (__is_space((unsigned char)*s)) s++; + } + + if (conv == 's') { + int w = has_width ? width : 0x7FFFFFFF; + char *out = suppress ? NULL : va_arg(ap, char *); + int wrote = 0; + if (!*s) return matched ? matched : -1; + while (*s && !__is_space((unsigned char)*s) && wrote < w) { + if (out) out[wrote] = *s; + s++; wrote++; + } + if (out) out[wrote] = '\0'; + if (!suppress) matched++; + saw_anything = 1; + continue; + } + + if (conv == '[') { + int negate = 0; + if (*f == '^') { negate = 1; f++; } + char set[256]; + memset(set, 0, sizeof(set)); + if (*f == ']') { set[(unsigned char)']'] = 1; f++; } + while (*f && *f != ']') { set[(unsigned char)*f] = 1; f++; } + if (*f == ']') f++; + int w = has_width ? width : 0x7FFFFFFF; + char *out = suppress ? NULL : va_arg(ap, char *); + int wrote = 0; + while (*s && wrote < w) { + int in = set[(unsigned char)*s] != 0; + if (negate) in = !in; + if (!in) break; + if (out) out[wrote] = *s; + s++; wrote++; + } + if (out) out[wrote] = '\0'; + if (wrote == 0) return matched ? matched : -1; + if (!suppress) matched++; + saw_anything = 1; + continue; + } + + if (conv == 'd' || conv == 'i' || conv == 'u' || + conv == 'o' || conv == 'x' || conv == 'X') + { + int base = 10; + int allow_neg = (conv == 'd' || conv == 'i'); + if (conv == 'o') base = 8; + else if (conv == 'x' || conv == 'X') base = 16; + + const char *start = s; + int neg = 0; + if (allow_neg && (*s == '+' || *s == '-')) { neg = (*s == '-'); s++; } + else if (conv == 'u' && (*s == '+')) s++; + if (conv == 'i' || conv == 'x' || conv == 'X') { + if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { + base = 16; s += 2; + } else if (conv == 'i' && s[0] == '0' && s[1] >= '0' && s[1] <= '7') { + base = 8; s++; + } + } + unsigned long long val = 0; + int got_digit = 0; + int wleft = has_width ? width - (int)(s - start) : 0x7FFFFFFF; + while (*s && wleft > 0) { + int d = -1; + if (*s >= '0' && *s <= '9') d = *s - '0'; + else if (*s >= 'a' && *s <= 'f') d = *s - 'a' + 10; + else if (*s >= 'A' && *s <= 'F') d = *s - 'A' + 10; + if (d < 0 || d >= base) break; + val = val * base + (unsigned)d; + s++; wleft--; + got_digit = 1; + } + if (!got_digit) return matched ? matched : -1; + if (!suppress) { + if (allow_neg && neg) { + long long sv = -(long long)val; + if (len_mod == 4) *va_arg(ap, long long *) = sv; + else if (len_mod == 3 || len_mod == 5) *va_arg(ap, long *) = (long)sv; + else if (len_mod == 1) *va_arg(ap, short *) = (short)sv; + else if (len_mod == 2) *va_arg(ap, signed char *) = (signed char)sv; + else *va_arg(ap, int *) = (int)sv; + } else { + if (len_mod == 4) *va_arg(ap, unsigned long long *) = val; + else if (len_mod == 3 || len_mod == 5) *va_arg(ap, unsigned long *) = (unsigned long)val; + else if (len_mod == 1) *va_arg(ap, unsigned short *) = (unsigned short)val; + else if (len_mod == 2) *va_arg(ap, unsigned char *) = (unsigned char)val; + else *va_arg(ap, unsigned int *) = (unsigned int)val; + } + matched++; + } + saw_anything = 1; + continue; + } + + if (conv == 'f' || conv == 'e' || conv == 'g' || + conv == 'E' || conv == 'G' || conv == 'a' || conv == 'A') + { + char *endp; + uint64_t bits = __cervus_strtod_bits(s, &endp); + if (endp == s) return matched ? matched : -1; + if (!suppress) { + if (len_mod == 3) { + double v; + __builtin_memcpy(&v, &bits, sizeof(double)); + *va_arg(ap, double *) = v; + } else { + double dv; + __builtin_memcpy(&dv, &bits, sizeof(double)); + *va_arg(ap, float *) = (float)dv; + } + matched++; + } + s = endp; + saw_anything = 1; + continue; + } + + return matched ? matched : -1; + } + return matched; +} + +int sscanf(const char *str, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int n = vsscanf(str, fmt, ap); + va_end(ap); + return n; +} + +int vscanf(const char *fmt, va_list ap) +{ + char buf[1024]; + if (!fgets(buf, (int)sizeof(buf), stdin)) return EOF; + return vsscanf(buf, fmt, ap); +} + +int scanf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int n = vscanf(fmt, ap); + va_end(ap); + return n; +} + +int vfscanf(FILE *stream, const char *fmt, va_list ap) +{ + char buf[1024]; + if (!fgets(buf, (int)sizeof(buf), stream)) return EOF; + return vsscanf(buf, fmt, ap); +} + +int fscanf(FILE *stream, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int n = vfscanf(stream, fmt, ap); + va_end(ap); + return n; +} \ No newline at end of file diff --git a/usr/lib/libcervus/stdio/stdio.c b/usr/lib/libcervus/stdio/stdio.c new file mode 100644 index 0000000..97d023b --- /dev/null +++ b/usr/lib/libcervus/stdio/stdio.c @@ -0,0 +1,430 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int __cervus_errno; + +struct __cervus_FILE { + int fd; + int eof; + int err; + int flags; + char *buf; + size_t buf_size; + size_t buf_pos; +}; + +static struct __cervus_FILE __stdin_s = { 0, 0, 0, 0, NULL, 0, 0 }; +static struct __cervus_FILE __stdout_s = { 1, 0, 0, 0, NULL, 0, 0 }; +static struct __cervus_FILE __stderr_s = { 2, 0, 0, 0, NULL, 0, 0 }; + +FILE *stdin = &__stdin_s; +FILE *stdout = &__stdout_s; +FILE *stderr = &__stderr_s; + +int fileno(FILE *s) { return s ? s->fd : -1; } +int feof(FILE *s) { return s ? s->eof : 1; } +int ferror(FILE *s) { return s ? s->err : 1; } +void clearerr(FILE *s) { if (s) { s->eof = 0; s->err = 0; } } + +FILE *fopen(const char *path, const char *mode) +{ + if (!path || !mode) return NULL; + int flags = 0; + int has_plus = 0; + for (const char *m = mode + 1; *m; m++) if (*m == '+') has_plus = 1; + switch (mode[0]) { + case 'r': flags = has_plus ? O_RDWR : O_RDONLY; break; + case 'w': flags = (has_plus ? O_RDWR : O_WRONLY) | O_CREAT | O_TRUNC; break; + case 'a': flags = (has_plus ? O_RDWR : O_WRONLY) | O_CREAT | O_APPEND; break; + default: return NULL; + } + int fd = open(path, flags, 0644); + if (fd < 0) return NULL; + FILE *f = (FILE *)malloc(sizeof(FILE)); + if (!f) { close(fd); return NULL; } + f->fd = fd; + f->eof = 0; + f->err = 0; + f->flags = 1; + f->buf = NULL; + f->buf_size = 0; + f->buf_pos = 0; + return f; +} + +int fclose(FILE *s) +{ + if (!s) return EOF; + int fd = s->fd; + int owned = s->flags & 1; + close(fd); + if (owned) free(s); + return 0; +} + +int fflush(FILE *s) { (void)s; return 0; } + +size_t fread(void *buf, size_t size, size_t nmemb, FILE *s) +{ + if (!s || size == 0 || nmemb == 0) return 0; + size_t total = size * nmemb; + size_t got = 0; + while (got < total) { + ssize_t r = read(s->fd, (char *)buf + got, total - got); + if (r < 0) { s->err = 1; break; } + if (r == 0) { s->eof = 1; break; } + got += (size_t)r; + } + return got / size; +} + +size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *s) +{ + if (!s || size == 0 || nmemb == 0) return 0; + size_t total = size * nmemb; + size_t sent = 0; + while (sent < total) { + ssize_t w = write(s->fd, (const char *)buf + sent, total - sent); + if (w < 0) { s->err = 1; break; } + if (w == 0) break; + sent += (size_t)w; + } + return sent / size; +} + +int fseek(FILE *s, long off, int whence) +{ + if (!s) return -1; + off_t r = lseek(s->fd, (off_t)off, whence); + if (r == (off_t)-1) { s->err = 1; return -1; } + s->eof = 0; + return 0; +} + +long ftell(FILE *s) +{ + if (!s) return -1; + return (long)lseek(s->fd, 0, SEEK_CUR); +} + +int fputc(int c, FILE *s) +{ + unsigned char ch = (unsigned char)c; + if (fwrite(&ch, 1, 1, s) != 1) return EOF; + return (int)ch; +} + +int fgetc(FILE *s) +{ + unsigned char ch; + if (fread(&ch, 1, 1, s) != 1) return EOF; + return (int)ch; +} + +int fputs(const char *str, FILE *s) +{ + if (!str) return EOF; + size_t n = strlen(str); + if (fwrite(str, 1, n, s) != n) return EOF; + return 0; +} + +char *fgets(char *str, int n, FILE *s) +{ + if (!str || n <= 0 || !s) return NULL; + int i = 0; + while (i < n - 1) { + int c = fgetc(s); + if (c == EOF) { + if (i == 0) return NULL; + break; + } + str[i++] = (char)c; + if (c == '\n') break; + } + str[i] = '\0'; + return str; +} + +int putchar(int c) { return fputc(c, stdout); } +int getchar(void) { return fgetc(stdin); } + +int puts(const char *s) +{ + if (fputs(s, stdout) == EOF) return EOF; + if (fputc('\n', stdout) == EOF) return EOF; + return 1; +} + +static void __u64_to_str(uint64_t v, char *out, int base, int upper) +{ + char tmp[32]; + int i = 0; + const char *digs = upper ? "0123456789ABCDEF" : "0123456789abcdef"; + if (v == 0) { out[0] = '0'; out[1] = 0; return; } + while (v) { tmp[i++] = digs[v % (uint64_t)base]; v /= (uint64_t)base; } + int j = 0; + while (i > 0) out[j++] = tmp[--i]; + out[j] = 0; +} + +int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap) +{ + size_t pos = 0; +#define __PUT(s, n) do { \ + size_t __n = (n); const char *__s = (s); \ + for (size_t __i = 0; __i < __n; __i++) { \ + if (pos + 1 < sz) buf[pos] = __s[__i]; \ + pos++; \ + } \ +} while (0) + + while (*fmt) { + if (*fmt != '%') { __PUT(fmt, 1); fmt++; continue; } + fmt++; + int pad_zero = 0, left_align = 0, plus_flag = 0; + while (*fmt == '0' || *fmt == '-' || *fmt == '+' || *fmt == ' ' || *fmt == '#') { + if (*fmt == '0') pad_zero = 1; + else if (*fmt == '-') left_align = 1; + else if (*fmt == '+') plus_flag = 1; + fmt++; + } + int width = 0; + if (*fmt == '*') { width = va_arg(ap, int); if (width < 0) { left_align = 1; width = -width; } fmt++; } + else while (*fmt >= '0' && *fmt <= '9') { width = width * 10 + (*fmt - '0'); fmt++; } + int prec = -1; + if (*fmt == '.') { + fmt++; + prec = 0; + if (*fmt == '*') { prec = va_arg(ap, int); if (prec < 0) prec = 0; fmt++; } + else while (*fmt >= '0' && *fmt <= '9') { prec = prec * 10 + (*fmt - '0'); fmt++; } + } + int is_long = 0, is_size_t = 0; + while (*fmt == 'l') { is_long++; fmt++; } + if (*fmt == 'z') { is_size_t = 1; fmt++; } + if (*fmt == 'h') { fmt++; } + + char nb[40]; + switch (*fmt) { + case 's': { + const char *s = va_arg(ap, const char *); + if (!s) s = "(null)"; + size_t l = strlen(s); + if (prec >= 0 && (size_t)prec < l) l = (size_t)prec; + int pad = (int)(width > (int)l ? width - (int)l : 0); + if (!left_align) for (int i = 0; i < pad; i++) __PUT(" ", 1); + __PUT(s, l); + if (left_align) for (int i = 0; i < pad; i++) __PUT(" ", 1); + break; + } + case 'd': case 'i': { + int64_t v; + if (is_long >= 2) v = va_arg(ap, long long); + else if (is_long) v = va_arg(ap, long); + else if (is_size_t) v = (int64_t)va_arg(ap, size_t); + else v = va_arg(ap, int); + int neg = v < 0; + uint64_t u = neg ? (uint64_t)(-v) : (uint64_t)v; + __u64_to_str(u, nb, 10, 0); + int numlen = (int)strlen(nb) + (neg || plus_flag ? 1 : 0); + int pad = width > numlen ? width - numlen : 0; + if (!left_align && !pad_zero) for (int i = 0; i < pad; i++) __PUT(" ", 1); + if (neg) __PUT("-", 1); + else if (plus_flag) __PUT("+", 1); + if (!left_align && pad_zero) for (int i = 0; i < pad; i++) __PUT("0", 1); + __PUT(nb, strlen(nb)); + if (left_align) for (int i = 0; i < pad; i++) __PUT(" ", 1); + break; + } + case 'u': { + uint64_t v; + if (is_long >= 2) v = va_arg(ap, unsigned long long); + else if (is_long) v = va_arg(ap, unsigned long); + else if (is_size_t) v = va_arg(ap, size_t); + else v = va_arg(ap, unsigned); + __u64_to_str(v, nb, 10, 0); + int numlen = (int)strlen(nb); + int pad = width > numlen ? width - numlen : 0; + if (!left_align) for (int i = 0; i < pad; i++) __PUT(pad_zero ? "0" : " ", 1); + __PUT(nb, strlen(nb)); + if (left_align) for (int i = 0; i < pad; i++) __PUT(" ", 1); + break; + } + case 'x': case 'X': { + uint64_t v; + if (is_long >= 2) v = va_arg(ap, unsigned long long); + else if (is_long) v = va_arg(ap, unsigned long); + else if (is_size_t) v = va_arg(ap, size_t); + else v = va_arg(ap, unsigned); + __u64_to_str(v, nb, 16, *fmt == 'X'); + int numlen = (int)strlen(nb); + int pad = width > numlen ? width - numlen : 0; + if (!left_align) for (int i = 0; i < pad; i++) __PUT(pad_zero ? "0" : " ", 1); + __PUT(nb, strlen(nb)); + if (left_align) for (int i = 0; i < pad; i++) __PUT(" ", 1); + break; + } + case 'o': { + uint64_t v; + if (is_long >= 2) v = va_arg(ap, unsigned long long); + else if (is_long) v = va_arg(ap, unsigned long); + else v = va_arg(ap, unsigned); + __u64_to_str(v, nb, 8, 0); + __PUT(nb, strlen(nb)); + break; + } + case 'p': { + uint64_t v = (uint64_t)(uintptr_t)va_arg(ap, void *); + __PUT("0x", 2); + __u64_to_str(v, nb, 16, 0); + __PUT(nb, strlen(nb)); + break; + } + case 'c': { + char c = (char)va_arg(ap, int); + __PUT(&c, 1); + break; + } + case '%': __PUT("%", 1); break; + default: { + char c = *fmt; + __PUT("%", 1); + __PUT(&c, 1); + break; + } + } + fmt++; + } + if (sz > 0) buf[pos < sz ? pos : sz - 1] = '\0'; +#undef __PUT + return (int)pos; +} + +int snprintf(char *buf, size_t sz, const char *fmt, ...) +{ + va_list ap; va_start(ap, fmt); + int n = vsnprintf(buf, sz, fmt, ap); + va_end(ap); + return n; +} + +int sprintf(char *buf, const char *fmt, ...) +{ + va_list ap; va_start(ap, fmt); + int n = vsnprintf(buf, (size_t)-1, fmt, ap); + va_end(ap); + return n; +} + +int vsprintf(char *buf, const char *fmt, va_list ap) +{ + return vsnprintf(buf, (size_t)-1, fmt, ap); +} + +int vfprintf(FILE *s, const char *fmt, va_list ap) +{ + char small[512]; + va_list ap2; + va_copy(ap2, ap); + int needed = vsnprintf(small, sizeof(small), fmt, ap2); + va_end(ap2); + if (needed < (int)sizeof(small)) { + fwrite(small, 1, (size_t)needed, s); + return needed; + } + char *big = (char *)malloc((size_t)needed + 1); + if (!big) { + fwrite(small, 1, sizeof(small) - 1, s); + return (int)sizeof(small) - 1; + } + vsnprintf(big, (size_t)needed + 1, fmt, ap); + fwrite(big, 1, (size_t)needed, s); + free(big); + return needed; +} + +int fprintf(FILE *s, const char *fmt, ...) +{ + va_list ap; va_start(ap, fmt); + int n = vfprintf(s, fmt, ap); + va_end(ap); + return n; +} + +int vprintf(const char *fmt, va_list ap) { return vfprintf(stdout, fmt, ap); } + +int printf(const char *fmt, ...) +{ + va_list ap; va_start(ap, fmt); + int n = vfprintf(stdout, fmt, ap); + va_end(ap); + return n; +} + +void perror(const char *msg) +{ + if (msg && *msg) { fputs(msg, stderr); fputs(": ", stderr); } + fputs(strerror(__cervus_errno), stderr); + fputc('\n', stderr); +} + +int remove(const char *path) { return unlink(path); } + +int mkstemp(char *template) +{ + if (!template) { __cervus_errno = EINVAL; return -1; } + size_t len = strlen(template); + if (len < 6) { __cervus_errno = EINVAL; return -1; } + char *suf = template + len - 6; + for (int i = 0; i < 6; i++) { + if (suf[i] != 'X') { __cervus_errno = EINVAL; return -1; } + } + static uint64_t __mkstemp_seq = 0; + uint64_t pid = (uint64_t)getpid(); + for (int attempt = 0; attempt < 100; attempt++) { + uint64_t seed = (cervus_uptime_ns() ^ (pid << 32)) + (__mkstemp_seq++); + const char *alpha = "0123456789abcdefghijklmnopqrstuvwxyz"; + for (int i = 0; i < 6; i++) { + suf[i] = alpha[seed % 36]; + seed /= 36; + } + struct stat st; + if (stat(template, &st) == 0) continue; + int fd = open(template, O_RDWR | O_CREAT, 0600); + if (fd >= 0) return fd; + } + __cervus_errno = EEXIST; + return -1; +} + +FILE *tmpfile(void) +{ + char tmpl[64]; + strcpy(tmpl, "/mnt/tmp/tmpXXXXXX"); + int fd = mkstemp(tmpl); + if (fd < 0) { + strcpy(tmpl, "/tmp/tmpXXXXXX"); + fd = mkstemp(tmpl); + if (fd < 0) return NULL; + } + unlink(tmpl); + FILE *f = (FILE *)malloc(sizeof(FILE)); + if (!f) { close(fd); return NULL; } + f->fd = fd; + f->eof = 0; + f->err = 0; + f->flags = 1; + f->buf = NULL; + f->buf_size = 0; + f->buf_pos = 0; + return f; +} \ No newline at end of file diff --git a/usr/lib/libcervus/stdlib/stdlib.c b/usr/lib/libcervus/stdlib/stdlib.c new file mode 100644 index 0000000..aa61b45 --- /dev/null +++ b/usr/lib/libcervus/stdlib/stdlib.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include +#include + +extern int __cervus_errno; +extern int __cervus_argc; +extern char **__cervus_argv; + +int abs(int x) { return x < 0 ? -x : x; } +long labs(long x) { return x < 0 ? -x : x; } +long long llabs(long long x){ return x < 0 ? -x : x; } + +static long long __parse_signed(const char *s, char **end, int base, int is_unsigned) +{ + while (isspace((unsigned char)*s)) s++; + int neg = 0; + if (*s == '-') { neg = 1; s++; } + else if (*s == '+') s++; + if ((base == 0 || base == 16) && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { + s += 2; base = 16; + } else if (base == 0 && *s == '0') { + s++; base = 8; + } else if (base == 0) { + base = 10; + } + unsigned long long v = 0; + while (*s) { + int d; + if (isdigit((unsigned char)*s)) d = *s - '0'; + else if (*s >= 'a' && *s <= 'z') d = *s - 'a' + 10; + else if (*s >= 'A' && *s <= 'Z') d = *s - 'A' + 10; + else break; + if (d >= base) break; + v = v * (unsigned long long)base + (unsigned long long)d; + s++; + } + if (end) *end = (char *)s; + if (is_unsigned) return (long long)v; + return neg ? -(long long)v : (long long)v; +} + +long strtol(const char *s, char **e, int b) { return (long)__parse_signed(s, e, b, 0); } +long long strtoll(const char *s, char **e, int b) { return __parse_signed(s, e, b, 0); } +unsigned long strtoul(const char *s, char **e, int b) { return (unsigned long)__parse_signed(s, e, b, 1); } +unsigned long long strtoull(const char *s, char **e, int b) { return (unsigned long long)__parse_signed(s, e, b, 1); } + +int atoi(const char *s) { return (int)strtol(s, NULL, 10); } +long atol(const char *s) { return strtol(s, NULL, 10); } +long long atoll(const char *s) { return strtoll(s, NULL, 10); } + +static unsigned long __rand_state = 1; +int rand(void) { __rand_state = __rand_state * 1103515245UL + 12345UL; return (int)((__rand_state >> 16) & 0x7FFF); } +void srand(unsigned int seed) { __rand_state = seed; } + +static void __qswap(void *a, void *b, size_t sz) +{ + unsigned char tmp; + unsigned char *pa = (unsigned char *)a; + unsigned char *pb = (unsigned char *)b; + while (sz--) { tmp = *pa; *pa++ = *pb; *pb++ = tmp; } +} + +void qsort(void *base, size_t nmemb, size_t sz, int (*cmp)(const void *, const void *)) +{ + if (nmemb < 2) return; + unsigned char *arr = (unsigned char *)base; + unsigned char *pivot = arr + (nmemb - 1) * sz; + size_t i = 0; + for (size_t j = 0; j < nmemb - 1; j++) { + if (cmp(arr + j * sz, pivot) <= 0) { + if (i != j) __qswap(arr + i * sz, arr + j * sz, sz); + i++; + } + } + __qswap(arr + i * sz, pivot, sz); + qsort(arr, i, sz, cmp); + qsort(arr + (i + 1) * sz, nmemb - i - 1, sz, cmp); +} + +char *getenv(const char *name) +{ + if (!name) return NULL; + size_t nl = strlen(name); + for (int i = 1; i < __cervus_argc; i++) { + const char *a = __cervus_argv[i]; + if (a && a[0] == '-' && a[1] == '-' && + a[2] == 'e' && a[3] == 'n' && a[4] == 'v' && a[5] == ':') { + const char *kv = a + 6; + if (strncmp(kv, name, nl) == 0 && kv[nl] == '=') + return (char *)(kv + nl + 1); + } + } + return NULL; +} + +int system(const char *cmd) +{ + (void)cmd; + __cervus_errno = ENOSYS; + return -1; +} + +#define ATEXIT_MAX 32 +static void (*__atexit_fns[ATEXIT_MAX])(void); +static int __atexit_cnt = 0; + +int atexit(void (*fn)(void)) +{ + if (__atexit_cnt >= ATEXIT_MAX) return -1; + __atexit_fns[__atexit_cnt++] = fn; + return 0; +} + +int fflush(FILE *stream); + +void exit(int status) +{ + while (__atexit_cnt > 0) { + __atexit_cnt--; + if (__atexit_fns[__atexit_cnt]) __atexit_fns[__atexit_cnt](); + } + extern FILE *stdout; + extern FILE *stderr; + fflush(stdout); + fflush(stderr); + syscall1(SYS_EXIT, status); + __builtin_unreachable(); +} + +void abort(void) +{ + syscall1(SYS_EXIT, 134); + __builtin_unreachable(); +} \ No newline at end of file diff --git a/usr/lib/libcervus/stdlib/strtod.c b/usr/lib/libcervus/stdlib/strtod.c new file mode 100644 index 0000000..c1b0dfc --- /dev/null +++ b/usr/lib/libcervus/stdlib/strtod.c @@ -0,0 +1,170 @@ +#include +#include + +uint64_t __cervus_strtod_bits(const char *s, char **endptr) +{ + if (!s) { + if (endptr) *endptr = (char *)s; + return 0; + } + const char *p = s; + while (*p == ' ' || *p == '\t' || *p == '\n' || + *p == '\r' || *p == '\f' || *p == '\v') p++; + + int sign = 0; + if (*p == '+') p++; + else if (*p == '-') { sign = 1; p++; } + + if ((p[0] == 'i' || p[0] == 'I') && + (p[1] == 'n' || p[1] == 'N') && + (p[2] == 'f' || p[2] == 'F')) { + p += 3; + if ((p[0] == 'i' || p[0] == 'I') && + (p[1] == 'n' || p[1] == 'N') && + (p[2] == 'i' || p[2] == 'I') && + (p[3] == 't' || p[3] == 'T') && + (p[4] == 'y' || p[4] == 'Y')) p += 5; + if (endptr) *endptr = (char *)p; + return ((uint64_t)sign << 63) | 0x7FF0000000000000ULL; + } + if ((p[0] == 'n' || p[0] == 'N') && + (p[1] == 'a' || p[1] == 'A') && + (p[2] == 'n' || p[2] == 'N')) { + p += 3; + if (endptr) *endptr = (char *)p; + return 0x7FF8000000000000ULL; + } + + uint64_t mant = 0; + int dec_exp = 0; + int seen_digit = 0; + + while (*p >= '0' && *p <= '9') { + seen_digit = 1; + if (mant <= (UINT64_MAX - 9) / 10) { + mant = mant * 10 + (uint64_t)(*p - '0'); + } else { + dec_exp++; + } + p++; + } + if (*p == '.') { + p++; + while (*p >= '0' && *p <= '9') { + seen_digit = 1; + if (mant <= (UINT64_MAX - 9) / 10) { + mant = mant * 10 + (uint64_t)(*p - '0'); + dec_exp--; + } + p++; + } + } + if (!seen_digit) { + if (endptr) *endptr = (char *)s; + return 0; + } + + if (*p == 'e' || *p == 'E') { + const char *ep = p + 1; + int esign = 0; + if (*ep == '+') ep++; + else if (*ep == '-') { esign = 1; ep++; } + if (*ep >= '0' && *ep <= '9') { + int eval = 0; + while (*ep >= '0' && *ep <= '9') { + if (eval < 10000) eval = eval * 10 + (*ep - '0'); + ep++; + } + dec_exp += esign ? -eval : eval; + p = ep; + } + } + if (endptr) *endptr = (char *)p; + + if (mant == 0) { + return (uint64_t)sign << 63; + } + + int bin_exp = 0; + while ((mant >> 63) == 0) { + mant <<= 1; + bin_exp--; + } + + while (dec_exp > 0) { + uint64_t a_hi = mant >> 32; + uint64_t a_lo = mant & 0xFFFFFFFFULL; + uint64_t p_lo = a_lo * 10; + uint64_t p_hi = a_hi * 10; + uint64_t mid_carry = p_lo >> 32; + uint64_t lo = ((p_hi + mid_carry) << 32) | (p_lo & 0xFFFFFFFFULL); + uint64_t hi = (p_hi + mid_carry) >> 32; + + while (hi != 0) { + lo = (lo >> 1) | (hi << 63); + hi >>= 1; + bin_exp++; + } + mant = lo; + while ((mant >> 63) == 0) { + mant <<= 1; + bin_exp--; + } + dec_exp--; + } + while (dec_exp < 0) { + mant = mant / 10; + if (mant == 0) break; + while ((mant >> 63) == 0) { + mant <<= 1; + bin_exp--; + } + dec_exp++; + } + + int ieee_exp = bin_exp + 63 + 1023; + uint64_t no_implicit = mant & 0x7FFFFFFFFFFFFFFFULL; + uint64_t round_bit = (no_implicit >> 10) & 1; + uint64_t sticky = (no_implicit & 0x3FFULL) ? 1 : 0; + uint64_t frac = no_implicit >> 11; + if (round_bit && (sticky || (frac & 1))) { + frac++; + if (frac == (1ULL << 52)) { + frac = 0; + ieee_exp++; + } + } + + if (ieee_exp >= 0x7FF) { + return ((uint64_t)sign << 63) | 0x7FF0000000000000ULL; + } + if (ieee_exp <= 0) { + return (uint64_t)sign << 63; + } + return ((uint64_t)sign << 63) | + ((uint64_t)ieee_exp << 52) | + (frac & 0xFFFFFFFFFFFFFULL); +} + +double strtod(const char *s, char **endptr) +{ + uint64_t bits = __cervus_strtod_bits(s, endptr); + double result; + __builtin_memcpy(&result, &bits, sizeof(double)); + return result; +} + +float strtof(const char *s, char **endptr) +{ + return (float)strtod(s, endptr); +} + +long double strtold(const char *s, char **endptr) +{ + return (long double)strtod(s, endptr); +} + +double atof(const char *s) +{ + return strtod(s, NULL); +} \ No newline at end of file diff --git a/usr/lib/libcervus/string/string.c b/usr/lib/libcervus/string/string.c new file mode 100644 index 0000000..0c71656 --- /dev/null +++ b/usr/lib/libcervus/string/string.c @@ -0,0 +1,296 @@ +#include +#include +#include +#include +#include + +void *memset(void *d, int c, size_t n) +{ + unsigned char *p = (unsigned char *)d; + while (n--) *p++ = (unsigned char)c; + return d; +} + +void *memcpy(void *d, const void *s, size_t n) +{ + unsigned char *dd = (unsigned char *)d; + const unsigned char *ss = (const unsigned char *)s; + while (n--) *dd++ = *ss++; + return d; +} + +void *memmove(void *d, const void *s, size_t n) +{ + unsigned char *dd = (unsigned char *)d; + const unsigned char *ss = (const unsigned char *)s; + if (dd < ss) { while (n--) *dd++ = *ss++; } + else { dd += n; ss += n; while (n--) *--dd = *--ss; } + return d; +} + +int memcmp(const void *a, const void *b, size_t n) +{ + const unsigned char *x = (const unsigned char *)a; + const unsigned char *y = (const unsigned char *)b; + for (size_t i = 0; i < n; i++) + if (x[i] != y[i]) return x[i] - y[i]; + return 0; +} + +void *memchr(const void *s, int c, size_t n) +{ + const unsigned char *p = (const unsigned char *)s; + while (n--) { if (*p == (unsigned char)c) return (void *)p; p++; } + return NULL; +} + +void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen) +{ + if (nlen == 0) return (void *)haystack; + if (hlen < nlen) return NULL; + const unsigned char *h = (const unsigned char *)haystack; + const unsigned char *n = (const unsigned char *)needle; + size_t last = hlen - nlen; + for (size_t i = 0; i <= last; i++) { + if (h[i] == n[0] && memcmp(h + i, n, nlen) == 0) + return (void *)(h + i); + } + return NULL; +} + +size_t strlen(const char *s) { size_t n = 0; while (s[n]) n++; return n; } + +size_t strnlen(const char *s, size_t max) +{ + size_t n = 0; + while (n < max && s[n]) n++; + return n; +} + +int strcmp(const char *a, const char *b) +{ + while (*a && *a == *b) { a++; b++; } + return (unsigned char)*a - (unsigned char)*b; +} + +int strncmp(const char *a, const char *b, size_t n) +{ + for (size_t i = 0; i < n; i++) { + if (a[i] != b[i]) return (unsigned char)a[i] - (unsigned char)b[i]; + if (!a[i]) return 0; + } + return 0; +} + +int strcasecmp(const char *a, const char *b) +{ + while (*a && tolower((unsigned char)*a) == tolower((unsigned char)*b)) { + a++; b++; + } + return tolower((unsigned char)*a) - tolower((unsigned char)*b); +} + +int strncasecmp(const char *a, const char *b, size_t n) +{ + for (size_t i = 0; i < n; i++) { + int ca = tolower((unsigned char)a[i]); + int cb = tolower((unsigned char)b[i]); + if (ca != cb) return ca - cb; + if (!a[i]) return 0; + } + return 0; +} + +char *strcpy(char *d, const char *s) +{ + char *r = d; + while ((*d++ = *s++)) { } + return r; +} + +char *strncpy(char *d, const char *s, size_t n) +{ + size_t i; + for (i = 0; i < n && s[i]; i++) d[i] = s[i]; + for (; i < n; i++) d[i] = 0; + return d; +} + +char *strcat(char *d, const char *s) +{ + char *r = d; + while (*d) d++; + while ((*d++ = *s++)) { } + return r; +} + +char *strncat(char *d, const char *s, size_t n) +{ + char *r = d; + while (*d) d++; + for (size_t i = 0; i < n && s[i]; i++) *d++ = s[i]; + *d = '\0'; + return r; +} + +char *strchr(const char *s, int c) +{ + for (; *s; s++) if (*s == (char)c) return (char *)s; + return c == 0 ? (char *)s : NULL; +} + +char *strrchr(const char *s, int c) +{ + const char *r = NULL; + for (; *s; s++) if (*s == (char)c) r = s; + return (char *)(c == 0 ? s : r); +} + +char *strstr(const char *h, const char *n) +{ + if (!*n) return (char *)h; + for (; *h; h++) { + const char *a = h, *b = n; + while (*a && *b && *a == *b) { a++; b++; } + if (!*b) return (char *)h; + } + return NULL; +} + +size_t strspn(const char *s, const char *accept) +{ + size_t n = 0; + while (s[n]) { + int found = 0; + for (size_t i = 0; accept[i]; i++) + if (s[n] == accept[i]) { found = 1; break; } + if (!found) break; + n++; + } + return n; +} + +size_t strcspn(const char *s, const char *reject) +{ + size_t n = 0; + while (s[n]) { + for (size_t i = 0; reject[i]; i++) + if (s[n] == reject[i]) return n; + n++; + } + return n; +} + +char *strpbrk(const char *s, const char *accept) +{ + while (*s) { + for (const char *a = accept; *a; a++) + if (*s == *a) return (char *)s; + s++; + } + return NULL; +} + +char *strdup(const char *s) +{ + size_t n = strlen(s) + 1; + char *p = (char *)malloc(n); + if (!p) return NULL; + memcpy(p, s, n); + return p; +} + +char *strndup(const char *s, size_t n) +{ + size_t len = strnlen(s, n); + char *p = (char *)malloc(len + 1); + if (!p) return NULL; + memcpy(p, s, len); + p[len] = '\0'; + return p; +} + +char *strtok_r(char *str, const char *delim, char **saveptr) +{ + char *s = str ? str : (saveptr ? *saveptr : NULL); + if (!s || !delim) return NULL; + + while (*s) { + const char *d; + for (d = delim; *d; d++) if (*s == *d) break; + if (!*d) break; + s++; + } + if (!*s) { + if (saveptr) *saveptr = NULL; + return NULL; + } + char *tok = s; + + while (*s) { + const char *d; + for (d = delim; *d; d++) if (*s == *d) break; + if (*d) { + *s = '\0'; + if (saveptr) *saveptr = s + 1; + return tok; + } + s++; + } + if (saveptr) *saveptr = NULL; + return tok; +} + +static char *__strtok_save = NULL; +char *strtok(char *str, const char *delim) +{ + return strtok_r(str, delim, &__strtok_save); +} + +char *strerror(int err) +{ + switch (err) { + case 0: return "Success"; + case EPERM: return "Operation not permitted"; + case ENOENT: return "No such file or directory"; + case ESRCH: return "No such process"; + case EINTR: return "Interrupted system call"; + case EIO: return "Input/output error"; + case EBADF: return "Bad file descriptor"; + case ECHILD: return "No child processes"; + case EAGAIN: return "Resource temporarily unavailable"; + case ENOMEM: return "Cannot allocate memory"; + case EACCES: return "Permission denied"; + case EFAULT: return "Bad address"; + case EBUSY: return "Device or resource busy"; + case EEXIST: return "File exists"; + case ENODEV: return "No such device"; + case ENOTDIR: return "Not a directory"; + case EISDIR: return "Is a directory"; + case EINVAL: return "Invalid argument"; + case EMFILE: return "Too many open files"; + case ENOTTY: return "Inappropriate ioctl for device"; + case ENOSPC: return "No space left on device"; + case EPIPE: return "Broken pipe"; + case ENOSYS: return "Function not implemented"; + default: return "Unknown error"; + } +} + +char *strsignal(int sig) +{ + switch (sig) { + case 1: return "Hangup"; + case 2: return "Interrupt"; + case 3: return "Quit"; + case 4: return "Illegal instruction"; + case 6: return "Aborted"; + case 8: return "Floating point exception"; + case 9: return "Killed"; + case 11: return "Segmentation fault"; + case 13: return "Broken pipe"; + case 14: return "Alarm clock"; + case 15: return "Terminated"; + default: return "Unknown signal"; + } +} \ No newline at end of file diff --git a/usr/lib/libcervus/time/time.c b/usr/lib/libcervus/time/time.c new file mode 100644 index 0000000..c2a9d05 --- /dev/null +++ b/usr/lib/libcervus/time/time.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include +#include + +extern int __cervus_errno; + +typedef struct { int64_t tv_sec; int64_t tv_nsec; } __cervus_ts_raw_t; + +time_t time(time_t *t) +{ + __cervus_ts_raw_t ts = {0, 0}; + syscall2(SYS_CLOCK_GET, 0, &ts); + time_t v = (time_t)ts.tv_sec; + if (t) *t = v; + return v; +} + +int clock_gettime(int clk, struct timespec *tp) +{ + if (!tp) { __cervus_errno = EINVAL; return -1; } + __cervus_ts_raw_t ts = {0, 0}; + long r = syscall2(SYS_CLOCK_GET, clk, &ts); + if (r < 0 && r > -4096) { __cervus_errno = (int)-r; return -1; } + tp->tv_sec = (time_t)ts.tv_sec; + tp->tv_nsec = (long)ts.tv_nsec; + return 0; +} + +clock_t clock(void) +{ + uint64_t up_ns = (uint64_t)syscall0(SYS_UPTIME); + return (clock_t)(up_ns / 1000ULL); +} + +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + (void)tz; + if (!tv) { __cervus_errno = EINVAL; return -1; } + __cervus_ts_raw_t ts = {0, 0}; + syscall2(SYS_CLOCK_GET, 0, &ts); + tv->tv_sec = (time_t)ts.tv_sec; + tv->tv_usec = (long)(ts.tv_nsec / 1000); + return 0; +} + +int nanosleep(const struct timespec *req, struct timespec *rem) +{ + if (!req) { __cervus_errno = EINVAL; return -1; } + uint64_t ns = (uint64_t)req->tv_sec * 1000000000ULL + (uint64_t)req->tv_nsec; + long r = syscall1(SYS_SLEEP_NS, ns); + if (rem) { rem->tv_sec = 0; rem->tv_nsec = 0; } + if (r < 0 && r > -4096) { __cervus_errno = (int)-r; return -1; } + return 0; +} + +static int __is_leap(int y) +{ + return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0); +} + +static const int __days_in_mon[2][12] = { + {31,28,31,30,31,30,31,31,30,31,30,31}, + {31,29,31,30,31,30,31,31,30,31,30,31}, +}; + +static struct tm __tm_buf; + +struct tm *gmtime(const time_t *t) +{ + if (!t) return NULL; + long long sec = (long long)*t; + long days = (long)(sec / 86400); + long rem = (long)(sec % 86400); + if (rem < 0) { rem += 86400; days--; } + + __tm_buf.tm_hour = rem / 3600; + rem -= __tm_buf.tm_hour * 3600; + __tm_buf.tm_min = rem / 60; + __tm_buf.tm_sec = rem - __tm_buf.tm_min * 60; + + __tm_buf.tm_wday = (int)((days + 4) % 7); + if (__tm_buf.tm_wday < 0) __tm_buf.tm_wday += 7; + + int year = 1970; + while (1) { + int ly = __is_leap(year); + int dy = ly ? 366 : 365; + if (days >= dy) { days -= dy; year++; } + else if (days < 0) { year--; days += __is_leap(year) ? 366 : 365; } + else break; + } + __tm_buf.tm_year = year - 1900; + __tm_buf.tm_yday = (int)days; + int ly = __is_leap(year); + int m = 0; + while (m < 12 && days >= __days_in_mon[ly][m]) { + days -= __days_in_mon[ly][m]; + m++; + } + __tm_buf.tm_mon = m; + __tm_buf.tm_mday = (int)days + 1; + __tm_buf.tm_isdst = 0; + return &__tm_buf; +} + +struct tm *localtime(const time_t *t) { return gmtime(t); } + +time_t mktime(struct tm *tm) +{ + if (!tm) return (time_t)-1; + int year = tm->tm_year + 1900; + int mon = tm->tm_mon; + long days = 0; + for (int y = 1970; y < year; y++) days += __is_leap(y) ? 366 : 365; + int ly = __is_leap(year); + for (int m = 0; m < mon; m++) days += __days_in_mon[ly][m]; + days += tm->tm_mday - 1; + long long sec = (long long)days * 86400LL + + (long long)tm->tm_hour * 3600LL + + (long long)tm->tm_min * 60LL + + (long long)tm->tm_sec; + return (time_t)sec; +} + +static const char *__wday_name[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; +static const char *__mon_name[] = {"Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec"}; + +static char __asctime_buf[32]; + +char *asctime(const struct tm *tm) +{ + if (!tm) return NULL; + int wday = tm->tm_wday; if (wday < 0 || wday > 6) wday = 0; + int mon = tm->tm_mon; if (mon < 0 || mon > 11) mon = 0; + int y = tm->tm_year + 1900; + int pos = 0; + const char *w = __wday_name[wday]; + const char *mn = __mon_name[mon]; + __asctime_buf[pos++] = w[0]; __asctime_buf[pos++] = w[1]; __asctime_buf[pos++] = w[2]; + __asctime_buf[pos++] = ' '; + __asctime_buf[pos++] = mn[0]; __asctime_buf[pos++] = mn[1]; __asctime_buf[pos++] = mn[2]; + __asctime_buf[pos++] = ' '; + int md = tm->tm_mday; + __asctime_buf[pos++] = (char)('0' + (md/10 % 10)); + __asctime_buf[pos++] = (char)('0' + (md % 10)); + __asctime_buf[pos++] = ' '; + int hh = tm->tm_hour, mm = tm->tm_min, ss = tm->tm_sec; + __asctime_buf[pos++] = (char)('0' + (hh/10 % 10)); + __asctime_buf[pos++] = (char)('0' + (hh % 10)); + __asctime_buf[pos++] = ':'; + __asctime_buf[pos++] = (char)('0' + (mm/10 % 10)); + __asctime_buf[pos++] = (char)('0' + (mm % 10)); + __asctime_buf[pos++] = ':'; + __asctime_buf[pos++] = (char)('0' + (ss/10 % 10)); + __asctime_buf[pos++] = (char)('0' + (ss % 10)); + __asctime_buf[pos++] = ' '; + __asctime_buf[pos++] = (char)('0' + (y/1000 % 10)); + __asctime_buf[pos++] = (char)('0' + (y/100 % 10)); + __asctime_buf[pos++] = (char)('0' + (y/10 % 10)); + __asctime_buf[pos++] = (char)('0' + (y % 10)); + __asctime_buf[pos++] = '\n'; + __asctime_buf[pos] = '\0'; + return __asctime_buf; +} + +char *ctime(const time_t *t) { return asctime(gmtime(t)); } + +size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tm) +{ + if (!s || !fmt || !tm || max == 0) return 0; + size_t i = 0; + while (*fmt && i + 1 < max) { + if (*fmt != '%') { s[i++] = *fmt++; continue; } + fmt++; + char tmp[16]; + int n = 0; + switch (*fmt) { + case 'Y': { + int y = tm->tm_year + 1900; + n = 4; + tmp[0] = (char)('0' + (y/1000)%10); + tmp[1] = (char)('0' + (y/100)%10); + tmp[2] = (char)('0' + (y/10)%10); + tmp[3] = (char)('0' + y%10); + break; + } + case 'm': { int v=tm->tm_mon+1; tmp[0]=(char)('0'+v/10); tmp[1]=(char)('0'+v%10); n=2; break; } + case 'd': { int v=tm->tm_mday; tmp[0]=(char)('0'+v/10); tmp[1]=(char)('0'+v%10); n=2; break; } + case 'H': { int v=tm->tm_hour; tmp[0]=(char)('0'+v/10); tmp[1]=(char)('0'+v%10); n=2; break; } + case 'M': { int v=tm->tm_min; tmp[0]=(char)('0'+v/10); tmp[1]=(char)('0'+v%10); n=2; break; } + case 'S': { int v=tm->tm_sec; tmp[0]=(char)('0'+v/10); tmp[1]=(char)('0'+v%10); n=2; break; } + case '%': tmp[0]='%'; n=1; break; + default: tmp[0]='%'; tmp[1]=*fmt; n = (*fmt ? 2 : 1); break; + } + for (int k = 0; k < n && i + 1 < max; k++) s[i++] = tmp[k]; + if (*fmt) fmt++; + } + s[i] = '\0'; + return i; +} \ No newline at end of file diff --git a/usr/sysroot/usr/include/assert.h b/usr/sysroot/usr/include/assert.h new file mode 100644 index 0000000..2cdfb3f --- /dev/null +++ b/usr/sysroot/usr/include/assert.h @@ -0,0 +1,16 @@ +#ifndef _ASSERT_H +#define _ASSERT_H + +#ifdef NDEBUG +#define assert(cond) ((void)0) +#else + +void __cervus_assert_fail(const char *expr, const char *file, int line, const char *func) + __attribute__((noreturn)); + +#define assert(cond) \ + ((cond) ? (void)0 : __cervus_assert_fail(#cond, __FILE__, __LINE__, __func__)) + +#endif + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/cervus_util.h b/usr/sysroot/usr/include/cervus_util.h new file mode 100644 index 0000000..5ca46eb --- /dev/null +++ b/usr/sysroot/usr/include/cervus_util.h @@ -0,0 +1,162 @@ +#ifndef _CERVUS_UTIL_H +#define _CERVUS_UTIL_H + +#include +#include +#include + +#define C_RESET "\x1b[0m" +#define C_BOLD "\x1b[1m" +#define C_RED "\x1b[1;31m" +#define C_GREEN "\x1b[1;32m" +#define C_YELLOW "\x1b[1;33m" +#define C_BLUE "\x1b[1;34m" +#define C_MAGENTA "\x1b[1;35m" +#define C_CYAN "\x1b[1;36m" +#define C_GRAY "\x1b[90m" + +static inline void path_join(const char *base, const char *name, + char *out, size_t sz) +{ + if (!name || !name[0]) { + strncpy(out, base ? base : "", sz - 1); + out[sz - 1] = '\0'; + return; + } + if (name[0] == '/') { + strncpy(out, name, sz - 1); + out[sz - 1] = '\0'; + return; + } + strncpy(out, base ? base : "", sz - 1); + out[sz - 1] = '\0'; + size_t bl = strlen(out); + if (bl > 0 && out[bl - 1] != '/' && bl + 1 < sz) { + out[bl++] = '/'; + out[bl] = '\0'; + } + size_t nl = strlen(name); + if (bl + nl + 1 < sz) memcpy(out + bl, name, nl + 1); + else out[sz - 1] = '\0'; +} + +static inline void path_norm(char *path) +{ + char tmp[512]; + strncpy(tmp, path, 511); + tmp[511] = '\0'; + + char *parts[64]; + int np = 0; + char *p = tmp; + while (*p) { + while (*p == '/') p++; + if (!*p) break; + char *s = p; + while (*p && *p != '/') p++; + if (*p) *p++ = '\0'; + if (strcmp(s, ".") == 0) continue; + if (strcmp(s, "..") == 0) { if (np > 0) np--; continue; } + if (np < 64) parts[np++] = s; + } + char out[512]; + size_t ol = 0; + for (int i = 0; i < np; i++) { + if (ol + 1 >= sizeof(out)) break; + out[ol++] = '/'; + size_t pl = strlen(parts[i]); + if (ol + pl >= sizeof(out)) pl = sizeof(out) - 1 - ol; + memcpy(out + ol, parts[i], pl); + ol += pl; + } + out[ol] = '\0'; + if (ol == 0) { out[0] = '/'; out[1] = '\0'; } + strncpy(path, out, 512); +} + +static inline void resolve_path(const char *cwd, const char *path, + char *out, size_t sz) +{ + if (!path || !path[0]) { + strncpy(out, cwd ? cwd : "/", sz - 1); + out[sz - 1] = '\0'; + return; + } + if (path[0] == '/') { + strncpy(out, path, sz - 1); + out[sz - 1] = '\0'; + return; + } + path_join(cwd, path, out, sz); + path_norm(out); +} + +extern int __cervus_argc; +extern char **__cervus_argv; + +static inline int is_shell_flag(const char *a) +{ + if (!a) return 0; + if (a[0] == '-' && a[1] == '-' && + a[2] == 'c' && a[3] == 'w' && a[4] == 'd' && a[5] == '=') return 1; + if (a[0] == '-' && a[1] == '-' && + a[2] == 'e' && a[3] == 'n' && a[4] == 'v' && a[5] == ':') return 1; + return 0; +} + +static inline const char *get_cwd_flag(int argc, char **argv) +{ + (void)argc; (void)argv; + for (int i = 1; i < __cervus_argc; i++) { + char *a = __cervus_argv[i]; + if (a && a[0] == '-' && a[1] == '-' && + a[2] == 'c' && a[3] == 'w' && a[4] == 'd' && a[5] == '=') + return a + 6; + } + return "/"; +} + +static inline const char *getenv_argv(int argc, char **argv, + const char *name, const char *def) +{ + (void)argc; (void)argv; + if (!name) return def; + size_t nl = strlen(name); + for (int i = 1; i < __cervus_argc; i++) { + const char *a = __cervus_argv[i]; + if (!a) continue; + if (a[0] == '-' && a[1] == '-' && + a[2] == 'e' && a[3] == 'n' && a[4] == 'v' && a[5] == ':') { + const char *kv = a + 6; + if (strncmp(kv, name, nl) == 0 && kv[nl] == '=') + return kv + nl + 1; + } + } + return def; +} + +static inline int util_readline(int fd, char *buf, int maxlen) +{ + int i = 0; + while (i < maxlen - 1) { + char c; + ssize_t r = read(fd, &c, 1); + if (r <= 0) { buf[i] = '\0'; return i > 0 ? i : -1; } + if (c == '\r') continue; + buf[i++] = c; + if (c == '\n') break; + } + buf[i] = '\0'; + return i; +} + +static inline void util_write_stdout(const char *s) +{ + write(1, s, strlen(s)); +} +static inline void util_write_stderr(const char *s) +{ + write(2, s, strlen(s)); +} + +#endif diff --git a/usr/sysroot/usr/include/ctype.h b/usr/sysroot/usr/include/ctype.h new file mode 100644 index 0000000..2002e1d --- /dev/null +++ b/usr/sysroot/usr/include/ctype.h @@ -0,0 +1,19 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +int isdigit(int c); +int isalpha(int c); +int isalnum(int c); +int isupper(int c); +int islower(int c); +int isspace(int c); +int isprint(int c); +int isgraph(int c); +int ispunct(int c); +int isxdigit(int c); +int iscntrl(int c); +int isblank(int c); +int toupper(int c); +int tolower(int c); + +#endif diff --git a/usr/sysroot/usr/include/dirent.h b/usr/sysroot/usr/include/dirent.h new file mode 100644 index 0000000..4c3aba0 --- /dev/null +++ b/usr/sysroot/usr/include/dirent.h @@ -0,0 +1,30 @@ +#ifndef _DIRENT_H +#define _DIRENT_H + +#include + +#define DT_UNKNOWN 0 +#define DT_FILE 0 +#define DT_REG 0 +#define DT_DIR 1 +#define DT_CHR 2 +#define DT_BLK 3 +#define DT_LNK 4 +#define DT_PIPE 5 +#define DT_FIFO 5 + +struct dirent { + ino_t d_ino; + uint8_t d_type; + char d_name[256]; +}; + +typedef struct __cervus_DIR DIR; + +DIR *opendir(const char *path); +struct dirent *readdir(DIR *dirp); +int closedir(DIR *dirp); +void rewinddir(DIR *dirp); +int dirfd(DIR *dirp); + +#endif diff --git a/usr/sysroot/usr/include/errno.h b/usr/sysroot/usr/include/errno.h new file mode 100644 index 0000000..be05090 --- /dev/null +++ b/usr/sysroot/usr/include/errno.h @@ -0,0 +1,45 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +extern int __cervus_errno; +#define errno __cervus_errno + +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define ENAMETOOLONG 36 +#define ENOSYS 38 +#define ENOTEMPTY 39 +#define ELOOP 40 +#define EOVERFLOW 75 + +#endif diff --git a/usr/sysroot/usr/include/fcntl.h b/usr/sysroot/usr/include/fcntl.h new file mode 100644 index 0000000..d56082b --- /dev/null +++ b/usr/sysroot/usr/include/fcntl.h @@ -0,0 +1,27 @@ +#ifndef _FCNTL_H +#define _FCNTL_H + +#include + +#define O_RDONLY 0x000 +#define O_WRONLY 0x001 +#define O_RDWR 0x002 +#define O_ACCMODE 0x003 +#define O_CREAT 0x040 +#define O_TRUNC 0x200 +#define O_APPEND 0x400 +#define O_NONBLOCK 0x800 +#define O_DIRECTORY 0x10000 +#define O_CLOEXEC 0x80000 + +#define F_GETFD 1 +#define F_SETFD 2 +#define F_GETFL 3 +#define F_SETFL 4 +#define FD_CLOEXEC 1 + +int open(const char *path, int flags, ...); +int fcntl(int fd, int cmd, ...); +int creat(const char *path, mode_t mode); + +#endif diff --git a/usr/sysroot/usr/include/inttypes.h b/usr/sysroot/usr/include/inttypes.h new file mode 100644 index 0000000..a4d450d --- /dev/null +++ b/usr/sysroot/usr/include/inttypes.h @@ -0,0 +1,76 @@ +#ifndef _INTTYPES_H +#define _INTTYPES_H + +#include + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 "ld" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 "lu" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 "lx" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 "lX" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 "li" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 "lo" + +#define PRIdMAX "ld" +#define PRIuMAX "lu" +#define PRIxMAX "lx" +#define PRIiMAX "li" + +#define PRIdPTR "ld" +#define PRIuPTR "lu" +#define PRIxPTR "lx" + +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 "ld" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 "lu" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 "lx" + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +static inline intmax_t imaxabs(intmax_t j) { + return j < 0 ? -j : j; +} + +static inline imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom) { + imaxdiv_t r; + r.quot = numer / denom; + r.rem = numer % denom; + return r; +} + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/limits.h b/usr/sysroot/usr/include/limits.h new file mode 100644 index 0000000..a216445 --- /dev/null +++ b/usr/sysroot/usr/include/limits.h @@ -0,0 +1,30 @@ +#ifndef _LIMITS_H +#define _LIMITS_H + +#define CHAR_BIT 8 +#define SCHAR_MIN (-128) +#define SCHAR_MAX (127) +#define UCHAR_MAX (255) +#define CHAR_MIN SCHAR_MIN +#define CHAR_MAX SCHAR_MAX + +#define SHRT_MIN (-32768) +#define SHRT_MAX (32767) +#define USHRT_MAX (65535) + +#define INT_MIN (-2147483647 - 1) +#define INT_MAX (2147483647) +#define UINT_MAX (4294967295u) + +#define LONG_MIN (-9223372036854775807L - 1) +#define LONG_MAX (9223372036854775807L) +#define ULONG_MAX (18446744073709551615UL) + +#define LLONG_MIN LONG_MIN +#define LLONG_MAX LONG_MAX +#define ULLONG_MAX ULONG_MAX + +#define PATH_MAX 512 +#define NAME_MAX 255 + +#endif diff --git a/usr/sysroot/usr/include/math.h b/usr/sysroot/usr/include/math.h new file mode 100644 index 0000000..0a649c9 --- /dev/null +++ b/usr/sysroot/usr/include/math.h @@ -0,0 +1,77 @@ +#ifndef _MATH_H +#define _MATH_H + +#include + +#define INFINITY (1.0/0.0) +#define NAN (0.0/0.0) + +int abs(int x); +double fabs(double x); +double pow(double base, double exp); +double pow10(int n); +int isinf(double x); +int isnan(double x); + +static inline double ldexp(double x, int exp) { + union { double d; uint64_t u; } v; + v.d = x; + int e = (int)((v.u >> 52) & 0x7FF); + if (e == 0 || e == 0x7FF) + return x; + e += exp; + if (e <= 0) + return 0.0; + if (e >= 0x7FF) + return INFINITY; + v.u = (v.u & ~((uint64_t)0x7FF << 52)) | ((uint64_t)e << 52); + return v.d; +} + +static inline double floor(double x) { + int64_t i = (int64_t)x; + return (double)(i - (x < (double)i)); +} + +static inline double ceil(double x) { + int64_t i = (int64_t)x; + return (double)(i + (x > (double)i)); +} + +static inline double round(double x) { + return (x >= 0.0) ? floor(x + 0.5) : ceil(x - 0.5); +} + +static inline double sqrt(double x) { + double result; + asm volatile ("sqrtsd %1, %0" : "=x"(result) : "x"(x)); + return result; +} + +static inline float sqrtf(float x) { + float result; + asm volatile ("sqrtss %1, %0" : "=x"(result) : "x"(x)); + return result; +} + +static inline double log2(double x) { + double result; + asm volatile ( + "fld1\n\t" + "fld %1\n\t" + "fyl2x\n\t" + "fstp %0\n\t" + : "=m"(result) : "m"(x) + ); + return result; +} + +#define MIN(a, b) ({ __typeof__(a) _a = (a); __typeof__(b) _b = (b); _a < _b ? _a : _b; }) +#define MAX(a, b) ({ __typeof__(a) _a = (a); __typeof__(b) _b = (b); _a > _b ? _a : _b; }) + +#define ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1)) +#define ALIGN_DOWN(x, align) ((x) & ~((align) - 1)) + +#define IS_POWER_OF_TWO(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/setjmp.h b/usr/sysroot/usr/include/setjmp.h new file mode 100644 index 0000000..1585cb3 --- /dev/null +++ b/usr/sysroot/usr/include/setjmp.h @@ -0,0 +1,13 @@ +#ifndef _SETJMP_H +#define _SETJMP_H + +typedef long jmp_buf[8]; + +int setjmp(jmp_buf env); +void longjmp(jmp_buf env, int val) __attribute__((noreturn)); + +#define sigjmp_buf jmp_buf +#define sigsetjmp(env, savesigs) setjmp(env) +#define siglongjmp(env, val) longjmp(env, val) + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/signal.h b/usr/sysroot/usr/include/signal.h new file mode 100644 index 0000000..7d4eb1f --- /dev/null +++ b/usr/sysroot/usr/include/signal.h @@ -0,0 +1,169 @@ +#ifndef _SIGNAL_H +#define _SIGNAL_H + +#include +#include +#include + +typedef int sig_atomic_t; + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT SIGABRT +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGWINCH 28 + +#define NSIG 32 + +typedef void (*sighandler_t)(int); + +#define SIG_DFL ((sighandler_t)0) +#define SIG_IGN ((sighandler_t)1) +#define SIG_ERR ((sighandler_t)-1) + +#define SA_NOCLDSTOP 0x00000001 +#define SA_NOCLDWAIT 0x00000002 +#define SA_SIGINFO 0x00000004 +#define SA_ONSTACK 0x08000000 +#define SA_RESTART 0x10000000 +#define SA_NODEFER 0x40000000 +#define SA_RESETHAND 0x80000000 + +#define SI_USER 0 +#define SI_KERNEL 0x80 +#define SI_QUEUE -1 +#define SI_TIMER -2 +#define SI_MESGQ -3 +#define SI_ASYNCIO -4 +#define SI_SIGIO -5 +#define SI_TKILL -6 + +#define FPE_INTDIV 1 +#define FPE_INTOVF 2 +#define FPE_FLTDIV 3 +#define FPE_FLTOVF 4 +#define FPE_FLTUND 5 +#define FPE_FLTRES 6 +#define FPE_FLTINV 7 +#define FPE_FLTSUB 8 + +#define ILL_ILLOPC 1 +#define ILL_ILLOPN 2 +#define ILL_ILLADR 3 +#define ILL_ILLTRP 4 +#define ILL_PRVOPC 5 +#define ILL_PRVREG 6 +#define ILL_COPROC 7 +#define ILL_BADSTK 8 + +#define SEGV_MAPERR 1 +#define SEGV_ACCERR 2 + +#define BUS_ADRALN 1 +#define BUS_ADRERR 2 +#define BUS_OBJERR 3 + +typedef struct { + unsigned long __bits[2]; +} sigset_t; + +union sigval { + int sival_int; + void *sival_ptr; +}; + +typedef struct { + int si_signo; + int si_errno; + int si_code; + union { + struct { + pid_t si_pid; + uid_t si_uid; + } _kill; + struct { + int si_tid; + int si_overrun; + union sigval si_sigval; + } _timer; + struct { + pid_t si_pid; + uid_t si_uid; + union sigval si_sigval; + } _rt; + struct { + pid_t si_pid; + uid_t si_uid; + int si_status; + } _sigchld; + struct { + void *si_addr; + } _sigfault; + struct { + long si_band; + int si_fd; + } _sigpoll; + } _sifields; +} siginfo_t; + +#define si_pid _sifields._kill.si_pid +#define si_uid _sifields._kill.si_uid +#define si_status _sifields._sigchld.si_status +#define si_addr _sifields._sigfault.si_addr +#define si_band _sifields._sigpoll.si_band +#define si_fd _sifields._sigpoll.si_fd + +typedef struct { + void *ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +struct sigaction { + union { + sighandler_t sa_handler; + void (*sa_sigaction)(int, siginfo_t *, void *); + }; + sigset_t sa_mask; + int sa_flags; + void (*sa_restorer)(void); +}; + +sighandler_t signal(int signum, sighandler_t handler); +int raise(int sig); + +int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact); +int sigemptyset(sigset_t *set); +int sigfillset(sigset_t *set); +int sigaddset(sigset_t *set, int sig); +int sigdelset(sigset_t *set, int sig); +int sigismember(const sigset_t *set, int sig); +int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); +int sigaltstack(const stack_t *ss, stack_t *oss); + +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/stdarg.h b/usr/sysroot/usr/include/stdarg.h new file mode 100644 index 0000000..92c990c --- /dev/null +++ b/usr/sysroot/usr/include/stdarg.h @@ -0,0 +1,11 @@ +#ifndef _STDARG_H +#define _STDARG_H + +typedef __builtin_va_list va_list; + +#define va_start(ap, last) __builtin_va_start(ap, last) +#define va_arg(ap, t) __builtin_va_arg(ap, t) +#define va_end(ap) __builtin_va_end(ap) +#define va_copy(d, s) __builtin_va_copy(d, s) + +#endif diff --git a/usr/sysroot/usr/include/stdbool.h b/usr/sysroot/usr/include/stdbool.h new file mode 100644 index 0000000..848dd60 --- /dev/null +++ b/usr/sysroot/usr/include/stdbool.h @@ -0,0 +1,9 @@ +#ifndef _STDBOOL_H +#define _STDBOOL_H +#ifndef __cplusplus +#define bool _Bool +#define true 1 +#define false 0 +#endif +#define __bool_true_false_are_defined 1 +#endif diff --git a/usr/sysroot/usr/include/stddef.h b/usr/sysroot/usr/include/stddef.h new file mode 100644 index 0000000..3e4cdab --- /dev/null +++ b/usr/sysroot/usr/include/stddef.h @@ -0,0 +1,15 @@ +#ifndef _STDDEF_H +#define _STDDEF_H + +#ifndef NULL +#define NULL ((void*)0) +#endif + +typedef unsigned long size_t; +typedef long ssize_t; +typedef long ptrdiff_t; +typedef int wchar_t; + +#define offsetof(t, m) __builtin_offsetof(t, m) + +#endif diff --git a/usr/sysroot/usr/include/stdint.h b/usr/sysroot/usr/include/stdint.h new file mode 100644 index 0000000..5256dfe --- /dev/null +++ b/usr/sysroot/usr/include/stdint.h @@ -0,0 +1,48 @@ +#ifndef _STDINT_H +#define _STDINT_H + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef long int64_t; +typedef unsigned long uint64_t; + +typedef long intptr_t; +typedef unsigned long uintptr_t; + +typedef long intmax_t; +typedef unsigned long uintmax_t; + +#define INT8_MIN (-128) +#define INT8_MAX (127) +#define INT16_MIN (-32768) +#define INT16_MAX (32767) +#define INT32_MIN (-2147483647 - 1) +#define INT32_MAX (2147483647) +#define INT64_MIN (-9223372036854775807L - 1) +#define INT64_MAX (9223372036854775807L) + +#define UINT8_MAX (0xFFu) +#define UINT16_MAX (0xFFFFu) +#define UINT32_MAX (0xFFFFFFFFu) +#define UINT64_MAX (0xFFFFFFFFFFFFFFFFUL) + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX + +#define SIZE_MAX UINT64_MAX + +#define INT8_C(v) v +#define INT16_C(v) v +#define INT32_C(v) v +#define INT64_C(v) v ## L +#define UINT8_C(v) v ## u +#define UINT16_C(v) v ## u +#define UINT32_C(v) v ## u +#define UINT64_C(v) v ## UL + +#endif diff --git a/usr/sysroot/usr/include/stdio.h b/usr/sysroot/usr/include/stdio.h new file mode 100644 index 0000000..be0a90c --- /dev/null +++ b/usr/sysroot/usr/include/stdio.h @@ -0,0 +1,66 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#include +#include + +#define EOF (-1) + +#define BUFSIZ 1024 + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +typedef struct __cervus_FILE FILE; + +extern FILE *stdin; +extern FILE *stdout; +extern FILE *stderr; + +int putchar(int c); +int getchar(void); +int puts(const char *s); +int fputs(const char *s, FILE *stream); +int fputc(int c, FILE *stream); +int fgetc(FILE *stream); +char *fgets(char *s, int n, FILE *stream); +int ungetc(int c, FILE *stream); + +int printf(const char *fmt, ...); +int fprintf(FILE *stream, const char *fmt, ...); +int sprintf(char *buf, const char *fmt, ...); +int snprintf(char *buf, size_t sz, const char *fmt, ...); +int vsprintf(char *buf, const char *fmt, va_list ap); +int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap); +int vfprintf(FILE *stream, const char *fmt, va_list ap); +int vprintf(const char *fmt, va_list ap); +int sscanf(const char *str, const char *fmt, ...); +int vsscanf(const char *str, const char *fmt, va_list ap); +int fscanf(FILE *stream, const char *fmt, ...); +int scanf(const char *fmt, ...); + +FILE *fopen(const char *path, const char *mode); +FILE *fdopen(int fd, const char *mode); +FILE *tmpfile(void); +int fclose(FILE *stream); +size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream); +size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream); +int fflush(FILE *stream); +int fseek(FILE *stream, long off, int whence); +long ftell(FILE *stream); +void rewind(FILE *stream); +int feof(FILE *stream); +int ferror(FILE *stream); +void clearerr(FILE *stream); +int fileno(FILE *stream); + +FILE *popen(const char *cmd, const char *type); +int pclose(FILE *stream); + +void perror(const char *msg); +int rename(const char *oldp, const char *newp); +int remove(const char *path); +char *tmpnam(char *buf); + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/stdlib.h b/usr/sysroot/usr/include/stdlib.h new file mode 100644 index 0000000..eb86b54 --- /dev/null +++ b/usr/sysroot/usr/include/stdlib.h @@ -0,0 +1,76 @@ +#ifndef _STDLIB_H +#define _STDLIB_H + +#include + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + +#define RAND_MAX 0x7FFFFFFF + +void *malloc(size_t n); +void *calloc(size_t nmemb, size_t size); +void *realloc(void *p, size_t n); +void free(void *p); + +void exit(int status) __attribute__((noreturn)); +void abort(void) __attribute__((noreturn)); +int atexit(void (*fn)(void)); + +int atoi(const char *s); +long atol(const char *s); +long long atoll(const char *s); +long strtol(const char *s, char **end, int base); +unsigned long strtoul(const char *s, char **end, int base); +long long strtoll(const char *s, char **end, int base); +unsigned long long strtoull(const char *s, char **end, int base); + +#include +uint64_t __cervus_strtod_bits(const char *s, char **endptr); + +static __inline__ double strtod(const char *s, char **endp) +{ + uint64_t b = __cervus_strtod_bits(s, endp); + double d; + __builtin_memcpy(&d, &b, sizeof(d)); + return d; +} + +static __inline__ float strtof(const char *s, char **endp) +{ + return (float)strtod(s, endp); +} + +static __inline__ long double strtold(const char *s, char **endp) +{ + return (long double)strtod(s, endp); +} + +static __inline__ double atof(const char *s) +{ + return strtod(s, (char **)0); +} + +int abs(int x); +long labs(long x); +long long llabs(long long x); + +int rand(void); +void srand(unsigned int seed); + +char *getenv(const char *name); +int putenv(char *str); +int setenv(const char *name, const char *value, int overwrite); +int unsetenv(const char *name); + +void qsort(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, const void *)); +void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, + int (*cmp)(const void *, const void *)); + +int system(const char *cmd); + +int mkstemp(char *template); +char *mkdtemp(char *template); +char *realpath(const char *path, char *resolved); + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/string.h b/usr/sysroot/usr/include/string.h new file mode 100644 index 0000000..61a1d27 --- /dev/null +++ b/usr/sysroot/usr/include/string.h @@ -0,0 +1,36 @@ +#ifndef _STRING_H +#define _STRING_H + +#include + +void *memset(void *dst, int c, size_t n); +void *memcpy(void *dst, const void *src, size_t n); +void *memmove(void *dst, const void *src, size_t n); +int memcmp(const void *a, const void *b, size_t n); +void *memchr(const void *s, int c, size_t n); +void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen); + +size_t strlen(const char *s); +size_t strnlen(const char *s, size_t max); +int strcmp(const char *a, const char *b); +int strncmp(const char *a, const char *b, size_t n); +int strcasecmp(const char *a, const char *b); +int strncasecmp(const char *a, const char *b, size_t n); +char *strcpy(char *dst, const char *src); +char *strncpy(char *dst, const char *src, size_t n); +char *strcat(char *dst, const char *src); +char *strncat(char *dst, const char *src, size_t n); +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); +char *strstr(const char *hay, const char *needle); +char *strdup(const char *s); +char *strndup(const char *s, size_t n); +size_t strspn(const char *s, const char *accept); +size_t strcspn(const char *s, const char *reject); +char *strpbrk(const char *s, const char *accept); +char *strtok(char *str, const char *delim); +char *strtok_r(char *str, const char *delim, char **saveptr); +char *strerror(int errnum); +char *strsignal(int sig); + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/sys/cervus.h b/usr/sysroot/usr/include/sys/cervus.h new file mode 100644 index 0000000..edd1337 --- /dev/null +++ b/usr/sysroot/usr/include/sys/cervus.h @@ -0,0 +1,140 @@ +#ifndef _SYS_CERVUS_H +#define _SYS_CERVUS_H + +#include +#include +#include + +#define CAP_IOPORT (1ULL << 0) +#define CAP_RAWMEM (1ULL << 1) +#define CAP_KILL_ANY (1ULL << 4) +#define CAP_SET_PRIO (1ULL << 5) +#define CAP_TASK_SPAWN (1ULL << 6) +#define CAP_TASK_INFO (1ULL << 7) +#define CAP_MMAP_EXEC (1ULL << 8) +#define CAP_SETUID (1ULL << 17) +#define CAP_DBG_SERIAL (1ULL << 20) + +typedef struct __attribute__((packed)) { + uint8_t boot_flag; + uint8_t type; + uint32_t lba_start; + uint32_t sector_count; +} cervus_mbr_part_t; + +typedef struct __attribute__((packed)) { + char disk_name[32]; + char part_name[32]; + uint32_t part_num; + uint8_t type; + uint8_t bootable; + uint64_t lba_start; + uint64_t sector_count; + uint64_t size_bytes; +} cervus_part_info_t; + +typedef struct { + char name[32]; + uint64_t sectors; + uint64_t size_bytes; + char model[41]; + uint8_t present; + uint8_t _pad[6]; +} cervus_disk_info_t; + +typedef struct { + uint32_t pid, ppid, uid, gid; + uint64_t capabilities; + char name[32]; + uint32_t state; + uint32_t priority; + uint64_t total_runtime_ns; +} cervus_task_info_t; + +typedef struct { + uint64_t total_bytes; + uint64_t free_bytes; + uint64_t used_bytes; + uint64_t usable_bytes; + uint64_t page_size; +} cervus_meminfo_t; + +typedef struct { + int64_t tv_sec; + int64_t tv_nsec; +} cervus_timespec_t; + +typedef struct { + char path[512]; + char device[32]; + char fstype[16]; + uint32_t flags; +} cervus_mount_info_t; + +typedef struct { + uint64_t f_bsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + uint32_t f_flag; + uint32_t f_namemax; +} cervus_statvfs_t; + +#define CLOCK_REALTIME 0 +#define CLOCK_MONOTONIC 1 + +#define WNOHANG 0x1 +#define WEXITSTATUS(s) (((s) >> 8) & 0xFF) +#define WIFEXITED(s) (((s) & 0x7F) == 0) + +int cervus_task_info(pid_t pid, cervus_task_info_t *out); +int cervus_task_kill(pid_t pid); +uint64_t cervus_cap_get(void); +int cervus_cap_drop(uint64_t mask); + +int cervus_meminfo(cervus_meminfo_t *out); +uint64_t cervus_uptime_ns(void); +int cervus_clock_gettime(int id, cervus_timespec_t *ts); +int cervus_nanosleep(uint64_t ns); + +int cervus_shutdown(void); +int cervus_reboot(void); + +int cervus_disk_info(int index, cervus_disk_info_t *out); +int cervus_disk_mount(const char *dev, const char *path); +int cervus_disk_umount(const char *path); +int cervus_disk_format(const char *dev, const char *label); +int cervus_disk_mkfs_fat32(const char *dev, const char *label); +int cervus_disk_partition(const char *dev, const cervus_mbr_part_t *specs, uint64_t n); +int cervus_disk_read_raw(const char *dev, uint64_t lba, uint64_t count, void *buf); +int cervus_disk_write_raw(const char *dev, uint64_t lba, uint64_t count, const void *buf); +long cervus_disk_list_parts(cervus_part_info_t *out, int max); +long cervus_disk_bios_install(const char *disk, const void *sys_data, uint32_t sys_size); + +long cervus_list_mounts(cervus_mount_info_t *out, int max); +long cervus_statvfs(const char *path, cervus_statvfs_t *out); + +uint32_t cervus_ioport_read(uint16_t port, int width); +int cervus_ioport_write(uint16_t port, int width, uint32_t val); + +#define PROT_NONE 0x0 +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define MAP_PRIVATE 0x02 +#define MAP_ANONYMOUS 0x20 +#define MAP_FIXED 0x10 +#define MAP_FAILED ((void *)-1) + +void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off); +int munmap(void *addr, size_t len); + +pid_t waitpid(pid_t pid, int *status, int options); +pid_t wait(int *status); + +ssize_t cervus_dbg_print(const char *buf, size_t n); + +#endif diff --git a/usr/sysroot/usr/include/sys/ioctl.h b/usr/sysroot/usr/include/sys/ioctl.h new file mode 100644 index 0000000..416be0e --- /dev/null +++ b/usr/sysroot/usr/include/sys/ioctl.h @@ -0,0 +1,29 @@ +#ifndef _SYS_IOCTL_H +#define _SYS_IOCTL_H + +#include +#include + +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCGPTN 0x80045430 +#define TIOCSPTLCK 0x40045431 + +#define FIOCLEX 0x5451 +#define FIONCLEX 0x5450 +#define FIONREAD 0x541B +#define FIONBIO 0x5421 +#define FIOASYNC 0x5452 + +struct winsize { + uint16_t ws_row; + uint16_t ws_col; + uint16_t ws_xpixel; + uint16_t ws_ypixel; +}; + +int ioctl(int fd, unsigned long request, ...); + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/sys/mman.h b/usr/sysroot/usr/include/sys/mman.h new file mode 100644 index 0000000..f653977 --- /dev/null +++ b/usr/sysroot/usr/include/sys/mman.h @@ -0,0 +1,24 @@ +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H + +#include +#include + +#define PROT_NONE 0x0 +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_ANON MAP_ANONYMOUS + +#define MAP_FAILED ((void *)-1) + +void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off); +int munmap(void *addr, size_t len); +int mprotect(void *addr, size_t len, int prot); + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/sys/stat.h b/usr/sysroot/usr/include/sys/stat.h new file mode 100644 index 0000000..6b898f1 --- /dev/null +++ b/usr/sysroot/usr/include/sys/stat.h @@ -0,0 +1,50 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include + +#define S_IFMT 0170000 +#define S_IFREG 0100000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFBLK 0060000 +#define S_IFIFO 0010000 +#define S_IFLNK 0120000 +#define S_IFSOCK 0140000 + +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) + +#define S_IRWXU 00700 +#define S_IRUSR 00400 +#define S_IWUSR 00200 +#define S_IXUSR 00100 +#define S_IRWXG 00070 +#define S_IRGRP 00040 +#define S_IWGRP 00020 +#define S_IXGRP 00010 +#define S_IRWXO 00007 +#define S_IROTH 00004 +#define S_IWOTH 00002 +#define S_IXOTH 00001 + +struct stat { + ino_t st_ino; + uint32_t st_type; + mode_t st_mode; + uid_t st_uid; + gid_t st_gid; + off_t st_size; + blkcnt_t st_blocks; +}; + +int stat(const char *path, struct stat *out); +int fstat(int fd, struct stat *out); +int mkdir(const char *path, mode_t mode); +int chmod(const char *path, mode_t mode); + +#endif diff --git a/usr/sysroot/usr/include/sys/syscall.h b/usr/sysroot/usr/include/sys/syscall.h new file mode 100644 index 0000000..d6adff0 --- /dev/null +++ b/usr/sysroot/usr/include/sys/syscall.h @@ -0,0 +1,98 @@ +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#include + +#define SYS_EXIT 0 +#define SYS_EXIT_GROUP 1 +#define SYS_GETPID 2 +#define SYS_GETPPID 3 +#define SYS_FORK 4 +#define SYS_WAIT 5 +#define SYS_YIELD 6 +#define SYS_GETUID 7 +#define SYS_GETGID 8 +#define SYS_SETUID 9 +#define SYS_SETGID 10 +#define SYS_CAP_GET 11 +#define SYS_CAP_DROP 12 +#define SYS_TASK_INFO 13 +#define SYS_EXECVE 14 + +#define SYS_READ 20 +#define SYS_WRITE 21 +#define SYS_OPEN 22 +#define SYS_CLOSE 23 +#define SYS_SEEK 24 +#define SYS_STAT 25 +#define SYS_FSTAT 26 +#define SYS_IOCTL 27 +#define SYS_DUP 28 +#define SYS_DUP2 29 +#define SYS_PIPE 30 +#define SYS_FCNTL 31 +#define SYS_READDIR 32 + +#define SYS_MMAP 40 +#define SYS_MUNMAP 41 +#define SYS_MPROTECT 42 +#define SYS_BRK 43 + +#define SYS_CLOCK_GET 60 +#define SYS_SLEEP_NS 61 +#define SYS_UPTIME 62 +#define SYS_MEMINFO 63 + +#define SYS_FUTEX_WAIT 80 +#define SYS_FUTEX_WAKE 81 + +#define SYS_DBG_PRINT 512 +#define SYS_TASK_KILL 515 +#define SYS_IOPORT_READ 521 +#define SYS_IOPORT_WRITE 522 +#define SYS_SHUTDOWN 523 +#define SYS_REBOOT 524 + +#define SYS_DISK_MOUNT 530 +#define SYS_DISK_UMOUNT 531 +#define SYS_DISK_FORMAT 532 +#define SYS_DISK_INFO 533 +#define SYS_UNLINK 534 +#define SYS_RMDIR 535 +#define SYS_MKDIR 536 +#define SYS_RENAME 537 + +#define SYS_DISK_READ_RAW 540 +#define SYS_DISK_WRITE_RAW 541 +#define SYS_DISK_PARTITION 542 +#define SYS_DISK_MKFS_FAT32 543 +#define SYS_DISK_LIST_PARTS 544 +#define SYS_DISK_BIOS_INSTALL 545 + +#define SYS_LIST_MOUNTS 546 +#define SYS_STATVFS 547 + +static inline int64_t +__syscall6(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, + uint64_t a4, uint64_t a5, uint64_t a6) +{ + int64_t ret; + register uint64_t r10 asm("r10") = a4; + register uint64_t r8 asm("r8") = a5; + register uint64_t r9 asm("r9") = a6; + asm volatile ("syscall" + : "=a"(ret) + : "0"(nr), "D"(a1), "S"(a2), "d"(a3), "r"(r10), "r"(r8), "r"(r9) + : "rcx", "r11", "memory"); + return ret; +} + +#define syscall0(n) __syscall6((n), 0, 0, 0, 0, 0, 0) +#define syscall1(n,a) __syscall6((n), (uint64_t)(a), 0, 0, 0, 0, 0) +#define syscall2(n,a,b) __syscall6((n), (uint64_t)(a), (uint64_t)(b), 0, 0, 0, 0) +#define syscall3(n,a,b,c) __syscall6((n), (uint64_t)(a), (uint64_t)(b), (uint64_t)(c), 0, 0, 0) +#define syscall4(n,a,b,c,d) __syscall6((n), (uint64_t)(a), (uint64_t)(b), (uint64_t)(c), (uint64_t)(d), 0, 0) +#define syscall5(n,a,b,c,d,e) __syscall6((n), (uint64_t)(a), (uint64_t)(b), (uint64_t)(c), (uint64_t)(d), (uint64_t)(e), 0) +#define syscall6(n,a,b,c,d,e,f) __syscall6((n), (uint64_t)(a), (uint64_t)(b), (uint64_t)(c), (uint64_t)(d), (uint64_t)(e), (uint64_t)(f)) + +#endif diff --git a/usr/sysroot/usr/include/sys/time.h b/usr/sysroot/usr/include/sys/time.h new file mode 100644 index 0000000..7e507ce --- /dev/null +++ b/usr/sysroot/usr/include/sys/time.h @@ -0,0 +1,19 @@ +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +#include +#include + +struct timeval { + time_t tv_sec; + long tv_usec; +}; + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +int gettimeofday(struct timeval *tv, struct timezone *tz); + +#endif diff --git a/usr/sysroot/usr/include/sys/types.h b/usr/sysroot/usr/include/sys/types.h new file mode 100644 index 0000000..dc1136a --- /dev/null +++ b/usr/sysroot/usr/include/sys/types.h @@ -0,0 +1,18 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#include +#include + +typedef int32_t pid_t; +typedef uint32_t uid_t; +typedef uint32_t gid_t; +typedef int64_t off_t; +typedef uint64_t ino_t; +typedef uint32_t mode_t; +typedef uint32_t dev_t; +typedef uint64_t blkcnt_t; +typedef uint64_t blksize_t; +typedef int64_t time_t; + +#endif diff --git a/usr/sysroot/usr/include/sys/ucontext.h b/usr/sysroot/usr/include/sys/ucontext.h new file mode 100644 index 0000000..c18a33c --- /dev/null +++ b/usr/sysroot/usr/include/sys/ucontext.h @@ -0,0 +1,67 @@ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H + +#include +#include + +typedef unsigned long greg_t; + +#define NGREG 23 + +typedef greg_t gregset_t[NGREG]; + +enum { + REG_R8 = 0, + REG_R9 = 1, + REG_R10 = 2, + REG_R11 = 3, + REG_R12 = 4, + REG_R13 = 5, + REG_R14 = 6, + REG_R15 = 7, + REG_RDI = 8, + REG_RSI = 9, + REG_RBP = 10, + REG_RBX = 11, + REG_RDX = 12, + REG_RAX = 13, + REG_RCX = 14, + REG_RSP = 15, + REG_RIP = 16, + REG_EFL = 17, + REG_CSGSFS = 18, + REG_ERR = 19, + REG_TRAPNO = 20, + REG_OLDMASK = 21, + REG_CR2 = 22, +}; + +typedef struct { + uint16_t cwd; + uint16_t swd; + uint16_t ftw; + uint16_t fop; + uint64_t rip; + uint64_t rdp; + uint32_t mxcsr; + uint32_t mxcr_mask; + uint32_t st_space[32]; + uint32_t xmm_space[64]; + uint32_t padding[24]; +} fpregset_t; + +typedef struct { + gregset_t gregs; + fpregset_t *fpregs; + uint64_t __reserved[8]; +} mcontext_t; + +typedef struct ucontext { + uint64_t uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + sigset_t uc_sigmask; +} ucontext_t; + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/sys/utsname.h b/usr/sysroot/usr/include/sys/utsname.h new file mode 100644 index 0000000..affde89 --- /dev/null +++ b/usr/sysroot/usr/include/sys/utsname.h @@ -0,0 +1,16 @@ +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H + +#define _UTSNAME_LENGTH 65 + +struct utsname { + char sysname[_UTSNAME_LENGTH]; + char nodename[_UTSNAME_LENGTH]; + char release[_UTSNAME_LENGTH]; + char version[_UTSNAME_LENGTH]; + char machine[_UTSNAME_LENGTH]; +}; + +int uname(struct utsname *buf); + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/sys/wait.h b/usr/sysroot/usr/include/sys/wait.h new file mode 100644 index 0000000..924a788 --- /dev/null +++ b/usr/sysroot/usr/include/sys/wait.h @@ -0,0 +1,19 @@ +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H + +#include + +#define WNOHANG 0x1 +#define WUNTRACED 0x2 + +#define WIFEXITED(s) (((s) & 0x7F) == 0) +#define WEXITSTATUS(s) (((s) >> 8) & 0xFF) +#define WIFSIGNALED(s) (((s) & 0x7F) != 0 && ((s) & 0x7F) != 0x7F) +#define WTERMSIG(s) ((s) & 0x7F) +#define WIFSTOPPED(s) (((s) & 0xFF) == 0x7F) +#define WSTOPSIG(s) (((s) >> 8) & 0xFF) + +pid_t wait(int *status); +pid_t waitpid(pid_t pid, int *status, int options); + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/termios.h b/usr/sysroot/usr/include/termios.h new file mode 100644 index 0000000..6839057 --- /dev/null +++ b/usr/sysroot/usr/include/termios.h @@ -0,0 +1,58 @@ +#ifndef _TERMIOS_H +#define _TERMIOS_H + +#include + +typedef unsigned int tcflag_t; +typedef unsigned char cc_t; +typedef unsigned int speed_t; + +#define NCCS 32 + +struct termios { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t c_cc[NCCS]; +}; + +#define BRKINT 0x0001 +#define ICRNL 0x0002 +#define INPCK 0x0004 +#define ISTRIP 0x0008 +#define IXON 0x0010 + +#define OPOST 0x0001 + +#define CS8 0x0030 + +#define ISIG 0x0001 +#define ICANON 0x0002 +#define ECHO 0x0008 +#define ECHOE 0x0010 +#define ECHOK 0x0020 +#define ECHONL 0x0040 +#define IEXTEN 0x0100 + +#define VMIN 6 +#define VTIME 5 +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 + +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 + +int tcgetattr(int fd, struct termios *t); +int tcsetattr(int fd, int optional_actions, const struct termios *t); + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/time.h b/usr/sysroot/usr/include/time.h new file mode 100644 index 0000000..a6fa584 --- /dev/null +++ b/usr/sysroot/usr/include/time.h @@ -0,0 +1,47 @@ +#ifndef _TIME_H +#define _TIME_H + +#include +#include + +typedef long clock_t; + +#define CLOCKS_PER_SEC 1000000L + +struct tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +struct timespec { + time_t tv_sec; + long tv_nsec; +}; + +time_t time(time_t *t); +clock_t clock(void); + +struct tm *localtime(const time_t *t); +struct tm *gmtime(const time_t *t); +time_t mktime(struct tm *tm); + +size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tm); +char *asctime(const struct tm *tm); +char *ctime(const time_t *t); + +int nanosleep(const struct timespec *req, struct timespec *rem); + +#define CLOCK_REALTIME 0 +#define CLOCK_MONOTONIC 1 +int clock_gettime(int clk, struct timespec *tp); + +static inline long difftime_l(time_t a, time_t b) { return (long)(a - b); } + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/include/unistd.h b/usr/sysroot/usr/include/unistd.h new file mode 100644 index 0000000..0716e18 --- /dev/null +++ b/usr/sysroot/usr/include/unistd.h @@ -0,0 +1,68 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#include +#include + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +#define F_OK 0 +#define X_OK 1 +#define W_OK 2 +#define R_OK 4 + +ssize_t read(int fd, void *buf, size_t n); +ssize_t write(int fd, const void *buf, size_t n); +int close(int fd); +off_t lseek(int fd, off_t off, int whence); +int dup(int fd); +int dup2(int oldfd, int newfd); +int pipe(int fds[2]); +int unlink(const char *path); +int rmdir(const char *path); +int access(const char *path, int mode); +int chdir(const char *path); +int fchdir(int fd); +char *getcwd(char *buf, size_t size); + +int symlink(const char *target, const char *linkpath); +ssize_t readlink(const char *path, char *buf, size_t bufsiz); + +pid_t getpid(void); +pid_t getppid(void); +uid_t getuid(void); +gid_t getgid(void); +int setuid(uid_t uid); +int setgid(gid_t gid); +pid_t fork(void); +int execve(const char *path, char *const argv[], char *const envp[]); +int execv(const char *path, char *const argv[]); +int execvp(const char *file, char *const argv[]); +void _exit(int status) __attribute__((noreturn)); + +unsigned int sleep(unsigned int sec); +int usleep(unsigned int usec); + +void *sbrk(intptr_t increment); +int brk(void *addr); + +void sched_yield_cervus(void); +int sched_yield(void); + +int isatty(int fd); +long pathconf(const char *path, int name); +long fpathconf(int fd, int name); + +extern char *optarg; +extern int optind; +extern int optopt; +extern int opterr; +int getopt(int argc, char *const argv[], const char *optstring); + +#endif \ No newline at end of file diff --git a/usr/sysroot/usr/share/cervus/README.sysroot b/usr/sysroot/usr/share/cervus/README.sysroot new file mode 100644 index 0000000..cfbef02 --- /dev/null +++ b/usr/sysroot/usr/share/cervus/README.sysroot @@ -0,0 +1 @@ +Hello from sysroot! diff --git a/wallpapers/cervus1024x768.png b/wallpapers/cervus1024x768.png new file mode 100644 index 0000000000000000000000000000000000000000..a96e0a3680d9be273308e585aa126dcfa22fc0f7 GIT binary patch literal 160768 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�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

-2IG)!uWhKM@DncvD`l(j&OFdk<%(G>|fem3{h# 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

dE3jHEdlFe%!aBj-eMcd}U6H^EY$ChtE+%&T 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

QKhQZpI(zU?t}2BZa@b&G>?G1~U3uR3 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 H?fd@$%8qve literal 0 HcmV?d00001 diff --git a/wallpapers/cervus1280x800.png b/wallpapers/cervus1280x800.png new file mode 100644 index 0000000000000000000000000000000000000000..62efb4c060365a2af17210ec501ad0274166e48d GIT binary patch literal 199710 zcmeEu2UnBZwst~Ss-l2&8*B?r2q0ZiP!SO69YiUKbVBF^QP3^LN^go%5~>&ip#=dE zr9%ikAW91%Ku7|Cz=yc^+2@>b@A&?}U1RW;B=1~n&GpP@mKE~kmWd(nLD7Q%0D$-U zwJWy)0QS90R%ro_z0-Lv!J54jFz~kFW#CB1`RKhHHjhijmjHmuWbSR(UmulryLQ_c z00@%-0N@V+0LI=+@Oc0Lst5oqx&QzgX#jw*UlztpYwrz?J4S|AcK6!>8~XU(D+m0p z*#-gt@+W`&0Yl#F2JgMd8FbzFD(3=^fFS2li$6jBdz}ETU%6xvGP*PY`#1}AC2!Gv z$=VI{I3Ctc#h_+l-KRJjOg3dQ#qbmN>2;~6Nm2@t2{aV#8L31C}fEP zD0bqHPrcu;>mxnP*bYbHc=)pRZg#q%b2-YUXA;sy5gVG@!dDH2H}+JlUHqm~Gn<`n zwl|#L4Lh8s2>km7kRSz={^#cS|J@|~pAG>3rvt$M>0pl){tpNLe;r`Ui%vAe)k#>W8GlzMK}* zfe7z^4(@*(zy<(p9IaYC)ZVGJwhCRFtjmTjegpq}fTKIt7FIXGw$`hmwBO_{BFv(< z=b@aH+M^f`6>?Yjp{;XC+jS?AB=T6LfBVx#hEaJmiKdF@~M9ZrSTp|D-`oN){DLe)(YlKv5@xeb4J+6>0~fLdb@M ztt^eDz|6+_)t{i%zGF?QsD`qpl{huR#tY2O1Bf$}1R?zz;@*Qk;{YxIV8v*$Osc+J zH#aOIJE-N1g3jhUyMUIp9{F$=QfSwt^U}mEwQ>Iz-ElvY2@EkM5iRK)*+dL~G_fxP z@cEG#U{A+U*Rvx=CJM=o6@1a33sQZznHhE$DC@R!_+`$eNbDpTCr57BOjOIYAKRIt zP1DMUx%Z!U8Lt5f002{|ofD=tJ%bB9B`;}NYsD|ogCF!$qdhi1WYmPMZN4OwIy#S0 zizb}QGNU3|&ZyPrmqqoPmT!%CEd7dDeoclAzISRmmC_VIeeu(`{AI4+;+%=CMP`am z7``BWs6?S_XJ<(e5=L8jom7$?2rD5p*84El5~b>0q0~_)u=d{Ldk|TjIS1dLk9Zia zph``yT+lgct@`CIDkUOx#96MP!k`J{pfR4$Xq`_Uv#d*=Xz-@ngYi!^b1G+Y{~k;k z8+=bz)2XE0uDZz(eDWXz=DUI9H7zb4sgloy`X`z!Eoj$jl<_A-H3UaQZ3Uux$|bmi zBcj{Mqr7`h0st-!2Y#vb^Z0Y}#p!joT<7-s#SQE1idvzj`y*;84J8J2k?ve|bcPR1 z3hAWEZ0_6Ba4yCxXkZqz>894ibf^4AenRP)Ul2<`&k#cUKfNpjx15Q0gw2P8XPdfo z?$Dyk`(iae)LHKKB{K>aOY_Tb>el&aQihCtLLIy#zm+O9Qol#$@+f@R3)S`-w&u_; z!$>IBSI}kDca@jS$e2cS9B?jwZCKJs&Ilj!!*}S*I5{+YeBD*9suq-+u`}+uJa2@W z;U3eeVP>Kz)g(ypQc2EueCdIGiHcFb;hUzhMo5k#_K}e-J3%wWVhYHMVzZ5*-I0)x zJ05(|HZAs;%0!S>aeiFkP>y4G_0q+X<&7#$C;#^9(OO7*rRMlH=Wl`4Z1BAcH}{|1 z ziSbg_b3uOXI6t3w{$zwJZUt^qx-dZ7`MfR*nL|i;kn6uD?Mnm9nEbLlMR&ff&Ck4I zbAy*mbvKT3?nZTm%#<``Q~7bsa0?GhVx2X;Odfolf)K;JGlHyl_N_*i8OSCKQGuGj z*)l;BD808RX*RHyH_`PwJzxr1lDcKc43&!}thJc#k#4FH?qJ-*O&MbJ?Vhn*-oMOOx*ul zd9wS;6Ew_;>|AKSUj(%lUoVB8121NpOQkbzQJ+i>G8R+%prz%rDkGhuNuF1qBEMmL z*7HZ9OJ$*TI!>B7wKJDAeJW%DzZ$ki@D~Whr}%Q37I@3gK9qsb@lP8s#vSyZb!x>KDNI?#JJsSQ(3Va5{%Bjao$@!QV@soRiJ5 z%fBa~hIt#O96sfD1L{EcHbA{eCn1)HsK(ajjzb_^rXl~ahCB^$5I*NNE_q90>#r3* zr?x-$ydlTh>0(a8?Rbak9U9fS^eWkQo%3l~Szk{kJ`{J|aik45IvaE^QAdN((pLvw z$8{4Gkni)GNb#UB%KTiuF>32)cuwV97s`W@Gq)Utj{Ixf*??bs3_$HnikT4nEWL*V z=Joj^eY!%KOHJv_HBsifQf&mL;h2Oqvm(==4s0`ag&UEatTSSb3=B8kwFrlqlpkXn zO!#k0peOwAPc#M-xqYKk|4Tfym&nJMh?R6gT9=11GlX%iVzO!`jUO3$!u$|KEXH5G z)TlGU;2FM5nTGU_P?sg;L! zU{ciDLACKfg^UWY!il+RI3Ji$;5J z7LCk<#Mgqfsv!nwYdq~4VtLZcyL6{iDoMwhv>;_@XtkT~yZ#w$A8zN=RSnt~k5vz3 zmEJQPp!>-8pT3TbwJAFb{jZI3EM7WiuPz-^D2nQ*$9Y)Ok2xx5S$HqU?-?R>1ksn$ zIBEek*VII5e30c!E{dA8NVO)Ah>uK;d8oqwBT~xRBWbw^Y~}133^ht!{{jxyHyoU=)*%QZh>Y2J zeO#mlLUZYFrLe*G`rv&0Q^Ah;?C2O|)7&bn=KChdV_{sOd&0?)z*x4;R?@0zz#Z}i zTPBu)-;Ur2D!5zT3+r)UGfq_DD9&`totJ;gBJcP1{NcMb75l=60@IS-ScZ z^7&J`ROTjTQ8rs^JCs`9f^jV>ukBd7 zZf|W9Y%1FM*n+`e@=+6ZE!y@t67D$DgMzR$M&-pBg33cdjLU{9bq1Lk1Gid~@{1%Yx9^?H`S867{{pWNO8PE5_@hcD#dO>% zpB`*xgrI-)*dri$u!&Sj-_Lwss9U1WD8BBkK`N+D3b(T1)N4VVu~Mm%p__R$=NCi%bQ~B! zw819V@tj*Xge~ysI=Z!{{boMTL56eYmORZLe^W-hpK*Sq43F~~}YQ&SpcTaRBl1iqtp3KNbfqnO-|IHbC=Qpqq z`W}pcATwENJ)2viOo;NBS!AXCn7!QcIm_(+<-SRnB)Y=_>%g?tDtu3^QP-F<854>g`H$h#s*ZY;OjIoDgSH9-$$JM7g-PYHI0`sqM_v&gwXFbiccF`^$gSFT6Uv#W_WQ4R%%so;i$SqTz_BBn8iy% zZpcXMN$~1SN~goxkllJqTdD#By2ZNRLBctp^d7B8scN~05LU7l>G4}Aw1K7}dFhui zYckwXXif5leHEGa<*pQe#>f?AhZ*}U|)1AjBBSf)EIg7gE8 z2&ey;2I4*qfe`K>6gio1cPu^;VLysX#3lK7hEo?LwX+=atK#`-FYRi4ro)AGs#C@* z*87YUP`dj%!PaD4*b8N_JD^JUJG9mj(B|M1;hW<2E&eTrna?)d>m$%=MbD z3r5v3>9acjZ<^KyZS4Q-Wr31 z5m&NB3*w}Ba4SRIq-LC1OQfB-_IpZZiK{n166_8u27hj(@8XFid_KXvNR2mDh;JB_ zHYm)4yzGo<=pyZa{I>_&UZxIyFtXB$*rb40BU7{@JF3KgL-(&ta>-Xg#1W+NhOsjL zwa*q8>Rm1>IdpQ%pSlv&ppB~v3&O4B30d>fk1adeeg!RysZUWX`m)Mre2BJGbzzom?~(VOU<@tn_$l~z?$JtiVeN&Ge?IW2l{n*!-l8!B_8Y)9@Y3v2$aB*FcsIrR2i zGINQhTg!YkMlKqYtb*c)@VK0d;qrtnl4#C|#TYW36#&G`(AX_gnpAj z$Z@x7Q7jL)QqCMXi9FgxP5}D|c1_TG-)La6yAabb`+@C6YW6r{@lA_6h8l6nle^KMAI&Zi3_`!AL6mj;J>XpPZ56Evq=b#u!*&C9PrOlAW)cjpf3u6k)L z?uEOmWlNT-nj_AinTL2&zO;3hzPZ>cGwPJBd0s5Va!xfc&0PEKQOlO6_V~A=I|c1j zk3B^HXpou3eTbJMG<=VO_LkLUMXubK`<*%cRl3|7DZ5&iQ$tBak-Wxy2(-S@z~*KA z@=n7dGO}t6S?kzG1JADwSyJ;Q9dJeOwCp2ijqW9m~2GG85u|sx4~|jb@hnX6Lkobb{XOgYOnVuL|?b0BX49G5y|d2 zu)Nrr66{VbiJE+ZJLWi4vMAP~pIMSFl>_bW%m@GUEz|J-sf7BGcTd5I;W+m@C-uww zosUZg?<~`j?>k%7DNLXO@T`a#2CSX0n_-)s966> zu6gRZ$2Y%bYl6vL zsLIa5xVkvp3ThW`ZBFuZf;u2I^27A_7pNeOCf5+}uHAu9-|XlJ3C4?-xRz?%@uten zY_Z%KhmBkbMtf$kRCS5uMk+run^U3aq!Vm#txKxnclmUQ|L-CBk%^7r%vlU+6Rop3 zw8z7{>jMUc_= znlDPtivzps`kGMFs-XnYoN=Q#;la)p51qiz=_vn&&vW+~w@bC%C#><>4Q2D3%;D9F z9_?8|AX$62Ox3AkwNfk@sab|;81oqUosQEue^)D{eWJ%m?e{0_(UD8l&f~P{(T2P9 zWLRXr24Z*q6L|iUPjT6jE&^knA7v(i@0CSxsv>hOdzQb%Ek^BuP&A4B)Y#%1<^$ql zSFvc)eXBr(FpmPs9~2Ssy;iWv9MbK?OtR!Jqk2fJCF<|A)%q0*?raQ}%4!#yXi{`vP$0rC+Yq4_-s!+$&a$2@)}-_EFy7a`8!Ru&gRl z87SgoGOZarGhaAyOJcMP;chX2JJW(`w9+oxvzXD|Pr;URFi*>9l)^?GAzO`;kCVK0 zXG%6WNEsYrs4#yW#Gp@`x0r)>h_l9>4KVL*^vSZx_2+h!6)N}gTJRhNxh&Z}L8%|m zu{LB5_3>*n7#SNsejp2@>VhNO+t0xozv}GUcZKf8L6`m14m8JHO2kJr`D}Oda{Fvc zq1?b*bJdY(p-xH1iggdreUZ57dQs*j2x3&RvlJZ4zxa7EN}|6ISu7M>4z_}5R*w#R zK;-m}B22v9En(h~`cPMHdou~uZCBHhy;=j5U~9CvV$Q$Cn3h6HHo0cR}N@OmV@JF;=e}AJ{i!~!w(uO%OD50E!&k)1k zcMNop*vT-asLCOH%QqJ#oCCF*0!+3h!Xv-06N+1Op&JicbSz#X3(7LIs;aXqNZw;n zrNO$Mc!|1P>xuW7jFaK}jE>#C{#TwG$UIlJJHJ;HEHy_*(yLJ*X7WI)aWn$+&2w!2 zDX!mS{_P@0l3;0>Jy3*jB$a_p!x0)_!pSCUT*;&}u72kO!ZNaIK~&O~SrlhTo0@LM zeST8Tn>zH}SDr~Zor^eWXxKDeWR1gw-w*lLYzot9I%_f>O5ZHpiOLSz>5$E-uNB(9 zyILn4*+3hwq~mFgAAFjE$7awC1;Nq5^txc?u+v{S;rg|2z^7gGBhlD>=7typjpDAba~#&8fv3&X+(bnAJ}5Sl0gk*s)_G7{rUl0NA)W;#KGj5%4>DGW2yw98SyxAB(vS@eFPx^oEa z6Zvh33Z=CBYOQ{@#^-cQkp)8(5V0Hu7ZD z#|3g$k3yZGQv_Y#L>px?9Q^&q0ekT3pYP}7!c7w0`PzA#tiyY9b?&WajZ!xpWyw2t zjdzD8<4t#;{ND9)iQeBI6nF8_o=@3C*XNZnx8%;D$8T#A(3Cg{>!FpBp^puicifn~ zj0t{*KPu1cDT2KVavg-rn6;{^izXBcp+06JZMT*=9WIQHmMtzvmXj^4(fPjCcvU4# zt=%Xi#bQ@$HRVZD$$L{9TE$Op$UwO2gxdhkZWm*$ptJ7Py^xAqb;b}g$zcxOA;izA zKHJocu=bLt?oQVE>@8JsReROWzS?{b{JL5JL5Z0tDxrdjQX%;KCr&rK^q+s4Z0*Ox+b?pU!w47Tl9XMOieIKX7LB9yYAUj@u zUsnpGhTNFRVyy-?0wE_RLh}hlV#o!sh2scA20@Hdpq6Ar4rlG^ghRc^TsPXAL05t9#pMP=-NvNNuayegv|`kc=5J0P))R4avcbmnO$LFCjd^_#1KoEo z-yTACq)*n~pM3R(O-=eRo}rcjJ)FVPH`aJJBt zG09a&GR!hH8W|B)8gK3FB1^*zP#-X;jv*_eM!}QC3RP8vyrfJW%5IW%%N80?XIO`D zUfO!Pi+E&g;k#I`I=G_w5-B4*=;)&!vN%N_d~T}CXg2IY_C(VL(A#4tvj-HOp3H@= zqmx6uBzDl5xnZr^;Gr{tK53NsjGb$Sw0zM?l`!Y0;INMQWBF~Ux%@ixQdHzbNUq#& z5R*#VPl@2nW?uN-R5**A>!%U%PE%9qg%QK^NT%9;;lP zo+8JP9gEMF>pRG2czJQL7>K1I3_OM~R7LVzA{m$P7KOAn1fP$GWva@^l|-F!Gw&jK zNgs)_l1*J(KjJopSQD6}JG()Jt}Ds%8)5Pc=8~LrH1Z1+L>j!;E&glR%yqQFZt^#03%opGEe^t0wh&8e z^e5}$S6&p@TS#1BTvxL=N1GU@JMS`^x_o^sO&3-zvqv)!DVBSM7Dq~56oD+|S!Ckl z1}k=L^INZY<317I-7}lzl&Mp{`O~noEWb=E_?r@cfXU44!`-J1TS;YzuX|tX8>df> zXHM#e#Xo%Z?4iKne!YyKtGBMST{u}?=}JyI8cybYUilVYl>e6HZ2x=Vh3r%7M=oFf zs@^P7>{ z6S=u62%rZVfCnQ$J*_@AmXgh;PNzlV5m#CdHOl$0ACWIDqXGg=9CUHM*$lolV*o? zy}UDKFtZf$MB-$ORXBUI_9<7mphFU{+AL9U<5@$&k&vFd>4wr%h0?ouc3*fq#4m9x5Kp7>Ml(b?k zwppv&E9|NnMxD4R8;`S{a$gJgRl9%q((#T(Z+{Zc&0A-?GF9(~aUft8!j|p&#HFE} z(u*!R?YWM69FbmZS?@**)1pVy$|WdEY5Z(42LPYHLmo7rdVc2<{0)z?5|*TewaFWd zxH}u0-{w(3ynSu>bz0gH?#)~(*Ea&k^@Z$nw^0|yn@T@E=$_HwkNY7}tWe;<(@5U1 z+AQPzKJv*%F}d$<+=Gh-2V&s|#9P>Jz7=k7_D{L^C37mIr}EQk&f1xM1@9jME))Z9 z?E~h=5wq8J3rz~#w2!2{!U4e3uHSEN73A{4SVk6Z@8`#JQzX0+u(Z32ENph>2KZJc zA7x#@-or}sz*wej#(A$CZq?Qk?ynK(JnEj_!M+;>{GRSGS ztiRi|$4Hk&iNC$1% zpSZR8KSCtn&tXsiaZ59}g@#7E-)|6I3?O!whx3YfBvyWotvx3DE#^d6-$C`xXy=@t z)ow~8B6|+s6+krLhUYXG+Xa>ZG!H&MaHKz1&*cn0&3~%C%Oj)b_%)}O4yjqds|{h% zHWA9LX|3}$o{3{kPv!4je2IzEpIb@Dz2Fl&<)M#ZZ{l>Xo{4C0aMAhBQNUvDQX}AJ zFLj9h-EDo?l($oXppAC=m*W*VbF4$>%Ky>%3E7ti0sCh9uBF2!8+ys$etSbB3GL(D zND5Y88Q6Kj9BAHhCpHe%Vgr}lL4Gp&UhIMURy=IpG#EXP>vy|90VO;iZw)0iCjtsu{<*Wt`^8U`IC1 zZh{>KbX3$=OEOf8tF!C;+-XIAbAyx5t{;OhxL*d`ESrFnbwf2i!mqjTPXTqX+9=vf3A0ySDdr#4qFR$ zFvCRVM(ELh=JgK&Nf=c9}xC z`=si&)3qAGei>L!>ZHVj9{yULQ+%CLo%!|d$zeyHT{?JFFBSz?sc8Htber#8dXD=E z#Rod;>{a9S-jeL?huhD#-}!0%FV}G8$KBh&ynXHp62JaAIbFa`%Ia_mM=1R#siW!G z3$=GUO7ClD9G4mCM1JoY!Qes?!w)9^(bzkOaF`?FZg#V|o)XrJqsWT5snN!RThjte~@wN1+z+jY9Za8>)Zq-litz&d)U*mpg&FIIZF?%|JzSEpcs*dCx%ER@eWT{DI`sLYXe zr|XlHP5S|HEPv~F7WWs|6ajOJ0-XvngBB0mie{3##iTDt7dTsFuATqKAY5O659Qvzsbu z`!Tww8R^n8N+sfjKQ$ZCt;xykkOp*>n&`FTuc&Y-J}@ABz*+FV+7yLf6a{b|^#q*AO)7l&dQ-+%_3iYL1?AofjZU;HEjC4$zAC%z`3rzLKfo1rkr8Nf*tog(KRBl z4gJFY26k!ksCF6Ij6W2=ZezAmHcM=>`=sqP(m~eyzSUuR8XA)quMgHwilK*3-qW?| zsYqgCl_2t4G0L7U3W~2zEyBSN891mt?6n~Fa)u`$ES*!_I(F>m2r-?n+qG<@TlTf@ zKP&$H<)y!gcv^+#S-(~z6~Z0TmT|C;+&(VFJo{?>Y_>&!{3$|;l3e7~_S(tPbg}Ph zz;C(EI}2-2zoMzBgjnsE)P_{MaJa|gLP0-JEg(Tj9uPLh8?sZTlU|DLURgF`8YfDG*^~k&*Icpd1+4g$h z-bq-dfSh+N@65K#w3fw~m}{KA>d2?lQ}-=WlI2{?>rT!KPkxF_-PN>@DIId&6yNB} z=yJ#Ag6m!Ww7m`zxSCeW8X<%s_-h{5lK!6a_~#V9z3Fpw-J0D0Xxmw{t+O8m&GSfU z=;3fK7G3U;(w}|IL@LO6dXzJR# zKDGy;83Hqa3rk(mth-NT^|}4rhFKE;s;n=uYY%GQH2`|AjIzUHwt4i_&OQPB*-;?i z*B`G{A(STXuE}=)07hnB^GkXb?E0j|AED(DJ|is|<-2DqliNV;?D`u$hf)oq_>%&~ z$r_Dp$|O6M0m7UnSK`5u zV_|$74byW(yyNEoZ0ja1`MfYGDPWgaW-6$Mb&hTB#+=FH#6Qm^aXl$(4ui_I(1 zG5+qUpe&-(Pe;bLHQS0EB8tCsf(IIn$aW&~JGg*s&9KHlY!b1sR#zZliY;%IEb3L| zcA8|*N`4<{KgA*alJ*JvgciR1fg8x}$u1ou5CJz^ml61KSH%^3nZgs>ydH$f=GVJ< zd;IP2{XaAsLQKf6THGJ z1_xMG9lqA0ui$bd{yH$Ml9%(=&6C>jJ6}aO-7E7uLpefn);nn>YV{X z5mI(^6>*{+VR!hpbnl{vBXFmQZBlZBCumE><5u^Tc{B46pXr(;7!&fRRc;kSc{p-) z`AK+vFQ)Y8I$OIB=IO$P(QLhU18eDPq*aP{{;4z zHhkt(9CDiB6cG|t6Zpb1!}7sD{g!kZMP2G~5JRI8zM^*0`DsbK6aEPKj~&(@oJW1m zhFqf1cP(wqH||Y)2}GHMK(B~xlmzm^vJVU?iO#b;eBp}$$ol!Qd7gYg!WvjnF7$p< zUFJ0D#q#SZ-n$E6mwA%o(ybOL{t}CxBx@1Wq+RyHL+sD5b^mDOOGn;cIoX0AxJ+Zw z+MLbsL(-DQ8t|hWeJB+6fcoT#(iXPqMA1dh6G2aVLeFho|8l)2abd^2y>_R;9M(CG zV?ib<(9iFRpDiEV`Z>vs-AWyLH6*EbfMUZYlfkaSDj6>55_?q|fa77G;vU6w-2cR= z<4cfWZQcMj+hnoB+wz0APfoR7Wfw5u+SC)gc!gDpB3#C1ZQA1rJNV9+9AS_leB;7b zCxz&v7+TksVqxy=>TcN|3w~LGPy)2-fkeS{ECAQem$GXn}Nk`i62A*bPp7slyV&mG9iE!R<`(L%v7_F~*s#>|d=K*bM(~@gt#Zlshpai+ovEU?*F{>LpEW8%UE4ca zM!$ky4qd^{E@V0pw1kqJ!?s6e24ak@5>WsV--hPf(gg5^eN3*f=leJ?_ReVtutXI} zl?rkJN@}Kzw(kJou15g!0l*fMw{W2cet^u?-lOWCG*LA+-UADgqFkFg>~!k2m{0ZJ z8`>g4$-BPnXbyh9bU^dVSm%Q|eC}^4m)bAt9j{#neDZQr5iqiji@C1)Xq@A2`kiIK z;+L7rdAgBbI0e7Dr?8$m(#sNYclm;Lvv$Aogz_;KH8w}d^{h4d|Ji>q?Spq~1LVZ{ zbo+_(sl8K#5L@$uHmNprdvq-I%yIE}y{4&iu~83vls^!eHqCfc(uDP4LzHoLH==i*7}l-Xw=fZ)O!3+fp!)|8F4BIh3b5i7Uni6hZ2lABq)?hgZN0>w{dy?m7w zB=FUcws5P9L2&KptS{;gvZe;=NqR_2pjC!U1=nQHaEL@Fp)!^WgCreSCa(%;T6! zVJO&Y=ih2cQAYpb7b13)HIr|W1>}pXza1`85`o0s;2?`eaIv))b~l>{pGrBMo2eyn z!$hH6KKfX{nujK4V!(fGg))9RS3!ag>0Vy%Zz-dqWkVp_$gg;O^O9qW82%KAHT3$KUtf{UDDvY$*yBbBn@bZ}yMdB?W<#2@@il#txJ*RC&JkYO5k&FwnwpgF{O z=Gk(DwWv8=SVc6HOw=ua5dscrTBIkU2NJKx&3c!yq)r|FnnmzvhF0U9>946 z;fq-2pVXejO>#&lb+y7#6D3nRTnHXXscoV4FQj9*Dv>|4-VYc}64gV8scS<8-svkd zU4*6$=856jpgD8Rfj4sbKi5-EV4FjS*rYStNRPtRMR-2GXoc#XJNXAowV$TRlv56H z%1gc~0}ho*@@)oRkj$yj^o}+ZqX0|1Lx65*$u_XOYuO!ctg?=C%pe!Wp&igZA*RE>n)#ywtRFjKsapf?} zpo=2bXWNS<=QJO8Nih#+#m-l68yC6n_lW9#3F1f&fSX~70bq2=nnY}=-8>98iD1Lp zX!ISJ|3-;m?PkLt!kb;|zQ)w}DLfxNgVp6*kB#w764AX|G)vVL+_G64-Y^lc5Ib^c z@Zd5|r%`7N&T0IimVI7dQVmEjyK3#C)~FtHzMIA6aO?^TeTN+wnV0F1D%{`g%_{v&69U1G_Ohgv-IkllWTgyp800sjnOP`jW03_R*$N z%s^23TEjxcV07Qbr%YGkqs+PcUNJ)zv$kE$Sf7GBa8Z*fHXY7J)+iP$7JI*5j=>pD zJu!cP%tLX&OCtdxfw*RtaL3vvkCEv-e^wt=F*Sj9tt^)dj|-0!fxg}3s8OJVj}fFk z=yqmi6XP1=Ie8>k&i}}E8thdzr)=p4IxkVuwuDyfXJB7^531`1xnIP`q`P__m%8Sn zX{)Dr=^?-;4wZXN9*z$DLO%tLcwboF8VjEipf04&2_NfpY z=#$c+@1JJQxz$}x_iY3H6nwKKtUcKs-Z=BaZNN)Ra@db2Mcgi{wuWCkKq5gy1z7*w zI~f(pGQ?TpdRmeDY1k+?fC)dTCy-|1lI3!CiNkk}4UpW+;?j*yj^Byx9(&3n7XWla z-2#XpyV(GI39FnC+0+1T#m>sMKAz((mu2IP<1XjERd{N3X<_o9VH@i+b(Ki>8@03a z@`xzf8Nbq-^6GW{{+e08(aMkC3#~J$X zdiKIfu-pU)HYZdR)yTjs+ISxDN%AxSOv)rg>an?Q#5_@q@4UN`J(Ed3#^>m}II0k+ z{>mz~$wrbVTkT%-GZ1C4r+w!`WCKDz_L2Rp^|p%O5c6a89VVY=MzmH_AA3ZPR7rsJ z6RU$UZ6Y6HPPqKxcT(VhgNY!ANaqE>pG9m_qqNsMoyT^kIw*Kc;7hnwo_JB)9mQVv z2iG`7Z>F5#7-+c<`qu29gY2RnJ$3gKTPuNsDa2n>w0mGa(!}=40=SFpTi|ZsQ$K;N5cwxcF!&2B(TH-55+EA0?m!vZy*sGF~(hpBK=*dL!04Rp% z55~L^Q3jTnId}$NT3O3`l?QlSdusOmeBE)4bE`?}`Kto|fNfLmUuC9xRvlaeV#d`v znY1~krr$Epz)?XiIr$lA__WFZo5d|tg}mX`v@ot()usMk+g{2?r_zRkOVg)MSA|_^G%{B*!*Mv25{M?>In}Y)q?nP$Ut>IO-B-w@PymXJgwGyA%5zxbOmTgOFStV`ul5aokIKuoG!Qj$*joG7DuGF$+C&G@oW4>Xx5U9*=yp<>gmTd>pt0%s6&K zvG)$kQsp(2>B60MXXnCR9z79F0H=;P@WoQq+oJbCb*$Y`EL8@y5hFYDlC%T-&i`5M zl#PI>aO1gcjl}qWi_d-kDO`}Ey~_&&be6Jem^%_zZ^7)lEKv}+@uX~tkfPY|XC1{{ zoAzNAcP&`@bC+s$x@I)|9d@wJoadE6ip05a_AqGqyhT`4dq>ZODs|{;Va4~7*TUrt zanZefXD==`<({t}zr)A8?*2g<0}y~ik}iPWKUviT+=O3{rf&eOp7CHK>ijyX{2HaK zmzSbb-IN4ElJnoO>DCqf%w@+tx6sIvXMO9*I+NhWh!D+7O`Q;ejj4I+%rPOw1|-dTKxLU z-P>lN=6TzG&bf_7c?_3(mOm{kWWi&t+2kxt=t$+gf!Iu6_$KSzP>)=!k6RtB=lr8G zw0n8iSB~~y@`Zs0Eiw*z%;H#;Q0$1fG<^if}HN>yR`U*9Nj;<2|euOIwobuevkKO_*duH z(PTbh@$2z%bwrq?QLKcrnzeT%4W`np*7xP?)M4f4%~0=;bc$Bpt8(g@brfxq0=(l`B_+pJuU|aceLSOR#CRI@jL# z4{b)DF8ynxu}KWK{PmHgZAG~^Ys{Fwc7?a$Oazq{n^$wmoTU80j6=pIhS2D?qtZ2%f7XuSw~$7bVh zOl9G5&4==*nS500)madi&Jp~~{%Yi&yW<&vbjKuH4Ndnx%Xk?sNsKfPkuqkTQul|y zd88s8BlIao)BicwtTb$uOFay;9H_%viEfK;kLD-@@!4oiS^Y6F?BU*K-@EX%hVpi9 zJ4q%)z`F)+aQ*>y)G*^ZTSiA4tKL~5xVFyjBWG@4=}ho_4hI@XcT9*s%f%y^IWF%r zH9Ix9c=@BWJXM0Chy>G30-&^zrt&zjp|u)T*Ouj{DA>8dkbvI8PgR zQ)WKl2#tgTzIiop^4w!jbUA3#d|W!qQ5+~g1phA#4krl2wC;?Y^-|Opd+a9kR7(JT4S+{YT(bC-%sSFxplG$@(;4+ zt0!=OnKlPRr~~yB(*Yal-6U<1rY7yD)#Zl1U#gO`?zKM;7U$OEodL=cNBCOKSp|J)4E>>yPsRG)m3>jhwjeCcqO)bvMy&4#0 zqoRA{g2EEb3E!mmHRj_;F--5fY%#g;K2W)Rvw>neB@>rUgx}o0#wLFEnCz5H=Niks z@h9v@`T+2kzQBr`2fg8KQC7ed9Cj;sj&#+tEBL^)M+6WHt_H-7jqnW$V1=I8$pzUUIdynzJ9jBA$}zi-VJa~==Fcr#qME1tTEyjmurl|} z1PBIsd9owR^Uls5|f_Sh60tum&0m)`0qNLY|>ivIoy>(QSkJbh{!OYM@cM1s7(#=pJBB_LQDBa!6fP{#E zAfV(RN=rye4uT*Z(mB%IotN)^=bZ0%*1GqfS+nM^cg>Dx@BKV`zf<6&rDvNwXzG-8 z9A(Ri_OfCgE7vsw*IF34ZHt^`t?x+4tkrFElB^sPF>p^7WoV)Cko-3+#EsX37r96J zmpUSp*#7h@{AmLbRozO-m09gS!6g*W8Th|^Sm<(53Fp+>;YP957Gs~=mil(Jch(UO8B0bAFZOjpJ15+-86%e1e%-Ddkw(Q*G%S= za4wVJjaB<5>(Nukov0s&EtmHF{^joHk!9j@uy4%Seqa5?KE9QR7e{if{2`Z!O@blK z-G*Uq3qt&8%*|q@x*8N~6aW}xG%u!n3N_@!yqvDcW+X4sZ$yTJPgF0M0MwNL++|Y0 zlTT30tGa#U{>Opdm$=Omz2r3{Pnh_m4NqhUnM8v&%RL^Oe-hn&qd>viE6P0b}VWE3KQf z2zruNQ@zq8h9q8QgF0(hMl0x8_k_KmjfACq@A>yh#dhlJ1}fI9wvIPT8TiXe|7qQ% zi2tR<`Mo=K0e0*t^9OPFHN#GuAall3H&Z@@b+6-J02wN8Uh;wR+_LqEcq_#YWCW9? zvVfcJ!Z9{`n;R{Iw*g#!Wvgtm%&)(%Uie)eg->L(!xp8o@4VN)Yrr!_>$U&&>YUJN zK*5gQwbJn_Ca30ynK@R*VFGONQv$d5Cl*p?uE&%El~1n%u|0ABFouzWIb2Q)o(4G6C++l=0P7=0W+5Ys?*k)I*= z66@T2 zamzjmHtY?6HJ45=A1p}!y(+E5X+vCHbNEMQtIp07WL4B~+2fWcr}UDN^#&_qt9c5k zUt)!YI}sRZg`V)357htppVuY+J>F_D9(6oxG1$TNxG*nfTmQ%$}szm!}H3SRj|`^Q3iMteSoS>e16 z2-XVR9vK*q4B8yXmi_OR3mS=UsE;5UxGzZ-UL~N&-7mI%;Jc4@n>Cry^&We5Ug9}bw zt}lp|4smlZevu2{`=8Rco|;Z&nUjN%EwkFx(piq3az4GcqAg=gfSKOP&}VPpgHKtP zE$StU7y?-vWrSqEOMkho=*i)4U=4Zx1Tmakzx&&jt^WSa>_>X^w7}%JO(^iq!#CDs zyRdQgakFvdW!3+$^f4ECAR0X0j5{qqN!7?kt?6VJP-o9ko&ooRu61?xLP9J`M+ub; zMH!$}pg))Zlm{`&e}Yi_J+@X}P^e4Ittg2*NJgrB|XtCKPn#|L0 zszWp{kRcq@-&gLsvqOJ!1n$Y-UavXFa8Vsl?NQ~{k*zl_(a>GIinnMx>y`wKu+(grX{!>z=k#5v<1xO4NWcrRfNt>702Wj_lWty z3ulo4%ysQk%Bg+%(r_A=&SsyhYCD0kxMe@!Q!PhnK+aV({hAUF7+Gm(K@}F7ar^Ct zp5=J@xz-a%`^)xOhQo{<@q_8#gnjkmn@=8Zj`_Q+p0f5*W-;7Ip3O2@KyK8||KsBS zOeM7&F<))@ZiP$I8m#v5qwY@Eok07 z*0Z(#owW&JUZr(YF8%8*cs6-6Sxje2^#{qE-VN!)Do@spw{?&qnC5H{qto3!@-4fe zQT1AcN|R;RMFatLFrFwZ?nw3k^pSrqwMh%vRkdR!JJ_pFxW`JRiB$@U2KWenFvKh< z1U5`wZg1P{3g;js;I!gy9H+pKfqf)^XD(9&WB0b;6b_w&(j6WQFt_{i^r2YLcR>tE z|7Yfp!NiM?!!Sh&uM-p!Zr%STWD)$0tsJ0}-Jn{lTsz9Y^p%5jF86L=!{6ro{S>L$ zxf_)dld{cMi8)#XhTzCN{|AQMbTy!+@CJ?y zES(pcH^5X5y1vazU5W%aO&>3DVJSP;A^b!*F@2KHGfcT8m#PmWwxS|+Mh zIte8L_O-wTZ9XV^0m$goEe84}5hf9i;igHz>$*kj!&+D42FPzB z{jX%sUO#xX+b`*TSiN3RJu4PO?0F~6z19$q{_)V~=~Jo?v(MgZ@00iuLw(>gxK%Ht zCn0CU%It#>cr$`V1whk)CTpCr?sULJz{|k1b{znFhBi>l3tS7c3i;?$`QUOk8gh_~ z8bxY&b*9G#;H`Ekh~YybB(LB7n>8N}Ghv{B6FWt-X=BbA%D-i>jiSh?3 zPl-cn3SbNtqF@~#ScJtDGFbu-C#Va}tleRIpZ25WwM8Gmi19_-1Cn#=k+a`rIhzG8 zW!~v{6@_Yg`)p{3{+(Bsd7I5_x0Q*uJ`e4g6&&0*Mn+l`_m&cN6*C6)tvKB9&KNv= zPoGb^GUW%o`FFSYyHJbgUxMQaABL$Z|7q{?2cb$g0tO07Ef<%YJs2a)QDZRjk-j$G zm~vhv9!dGQgoKR3 zd0r!v`5|*uA9~eq+`+x-S37?tQ!zfPDbB{tklp^3&npaWgxD855Ko?lNut=A@f7u6 z*5ZF_3=R)p2?B0np_r)Wm^az`K+t1RO|-bX1hR75r@z8j5*ABNqr}FFAU%|%-z!H+ z1KWrL068M$xGNr>0Symp|VR4?i)R0;s!k?h5vSTXs%U-0b~0dkm6_otr%d>*#)0$c2F-rY2?o`%oR{_s!uE^)ju zQtaLGKJ?ue>1XCo{E2is@aAgM0TuzR|UhH1|^v9KH3eFF(QCvExD_WcDPW`uS zqBAb4K>sWFi~crjYcQ5YS}x`Jsx^iHjV;akgD)3_DOPeJSFl_$Z!v9Tkody%Uur~OQQ8mD z_@AHCS7WbkN}q{`s`DGW?f!IH^Wu_{tA}2}A^mto;Y)A-=zpn4Rc3~0ihuM-ihzv8 z`w1d=90dXToAWi9$CZmD0EQFp&|pb`#97ih)Pigh$71_?sOu2HUS%3B?w5}UT_E%4 zH(X$3u$2v5Vaz^|amk`B_*s0Yi#hxj3HS2fQwHj_S zBAAnjDg|~`15kxevGTw)f^pCe3Z(0`Y?adl2__&yYz`%m2Oa=Kc8;t?Zlp0%#8gwH zKrs0=$n>`hplF>KqxnP|<12v&b@=n~0v$7d^pE33 zSj*SYQhDYY*O>{=9(d~9rd!_pdhx*0&ri}?S~7>CYhCp%Ej$H&)jEBksrSkhBw9RU z0R0Uz8emDG?|v#KmNR4-c!h(HbNC@yA3-;}MnsVm4h)diGelJD>=tYyD`viRpaL6K ziEG31q|@g|w?HC>f9#Yx?*F!L3jWof_kB0|HuFs2nYl(5(F4~nQVx9(t>(bAKv2QE zN2U-O`$zBGNy74Bw~eFDfhWBsZd zw8Xi2<3vvyT^`(e6-JB=t&z&Tu+$znkR;YlvQy+_K@BN`-gW)NSFWIgDC^=O2o(3h z27-@A!HXYW)h`q65g*Pj1(Hl@I<-_~GF}9G{i;KC4O-~hls$r*HlI%?S9*`c30S;X z{3@H;h%>F~YF^$X{5<19VC9zJ-nag7OSG>J9;V?06F>Qb&{}RF0k;&8 z6GlNs8R?RHzhK{jVp{e@yC6C3K)IW9kfnKOny4k=`q7o#y(tyOH&+Z~d|jknU$HT` z#PAbT|9vRYBiHKAGiX>DL5T3#1Gn9yynr$Fx&PSd&SI(Z>j18Q{m^3Bnc+O{WPW!M zz@@k{Sdd*)-7Nj;eqC`}DINhZIDIO24BYwV7f3>lmFRh})m~Vsb`IdfLnDJQhpumc zps=KH^dsZMl5ebyQU`t`ck_tOt<%cvFwY^%cmosgs)7F1^L-HphN{ygR40GS6icsQ?DhSvs$D7EDGD!jH!6`hmjL4xQw#H*fPP8*Gd6=^x`|G5z{sjKAi2m1Af;+x z1uW`~5Eb)`cBN7Pu&1+y6HLO#o{>S$20VCVU{-Lkd?q1FLO z!BhM*&~xX}BsR=-5f$CYG)jnD^gSg&<`vcBukR7O+Gx4u7uvSpn0kQGCe+g`HH=>U zJNjkD0&BE?2F7X`+qE>~9v6h3uedJ{sO$3ulTw*B?M-~v)ZVkc>9|ruI~KVXoa5W| z+KB;HDp&S%`-OGaMNy7UDF$i<<#B6fQs5~X*MqbrrMg;3x$X~w-9BuF8mf+kQ4y?|IM83^A+1GeQN2dts5}?@&!=||I0UBoEu=~ zi-F5a(4XJ=RC^F`A>2g$<986aH>@RH0v7?B17kzttYK*$9M>pcy%cVM_4jY@wrSew z-}rJKqjt1Tr$#q@*5v9=o9EP7TwV-s@9U(R-^3Bg4mX_X8@gL|HFLCCj`pe7mf=Pu zs{OK!*#!rQ4vf=at{dBUFwP~5gb78(KrXzJ+^v-`evBHL#O$j{H~}$y$l)ALy$;*N%z0X^fQ4K zwcBXNz=aZf$Q$i#ERmqtRFTsr>rF~KxteW`T4f3G3$bY0?6a3M#oyt)i3S+DV#j7zk~;`!Yeh`@m&+nr{_E^O3LTjMc12=|#LV4(o2 zt#QsoRKzFXN%h?PNdZn4Tg+4Kif(OIi}~foIUQ!*mT$tJH7Sq$9k3(7P~=vVZ0SxG z@z9^eLo0zc#logi#(in}){^3o{`6+rl%`s*rD0d}QRkvLV>VvLNo|#;{(DM5C;)sA%`J9ke`iGfyAab2;4Fr zdW*lr%ODX~OCaIgFDQ4S=Mj`nI8MjH>pN3r2(HeH3ik>adb23&&mCt3tYLi!xp-r4UZ_I)>xY$NNIqX7v)DlPVEwu#vxo)rSp{9zB%! zq}SG&(;t7_F*hA6@N@Yitt2ArR|4EepzXFD}eOU`15b?i(y1-mD)?CupO)??qe~l&5=lXGa)|Hrp z)*9vA8vsDvvScyuV!x0*S2y~MAj%^EFl#Fj?QvI15XLU@5F}aU>lTp-8Sbahspx25E?S~>oCe_x#j@0fyW3B_z_aGf#v}srvIxCeF zv)t!zHoFp86RTVOY-XA>Zwjt~`w`QH4sT`k;@#fJFi(C+H9MoEkjZGNv>?y;6nrsK z=#1W2Q+o;&I`+^+;;Vc*f9BWgM_d3bdieGNN!@qGi-k48jv_Gb7mc6BD*au8S>y|4^Ia~AsP!M)TOOaRkT(+<npZ-6VZz^K;*XR>Bopo)^m=Pm~pN)NH~#MN6%W3 znNUO2bCV2+(BAqXh8Cpav@Fr_!X%X7NPtGd z8zYXLzdJC$B5D|9H~05k7OVWkeR%(>hcmvoEhVHji0rjM%x~OK=)J7?Mz(u2bbYSh zr9AN_dcuqvN`Z;bBe+5R!-?#JfxZ1PwnsnYgG;{U&@ziIN&*Nw(%s+Df|Wj1`#)#7 zK(U}1yM4*YJ=;`gP`(Nlq^gaeYBYfe_|F{Fuc}jMTU%f z#F$Gfm^to8Fj(?g7X2It1!^WQ0mtdQ1LYw-(tjmUqBac-t`}Nwq$;To>A7l4Mmj41 zu)=%b5$cU+)`EV`c#h;Xur#>qXxV5}`BxjI{CC$_zi!evj-C*<8{3ER?fh?lzLVUI`0jHRXclZJKfoTK|4YIk8g{Y@dl^DR3dwCJz}9E9-HL2vYm{PY4y_ zVEj+0W>@u9TK0DsSnM}P)TnIcV3KZ?S~Ia_db1Vv;sui>zd%R%lFmqyv|(`hK8+ck)P2N9{wjD@(9{TfVT(Pvi%MOK20$ zWO%^LpIIW(`OY~i(VK&w)p}YU>5>hoFnJ!OW*H=qX;M~j^+^G*WN4c|%q=RbgB(M$ zuosRmF5jDXV?~-zYYc?OU_M$j<*q$B@r2RE1e$rmA3$ z72cW7;>rwf*6808HHZJL_^Xnr^bDlu;ZM`EI!>Cz1V;oB9>HG&;e8@ ze-v>Z7v@kHSIj*qFr3zh5FN?@I^YsM<+FVN*fu0WOFc||GFVygQhblLK>|>M7WPI7 zci319NmME>DDfujJLSH3w}HI1zWzQB5``7V8w^BH{(ZYDz=+>jChu{vcAXl+6i*~@ zvt#INC}KHRe_k8@>iyT2uSA3z-~G21(I?GS^nYx^`W#yZnBW&wc?Y-!h8SS|M|o=M&m|@@_idl+~QuSf72mz6|h*6Hc3Q2J{vS=&` z1R*@OL8rYh0v-H%ri0+8#s#1J(KLlQjnOQZ_AI1{7_&eb_=;FZ~VQxY8(l!CM3r!z~S8QMqI=oTVYG^U&v44VMPIF0r6x#~+Q53%!_d?197`$3Rg|1+jJ>!%2&h8uRpdg- zPpf4+vfLzo)QEhqqVn?ymOnRxjT$%`AhR^&r9dQFbZEP-w+LCv0WUO1rytcszQCF_ zqWV+nyvM#|tcbNKXcos9>QUUH{jeQH_a?a(Gc|Madi%j+x-5@-=X`djmign-rbL&+ zr%ZE~_m_6M&zKu{#LUt6h=FfHnh^&&bYRtnj>`;QFM`mR7X;yF<|5~ z*JnHmD)iu3Dw0H|8PN&&dwJFB_(m`i&Qbg?Wd0uyi0*m+e;v{7a7-jY5|!5L$Tvin zB0=N}7wx0%jnId= z&mQaC=rnw9@`TpP83GZVZnyAF<;STBR(6S5$FIh0+)Anj++CpKS7_U?XO=_oLzm2a z>>d`p%QT!CB1e#Pu*2g=P9^eb+HTI7ByG!Og9&D;Uhm(~kE(-_$KMYDq&U~`)i4Z- z4}BN_(5KlA67)qB_4zi15PDYedBHIK0hlM`%OJWvbTh!Ne*@n_8cH`|nNn-I_0qtm z0~8EIlwo3k8Tw3QC|w5~>Inpg7?xM93fxbo=EFSn)_;-H6c=I^G3Zd=BB{*gZh02)tJi+ps(wk&h<3#d9oDW0=S{7b= zTxgsTl3+UOHCqXU5<0Fv+<=9>KXa!G`Dl~gR$LD7B0NpN!JYHY2`tUUCtZ~hXR@S! zerkoex-Uup^+!+9gWu(%2Xquk1T{@HWVI{TRR{&uy*cpD9?cg-D!H{Jyl5Rzu+p@$ zALdIamlb7~#KWgs4oNvhE*bn+W)NimPvLfHnAGerSQK2&;eUwgTg6_X54H|)w3%j+ zV#rjsGvufp6hz+lvjE2vHHSiPe5?&dDI)aD4FCm%RA_{3w=KXyOl|>5mi$r#(s|q( z4;c@GTGMaa`O!d?2}3OQSl2ukF$utL=##jM>~ZJ7^Ci#I*UrXr?YVD-fEJdY@m?6hpHA<){mJ-9zZvn|m59N_~Bn7A-Y$M`+O|b*wrHK{wq_e+y^*8ilGYs^z z&${#DxW6q6O7|Ypgz6by?@M$ybP?$txvUV)`S(Y=%iu|lk3lt0^QWlx_8P-ut5fZRhBa zr@Lf&9gMwHdjur-2jcUq4gIXvo&~z#sK~j*eAc^b*!nAV zWKGwg(i8(n85I?k?kU>4OYAn_U3obrc4 z>C~s^Vvm7tU#KKuxLUce;= z+WqrdXi(ri6yfNt8-a38Jq+n=N;nAG4s>J=3z>%QFnt6yCpU*T)9exBOK)m~Cu>ke z@J}C>t?s+I@5Cr|m5HLm{oQ;Rn%od|X?@y&t?$ta z9q)1P|3)X$#=@^&z115cxqV_~w1BracG9%ssd)6~u90y^ck^W%<$+YZ*eTAaBAE9q z6L3wUvfpD!SYQP}UDUIYK}OuK6g=9kItM6l0OvfoQ!mg3MnxCT!!wa4p}39j5HaSG zGDUyEyCq+{d-wF*Yn%qwZdwOB$0A7YPd)N4WY2~NHsfOZ4r`hT|764MNj=#7O7|Z5 zmm>B1rcGuqNO7JBL@WBWOrZRC>uarcwpMfX!5L|TB2^EAtL4K)SC_#Kc1+7rQbj-%9?d2 z5q%v!S{A|GKJmd^>{V*@_a5NZ&rUij58&)&!f&O51pVakdvJ~6o7slJi&HNpQp~F= z&vHZM;scrHWnXH6CC*fK_QTs)SH8VYCzlGV^d3|g55US$iU5NXEw&J%j=;LN_$8Q! zP9iwG7;=miR;1tzp{kw=GG)Ano ze!vJvDuu`degSiVXwT|}QfR-;dkMOnXmuHkXe^)x{n)_w2G`AIu@B^uhzo^iU(ulX z_nMYo{1*@;{9lQfNqObRB^gTEyD96qxHU&2D|TPV2H-`sVQ%GUwKgdo*GCcgr@~*0`Q9mK96?0mnnGbYw33YHP?zL*6fKL@dase zeg?Xvrn1H};YjzJ__GFu0r88FrAFd=`Ko-e7o*NKNi28w_A&h+HP>c^tR_1X)$=y+w z4if+jU3cG55f)kxcz_8+Bz*ew_Q#KcL_{k#1O(BC4g$m7EWmgrQ19fJyDFSN@xk4w z_d@_lNiO3bMjh=2+a}iy4J5HnrhL~)YtCPoS-%Dks6@s8U;S>KURI89MRn_R&bci^4oKeG%+P-z{_@lR_U(R`MoC zEw^v8^4tHvf84U$p4Oa8+qN|t+lETnQYh!CoW7YP;FELu@p)MTyN9!h_81&5rZa;I z**}3M*X{MKEE9w*~x+NAZ0U zD9u_07RmGnOxz(j0iKQzrYsTE_S$={EK9qNHrPg_cVdz^LVXOS(8k$I_QRnv*MfkT z2BSNgs0_%mWG`TjCGSwfo!oNw>qji+X>i)k60^ESnotW-{`5XeCS}Gfj1jmP4pRG+ zP9E)#HQ)N()bLNrg#2+FbO_y4H6lVruSK8y?QA_L49*RHF!+|@9+1TrY58$!&tt5%1BIYXlTvKJ9wCy>zzJLp)ZBGZWd~Otk!~ z&lfZ^^MS_x*68z0K7-miIB{PWqc;m4v0P=;^`BQQ=Pmc_)ZBvhoc0&zts=wf6LGGP)B^a?Xfk<{$Ox;!XQOsfVWCMkMjBAt0qm5*D9NGa))WoeB{lLH zU3*)ziganezy1N=Kj_Z7BQ+rUUzl?hTBAHr&1VQA<;*pE8$v0=C_6N#KZt#)6dK@L zu2~`P%uG=KCLoFyGd-gKx(m>PA~rq1kuD`N9#e4|McjY zVjU@;!dc?w3z#u`M)ZcM$o!-M@)V%PfXMFnXE6zwGz_W|9vIQk+`w0|)jU#PCA!7j zY&(4;n(7jgI&QSLwE%C;TCVGMC*E3QRA*GmIY;Y@@(HsZdB=|)3JPKj^Fjdpg9?05 zxu2TmpxhK^9I4YEfbv10go+4s%^C;Fo^6>dB#jHj2ZkzK-!oehvgWHKDIbZYI=qa+ zBmC|>AVwh=?yDzg;U*r8B;9ZvCC#u7V`%L`XNg|7LUS>}?SJ|XN!q>MrZbE)*ld>H z>6_p@qd!$s{cb|$eBvkM{5x4Dj(1M>7`M?rmYK%7#jIOH(FSa)NTxioL@+n%`U7aF zeG$}@lmp0k{!I``CWcebxbY+``F#kyK-zEteKZ-TH>ztx ztQ1m>NweC<-=9wUnfNnDNn`bMKRp`T)>z>mic}Hrmy?)(aM>3sJx*d^uquZ8g7iE4 zOBotRUSE25j1;#a(eu9@fH2%g;QYyW$YX^e=m-4iU{#62Z}k^f}4eo2V%Sflo05 z*2X$!U#3nos+ooiL`45;Zl0ZNhSf!}i6l^crmbSzQek6edNtx_QE^z8NW?1*z4Rjb9K9wn<|;Gj+-}edOLsTs)NtwYBKh?&(NZS>(IOL7w_8BoY-fW)v8yL1=FL| z+^`aJi8RSDmL0`|kuOebN1k?h4brc7_Lc%&pyt)AS>1}VPw^Upx} zv}ZPA+_#$iy>ZC;NW??*O^?h5;=ZCD`sH`>E*gxQZXw*^_0&%hH+E@r_x|vzSg1Ok zM9%d{zprlyIOaY@DX&-SPR(@lEC(Cv*73(d#<;XJVz06lPeET>HkR{U0ERllQg&^2 z3rE{q;+2^v9f7u*=nDiZ{RHUwLO#ienst5!#XVo;7V=qeqMUkGN(K%g+VJ~-

6v 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�QTh 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ℑ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

6C;Q0k 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 HIQ0JkeQZta literal 0 HcmV?d00001 diff --git a/wallpapers/cervus1366x768.png b/wallpapers/cervus1366x768.png new file mode 100644 index 0000000000000000000000000000000000000000..62f958662d50dd6580de92fba6256e446dee01a7 GIT binary patch literal 164159 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

dzJO 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%0AlF2*VxTj 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�$!91ilE3?@7arqJXOEWNw}8A zK~dZeo)?P)n)9hg3nQwLvhAez7TQ9&ZuCEztYQ0-qP0aEj`9h!1 zKtHZMx3;;i!HEw7|KM4EJnXSRxXl!-jWnT#*Arx~1E)Ie08-j9fgHVkgHim2(zA+% z&o`#n9d-Dg(WcQ0;lh7<%0Dxm2^%+Cdr`zRU{|&F#dgok8&*AA>-ew(o}vfUld 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�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ⅆ;V+2_LZWQjztZOxo3Q02`yW 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 literal 0 HcmV?d00001 diff --git a/wallpapers/cervus800x600.png b/wallpapers/cervus800x600.png new file mode 100644 index 0000000000000000000000000000000000000000..c8d858bffd9a0b312f2a702757c87a5abdfe0311 GIT binary patch literal 102242 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 Bl;r>b literal 0 HcmV?d00001 diff --git a/wallpapers/cervus_logo.jpg b/wallpapers/cervus_logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b61d5cee6a58de09d34eb9a4be6f1ae56cad06dd GIT binary patch literal 41577 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 W$ZF%%L>^EHL+wL0I}^A5e*Hf)