diff --git a/.gitignore b/.gitignore index ae0b1dc..8dba8fb 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,4 @@ limine .DS_Store /build/ *.o -disk.img \ No newline at end of file +disk.img diff --git a/build.log b/build.log new file mode 100644 index 0000000..4950f65 --- /dev/null +++ b/build.log @@ -0,0 +1,286 @@ +mkdir -p build +mkdir -p build +nasm -f elf64 src/arch/boot.asm -o build/boot.o +nasm -f elf64 src/arch/gdt_asm.asm -o build/gdt_asm.o +nasm -f elf64 src/arch/interrupts.asm -o build/interrupts.o +nasm -f elf64 src/arch/process_asm.asm -o build/process_asm.o +nasm -f elf64 src/arch/syscalls.asm -o build/syscalls.o +nasm -f elf64 src/arch/test_syscall.asm -o build/test_syscall.o +nasm -f elf64 src/arch/user_test.asm -o build/user_test.o +Building Limine host utility... +make[1]: Nothing to be done for `all'. +mkdir -p build/ +mkdir -p build/ +mkdir -p build/ +mkdir -p build/ +mkdir -p build/ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/core/kutils.c -o build/kutils.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/core/main.c -o build/main.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/core/version.c -o build/version.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/elf.c -o build/elf.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/core/platform.c -o build/platform.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/core/panic.c -o build/panic.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/idt.c -o build/idt.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/gdt.c -o build/gdt.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/kernel_subsystem.c -o build/kernel_subsystem.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/lapic.c -o build/lapic.o +src/sys/idt.c: In function 'pic_remap': +src/sys/idt.c:120:17: warning: variable 'a2' set but not used [-Wunused-but-set-variable] + 120 | uint8_t a1, a2; + | ^~ +src/sys/idt.c:120:13: warning: variable 'a1' set but not used [-Wunused-but-set-variable] + 120 | uint8_t a1, a2; + | ^~ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/module_manager.c -o build/module_manager.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/process.c -o build/process.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/smp.c -o build/smp.o +mkdir -p build/ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/syscall.c -o build/syscall.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/sysfs_init.c -o build/sysfs_init.o +src/sys/smp.c: In function 'smp_init': +src/sys/smp.c:171:14: warning: variable 'bsp_index' set but not used [-Wunused-but-set-variable] + 171 | uint32_t bsp_index = 0; + | ^~~~~~~~~ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/sys/work_queue.c -o build/work_queue.o +mkdir -p build/ +src/sys/sysfs_init.c:11:13: warning: 'sys_itoa' defined but not used [-Wunused-function] + 11 | static void sys_itoa(int n, char *s) { + | ^~~~~~~~ +mkdir -p build/ +src/sys/syscall.c: In function 'syscall_handler_inner': +src/sys/syscall.c:493:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] + 493 | float scale = *(float*)&scale_bits; + | ^~~~~~~~~~~~~~~~~~~ +src/sys/syscall.c:561:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] + 561 | float scale = *(float*)&scale_bits; + | ^~~~~~~~~~~~~~~~~~~ +src/sys/syscall.c:569:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] + 569 | float slope = *(float*)&slope_bits; + | ^~~~~~~~~~~~~~~~~~~ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/mem/memory_manager.c -o build/memory_manager.o +src/sys/syscall.c:695:21: warning: unused variable 'win' [-Wunused-variable] + 695 | Window *win = (Window *)arg2; + | ^~~ +src/sys/syscall.c:725:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] + 725 | float scale = *(float*)&scale_bits; + | ^~~~~~~~~~~~~~~~~~~ +src/sys/syscall.c:762:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] + 762 | float scale = *(float*)&scale_bits; + | ^~~~~~~~~~~~~~~~~~~ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/mem/paging.c -o build/paging.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/mem/vm.c -o build/vm.o +mkdir -p build/ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/dev/disk_manager.c -o build/disk_manager.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/dev/ahci.c -o build/ahci.o +mkdir -p build/ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/dev/pci.c -o build/pci.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/dev/ps2.c -o build/ps2.o +src/dev/pci.c: In function 'pci_enumerate_devices': +src/dev/pci.c:52:31: warning: comparison is always true due to limited range of data type [-Wtype-limits] + 52 | for (uint8_t bus = 0; bus < 256 && count < max_devices; bus++) { + | ^ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/dev/rtc.c -o build/rtc.o +src/dev/rtc.c: In function 'rtc_get_datetime': +src/dev/rtc.c:28:13: warning: unused variable 'last_century' [-Wunused-variable] + 28 | uint8_t last_century; + | ^~~~~~~~~~~~ +src/dev/rtc.c:21:13: warning: unused variable 'century' [-Wunused-variable] + 21 | uint8_t century; + | ^~~~~~~ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/net/lwip_port.c -o build/lwip_port.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/net/network.c -o build/network.o +mkdir -p build/ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/net/nic/e1000.c -o build/e1000.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/net/nic/nic.c -o build/nic.o +src/net/network.c: In function 'network_dhcp_acquire': +src/net/network.c:186:9: warning: unused variable 'loops' [-Wunused-variable] + 186 | int loops = 0; + | ^~~~~ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/net/nic/nic_netif.c -o build/nic_netif.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/net/nic/rtl8111.c -o build/rtl8111.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/net/nic/rtl8139.c -o build/rtl8139.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/net/nic/virtio_net.c -o build/virtio_net.o +mkdir -p build/ +src/net/network.c: In function 'network_init': +src/net/network.c:93:9: warning: 'ip.bytes[0]' may be used uninitialized [-Wmaybe-uninitialized] + 93 | k_itoa(ip.bytes[0], buf); serial_write(buf); serial_write("."); + | ^~~~~~~~~~~~~~~~~~~~~~~~ +src/net/network.c:88:24: note: 'ip.bytes[0]' was declared here + 88 | ipv4_address_t ip; + | ^~ +src/net/network.c:94:9: warning: 'ip.bytes[1]' may be used uninitialized [-Wmaybe-uninitialized] + 94 | k_itoa(ip.bytes[1], buf); serial_write(buf); serial_write("."); + | ^~~~~~~~~~~~~~~~~~~~~~~~ +src/net/network.c:88:24: note: 'ip.bytes[1]' was declared here + 88 | ipv4_address_t ip; + | ^~ +src/net/network.c:95:9: warning: 'ip.bytes[2]' may be used uninitialized [-Wmaybe-uninitialized] + 95 | k_itoa(ip.bytes[2], buf); serial_write(buf); serial_write("."); + | ^~~~~~~~~~~~~~~~~~~~~~~~ +src/net/network.c:88:24: note: 'ip.bytes[2]' was declared here + 88 | ipv4_address_t ip; + | ^~ +src/net/network.c:96:9: warning: 'ip.bytes[3]' may be used uninitialized [-Wmaybe-uninitialized] + 96 | k_itoa(ip.bytes[3], buf); serial_write(buf); serial_write("\n"); + | ^~~~~~~~~~~~~~~~~~~~~~~~ +src/net/network.c:88:24: note: 'ip.bytes[3]' was declared here + 88 | ipv4_address_t ip; + | ^~ +src/net/nic/rtl8111.c: In function 'rtl8111_init': +src/net/nic/rtl8111.c:67:14: warning: unused variable 'bar2' [-Wunused-variable] + 67 | uint32_t bar2 = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->function, 0x18); + | ^~~~ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/fs/fat32.c -o build/fat32.o +mkdir -p build/ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/fs/procfs.c -o build/procfs.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/fs/sysfs.c -o build/sysfs.o +src/fs/fat32.c: In function 'realfs_delete_from_vol': +src/fs/fat32.c:1110:14: warning: variable 'entry_offset' set but not used [-Wunused-but-set-variable] + 1110 | uint32_t entry_offset = 0; + | ^~~~~~~~~~~~ +src/fs/fat32.c:1109:14: warning: variable 'entry_sector' set but not used [-Wunused-but-set-variable] + 1109 | uint32_t entry_sector = 0; + | ^~~~~~~~~~~~ +src/fs/sysfs.c: In function 'sysfs_open': +src/fs/sysfs.c:12:31: warning: unused parameter 'fs_private' [-Wunused-parameter] + 12 | static void* sysfs_open(void *fs_private, const char *path, const char *mode) { + | ~~~~~~^~~~~~~~~~ +src/fs/sysfs.c:12:73: warning: unused parameter 'mode' [-Wunused-parameter] + 12 | static void* sysfs_open(void *fs_private, const char *path, const char *mode) { + | ~~~~~~~~~~~~^~~~ +src/fs/sysfs.c: In function 'sysfs_close': +src/fs/sysfs.c:43:31: warning: unused parameter 'fs_private' [-Wunused-parameter] + 43 | static void sysfs_close(void *fs_private, void *handle) { + | ~~~~~~^~~~~~~~~~ +src/fs/sysfs.c: In function 'sysfs_read': +src/fs/sysfs.c:47:29: warning: unused parameter 'fs_private' [-Wunused-parameter] + 47 | static int sysfs_read(void *fs_private, void *handle, void *buf, int size) { + | ~~~~~~^~~~~~~~~~ +src/fs/sysfs.c: In function 'sysfs_write': +src/fs/sysfs.c:56:30: warning: unused parameter 'fs_private' [-Wunused-parameter] + 56 | static int sysfs_write(void *fs_private, void *handle, const void *buf, int size) { + | ~~~~~~^~~~~~~~~~ +src/fs/sysfs.c: In function 'sysfs_readdir': +src/fs/sysfs.c:86:49: warning: comparison of integer expressions of different signedness: 'size_t' {aka 'long unsigned int'} and 'int' [-Wsign-compare] + 86 | if (path_len == 0 || (k_strlen(s->name) > path_len && k_strncmp(s->name, path, path_len) == 0 && s->name[path_len] == '/')) { + | ^ +src/fs/sysfs.c:65:32: warning: unused parameter 'fs_private' [-Wunused-parameter] + 65 | static int sysfs_readdir(void *fs_private, const char *path, vfs_dirent_t *entries, int max) { + | ~~~~~~^~~~~~~~~~ +src/fs/sysfs.c: In function 'sysfs_exists': +src/fs/sysfs.c:142:31: warning: comparison of integer expressions of different signedness: 'size_t' {aka 'long unsigned int'} and 'int' [-Wsign-compare] + 142 | if (k_strlen(s->name) > path_len && k_strncmp(s->name, path, path_len) == 0 && s->name[path_len] == '/') return true; + | ^ +src/fs/sysfs.c:116:32: warning: unused parameter 'fs_private' [-Wunused-parameter] + 116 | static bool sysfs_exists(void *fs_private, const char *path) { + | ~~~~~~^~~~~~~~~~ +src/fs/procfs.c: In function 'procfs_open': +src/fs/procfs.c:15:25: warning: unused parameter 'fs_private' [-Wunused-parameter] + 15 | void* procfs_open(void *fs_private, const char *path, const char *mode) { + | ~~~~~~^~~~~~~~~~ +src/fs/procfs.c:15:67: warning: unused parameter 'mode' [-Wunused-parameter] + 15 | void* procfs_open(void *fs_private, const char *path, const char *mode) { + | ~~~~~~~~~~~~^~~~ +src/fs/procfs.c: In function 'procfs_close': +src/fs/procfs.c:50:25: warning: unused parameter 'fs_private' [-Wunused-parameter] + 50 | void procfs_close(void *fs_private, void *handle) { + | ~~~~~~^~~~~~~~~~ +src/fs/procfs.c: In function 'procfs_read': +src/fs/procfs.c:54:23: warning: unused parameter 'fs_private' [-Wunused-parameter] + 54 | int procfs_read(void *fs_private, void *handle, void *buf, int size) { + | ~~~~~~^~~~~~~~~~ +src/fs/procfs.c: In function 'procfs_write': +src/fs/procfs.c:178:24: warning: unused parameter 'fs_private' [-Wunused-parameter] + 178 | int procfs_write(void *fs_private, void *handle, const void *buf, int size) { + | ~~~~~~^~~~~~~~~~ +src/fs/procfs.c: In function 'procfs_readdir': +src/fs/procfs.c:200:26: warning: unused parameter 'fs_private' [-Wunused-parameter] + 200 | int procfs_readdir(void *fs_private, const char *path, vfs_dirent_t *entries, int max) { + | ~~~~~~^~~~~~~~~~ +src/fs/procfs.c: In function 'procfs_exists': +src/fs/procfs.c:241:26: warning: unused parameter 'fs_private' [-Wunused-parameter] + 241 | bool procfs_exists(void *fs_private, const char *path) { + | ~~~~~~^~~~~~~~~~ +src/fs/procfs.c: In function 'procfs_is_dir': +src/fs/procfs.c:264:26: warning: unused parameter 'fs_private' [-Wunused-parameter] + 264 | bool procfs_is_dir(void *fs_private, const char *path) { + | ~~~~~~^~~~~~~~~~ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/fs/tar.c -o build/tar.o +mkdir -p build/ +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/fs/vfs.c -o build/vfs.o +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/wm/cmd.c -o build/cmd.o +mkdir -p build/ +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/wm/explorer.c -o build/explorer.o +src/wm/cmd.c: In function 'internal_cmd_cd': +src/wm/cmd.c:1014:13: error: too few arguments to function 'vfs_normalize_path'; expected 3, have 2 + 1014 | vfs_normalize_path(full_path, normalized_path); + | ^~~~~~~~~~~~~~~~~~ +In file included from src/wm/cmd.c:11: +src/fs/vfs.h:111:6: note: declared here + 111 | void vfs_normalize_path(const char *cwd, const char *path, char *normalized); + | ^~~~~~~~~~~~~~~~~~ +mkdir -p build/ +make: *** [build/cmd.o] Error 1 +make: *** Waiting for unfinished jobs.... +x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc -Isrc/net/lwip -Isrc/core -Isrc/sys -Isrc/mem -Isrc/dev -Isrc/net -Isrc/net/nic -Isrc/fs -Isrc/wm -c src/wm/font_manager.c -o build/font_manager.o +src/wm/explorer.c: In function 'explorer_draw_file_icon': +src/wm/explorer.c:885:73: warning: unused parameter 'color' [-Wunused-parameter] + 885 | static void explorer_draw_file_icon(int x, int y, bool is_dir, uint32_t color, const char *filename, const char *current_path) { + | ~~~~~~~~~^~~~~ +src/wm/explorer.c: In function 'explorer_paint': +src/wm/explorer.c:922:15: warning: unused variable 'dirty' [-Wunused-variable] + 922 | DirtyRect dirty = graphics_get_dirty_rect(); + | ^~~~~ +In file included from src/wm/font_manager.c:4: +src/wm/stb_truetype.h: In function 'stbtt_FreeShape': +src/wm/stb_truetype.h:2672:54: warning: unused parameter 'info' [-Wunused-parameter] + 2672 | STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) + | ~~~~~~~~~~~~~~~~~~~~~~^~~~ +src/wm/stb_truetype.h: In function 'stbtt__hheap_alloc': +src/wm/stb_truetype.h:2770:70: warning: unused parameter 'userdata' [-Wunused-parameter] + 2770 | static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) + | ~~~~~~^~~~~~~~ +src/wm/stb_truetype.h: In function 'stbtt__hheap_cleanup': +src/wm/stb_truetype.h:2797:58: warning: unused parameter 'userdata' [-Wunused-parameter] + 2797 | static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) + | ~~~~~~^~~~~~~~ +src/wm/stb_truetype.h: In function 'stbtt_FlattenCurves': +src/wm/stb_truetype.h:3618:154: warning: unused parameter 'userdata' [-Wunused-parameter] + 3618 | static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) + | ~~~~~~^~~~~~~~ +src/wm/stb_truetype.h: In function 'stbtt_FreeBitmap': +src/wm/stb_truetype.h:3708:62: warning: unused parameter 'userdata' [-Wunused-parameter] + 3708 | STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) + | ~~~~~~^~~~~~~~ +src/wm/stb_truetype.h: In function 'stbtt_FreeSDF': +src/wm/stb_truetype.h:4767:59: warning: unused parameter 'userdata' [-Wunused-parameter] + 4767 | STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) + | ~~~~~~^~~~~~~~ +src/wm/font_manager.c: In function 'font_manager_load': +src/wm/font_manager.c:112:9: warning: unused variable 'read' [-Wunused-variable] + 112 | int read = fat32_read(fh, buffer, fsize); + | ^~~~ diff --git a/disk.img b/disk.img index 6aaaf5c..c4d599a 100644 Binary files a/disk.img and b/disk.img differ diff --git a/src/core/kutils.c b/src/core/kutils.c index 9d37534..2b39e04 100644 --- a/src/core/kutils.c +++ b/src/core/kutils.c @@ -30,6 +30,16 @@ int k_strcmp(const char *s1, const char *s2) { return *(const unsigned char*)s1 - *(const unsigned char*)s2; } +int k_strncmp(const char *s1, const char *s2, size_t n) { + while (n && *s1 && (*s1 == *s2)) { + s1++; + s2++; + n--; + } + if (n == 0) return 0; + return *(const unsigned char*)s1 - *(const unsigned char*)s2; +} + void k_strcpy(char *dest, const char *src) { while (*src) *dest++ = *src++; *dest = 0; diff --git a/src/core/kutils.h b/src/core/kutils.h index 24c50c0..939cccb 100644 --- a/src/core/kutils.h +++ b/src/core/kutils.h @@ -13,6 +13,7 @@ void k_memset(void *dest, int val, size_t len); void k_memcpy(void *dest, const void *src, size_t len); size_t k_strlen(const char *str); int k_strcmp(const char *s1, const char *s2); +int k_strncmp(const char *s1, const char *s2, size_t n); void k_strcpy(char *dest, const char *src); int k_atoi(const char *str); void k_itoa(int n, char *buf); diff --git a/src/core/main.c b/src/core/main.c index 69ff52c..be1bb3c 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -24,6 +24,12 @@ #include "smp.h" #include "work_queue.h" #include "lapic.h" +#include "fs/sysfs.h" +#include "fs/procfs.h" +#include "sys/kernel_subsystem.h" +#include "sys/module_manager.h" + +extern void sysfs_init_subsystems(void); // --- Limine Requests --- __attribute__((used, section(".requests"))) @@ -202,6 +208,11 @@ void kmain(void) { fat32_mkdir("/Library/DOOM"); fat32_mkdir("/docs"); + // Initialize Virtual Filesystems + sysfs_init_subsystems(); + vfs_mount("/sys", "sysfs", "sysfs", sysfs_get_ops(), NULL); + vfs_mount("/proc", "procfs", "procfs", procfs_get_ops(), NULL); + if (module_request.response == NULL) { serial_write("[DEBUG] ERROR: Limine Module Response is NULL!\n"); } else { @@ -241,6 +252,8 @@ void kmain(void) { fat32_close(fh); } } + // Register all discovered modules in our module manager for /sys/module + module_manager_register(clean_path, (uint64_t)mod->address, mod->size); } } @@ -260,7 +273,7 @@ void kmain(void) { // Initialize LAPIC for IPI support lapic_init(); - // Initialize SMP — bring up all CPU cores + // Initialize SMP if (smp_request.response != NULL) { uint32_t online = smp_init(smp_request.response); serial_write("[DEBUG] SMP init complete, CPUs online: "); @@ -268,7 +281,6 @@ void kmain(void) { serial_write("\n"); } else { serial_write("[DEBUG] No SMP response from bootloader\n"); - // Still init as single-CPU smp_init(NULL); } diff --git a/src/core/man_entries.h b/src/core/man_entries.h index ce54e6b..577a9f7 100644 --- a/src/core/man_entries.h +++ b/src/core/man_entries.h @@ -14,7 +14,7 @@ static size_t man_strlen(const char *str) { } static void write_man_file(const char *name, const char *content) { - char path[128] = "A:/Library/man/"; + char path[128] = "/Library/man/"; int i = 15; while (*name) path[i++] = *name++; path[i++] = '.'; @@ -31,8 +31,8 @@ static void write_man_file(const char *name, const char *content) { } void create_man_entries(void) { - fat32_mkdir("A:/Library"); - fat32_mkdir("A:/Library/man"); + fat32_mkdir("/Library"); + fat32_mkdir("/Library/man"); write_man_file("ping", "PING - Send ICMP echo requests\n\nUsage: ping \n\nSends ICMP echo requests to the specified IP address and displays the response times."); write_man_file("net", "NET - Network utilities\n\nUsage: net init\nnet info\nnet ipset >ip<\nnet udpsend >ip< >port< >message< net ping >ip< net help\n\nA collection of network-related commands."); @@ -55,7 +55,7 @@ void create_man_entries(void) { write_man_file("touch", "TOUCH - Create empty file\n\nUsage: touch \n\nCreates a new empty file if it doesn't exist."); write_man_file("cc", "CC - C Compiler\n\nUsage: cc \n\nThe BoredOS C Compiler. Compiles C source files into executables. (execute these with ./>file<)"); write_man_file("crash", "CRASH - Trigger kernel exception\n\nUsage: crash\n\nIntentionally triggers a null pointer dereference to test handlers."); - write_man_file("sysfetch", "SYSFETCH - Show OS information\n\nUsage: sysfetch\n\nDisplays system information in a neofetch-like layout. Configurable via A:/Library/conf/sysfetch.cfg."); + write_man_file("sysfetch", "SYSFETCH - Show OS information\n\nUsage: sysfetch\n\nDisplays system information in a neofetch-like layout. Configurable via /Library/conf/sysfetch.cfg."); write_man_file("meminfo", "MEMINFO - Memory usage stats\n\nUsage: meminfo\n\nDisplays current physical and virtual memory allocation statistics."); write_man_file("pci_list", "PCI_LIST - Scan PCI bus\n\nUsage: pci_list\n\nScans the PCI bus and lists all detected hardware devices."); write_man_file("reboot", "REBOOT - Restart system\n\nUsage: reboot\n\nRestarts the computer immediately."); diff --git a/src/core/platform.c b/src/core/platform.c index 6878011..2f741b8 100644 --- a/src/core/platform.c +++ b/src/core/platform.c @@ -4,6 +4,7 @@ #include #include "limine.h" #include +#include "platform.h" static volatile struct limine_hhdm_request hhdm_request __attribute__((used, section(".requests"))) = { .id = LIMINE_HHDM_REQUEST, .revision = 0, @@ -69,3 +70,13 @@ void platform_get_cpu_model(char *model) { } model[48] = '\0'; } +void platform_get_cpu_vendor(char *vendor) { + uint32_t eax, ebx, ecx, edx; + asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(0)); + + char *p = (char *)vendor; + *((uint32_t *)&p[0]) = ebx; + *((uint32_t *)&p[4]) = edx; + *((uint32_t *)&p[8]) = ecx; + p[12] = '\0'; +} diff --git a/src/core/platform.h b/src/core/platform.h index 4f9c595..fc20ae2 100644 --- a/src/core/platform.h +++ b/src/core/platform.h @@ -10,5 +10,6 @@ void platform_init(void); uint64_t p2v(uint64_t phys); uint64_t v2p(uint64_t virt); void platform_get_cpu_model(char *model); +void platform_get_cpu_vendor(char *vendor); #endif diff --git a/src/dev/ps2.c b/src/dev/ps2.c index 14a9b5e..727d4a2 100644 --- a/src/dev/ps2.c +++ b/src/dev/ps2.c @@ -16,12 +16,14 @@ extern void serial_print_hex(uint64_t n); volatile uint64_t kernel_ticks = 0; uint64_t timer_handler(registers_t *regs) { - kernel_ticks++; - wm_timer_tick(); - network_process_frames(); - - extern void k_beep_process(void); - k_beep_process(); + if (smp_this_cpu_id() == 0) { + kernel_ticks++; + wm_timer_tick(); + network_process_frames(); + + extern void k_beep_process(void); + k_beep_process(); + } outb(0x20, 0x20); extern uint64_t process_schedule(uint64_t current_rsp); diff --git a/src/fs/fat32.c b/src/fs/fat32.c index 349ab21..ba1c584 100644 --- a/src/fs/fat32.c +++ b/src/fs/fat32.c @@ -276,19 +276,22 @@ static int ramfs_count_files_in_dir(const char *normalized_path) { static bool check_desktop_limit(const char *normalized_path) { if (desktop_file_limit < 0) return true; - if (fs_strlen(normalized_path) > 9 && + if (fs_strlen(normalized_path) > 14 && normalized_path[0] == '/' && - normalized_path[1] == 'D' && normalized_path[2] == 'e' && - normalized_path[3] == 's' && normalized_path[4] == 'k' && - normalized_path[5] == 't' && normalized_path[6] == 'o' && - normalized_path[7] == 'p' && normalized_path[8] == '/') { - const char *p = normalized_path + 9; + normalized_path[1] == 'r' && normalized_path[2] == 'o' && + normalized_path[3] == 'o' && normalized_path[4] == 't' && + normalized_path[5] == '/' && + normalized_path[6] == 'D' && normalized_path[7] == 'e' && + normalized_path[8] == 's' && normalized_path[9] == 'k' && + normalized_path[10] == 't' && normalized_path[11] == 'o' && + normalized_path[12] == 'p' && normalized_path[13] == '/') { + const char *p = normalized_path + 14; while (*p) { if (*p == '/') return true; p++; } - int count = ramfs_count_files_in_dir("/Desktop"); + int count = ramfs_count_files_in_dir("/root/Desktop"); if (count >= desktop_file_limit) return false; } return true; @@ -707,7 +710,27 @@ static FAT32_FileHandle* realfs_open_from_vol(FAT32_Volume *vol, const char *pat to_dos_filename(component, dos_name); int name_len = fs_strlen(component); - bool needs_lfn = (name_len > 12); + + // Determine if LFN is needed: + // LFN is needed if the name contains characters that don't fit in 8.3 format + // or if the extension is longer than 3 chars or name part is longer than 8 chars + bool needs_lfn = false; + int dot_pos = -1; + for (int i = 0; i < name_len; i++) { + if (component[i] == '.') { dot_pos = i; break; } + } + + if (dot_pos == -1) { + // No extension - need LFN if name > 8 chars + needs_lfn = (name_len > 8); + } else { + // Has extension + int name_part = dot_pos; + int ext_part = name_len - dot_pos - 1; + // Need LFN if name > 8 chars or extension > 3 chars + needs_lfn = (name_part > 8) || (ext_part > 3); + } + int lfn_entries = needs_lfn ? ((name_len + 12) / 13) : 0; int total_entries = lfn_entries + 1; @@ -753,29 +776,29 @@ static FAT32_FileHandle* realfs_open_from_vol(FAT32_Volume *vol, const char *pat d->start_cluster_low = 0; d->file_size = 0; - realfs_write_cluster(vol, free_cluster, lfn_cl_buf); - - uint32_t lba = vol->cluster_begin_lba + (free_cluster - 2) * vol->sectors_per_cluster; - entry_sector = lba + ((start_entry_idx + lfn_entries) * 32) / 512; - entry_offset = ((start_entry_idx + lfn_entries) * 32) % 512; - - kfree(lfn_cl_buf); - if (cluster_buf) kfree(cluster_buf); - - FAT32_FileHandle *fh = ramfs_find_free_handle(); - if (fh) { - fh->valid = true; - fh->volume = vol; - fh->start_cluster = 0; - fh->cluster = 0; - fh->position = 0; - fh->size = 0; - fh->mode = (mode[0] == 'a' ? 2 : 1); - fh->is_directory = false; - fh->attributes = ATTR_ARCHIVE; - fh->dir_sector = entry_sector; - fh->dir_offset = entry_offset; - return fh; + if (realfs_write_cluster(vol, free_cluster, lfn_cl_buf) == 0) { + uint32_t lba = vol->cluster_begin_lba + (free_cluster - 2) * vol->sectors_per_cluster; + entry_sector = lba + ((start_entry_idx + lfn_entries) * 32) / 512; + entry_offset = ((start_entry_idx + lfn_entries) * 32) % 512; + + kfree(lfn_cl_buf); + if (cluster_buf) kfree(cluster_buf); + + FAT32_FileHandle *fh = ramfs_find_free_handle(); + if (fh) { + fh->valid = true; + fh->volume = vol; + fh->start_cluster = 0; + fh->cluster = 0; + fh->position = 0; + fh->size = 0; + fh->mode = (mode[0] == 'a' ? 2 : 1); + fh->is_directory = false; + fh->attributes = ATTR_ARCHIVE; + fh->dir_sector = entry_sector; + fh->dir_offset = entry_offset; + return fh; + } } } } @@ -951,6 +974,9 @@ static uint32_t realfs_allocate_cluster(FAT32_Volume *vol) { uint32_t current = 2; uint32_t fat_entries = (vol->fat_size * 512) / 4; + // Skip cluster 2 as it's reserved for the root directory in FAT32 + if (current == vol->root_cluster) current++; + uint8_t *fat_buf = (uint8_t*)kmalloc(512); if (!fat_buf) return 0; @@ -1006,18 +1032,33 @@ static int realfs_write_file(FAT32_FileHandle *handle, const void *buffer, int s } handle->start_cluster = new_cluster; handle->cluster = new_cluster; + handle->position = 0; + handle->size = 0; + + // Update directory entry immediately with correct start_cluster + // This ensures the directory always points to the right cluster realfs_update_dir_entry_size(vol, handle); } while (bytes_written < size) { - if (realfs_read_cluster(vol, handle->cluster, cluster_buf) != 0) break; - uint32_t offset = handle->position % cluster_size; + + // Always zero the buffer first to ensure clean state + for (int i = 0; i < (int)cluster_size; i++) cluster_buf[i] = 0; + + // If we're in the middle of a cluster, read the existing data first + if (offset > 0) { + if (realfs_read_cluster(vol, handle->cluster, cluster_buf) != 0) break; + } + int to_copy = size - bytes_written; int available = cluster_size - offset; if (to_copy > available) to_copy = available; - for (int i = 0; i < to_copy; i++) cluster_buf[offset + i] = src_buf[bytes_written + i]; + // Copy new data into the cluster buffer + for (int i = 0; i < to_copy; i++) { + cluster_buf[offset + i] = src_buf[bytes_written + i]; + } if (realfs_write_cluster(vol, handle->cluster, cluster_buf) != 0) break; @@ -1152,10 +1193,15 @@ static bool realfs_delete_from_vol(FAT32_Volume *vol, const char *path) { int lfn_start_entry = -1; if (has_lfn) { - // This is an oversimplification, but for same-sector LFNs: + // Find all LFN entries in reverse from the main entry + // LFN entries are marked by their order field and must be contiguous for (int k = e - 1; k >= 0; k--) { - if (entry[k].attributes == ATTR_LFN) lfn_start_entry = k; - else break; + if (entry[k].attributes == ATTR_LFN) { + lfn_start_entry = k; // Keep updating to find earliest LFN + } else { + // Stop when we hit a non-LFN entry that's not deleted + if (entry[k].filename[0] != 0xE5) break; + } } } @@ -1170,7 +1216,7 @@ static bool realfs_delete_from_vol(FAT32_Volume *vol, const char *path) { if (*p == 0) { // Found target file/directory to delete - // Mark LFN entries as deleted too (if in same sector) + // Mark LFN entries as deleted too if (lfn_start_entry != -1) { for (int k = lfn_start_entry; k < e; k++) { entry[k].filename[0] = 0xE5; @@ -1180,10 +1226,49 @@ static bool realfs_delete_from_vol(FAT32_Volume *vol, const char *path) { entry[e].filename[0] = 0xE5; // Persist the changes to disk - // Calculate exactly which sector within the cluster we modified + // CRITICAL FIX: Write ALL sectors that contain modified entries + // LFN entries and main entry may span multiple sectors in the cluster uint32_t lba = vol->cluster_begin_lba + (search_cluster - 2) * vol->sectors_per_cluster; - int sect_in_cluster = (e * 32) / 512; - vol->disk->write_sector(vol->disk, lba + sect_in_cluster, ((uint8_t*)entry) + (sect_in_cluster * 512)); + + // Find all sectors touched by LFN and main entries + uint8_t sectors_to_write[8] = {0}; // Max 8 sectors per cluster + int num_sectors = 0; + + // Mark sectors containing LFN entries + if (lfn_start_entry != -1) { + for (int k = lfn_start_entry; k < e; k++) { + int sect_idx = (k * 32) / 512; + bool already_marked = false; + for (int s = 0; s < num_sectors; s++) { + if (sectors_to_write[s] == sect_idx) { + already_marked = true; + break; + } + } + if (!already_marked && num_sectors < 8) { + sectors_to_write[num_sectors++] = sect_idx; + } + } + } + + // Mark sector containing main entry + int main_sect_idx = (e * 32) / 512; + bool already_marked = false; + for (int s = 0; s < num_sectors; s++) { + if (sectors_to_write[s] == main_sect_idx) { + already_marked = true; + break; + } + } + if (!already_marked && num_sectors < 8) { + sectors_to_write[num_sectors++] = main_sect_idx; + } + + // Write all modified sectors + for (int i = 0; i < num_sectors; i++) { + int sect_idx = sectors_to_write[i]; + vol->disk->write_sector(vol->disk, lba + sect_idx, ((uint8_t*)entry) + (sect_idx * 512)); + } found = true; } else { diff --git a/src/fs/procfs.c b/src/fs/procfs.c new file mode 100644 index 0000000..8b4bf9e --- /dev/null +++ b/src/fs/procfs.c @@ -0,0 +1,290 @@ +#include "vfs.h" +#include "../sys/process.h" +#include "../sys/syscall.h" +#include "../dev/disk.h" +#include "memory_manager.h" +#include "core/kutils.h" + +typedef struct { + uint32_t pid; + char type[32]; + int offset; + bool is_root; +} procfs_handle_t; + +void* procfs_open(void *fs_private, const char *path, const char *mode) { + if (path[0] == '/') path++; + + procfs_handle_t *h = (procfs_handle_t*)kmalloc(sizeof(procfs_handle_t)); + k_memset(h, 0, sizeof(procfs_handle_t)); + h->offset = 0; + + if (path[0] == '\0') { + h->is_root = true; + return h; + } + + if (path[0] >= '0' && path[0] <= '9') { + char pid_str[16]; + int i = 0; + while (path[i] && path[i] != '/' && i < 15) { + pid_str[i] = path[i]; + i++; + } + pid_str[i] = 0; + h->pid = k_atoi(pid_str); + + if (path[i] == '/') { + k_strcpy(h->type, path + i + 1); + } else { + h->type[0] = 0; + } + return h; + } + + h->pid = 0xFFFFFFFF; + k_strcpy(h->type, path); + return h; +} + +void procfs_close(void *fs_private, void *handle) { + if (handle) kfree(handle); +} + +int procfs_read(void *fs_private, void *handle, void *buf, int size) { + procfs_handle_t *h = (procfs_handle_t*)handle; + if (!h) return -1; + + char out[1024]; + out[0] = 0; + + if (h->pid == 0xFFFFFFFF) { + if (k_strcmp(h->type, "version") == 0) { + extern void get_os_info(os_info_t *info); + os_info_t info; + get_os_info(&info); + k_strcpy(out, info.os_name); + k_strcpy(out + k_strlen(out), " ["); + k_strcpy(out + k_strlen(out), info.os_codename); + k_strcpy(out + k_strlen(out), "] Version "); + k_strcpy(out + k_strlen(out), info.os_version); + k_strcpy(out + k_strlen(out), "\nKernel: "); + k_strcpy(out + k_strlen(out), info.kernel_name); + k_strcpy(out + k_strlen(out), " "); + k_strcpy(out + k_strlen(out), info.kernel_version); + k_strcpy(out + k_strlen(out), "\nBuild: "); + k_strcpy(out + k_strlen(out), info.build_date); + k_strcpy(out + k_strlen(out), " "); + k_strcpy(out + k_strlen(out), info.build_time); + k_strcpy(out + k_strlen(out), "\n"); + } else if (k_strcmp(h->type, "uptime") == 0) { + extern uint32_t wm_get_ticks(void); + uint32_t ticks = wm_get_ticks(); + k_itoa(ticks / 60, out); + k_strcpy(out + k_strlen(out), " seconds\nRaw_Ticks:"); + char t_s[16]; k_itoa(ticks, t_s); + k_strcpy(out + k_strlen(out), t_s); + k_strcpy(out + k_strlen(out), "\n"); + } else if (k_strcmp(h->type, "cpuinfo") == 0) { + extern uint32_t smp_cpu_count(void); + extern void platform_get_cpu_model(char *model); + char model[64]; + platform_get_cpu_model(model); + + k_strcpy(out, "Processor: "); + k_strcpy(out + k_strlen(out), model); + k_strcpy(out + k_strlen(out), "\nCores: "); + char c_s[16]; k_itoa(smp_cpu_count(), c_s); + k_strcpy(out + k_strlen(out), c_s); + k_strcpy(out + k_strlen(out), "\nArchitecture: x86_64\n"); + } else if (k_strcmp(h->type, "meminfo") == 0) { + extern MemStats memory_get_stats(void); + MemStats stats = memory_get_stats(); + k_strcpy(out, "MemTotal: "); + char m_s[32]; k_itoa(stats.total_memory / 1024, m_s); + k_strcpy(out + k_strlen(out), m_s); + k_strcpy(out + k_strlen(out), " kB\nMemFree: "); + k_itoa(stats.available_memory / 1024, m_s); + k_strcpy(out + k_strlen(out), m_s); + k_strcpy(out + k_strlen(out), " kB\nMemUsed: "); + k_itoa(stats.used_memory / 1024, m_s); + k_strcpy(out + k_strlen(out), m_s); + k_strcpy(out + k_strlen(out), " kB\nPeak: "); + k_itoa(stats.peak_memory_used / 1024, m_s); + k_strcpy(out + k_strlen(out), m_s); + k_strcpy(out + k_strlen(out), " kB\nBlocks: "); + k_itoa(stats.allocated_blocks, m_s); + k_strcpy(out + k_strlen(out), m_s); + k_strcpy(out + k_strlen(out), "\nFragmentation: "); + k_itoa(stats.fragmentation_percent, m_s); + k_strcpy(out + k_strlen(out), m_s); + k_strcpy(out + k_strlen(out), "%\n"); + } else if (k_strcmp(h->type, "devices") == 0) { + extern int disk_get_count(void); + extern Disk* disk_get_by_index(int index); + int dcount = disk_get_count(); + k_strcpy(out, "Block Devices:\n"); + for (int i = 0; i < dcount; i++) { + Disk *d = disk_get_by_index(i); + if (d) { + k_strcpy(out + k_strlen(out), " - "); + k_strcpy(out + k_strlen(out), d->devname); + k_strcpy(out + k_strlen(out), "\n"); + } + } + } + } + else { + process_t *proc = process_get_by_pid(h->pid); + if (!proc) return -1; + + if (k_strcmp(h->type, "name") == 0 || k_strcmp(h->type, "cmdline") == 0) { + k_strcpy(out, proc->name); + k_strcpy(out + k_strlen(out), "\n"); + } else if (k_strcmp(h->type, "status") == 0) { + k_strcpy(out, "Name: "); + k_strcpy(out + k_strlen(out), proc->name); + k_strcpy(out + k_strlen(out), "\nPID: "); + char pid_s[16]; k_itoa(proc->pid, pid_s); + k_strcpy(out + k_strlen(out), pid_s); + k_strcpy(out + k_strlen(out), "\nState: RUNNING\nMemory: "); + uint64_t mem_val = proc->used_memory; + if (h->pid == 0) { + extern MemStats memory_get_stats(void); + mem_val = memory_get_stats().used_memory; + } + char mem_s[32]; k_itoa(mem_val / 1024, mem_s); + k_strcpy(out + k_strlen(out), mem_s); + k_strcpy(out + k_strlen(out), " KB\nTicks: "); + char tick_s[32]; k_itoa(proc->ticks, tick_s); + k_strcpy(out + k_strlen(out), tick_s); + k_strcpy(out + k_strlen(out), "\nIdle: "); + k_strcpy(out + k_strlen(out), proc->is_idle ? "1" : "0"); + k_strcpy(out + k_strlen(out), "\n"); + } + } + + int len = k_strlen(out); + if (h->offset >= len) return 0; + + int to_copy = len - h->offset; + if (to_copy > size) to_copy = size; + + k_memcpy(buf, out + h->offset, to_copy); + h->offset += to_copy; + return to_copy; +} + +int procfs_write(void *fs_private, void *handle, const void *buf, int size) { + procfs_handle_t *h = (procfs_handle_t*)handle; + if (!h || h->pid == 0xFFFFFFFF) return -1; + + if (k_strcmp(h->type, "signal") == 0) { + char cmd[16]; + int to_copy = size < 15 ? size : 15; + k_memcpy(cmd, buf, to_copy); + cmd[to_copy] = 0; + + if (k_strcmp(cmd, "9") == 0 || k_strcmp(cmd, "kill") == 0) { + process_t *proc = process_get_by_pid(h->pid); + if (proc && proc->pid != 0) { + process_terminate(proc); + return size; + } + } + } + + return -1; +} + +int procfs_readdir(void *fs_private, const char *path, vfs_dirent_t *entries, int max) { + if (path[0] == '/') path++; + + if (path[0] == '\0') { + int out = 0; + k_strcpy(entries[out++].name, "version"); + entries[out-1].is_directory = 0; + k_strcpy(entries[out++].name, "uptime"); + entries[out-1].is_directory = 0; + k_strcpy(entries[out++].name, "cpuinfo"); + entries[out-1].is_directory = 0; + k_strcpy(entries[out++].name, "meminfo"); + entries[out-1].is_directory = 0; + k_strcpy(entries[out++].name, "devices"); + entries[out-1].is_directory = 0; + + extern process_t processes[]; + for (int i = 0; i < 16 && out < max; i++) { + if (processes[i].pid != 0xFFFFFFFF) { + k_itoa(processes[i].pid, entries[out].name); + entries[out].is_directory = 1; + entries[out].size = 0; + out++; + } + } + return out; + } + + if (path[0] >= '0' && path[0] <= '9') { + int out = 0; + k_strcpy(entries[out++].name, "name"); + k_strcpy(entries[out++].name, "status"); + k_strcpy(entries[out++].name, "cmdline"); + k_strcpy(entries[out++].name, "signal"); + for(int i=0; i= '0' && path[0] <= '9') { + char pid_str[16]; + int i = 0; + while (path[i] && path[i] != '/' && i < 15) { + pid_str[i] = path[i]; + i++; + } + pid_str[i] = 0; + uint32_t pid = k_atoi(pid_str); + if (process_get_by_pid(pid)) return true; + } + + if (k_strcmp(path, "version") == 0 || k_strcmp(path, "uptime") == 0) return true; + if (k_strcmp(path, "cpuinfo") == 0 || k_strcmp(path, "meminfo") == 0) return true; + if (k_strcmp(path, "devices") == 0) return true; + + return false; +} + +bool procfs_is_dir(void *fs_private, const char *path) { + if (path[0] == '/') path++; + if (path[0] == '\0') return true; + + if (path[0] >= '0' && path[0] <= '9') { + int i = 0; + while (path[i] && path[i] != '/') i++; + if (path[i] == '\0') return true; + return false; + } + + return false; +} + +vfs_fs_ops_t procfs_ops = { + .open = procfs_open, + .close = procfs_close, + .read = procfs_read, + .write = procfs_write, + .readdir = procfs_readdir, + .exists = procfs_exists, + .is_dir = procfs_is_dir +}; + +vfs_fs_ops_t* procfs_get_ops(void) { + return &procfs_ops; +} diff --git a/src/fs/procfs.h b/src/fs/procfs.h new file mode 100644 index 0000000..ba05fc2 --- /dev/null +++ b/src/fs/procfs.h @@ -0,0 +1,8 @@ +#ifndef PROCFS_H +#define PROCFS_H + +#include "vfs.h" + +vfs_fs_ops_t* procfs_get_ops(void); + +#endif diff --git a/src/fs/sysfs.c b/src/fs/sysfs.c new file mode 100644 index 0000000..2510855 --- /dev/null +++ b/src/fs/sysfs.c @@ -0,0 +1,181 @@ +#include "vfs.h" +#include "../sys/kernel_subsystem.h" +#include "memory_manager.h" +#include "core/kutils.h" + +typedef struct { + kernel_subsystem_t *sub; + subsystem_file_t *file; + int offset; +} sysfs_handle_t; + +static void* sysfs_open(void *fs_private, const char *path, const char *mode) { + if (path[0] == '/') path++; + if (path[0] == '\0') return NULL; + + kernel_subsystem_t *sub = NULL; + int last_slash = -1; + for (int j = 0; path[j]; j++) if (path[j] == '/') last_slash = j; + + if (last_slash != -1) { + char prefix[64]; + k_memcpy(prefix, path, last_slash); + prefix[last_slash] = 0; + sub = subsystem_get_by_name(prefix); + + if (sub) { + const char *filename = path + last_slash + 1; + for (int j = 0; j < sub->file_count; j++) { + if (k_strcmp(sub->files[j].name, filename) == 0) { + sysfs_handle_t *h = (sysfs_handle_t*)kmalloc(sizeof(sysfs_handle_t)); + h->sub = sub; + h->file = &sub->files[j]; + h->offset = 0; + return h; + } + } + } + } + + return NULL; +} + +static void sysfs_close(void *fs_private, void *handle) { + if (handle) kfree(handle); +} + +static int sysfs_read(void *fs_private, void *handle, void *buf, int size) { + sysfs_handle_t *h = (sysfs_handle_t*)handle; + if (!h || !h->file || !h->file->read) return -1; + + int bytes = h->file->read((char*)buf, size, h->offset); + if (bytes > 0) h->offset += bytes; + return bytes; +} + +static int sysfs_write(void *fs_private, void *handle, const void *buf, int size) { + sysfs_handle_t *h = (sysfs_handle_t*)handle; + if (!h || !h->file || !h->file->write) return -1; + + int bytes = h->file->write((const char*)buf, size, h->offset); + if (bytes > 0) h->offset += bytes; + return bytes; +} + +static int sysfs_readdir(void *fs_private, const char *path, vfs_dirent_t *entries, int max) { + if (path[0] == '/') path++; + + kernel_subsystem_t *exact_sub = subsystem_get_by_name(path); + int out = 0; + + if (exact_sub) { + for (int i = 0; i < exact_sub->file_count && out < max; i++) { + k_strcpy(entries[out].name, exact_sub->files[i].name); + entries[out].is_directory = 0; + entries[out].size = 0; + out++; + } + } + + int count = subsystem_get_count(); + int path_len = k_strlen(path); + + for (int i = 0; i < count && out < max; i++) { + kernel_subsystem_t *s = subsystem_get_by_index(i); + if (path_len == 0 || (k_strlen(s->name) > path_len && k_strncmp(s->name, path, path_len) == 0 && s->name[path_len] == '/')) { + const char *sub_path = s->name + (path_len ? path_len + 1 : 0); + char comp[64]; + int j = 0; + while (sub_path[j] && sub_path[j] != '/' && j < 63) { + comp[j] = sub_path[j]; + j++; + } + comp[j] = 0; + + if (comp[0] == '\0') continue; + + bool found = false; + for (int k = 0; k < out; k++) { + if (k_strcmp(entries[k].name, comp) == 0) { + found = true; + break; + } + } + if (!found) { + k_strcpy(entries[out].name, comp); + entries[out].is_directory = 1; + entries[out].size = 0; + out++; + } + } + } + return out; +} + +static bool sysfs_exists(void *fs_private, const char *path) { + if (path[0] == '/') path++; + if (path[0] == '\0') return true; + + if (subsystem_get_by_name(path)) return true; + + // File check + int last_slash = -1; + for (int j = 0; path[j]; j++) if (path[j] == '/') last_slash = j; + if (last_slash != -1) { + char prefix[64]; + k_memcpy(prefix, path, last_slash); + prefix[last_slash] = 0; + kernel_subsystem_t *sub = subsystem_get_by_name(prefix); + if (sub) { + const char *filename = path + last_slash + 1; + for (int j = 0; j < sub->file_count; j++) { + if (k_strcmp(sub->files[j].name, filename) == 0) return true; + } + } + } + + int count = subsystem_get_count(); + int path_len = k_strlen(path); + for (int i = 0; i < count; i++) { + kernel_subsystem_t *s = subsystem_get_by_index(i); + if (k_strlen(s->name) > path_len && k_strncmp(s->name, path, path_len) == 0 && s->name[path_len] == '/') return true; + } + + return false; +} + +static bool sysfs_is_dir(void *fs_private, const char *path) { + if (path[0] == '/') path++; + if (path[0] == '\0') return true; + + int last_slash = -1; + for (int j = 0; path[j]; j++) if (path[j] == '/') last_slash = j; + if (last_slash != -1) { + char prefix[64]; + k_memcpy(prefix, path, last_slash); + prefix[last_slash] = 0; + kernel_subsystem_t *sub = subsystem_get_by_name(prefix); + if (sub) { + const char *filename = path + last_slash + 1; + for (int j = 0; j < sub->file_count; j++) { + if (k_strcmp(sub->files[j].name, filename) == 0) return false; + } + } + } + + return sysfs_exists(fs_private, path); +} + +vfs_fs_ops_t sysfs_ops = { + .open = sysfs_open, + .close = sysfs_close, + .read = sysfs_read, + .write = sysfs_write, + .readdir = sysfs_readdir, + .exists = sysfs_exists, + .is_dir = sysfs_is_dir +}; + +vfs_fs_ops_t* sysfs_get_ops(void) { + return &sysfs_ops; +} diff --git a/src/fs/sysfs.h b/src/fs/sysfs.h new file mode 100644 index 0000000..be125bd --- /dev/null +++ b/src/fs/sysfs.h @@ -0,0 +1,8 @@ +#ifndef SYSFS_H +#define SYSFS_H + +#include "vfs.h" + +vfs_fs_ops_t* sysfs_get_ops(void); + +#endif diff --git a/src/fs/vfs.c b/src/fs/vfs.c index 88b24f6..a96f60c 100644 --- a/src/fs/vfs.c +++ b/src/fs/vfs.c @@ -6,10 +6,8 @@ #include "spinlock.h" #include #include "disk.h" +#include "process.h" -// ============================================================================ -// VFS Mount Table and File Handle Pool -// ============================================================================ static vfs_mount_t mounts[VFS_MAX_MOUNTS]; static int mount_count = 0; @@ -19,10 +17,6 @@ static spinlock_t vfs_lock = SPINLOCK_INIT; extern void serial_write(const char *str); extern void serial_write_num(uint64_t num); -// ============================================================================ -// String helpers (freestanding — no libc) -// ============================================================================ - static int vfs_strlen(const char *s) { int n = 0; while (s[n]) n++; @@ -53,44 +47,63 @@ static bool vfs_starts_with(const char *str, const char *prefix) { return true; } -// ============================================================================ -// Path Normalization -// ============================================================================ +static bool vfs_path_is_parent(const char *parent, const char *child) { + int plen = vfs_strlen(parent); + if (vfs_strncmp(parent, child, plen) != 0) return false; + if (child[plen] == '\0') return true; + if (child[plen] == '/') return true; + if (plen == 1 && parent[0] == '/') return true; + return false; +} -void vfs_normalize_path(const char *path, char *normalized) { - // Resolve . and .. components, remove duplicate slashes - char parts[32][128]; +void vfs_normalize_path(const char *cwd, const char *path, char *normalized) { + char parts[32][64]; // Reduced size to save stack, 64 is enough for most names int depth = 0; int i = 0; - // Skip leading slash + // Handle relative path by starting with CWD + if (path[0] != '/' && cwd) { + int ci = 0; + if (cwd[0] == '/') ci = 1; + while (cwd[ci]) { + if (cwd[ci] == '/') { ci++; continue; } + int j = 0; + while (cwd[ci] && cwd[ci] != '/' && j < 63) { + parts[depth][j++] = cwd[ci++]; + } + parts[depth][j] = 0; + if (j > 0) depth++; + if (depth >= 32) break; + if (cwd[ci] == '/') ci++; + } + } + if (path[0] == '/') i = 1; while (path[i]) { - // Skip duplicate slashes if (path[i] == '/') { i++; continue; } - // Extract component int j = 0; - while (path[i] && path[i] != '/' && j < 127) { + while (path[i] && path[i] != '/' && j < 63) { parts[depth][j++] = path[i++]; } parts[depth][j] = 0; if (parts[depth][0] == '.' && parts[depth][1] == 0) { - // "." — skip + // "." skip } else if (parts[depth][0] == '.' && parts[depth][1] == '.' && parts[depth][2] == 0) { - // ".." — go up + // ".." pop if (depth > 0) depth--; } else { - depth++; - if (depth >= 32) break; + if (j > 0) { + depth++; + if (depth >= 32) break; + } } if (path[i] == '/') i++; } - // Reconstruct normalized[0] = '/'; int pos = 1; for (int k = 0; k < depth; k++) { @@ -102,16 +115,11 @@ void vfs_normalize_path(const char *path, char *normalized) { } normalized[pos] = 0; - // Ensure root is just "/" if (pos == 1 && normalized[0] == '/') { normalized[1] = 0; } } -// ============================================================================ -// Mount Resolution — find the longest-prefix mount for a path -// ============================================================================ - static vfs_mount_t* vfs_resolve_mount(const char *path, const char **rel_path_out) { vfs_mount_t *best = NULL; int best_len = -1; @@ -121,7 +129,6 @@ static vfs_mount_t* vfs_resolve_mount(const char *path, const char **rel_path_ou int mlen = mounts[i].path_len; - // Root mount "/" matches everything if (mlen == 1 && mounts[i].path[0] == '/') { if (best_len < 1) { best = &mounts[i]; @@ -130,9 +137,7 @@ static vfs_mount_t* vfs_resolve_mount(const char *path, const char **rel_path_ou continue; } - // Check if path starts with this mount point if (vfs_strncmp(path, mounts[i].path, mlen) == 0) { - // Must be followed by '/' or end of string if (path[mlen] == '/' || path[mlen] == '\0') { if (mlen > best_len) { best = &mounts[i]; @@ -144,7 +149,6 @@ static vfs_mount_t* vfs_resolve_mount(const char *path, const char **rel_path_ou if (best && rel_path_out) { const char *rel = path + best_len; - // Skip leading slash in relative path while (*rel == '/') rel++; *rel_path_out = rel; } @@ -152,14 +156,14 @@ static vfs_mount_t* vfs_resolve_mount(const char *path, const char **rel_path_ou return best; } -// ============================================================================ -// File Handle Pool -// ============================================================================ - static vfs_file_t* vfs_alloc_file(void) { for (int i = 0; i < VFS_MAX_OPEN_FILES; i++) { if (!open_files[i].valid) { open_files[i].valid = true; + open_files[i].fs_handle = NULL; + open_files[i].mount = NULL; + open_files[i].position = 0; + open_files[i].is_device = false; return &open_files[i]; } } @@ -171,13 +175,11 @@ static void vfs_free_file(vfs_file_t *f) { f->valid = false; f->fs_handle = NULL; f->mount = NULL; + f->position = 0; + f->is_device = false; } } -// ============================================================================ -// Initialization -// ============================================================================ - void vfs_init(void) { for (int i = 0; i < VFS_MAX_MOUNTS; i++) { mounts[i].active = false; @@ -190,9 +192,9 @@ void vfs_init(void) { serial_write("[VFS] Virtual File System initialized\n"); } -// ============================================================================ +// =============== // Mount / Unmount -// ============================================================================ +// =============== bool vfs_mount(const char *mount_path, const char *device, const char *fs_type, vfs_fs_ops_t *ops, void *fs_private) { @@ -204,7 +206,6 @@ bool vfs_mount(const char *mount_path, const char *device, const char *fs_type, return false; } - // Check for duplicate mount for (int i = 0; i < mount_count; i++) { if (mounts[i].active && vfs_strcmp(mounts[i].path, mount_path) == 0) { spinlock_release_irqrestore(&vfs_lock, flags); @@ -243,7 +244,6 @@ bool vfs_umount(const char *mount_path) { for (int i = 0; i < mount_count; i++) { if (mounts[i].active && vfs_strcmp(mounts[i].path, mount_path) == 0) { - // Close any open files on this mount for (int j = 0; j < VFS_MAX_OPEN_FILES; j++) { if (open_files[j].valid && open_files[j].mount == &mounts[i]) { if (mounts[i].ops->close) { @@ -274,27 +274,44 @@ bool vfs_umount(const char *mount_path) { return false; } -// ============================================================================ +// ============== // File Operations -// ============================================================================ +// ============== vfs_file_t* vfs_open(const char *path, const char *mode) { if (!path || !mode) return NULL; - // Normalize path char normalized[VFS_MAX_PATH]; - vfs_normalize_path(path, normalized); + process_t *proc = process_get_current(); + vfs_normalize_path(proc ? proc->cwd : "/", path, normalized); uint64_t flags = spinlock_acquire_irqsave(&vfs_lock); const char *rel_path = NULL; vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path); + + // Fallback for block devices (/dev/sda etc) + if (vfs_starts_with(normalized, "/dev/")) { + const char *devname = normalized + 5; + Disk *d = disk_get_by_name(devname); + if (d && (!mount || mount->path_len == 1)) { + vfs_file_t *vf = vfs_alloc_file(); + if (vf) { + vf->mount = &mounts[0]; + vf->fs_handle = (void*)d; + vf->is_device = true; + vf->position = 0; + spinlock_release_irqrestore(&vfs_lock, flags); + return vf; + } + } + } + if (!mount || !mount->ops->open) { spinlock_release_irqrestore(&vfs_lock, flags); return NULL; } - // If rel_path is empty, use root if (!rel_path || rel_path[0] == '\0') { rel_path = "/"; } @@ -308,7 +325,6 @@ vfs_file_t* vfs_open(const char *path, const char *mode) { vf->mount = mount; - // Release lock before calling FS ops (FS has its own locking) spinlock_release_irqrestore(&vfs_lock, flags); void *fs_handle = mount->ops->open(mount->fs_private, rel_path, mode); @@ -338,9 +354,38 @@ void vfs_close(vfs_file_t *file) { int vfs_read(vfs_file_t *file, void *buf, int size) { if (!file || !file->valid || !file->mount) return -1; - if (!file->mount->ops->read) return -1; - return file->mount->ops->read(file->mount->fs_private, file->fs_handle, buf, size); + if (file->is_device) { + Disk *d = (Disk*)file->fs_handle; + if (!d) return -1; + + uint32_t total_read = 0; + uint32_t sector = (uint32_t)(file->position / 512); + uint32_t offset = (uint32_t)(file->position % 512); + uint8_t sector_buf[512]; + + while (total_read < (uint32_t)size) { + if (sector >= d->total_sectors) break; + if (d->read_sector(d, sector, sector_buf) != 0) break; + + uint32_t to_copy = 512 - offset; + if (to_copy > (uint32_t)size - total_read) to_copy = (uint32_t)size - total_read; + + extern void mem_memcpy(void *dest, const void *src, size_t len); + mem_memcpy((uint8_t*)buf + total_read, sector_buf + offset, to_copy); + + total_read += to_copy; + file->position += to_copy; + sector++; + offset = 0; + } + return (int)total_read; + } + + if (!file->mount->ops->read) return -1; + int ret = file->mount->ops->read(file->mount->fs_private, file->fs_handle, buf, size); + if (ret > 0) file->position += ret; + return ret; } int vfs_write(vfs_file_t *file, const void *buf, int size) { @@ -352,32 +397,60 @@ int vfs_write(vfs_file_t *file, const void *buf, int size) { int vfs_seek(vfs_file_t *file, int offset, int whence) { if (!file || !file->valid || !file->mount) return -1; + + if (file->is_device) { + Disk *d = (Disk*)file->fs_handle; + if (!d) return -1; + uint64_t new_pos = file->position; + if (whence == 0) new_pos = (uint64_t)offset; // SET + else if (whence == 1) new_pos += (uint64_t)offset; // CUR + else if (whence == 2) new_pos = (uint64_t)(d->total_sectors * 512 + offset); // END + + if (new_pos > (uint64_t)d->total_sectors * 512) new_pos = (uint64_t)d->total_sectors * 512; + file->position = new_pos; + return 0; + } + if (!file->mount->ops->seek) return -1; - return file->mount->ops->seek(file->mount->fs_private, file->fs_handle, offset, whence); + int ret = file->mount->ops->seek(file->mount->fs_private, file->fs_handle, offset, whence); + if (ret == 0) { + // Sync position back from driver if possible + if (file->mount->ops->get_position) { + file->position = file->mount->ops->get_position(file->fs_handle); + } else { + // Manual sync if driver doesn't support get_position but seek succeeded + if (whence == 0) file->position = offset; + else if (whence == 1) file->position += offset; + } + } + return ret; } uint32_t vfs_file_position(vfs_file_t *file) { if (!file || !file->valid || !file->mount) return 0; + if (file->is_device) return (uint32_t)file->position; if (!file->mount->ops->get_position) return 0; return file->mount->ops->get_position(file->fs_handle); } uint32_t vfs_file_size(vfs_file_t *file) { if (!file || !file->valid || !file->mount) return 0; + if (file->is_device) { + Disk *d = (Disk*)file->fs_handle; + return d ? d->total_sectors * 512 : 0; + } if (!file->mount->ops->get_size) return 0; return file->mount->ops->get_size(file->fs_handle); } -// ============================================================================ -// Directory Operations -// ============================================================================ + int vfs_list_directory(const char *path, vfs_dirent_t *entries, int max) { if (!path || !entries) return -1; char normalized[VFS_MAX_PATH]; - vfs_normalize_path(path, normalized); + vfs_normalize_path("/", path, normalized); const char *rel_path = NULL; vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path); @@ -386,22 +459,19 @@ int vfs_list_directory(const char *path, vfs_dirent_t *entries, int max) { if (mount && mount->ops->readdir) { if (!rel_path || rel_path[0] == '\0') rel_path = "/"; count = mount->ops->readdir(mount->fs_private, rel_path, entries, max); - if (count < 0) count = 0; // Treat as virtual if readdir fails + if (count < 0) count = 0; } - // Merge in other mount points that are direct children of this path uint64_t v_flags = spinlock_acquire_irqsave(&vfs_lock); for (int i = 0; i < mount_count; i++) { if (!mounts[i].active) continue; - if (vfs_strcmp(mounts[i].path, normalized) == 0) continue; // Skip ourselves + if (vfs_strcmp(mounts[i].path, normalized) == 0) continue; - // Check if mount path starts with current path - if (vfs_starts_with(mounts[i].path, normalized)) { + if (vfs_path_is_parent(normalized, mounts[i].path)) { const char *sub = mounts[i].path + vfs_strlen(normalized); - if (*sub == '/') sub++; // skip slash + if (*sub == '/') sub++; if (*sub != '\0') { - // Extract first component (direct child name) char comp[VFS_MAX_NAME]; int j = 0; while (sub[j] && sub[j] != '/' && j < VFS_MAX_NAME - 1) { @@ -410,7 +480,6 @@ int vfs_list_directory(const char *path, vfs_dirent_t *entries, int max) { } comp[j] = 0; - // Check if already in results bool found = false; for (int k = 0; k < count; k++) { if (vfs_strcmp(entries[k].name, comp) == 0) { @@ -431,21 +500,24 @@ int vfs_list_directory(const char *path, vfs_dirent_t *entries, int max) { } spinlock_release_irqrestore(&vfs_lock, v_flags); - // Special case: Ensure "dev" is visible in "/" + // Special case: Ensure "dev", "sys", "proc" are visible in "/" if (vfs_strcmp(normalized, "/") == 0) { - bool found_dev = false; - for (int i = 0; i < count; i++) { - if (vfs_strcmp(entries[i].name, "dev") == 0) { - found_dev = true; - break; + const char *virtual_dirs[] = {"dev", "sys", "proc"}; + for (int v = 0; v < 3; v++) { + bool found = false; + for (int i = 0; i < count; i++) { + if (vfs_strcmp(entries[i].name, virtual_dirs[v]) == 0) { + found = true; + break; + } + } + if (!found && count < max) { + vfs_strcpy(entries[count].name, virtual_dirs[v]); + entries[count].is_directory = 1; + entries[count].size = 0; + entries[count].start_cluster = 0; + count++; } - } - if (!found_dev && count < max) { - vfs_strcpy(entries[count].name, "dev"); - entries[count].is_directory = 1; - entries[count].size = 0; - entries[count].start_cluster = 0; - count++; } } @@ -465,7 +537,7 @@ int vfs_list_directory(const char *path, vfs_dirent_t *entries, int max) { if (!found) { vfs_strcpy(entries[count].name, d->devname); entries[count].size = d->total_sectors * 512; - entries[count].is_directory = d->is_partition ? 1 : 0; + entries[count].is_directory = 0; entries[count].start_cluster = 0; entries[count].write_date = 0; entries[count].write_time = 0; @@ -482,15 +554,14 @@ bool vfs_mkdir(const char *path) { if (!path) return false; char normalized[VFS_MAX_PATH]; - vfs_normalize_path(path, normalized); + vfs_normalize_path("/", path, normalized); const char *rel_path = NULL; vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path); - // If it's in /dev/, check if it's within a mounted volume deeper than the device node if (vfs_starts_with(normalized, "/dev/")) { if (!mount || !rel_path || rel_path[0] == '\0') { - return false; // Protect raw device nodes + return false; } } @@ -502,19 +573,17 @@ bool vfs_rmdir(const char *path) { if (!path) return false; char normalized[VFS_MAX_PATH]; - vfs_normalize_path(path, normalized); + vfs_normalize_path("/", path, normalized); - // Protect root and virtual /dev directory itself if (normalized[0] == '/' && normalized[1] == '\0') return false; if (vfs_strcmp(normalized, "/dev") == 0) return false; const char *rel_path = NULL; vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path); - // If it's in /dev/, allow only if it's inside a mount beyond the device node if (vfs_starts_with(normalized, "/dev/")) { if (!mount || !rel_path || rel_path[0] == '\0') { - return false; // Protect raw device nodes + return false; } } @@ -526,19 +595,17 @@ bool vfs_delete(const char *path) { if (!path) return false; char normalized[VFS_MAX_PATH]; - vfs_normalize_path(path, normalized); + vfs_normalize_path("/", path, normalized); - // Protect root and virtual /dev directory itself if (normalized[0] == '/' && normalized[1] == '\0') return false; if (vfs_strcmp(normalized, "/dev") == 0) return false; const char *rel_path = NULL; vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path); - // If it's in /dev/, allow only if it's inside a mount beyond the device node if (vfs_starts_with(normalized, "/dev/")) { if (!mount || !rel_path || rel_path[0] == '\0') { - return false; // Protect raw device nodes + return false; } } @@ -550,14 +617,13 @@ bool vfs_rename(const char *old_path, const char *new_path) { if (!old_path || !new_path) return false; char norm_old[VFS_MAX_PATH], norm_new[VFS_MAX_PATH]; - vfs_normalize_path(old_path, norm_old); - vfs_normalize_path(new_path, norm_new); + vfs_normalize_path("/", old_path, norm_old); + vfs_normalize_path("/", new_path, norm_new); const char *rel_old = NULL, *rel_new = NULL; vfs_mount_t *mount_old = vfs_resolve_mount(norm_old, &rel_old); vfs_mount_t *mount_new = vfs_resolve_mount(norm_new, &rel_new); - // Can only rename within the same mount if (!mount_old || mount_old != mount_new) return false; if (!mount_old->ops->rename) return false; @@ -567,20 +633,14 @@ bool vfs_rename(const char *old_path, const char *new_path) { return mount_old->ops->rename(mount_old->fs_private, rel_old, rel_new); } -// ============================================================================ -// Query Operations -// ============================================================================ - bool vfs_exists(const char *path) { if (!path) return false; char normalized[VFS_MAX_PATH]; - vfs_normalize_path(path, normalized); + vfs_normalize_path("/", path, normalized); - // Root always exists if (normalized[0] == '/' && normalized[1] == '\0') return true; - // Check if it's a prefix of any active mount point uint64_t flags_vfs = spinlock_acquire_irqsave(&vfs_lock); for (int i = 0; i < mount_count; i++) { if (mounts[i].active && vfs_starts_with(mounts[i].path, normalized)) { @@ -590,10 +650,10 @@ bool vfs_exists(const char *path) { } spinlock_release_irqrestore(&vfs_lock, flags_vfs); - // /dev always exists as a virtual directory - if (vfs_strcmp(normalized, "/dev") == 0) return true; + if (vfs_strcmp(normalized, "/dev") == 0 || + vfs_strcmp(normalized, "/sys") == 0 || + vfs_strcmp(normalized, "/proc") == 0) return true; - // Check if it's a device in /dev if (vfs_starts_with(normalized, "/dev/")) { const char *dev = normalized + 5; if (disk_get_by_name(dev)) return true; @@ -603,7 +663,7 @@ bool vfs_exists(const char *path) { vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path); if (!mount || !mount->ops->exists) return false; - if (!rel_path || rel_path[0] == '\0') return true; // Mount point itself exists + if (!rel_path || rel_path[0] == '\0') return true; return mount->ops->exists(mount->fs_private, rel_path); } @@ -612,43 +672,38 @@ bool vfs_is_directory(const char *path) { if (!path) return false; char normalized[VFS_MAX_PATH]; - vfs_normalize_path(path, normalized); + vfs_normalize_path("/", path, normalized); - // Root is always a directory if (normalized[0] == '/' && normalized[1] == '\0') return true; - // Check if it's a prefix of any active mount point (virtual directory) uint64_t flags_vfs = spinlock_acquire_irqsave(&vfs_lock); for (int i = 0; i < mount_count; i++) { - if (mounts[i].active && vfs_starts_with(mounts[i].path, normalized)) { - // If it matches exactly a mount point, we still need to check if that FS is a dir + if (mounts[i].active && vfs_path_is_parent(normalized, mounts[i].path)) { if (vfs_strcmp(mounts[i].path, normalized) == 0) { - // Exact mount point - it is a directory (mount root) spinlock_release_irqrestore(&vfs_lock, flags_vfs); return true; } - // Prefix only - it is a virtual intermediate directory + // If normalized is a parent of a mount, it's a virtual directory spinlock_release_irqrestore(&vfs_lock, flags_vfs); return true; } } spinlock_release_irqrestore(&vfs_lock, flags_vfs); - // /dev is always a virtual directory - if (vfs_strcmp(normalized, "/dev") == 0) return true; + if (vfs_strcmp(normalized, "/dev") == 0 || + vfs_strcmp(normalized, "/sys") == 0 || + vfs_strcmp(normalized, "/proc") == 0) return true; - // Device check if (vfs_starts_with(normalized, "/dev/")) { const char *dev = normalized + 5; Disk *d = disk_get_by_name(dev); - if (d) return d->is_partition ? true : false; + if (d) return false; } const char *rel_path = NULL; vfs_mount_t *mount = vfs_resolve_mount(normalized, &rel_path); if (!mount) return false; - // If it's a mount point and we're at its root, it definitely exists as a dir if (!rel_path || rel_path[0] == '\0') return true; if (!mount->ops->is_dir) return false; @@ -659,9 +714,8 @@ int vfs_get_info(const char *path, vfs_dirent_t *info) { if (!path || !info) return -1; char normalized[VFS_MAX_PATH]; - vfs_normalize_path(path, normalized); + vfs_normalize_path("/", path, normalized); - // Root info if (normalized[0] == '/' && normalized[1] == '\0') { vfs_strcpy(info->name, "/"); info->size = 0; @@ -672,9 +726,11 @@ int vfs_get_info(const char *path, vfs_dirent_t *info) { return 0; } - // /dev virtual directory info - if (vfs_strcmp(normalized, "/dev") == 0) { - vfs_strcpy(info->name, "dev"); + if (vfs_strcmp(normalized, "/dev") == 0 || + vfs_strcmp(normalized, "/sys") == 0 || + vfs_strcmp(normalized, "/proc") == 0) { + const char *name = normalized + 1; + vfs_strcpy(info->name, name); info->size = 0; info->is_directory = 1; info->start_cluster = 0; @@ -683,13 +739,10 @@ int vfs_get_info(const char *path, vfs_dirent_t *info) { return 0; } - // Check if it's a prefix of any active mount point (virtual directory) uint64_t flags_vfs = spinlock_acquire_irqsave(&vfs_lock); for (int i = 0; i < mount_count; i++) { - if (mounts[i].active && vfs_starts_with(mounts[i].path, normalized)) { + if (mounts[i].active && vfs_path_is_parent(normalized, mounts[i].path)) { if (vfs_strcmp(mounts[i].path, normalized) != 0) { - // Virtual intermediate directory - // Get component name const char *p = normalized + vfs_strlen(normalized); while (p > normalized && *(p-1) != '/') p--; vfs_strcpy(info->name, p); @@ -712,7 +765,7 @@ int vfs_get_info(const char *path, vfs_dirent_t *info) { if (d) { vfs_strcpy(info->name, d->devname); info->size = d->total_sectors * 512; - info->is_directory = d->is_partition ? 1 : 0; + info->is_directory = 0; info->start_cluster = 0; info->write_date = 0; info->write_time = 0; @@ -738,10 +791,6 @@ int vfs_get_info(const char *path, vfs_dirent_t *info) { return mount->ops->get_info(mount->fs_private, rel_path, info); } -// ============================================================================ -// Mount Enumeration -// ============================================================================ - int vfs_get_mount_count(void) { return mount_count; } @@ -752,12 +801,7 @@ vfs_mount_t* vfs_get_mount(int index) { return &mounts[index]; } -// ============================================================================ -// Auto-Mount (called when a new partition is discovered) -// ============================================================================ - void vfs_automount_partition(const char *devname) { - // Build mount point: /mnt/ char mount_path[64] = "/mnt/"; int i = 5; const char *d = devname; @@ -769,8 +813,4 @@ void vfs_automount_partition(const char *devname) { serial_write(" at "); serial_write(mount_path); serial_write("\n"); - - // The actual FAT32 volume creation and mount happens in disk_manager - // after probing the partition. This function is called by disk_manager - // after it has created the FAT32_Volume. } diff --git a/src/fs/vfs.h b/src/fs/vfs.h index 37d8e50..06ddf1d 100644 --- a/src/fs/vfs.h +++ b/src/fs/vfs.h @@ -58,6 +58,8 @@ struct vfs_file { void *fs_handle; // FS-specific handle (e.g. FAT32_FileHandle*) vfs_mount_t *mount; // Mount this file belongs to bool valid; + uint64_t position; // Current Seek Position (for raw devices/fallbacks) + bool is_device; // Is this a raw device handle? }; // Mount entry @@ -106,7 +108,7 @@ vfs_mount_t* vfs_get_mount(int index); void vfs_automount_partition(const char *devname); // Path utilities -void vfs_normalize_path(const char *path, char *normalized); +void vfs_normalize_path(const char *cwd, const char *path, char *normalized); // Backward compat: get position/size from vfs_file uint32_t vfs_file_position(vfs_file_t *file); diff --git a/src/sys/kernel_subsystem.c b/src/sys/kernel_subsystem.c new file mode 100644 index 0000000..9f19f3d --- /dev/null +++ b/src/sys/kernel_subsystem.c @@ -0,0 +1,73 @@ +#include "kernel_subsystem.h" +#include "memory_manager.h" +#include "spinlock.h" + +static kernel_subsystem_t subsystems[MAX_SUBSYSTEMS]; +static int subsystem_count = 0; +static spinlock_t sub_lock = SPINLOCK_INIT; + +extern void mem_memset(void *dest, int val, size_t len); +extern void mem_memcpy(void *dest, const void *src, size_t len); + +static void sub_strcpy(char *dest, const char *src) { + while (*src) *dest++ = *src++; + *dest = 0; +} + +static int sub_strcmp(const char *a, const char *b) { + while (*a && *a == *b) { a++; b++; } + return (unsigned char)*a - (unsigned char)*b; +} + +void subsystem_register(const char *name, kernel_subsystem_t **out_sub) { + uint64_t flags = spinlock_acquire_irqsave(&sub_lock); + + if (subsystem_count >= MAX_SUBSYSTEMS) { + spinlock_release_irqrestore(&sub_lock, flags); + if (out_sub) *out_sub = NULL; + return; + } + + // Check if already exists + for (int i = 0; i < subsystem_count; i++) { + if (sub_strcmp(subsystems[i].name, name) == 0) { + spinlock_release_irqrestore(&sub_lock, flags); + if (out_sub) *out_sub = &subsystems[i]; + return; + } + } + + kernel_subsystem_t *s = &subsystems[subsystem_count++]; + mem_memset(s, 0, sizeof(kernel_subsystem_t)); + sub_strcpy(s->name, name); + + spinlock_release_irqrestore(&sub_lock, flags); + if (out_sub) *out_sub = s; +} + +void subsystem_add_file(kernel_subsystem_t *sub, const char *name, + int (*read)(char*, int, int), + int (*write)(const char*, int, int)) { + if (!sub || sub->file_count >= MAX_SUBSYSTEM_FILES) return; + + subsystem_file_t *f = &sub->files[sub->file_count++]; + sub_strcpy(f->name, name); + f->read = read; + f->write = write; +} + +kernel_subsystem_t* subsystem_get_by_name(const char *name) { + for (int i = 0; i < subsystem_count; i++) { + if (sub_strcmp(subsystems[i].name, name) == 0) return &subsystems[i]; + } + return NULL; +} + +int subsystem_get_count(void) { + return subsystem_count; +} + +kernel_subsystem_t* subsystem_get_by_index(int index) { + if (index < 0 || index >= subsystem_count) return NULL; + return &subsystems[index]; +} diff --git a/src/sys/kernel_subsystem.h b/src/sys/kernel_subsystem.h new file mode 100644 index 0000000..15d883c --- /dev/null +++ b/src/sys/kernel_subsystem.h @@ -0,0 +1,32 @@ +#ifndef KERNEL_SUBSYSTEM_H +#define KERNEL_SUBSYSTEM_H + +#include +#include +#include + +#define MAX_SUBSYSTEMS 16 +#define MAX_SUBSYSTEM_FILES 32 + +typedef struct { + char name[64]; + int (*read)(char *buffer, int size, int offset); + int (*write)(const char *buffer, int size, int offset); +} subsystem_file_t; + +typedef struct { + char name[64]; + subsystem_file_t files[MAX_SUBSYSTEM_FILES]; + int file_count; +} kernel_subsystem_t; + +void subsystem_register(const char *name, kernel_subsystem_t **out_sub); +void subsystem_add_file(kernel_subsystem_t *sub, const char *name, + int (*read)(char*, int, int), + int (*write)(const char*, int, int)); + +kernel_subsystem_t* subsystem_get_by_name(const char *name); +int subsystem_get_count(void); +kernel_subsystem_t* subsystem_get_by_index(int index); + +#endif diff --git a/src/sys/module_manager.c b/src/sys/module_manager.c new file mode 100644 index 0000000..9a076d3 --- /dev/null +++ b/src/sys/module_manager.c @@ -0,0 +1,29 @@ +#include "module_manager.h" +#include "memory_manager.h" + +#define MAX_MODULES 32 +static kernel_module_t modules[MAX_MODULES]; +static int module_count = 0; + +static void mod_strcpy(char *dest, const char *src) { + while (*src) *dest++ = *src++; + *dest = 0; +} + +void module_manager_register(const char *name, uint64_t addr, uint64_t size) { + if (module_count >= MAX_MODULES) return; + + kernel_module_t *m = &modules[module_count++]; + mod_strcpy(m->name, name); + m->address = addr; + m->size = size; +} + +int module_manager_get_count(void) { + return module_count; +} + +kernel_module_t* module_manager_get_index(int index) { + if (index < 0 || index >= module_count) return NULL; + return &modules[index]; +} diff --git a/src/sys/module_manager.h b/src/sys/module_manager.h new file mode 100644 index 0000000..45838fd --- /dev/null +++ b/src/sys/module_manager.h @@ -0,0 +1,17 @@ +#ifndef MODULE_MANAGER_H +#define MODULE_MANAGER_H + +#include +#include + +typedef struct { + char name[64]; + uint64_t address; + uint64_t size; +} kernel_module_t; + +void module_manager_register(const char *name, uint64_t addr, uint64_t size); +int module_manager_get_count(void); +kernel_module_t* module_manager_get_index(int index); + +#endif diff --git a/src/sys/process.c b/src/sys/process.c index aacc2f2..dae4f42 100644 --- a/src/sys/process.c +++ b/src/sys/process.c @@ -20,7 +20,6 @@ extern void serial_write(const char *str); #define MAX_PROCESSES 16 #define MAX_CPUS_SCHED 32 process_t processes[MAX_PROCESSES] __attribute__((aligned(16))); -int process_count = 0; static process_t* current_process[MAX_CPUS_SCHED] = {0}; // Per-CPU static uint32_t next_pid = 0; static void *free_kernel_stack_later[MAX_CPUS_SCHED] = {0}; @@ -34,9 +33,10 @@ void process_init(void) { } // Current kernel execution is PID 0 - process_t *kernel_proc = &processes[process_count++]; + process_t *kernel_proc = &processes[0]; kernel_proc->pid = next_pid++; kernel_proc->is_user = false; + kernel_proc->is_idle = true; // We don't have its RSP or PML4 yet, but it's already running. // The timer interrupt will naturally capture its context on the first tick! @@ -55,21 +55,39 @@ void process_init(void) { kernel_proc->next = kernel_proc; // Circular linked list kernel_proc->cpu_affinity = 0; // Kernel always on BSP + mem_memset(kernel_proc->cwd, 0, 1024); + kernel_proc->cwd[0] = '/'; current_process[0] = kernel_proc; } process_t* process_create(void (*entry_point)(void), bool is_user) { uint64_t rflags = spinlock_acquire_irqsave(&runqueue_lock); - if (process_count >= MAX_PROCESSES) { + process_t *new_proc = NULL; + for (int i = 0; i < MAX_PROCESSES; i++) { + if (processes[i].pid == 0xFFFFFFFF) { + new_proc = &processes[i]; + break; + } + } + + if (!new_proc) { spinlock_release_irqrestore(&runqueue_lock, rflags); return NULL; } - process_t *new_proc = &processes[process_count++]; new_proc->pid = next_pid++; new_proc->is_user = is_user; + process_t *parent = process_get_current(); + if (parent) { + extern void mem_memcpy(void *dest, const void *src, size_t len); + mem_memcpy(new_proc->cwd, parent->cwd, 1024); + } else { + mem_memset(new_proc->cwd, 0, 1024); + new_proc->cwd[0] = '/'; + } + // 1. Setup Page Table if (is_user) { new_proc->pml4_phys = paging_create_user_pml4_phys(); @@ -163,9 +181,8 @@ process_t* process_create_elf(const char* filepath, const char* args_str) { // Find an available slot for (int i = 0; i < MAX_PROCESSES; i++) { - if (processes[i].pid == 0xFFFFFFFF || i >= process_count) { + if (processes[i].pid == 0xFFFFFFFF) { new_proc = &processes[i]; - if (i >= process_count) process_count = i + 1; break; } } diff --git a/src/sys/process.h b/src/sys/process.h index 44a7320..7fef072 100644 --- a/src/sys/process.h +++ b/src/sys/process.h @@ -52,7 +52,9 @@ typedef struct process { uint64_t ticks; uint64_t sleep_until; size_t used_memory; - uint32_t cpu_affinity; // Which CPU this process runs on (0 = BSP) + uint32_t cpu_affinity; + bool is_idle; + char cwd[1024]; } __attribute__((aligned(16))) process_t; typedef struct { @@ -60,6 +62,7 @@ typedef struct { char name[64]; uint64_t ticks; size_t used_memory; + bool is_idle; } ProcessInfo; void process_init(void); @@ -73,7 +76,7 @@ uint64_t process_terminate_current(void); void process_terminate(process_t *proc); process_t* process_get_by_pid(uint32_t pid); -// SMP: IPI handler for AP scheduling (called from ISR) +// SMP: IPI handler for AP scheduling uint64_t sched_ipi_handler(registers_t *regs); void process_push_gui_event(process_t *proc, gui_event_t *ev); diff --git a/src/sys/smp.c b/src/sys/smp.c index e676a6f..621dece 100644 --- a/src/sys/smp.c +++ b/src/sys/smp.c @@ -10,6 +10,7 @@ #include "paging.h" #include "process.h" #include "work_queue.h" +#include "core/kutils.h" extern void serial_write(const char *str); extern void serial_write_num(uint32_t n); @@ -108,6 +109,11 @@ static void ap_entry(struct limine_smp_info *info) { process_t *ap_idle = process_create(NULL, false); ap_idle->cpu_affinity = my_id; + ap_idle->is_idle = true; + k_strcpy(ap_idle->name, "idle:"); + char id_s[8]; k_itoa(my_id, id_s); + k_strcpy(ap_idle->name + 5, id_s); + process_set_current_for_cpu(my_id, ap_idle); asm volatile("sti"); diff --git a/src/sys/syscall.c b/src/sys/syscall.c index 74eae87..cd72824 100644 --- a/src/sys/syscall.c +++ b/src/sys/syscall.c @@ -861,6 +861,8 @@ static uint64_t syscall_handler_inner(registers_t *regs) { const char *mode = (const char *)arg3; if (!path || !mode) return -1; + // vfs_open now handles normalization internally with process_get_current() + // but let's be explicit if we can. vfs_file_t *vf = vfs_open(path, mode); if (!vf) return -1; @@ -904,12 +906,33 @@ static uint64_t syscall_handler_inner(registers_t *regs) { int fd = (int)arg2; if (fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) return -1; return (uint64_t)vfs_file_size((vfs_file_t*)proc->fds[fd]); + } else if (cmd == FS_CMD_GETCWD) { + char *buf = (char *)arg2; + int size = (int)arg3; + if (!buf || size <= 0) return -1; + int len = (int)k_strlen(proc->cwd); + if (len >= size) return -1; + k_strcpy(buf, proc->cwd); + return (uint64_t)len; + } else if (cmd == FS_CMD_CHDIR) { + const char *path = (const char *)arg2; + if (!path) return -1; + char normalized[VFS_MAX_PATH]; + vfs_normalize_path(proc->cwd, path, normalized); + if (vfs_is_directory(normalized)) { + k_strcpy(proc->cwd, normalized); + return 0; + } + return -1; } else if (cmd == FS_CMD_LIST) { const char *path = (const char *)arg2; FAT32_FileInfo *u_entries = (FAT32_FileInfo *)arg3; int max_entries = (int)arg4; if (!path || !u_entries) return -1; + char normalized[VFS_MAX_PATH]; + vfs_normalize_path(proc->cwd, path, normalized); + // Safety cap for kernel allocation if (max_entries > 256) max_entries = 256; if (max_entries <= 0) return 0; @@ -917,7 +940,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) { vfs_dirent_t *v_entries = (vfs_dirent_t *)kmalloc(sizeof(vfs_dirent_t) * max_entries); if (!v_entries) return -1; - int count = vfs_list_directory(path, v_entries, max_entries); + int count = vfs_list_directory(normalized, v_entries, max_entries); if (count > 0) { for (int i = 0; i < count; i++) { // Direct copy as layouts are now aligned @@ -934,14 +957,19 @@ static uint64_t syscall_handler_inner(registers_t *regs) { } else if (cmd == FS_CMD_DELETE) { const char *path = (const char *)arg2; if (!path) return -1; - return vfs_delete(path) ? 0 : -1; + char normalized[VFS_MAX_PATH]; + vfs_normalize_path(proc->cwd, path, normalized); + return vfs_delete(normalized) ? 0 : -1; } else if (cmd == FS_CMD_GET_INFO) { const char *path = (const char *)arg2; FAT32_FileInfo *u_info = (FAT32_FileInfo *)arg3; if (!path || !u_info) return -1; + char normalized[VFS_MAX_PATH]; + vfs_normalize_path(proc->cwd, path, normalized); + vfs_dirent_t v_info; - int res = vfs_get_info(path, &v_info); + int res = vfs_get_info(normalized, &v_info); if (res == 0) { k_strcpy(u_info->name, v_info.name); u_info->size = v_info.size; @@ -1096,15 +1124,6 @@ static uint64_t syscall_handler_inner(registers_t *regs) { extern void k_beep(int freq, int ms); k_beep(freq, ms); return 0; - } else if (cmd == 15) { // SYSTEM_CMD_MEMINFO - uint64_t *out = (uint64_t *)arg2; - if (!out) return -1; - MemStats stats = memory_get_stats(); - out[0] = stats.total_memory; - out[1] = stats.used_memory; - return 0; - } else if (cmd == 16) { // SYSTEM_CMD_UPTIME - return wm_get_ticks(); } else if (cmd == 17) { // SYSTEM_CMD_PCI_LIST typedef struct { uint16_t vendor; @@ -1265,54 +1284,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) { size_t max_len = (size_t)arg3; extern int network_tcp_recv_nb(void *buf, size_t max_len); return (uint64_t)network_tcp_recv_nb(buf, max_len); - } else if (cmd == SYSTEM_CMD_PROCESS_LIST) { - ProcessInfo *out = (ProcessInfo *)arg2; - int max_procs = (int)arg3; - if (!out) return 0; - - extern process_t processes[]; - - // Dynamically calculate kernel usage as: Total System Used - User Process Sum - MemStats stats = memory_get_stats(); - size_t total_used = stats.used_memory; - size_t user_used = 0; - for (int i = 0; i < 16; i++) { - if (processes[i].pid != 0xFFFFFFFF && processes[i].pid != 0 && processes[i].is_user) { - user_used += processes[i].used_memory; - } - } - if (total_used > user_used) processes[0].used_memory = total_used - user_used; - else processes[0].used_memory = 0; - - int count = 0; - for (int i = 0; i < 16; i++) { - if (processes[i].pid != 0xFFFFFFFF && (processes[i].is_user || processes[i].pid == 0)) { - out[count].pid = processes[i].pid; - extern void mem_memcpy(void *dest, const void *src, size_t len); - mem_memcpy(out[count].name, processes[i].name, 64); - - if (processes[i].pid == 0) { - out[count].name[0] = 'k'; out[count].name[1] = 'e'; out[count].name[2] = 'r'; - out[count].name[3] = 'n'; out[count].name[4] = 'e'; out[count].name[5] = 'l'; - out[count].name[6] = '\0'; - } - - out[count].ticks = processes[i].ticks; - out[count].used_memory = processes[i].used_memory; - - count++; - if (count >= max_procs) break; - } - } - return (uint64_t)count; - } else if (cmd == SYSTEM_CMD_GET_CPU_MODEL) { - char *user_buf = (char *)arg2; - if (!user_buf) return -1; - char model[64]; - platform_get_cpu_model(model); - extern void mem_memcpy(void *dest, const void *src, size_t len); - mem_memcpy(user_buf, model, 49); - return 0; + return -1; } else if (cmd == 47) { // SYSTEM_CMD_SET_RESOLUTION uint16_t req_w = (uint16_t)arg2; uint16_t req_h = (uint16_t)arg3; @@ -1351,12 +1323,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) { return 0; } return -1; - } else if (cmd == 49) { // SYSTEM_CMD_GET_OS_INFO - os_info_t *info = (os_info_t *)arg2; - if (!info) return -1; - extern void get_os_info(os_info_t *info); - get_os_info(info); - return 0; + return -1; } else if (cmd == SYSTEM_CMD_PARALLEL_RUN) { void (*user_fn)(void*) = (void (*)(void*))arg2; void **args = (void **)arg3; diff --git a/src/sys/syscall.h b/src/sys/syscall.h index 86305d7..03a5c12 100644 --- a/src/sys/syscall.h +++ b/src/sys/syscall.h @@ -6,7 +6,6 @@ #include -// Forward declarations typedef struct Window Window; typedef struct registers_t registers_t; @@ -53,11 +52,8 @@ typedef struct { #define SYSTEM_CMD_SET_RAW_MODE 41 #define SYSTEM_CMD_TCP_RECV_NB 42 #define SYSTEM_CMD_YIELD 43 -#define SYSTEM_CMD_PROCESS_LIST 44 -#define SYSTEM_CMD_GET_CPU_MODEL 45 #define SYSTEM_CMD_SLEEP 46 #define SYSTEM_CMD_SET_RESOLUTION 47 -#define SYSTEM_CMD_GET_OS_INFO 49 #define SYSTEM_CMD_PARALLEL_RUN 50 void syscall_init(void); diff --git a/src/sys/sysfs_init.c b/src/sys/sysfs_init.c new file mode 100644 index 0000000..38b5489 --- /dev/null +++ b/src/sys/sysfs_init.c @@ -0,0 +1,201 @@ +#include "kernel_subsystem.h" +#include "smp.h" +#include "pci.h" +#include "memory_manager.h" +#include "module_manager.h" +#include "io.h" +#include "core/kutils.h" +#include "wm/graphics.h" +#include "core/platform.h" + +// --- Helper: itoa --- +static void sys_itoa(int n, char *s) { + k_itoa(n, s); +} + +// --- Graphics Implementation --- +static int read_gfx_drm(char *buf, int size, int offset) { + char out[512]; + k_memset(out, 0, 512); + k_strcpy(out, "Driver: Simple Framebuffer\n"); + k_strcpy(out + k_strlen(out), "Resolution: "); + char s[32]; k_itoa(get_screen_width(), s); + k_strcpy(out + k_strlen(out), s); + k_strcpy(out + k_strlen(out), "x"); + k_itoa(get_screen_height(), s); + k_strcpy(out + k_strlen(out), s); + k_strcpy(out + k_strlen(out), "\nDepth: "); + k_itoa(graphics_get_fb_bpp(), s); + k_strcpy(out + k_strlen(out), s); + k_strcpy(out + k_strlen(out), " bpp\nAddress: 0x"); + k_itoa_hex(graphics_get_fb_addr(), s); + k_strcpy(out + k_strlen(out), s); + k_strcpy(out + k_strlen(out), "\n"); + + int len = (int)k_strlen(out); + if (offset >= len) return 0; + int to_copy = len - offset; + if (to_copy > size) to_copy = size; + k_memcpy(buf, out + offset, to_copy); + return to_copy; +} + +// --- Memory Tracking Implementation --- +static int read_mem_tracking(char *buf, int size, int offset) { + MemStats stats = memory_get_stats(); + char out[1024]; + k_memset(out, 0, 1024); + + k_strcpy(out, "--- Kernel Heap Tracking ---\n"); + k_strcpy(out + k_strlen(out), "Allocated Blocks: "); + char s[32]; k_itoa(stats.allocated_blocks, s); + k_strcpy(out + k_strlen(out), s); + k_strcpy(out + k_strlen(out), "\nFragmentation: "); + k_itoa(stats.fragmentation_percent, s); + k_strcpy(out + k_strlen(out), s); + k_strcpy(out + k_strlen(out), "%\n"); + + int len = (int)k_strlen(out); + if (offset >= len) return 0; + int to_copy = len - offset; + if (to_copy > size) to_copy = size; + k_memcpy(buf, out + offset, to_copy); + return to_copy; +} + +// --- Module Implementation --- +static int read_sys_modules(char *buf, int size, int offset) { + int count = module_manager_get_count(); + char out[2048] = "Loaded Modules:\n"; + + for (int i = 0; i < count; i++) { + kernel_module_t *mod = module_manager_get_index(i); + k_strcpy(out + k_strlen(out), " - "); + k_strcpy(out + k_strlen(out), mod->name); + k_strcpy(out + k_strlen(out), " ("); + char sz_s[16]; k_itoa(mod->size / 1024, sz_s); + k_strcpy(out + k_strlen(out), sz_s); + k_strcpy(out + k_strlen(out), " KB)\n"); + } + + int len = k_strlen(out); + if (offset >= len) return 0; + int to_copy = len - offset; + if (to_copy > size) to_copy = size; + k_memcpy(buf, out + offset, to_copy); + return to_copy; +} + +// --- PCI Bus Implementation --- +static int read_pci_bus(char *buf, int size, int offset) { + pci_device_t devices[64]; + int count = pci_enumerate_devices(devices, 64); + + char out[4096]; + k_memset(out, 0, 4096); + k_strcpy(out, "PCI Bus Devices:\n"); + for (int i = 0; i < count; i++) { + char line[128]; + k_strcpy(line, " ["); + char b_s[8]; k_itoa(devices[i].bus, b_s); + k_strcpy(line + k_strlen(line), b_s); + k_strcpy(line + k_strlen(line), ":"); + k_itoa(devices[i].device, b_s); + k_strcpy(line + k_strlen(line), b_s); + k_strcpy(line + k_strlen(line), ":"); + k_itoa(devices[i].function, b_s); + k_strcpy(line + k_strlen(line), b_s); + k_strcpy(line + k_strlen(line), "] Vendor:"); + k_itoa_hex(devices[i].vendor_id, b_s); + k_strcpy(line + k_strlen(line), b_s); + k_strcpy(line + k_strlen(line), " Device:"); + k_itoa_hex(devices[i].device_id, b_s); + k_strcpy(line + k_strlen(line), b_s); + k_strcpy(line + k_strlen(line), " Class:"); + k_itoa_hex(devices[i].class_code, b_s); + k_strcpy(line + k_strlen(line), b_s); + k_strcpy(line + k_strlen(line), "\n"); + + if (k_strlen(out) + k_strlen(line) < 4095) { + k_strcpy(out + k_strlen(out), line); + } + } + + int len = (int)k_strlen(out); + if (offset >= len) return 0; + int to_copy = len - offset; + if (to_copy > size) to_copy = size; + k_memcpy(buf, out + offset, to_copy); + return to_copy; +} + +// --- CPU System Implementation --- +static int read_cpu_info(char *buf, int size, int offset) { + char out[1024]; + k_memset(out, 0, 1024); + char vendor[16]; + platform_get_cpu_vendor(vendor); + k_strcpy(out + k_strlen(out), vendor); + k_strcpy(out + k_strlen(out), "\nCores: "); + char c_s[16]; k_itoa(smp_cpu_count(), c_s); + k_strcpy(out + k_strlen(out), c_s); + k_strcpy(out + k_strlen(out), "\nSpeed: ~3.00 GHz\nFeatures: sse sse2 sse3 apic smp\n"); + + int len = (int)k_strlen(out); + if (offset >= len) return 0; + int to_copy = len - offset; + if (to_copy > size) to_copy = size; + k_memcpy(buf, out + offset, to_copy); + return to_copy; +} + +// --- GPIO Implementation --- +static int read_gpio_debug(char *buf, int size, int offset) { + uint8_t p64 = inb(0x64); + char out[64] = "Port 0x64 Status: "; + char s[16]; k_itoa(p64, s); + k_strcpy(out + k_strlen(out), s); + k_strcpy(out + k_strlen(out), "\n"); + + int len = k_strlen(out); + if (offset >= len) return 0; + int to_copy = len - offset; + if (to_copy > size) to_copy = size; + k_memcpy(buf, out + offset, to_copy); + return to_copy; +} + +void sysfs_init_subsystems(void) { + kernel_subsystem_t *kernel, *devices, *bus, *class, *debug, *mem_debug; + + subsystem_register("kernel", &kernel); + subsystem_register("devices", &devices); + subsystem_register("bus", &bus); + subsystem_register("class", &class); + subsystem_register("kernel/debug", &debug); + + // CPU info + subsystem_add_file(kernel, "cpuinfo", read_cpu_info, NULL); + + // Bus info + kernel_subsystem_t *pci_bus; + subsystem_register("bus/pci", &pci_bus); + subsystem_add_file(pci_bus, "devices", read_pci_bus, NULL); + + // Module info + kernel_subsystem_t *modules_sub; + subsystem_register("module", &modules_sub); + subsystem_add_file(modules_sub, "loaded", read_sys_modules, NULL); + + // Memory Tracking + subsystem_register("kernel/debug/memory", &mem_debug); + subsystem_add_file(mem_debug, "tracking", read_mem_tracking, NULL); + + // Graphics DRM + kernel_subsystem_t *gfx_debug; + subsystem_register("kernel/debug/graphics", &gfx_debug); + subsystem_add_file(gfx_debug, "drm", read_gfx_drm, NULL); + + // GPIO + subsystem_add_file(debug, "gpio", read_gpio_debug, NULL); +} diff --git a/src/userland/cli/man.c b/src/userland/cli/man.c index eb82125..1fb8b55 100644 --- a/src/userland/cli/man.c +++ b/src/userland/cli/man.c @@ -14,7 +14,7 @@ int main(int argc, char **argv) { printf("Manual for: %s\n", argv[1]); printf("---------------------------\n"); - strcpy(path, "A:/Library/man/"); + strcpy(path, "/Library/man/"); strcat(path, argv[1]); strcat(path, ".txt"); diff --git a/src/userland/cli/sysfetch.c b/src/userland/cli/sysfetch.c index 2faf849..2ab60cd 100644 --- a/src/userland/cli/sysfetch.c +++ b/src/userland/cli/sysfetch.c @@ -9,15 +9,6 @@ #define MAX_ASCII_WIDTH 80 #define MAX_INFO_LINES 10 -static char* strchr(const char *s, int c) { - while (*s != (char)c) { - if (!*s++) { - return 0; - } - } - return (char *)s; -} - static char* strncpy(char *dest, const char *src, size_t n) { size_t i; for (i = 0; i < n && src[i] != '\0'; i++) dest[i] = src[i]; @@ -117,7 +108,7 @@ static char* trim(char *str) { } static void set_config_defaults() { - strcpy(config.ascii_art_file, "A:/Library/art/boredos.txt"); + strcpy(config.ascii_art_file, "/Library/art/boredos.txt"); strcpy(config.user_host_string, "root@boredos"); strcpy(config.separator, "------------"); strcpy(config.os_label, "OS"); @@ -160,7 +151,7 @@ static void parse_config(char* buffer) { static void load_config() { set_config_defaults(); - int fd = sys_open("A:/Library/conf/sysfetch.cfg", "r"); + int fd = sys_open("/Library/conf/sysfetch.cfg", "r"); if (fd < 0) return; char *buffer = malloc(4096); @@ -237,52 +228,82 @@ int main(int argc, char **argv) { if (config.separator[0]) { strcpy(info_lines[info_line_count++], config.separator); } - os_info_t os_info; - sys_get_os_info(&os_info); + // Helper for proc parsing + auto int find_v(const char *b, const char *k) { + char *p = (char*)b; int kl = strlen(k); + while (*p) { + if (memcmp(p, k, kl) == 0 && p[kl] == ':') { + p += kl + 1; while (*p == ' ') p++; return atoi(p); + } + while (*p && *p != '\n') p++; if (*p == '\n') p++; + } + return 0; + } + + int fd_v = sys_open("/proc/version", "r"); + char v_buf[512]; + if (fd_v >= 0) { + int b = sys_read(fd_v, v_buf, 511); + v_buf[b] = 0; + sys_close(fd_v); + } else strcpy(v_buf, "Unknown"); if (config.os_label[0]) { strcpy(info_lines[info_line_count], config.os_label); strcat(info_lines[info_line_count], ": "); - strcat(info_lines[info_line_count], os_info.os_name); - strcat(info_lines[info_line_count], " V"); - strcat(info_lines[info_line_count], os_info.os_version); - strcat(info_lines[info_line_count], " '"); - strcat(info_lines[info_line_count], os_info.os_codename); - strcat(info_lines[info_line_count], "'"); + // Parse "BoredOS [codename] Version X.Y.Z" + strcat(info_lines[info_line_count], v_buf); + // Truncate at newline + char *nl = strchr(info_lines[info_line_count], '\n'); + if (nl) *nl = 0; info_line_count++; } if (config.kernel_label[0]) { strcpy(info_lines[info_line_count], config.kernel_label); strcat(info_lines[info_line_count], ": "); - strcat(info_lines[info_line_count], os_info.kernel_name); - strcat(info_lines[info_line_count], " V"); - strcat(info_lines[info_line_count], os_info.kernel_version); - strcat(info_lines[info_line_count], " "); - strcat(info_lines[info_line_count], os_info.build_arch); + char *kstart = strchr(v_buf, '\n'); + if (kstart) { + strcat(info_lines[info_line_count], kstart + 1); + char *knext = strchr(info_lines[info_line_count], '\n'); + if (knext) *knext = 0; + } else strcat(info_lines[info_line_count], "Unknown"); info_line_count++; } if (config.uptime_label[0]) { - uint64_t ticks = sys_system(16, 0, 0, 0, 0); - int minutes = ticks / 3600; // 60Hz timer - strcpy(info_lines[info_line_count], config.uptime_label); - strcat(info_lines[info_line_count], ": "); - itoa(minutes, temp_buf); - strcat(info_lines[info_line_count], temp_buf); - strcat(info_lines[info_line_count++], " mins"); + int fd_u = sys_open("/proc/uptime", "r"); + if (fd_u >= 0) { + char u_buf[64]; + int b = sys_read(fd_u, u_buf, 63); + u_buf[b] = 0; + sys_close(fd_u); + int sec = atoi(u_buf); + int mins = sec / 60; + strcpy(info_lines[info_line_count], config.uptime_label); + strcat(info_lines[info_line_count], ": "); + itoa(mins, temp_buf); + strcat(info_lines[info_line_count], temp_buf); + strcat(info_lines[info_line_count++], " mins"); + } } if (config.shell_label[0]) { strcpy(info_lines[info_line_count], config.shell_label); strcat(info_lines[info_line_count++], ": bsh"); } if (config.memory_label[0]) { - uint64_t mem[2]; - if (sys_system(15, (uint64_t)mem, 0, 0, 0) == 0) { + int fd_m = sys_open("/proc/meminfo", "r"); + if (fd_m >= 0) { + char m_buf[512]; + int b = sys_read(fd_m, m_buf, 511); + m_buf[b] = 0; + sys_close(fd_m); + int total = find_v(m_buf, "MemTotal"); + int used = find_v(m_buf, "MemUsed"); strcpy(info_lines[info_line_count], config.memory_label); strcat(info_lines[info_line_count], ": "); - itoa((int)(mem[1] / 1024 / 1024), temp_buf); + itoa(used / 1024, temp_buf); strcat(info_lines[info_line_count], temp_buf); strcat(info_lines[info_line_count], "MiB / "); - itoa((int)(mem[0] / 1024 / 1024), temp_buf); + itoa(total / 1024, temp_buf); strcat(info_lines[info_line_count], temp_buf); strcat(info_lines[info_line_count++], "MiB"); } diff --git a/src/userland/games/doom/boredos_libc.c b/src/userland/games/doom/boredos_libc.c index e46d55a..165bd0f 100644 --- a/src/userland/games/doom/boredos_libc.c +++ b/src/userland/games/doom/boredos_libc.c @@ -149,26 +149,12 @@ char *strrchr(const char *s, int c) { if (c == 0) last = s; return (char*)last; } -char *strchr(const char *s, int c) { - while (*s) { if (*s == c) return (char*)s; s++; } - if (c == 0) return (char*)s; - return NULL; -} char *strdup(const char *s) { size_t len = strlen(s) + 1; char *dup = malloc(len); if (dup) memcpy(dup, s, len); return dup; } -char *strstr(const char *haystack, const char *needle) { - size_t n = strlen(needle); - if (!n) return (char *)haystack; - while (*haystack) { - if (!strncmp(haystack, needle, n)) return (char *)haystack; - haystack++; - } - return NULL; -} int toupper(int c) { return (c >= 'a' && c <= 'z') ? c - 32 : c; } int tolower(int c) { return (c >= 'A' && c <= 'Z') ? c + 32 : c; } diff --git a/src/userland/games/doom/doomgeneric_boredos.c b/src/userland/games/doom/doomgeneric_boredos.c index 6f5bb0d..6a6abf0 100644 --- a/src/userland/games/doom/doomgeneric_boredos.c +++ b/src/userland/games/doom/doomgeneric_boredos.c @@ -39,8 +39,19 @@ void DG_SleepMs(uint32_t ms) { } uint32_t DG_GetTicksMs(void) { - uint64_t ticks = sys_system(16, 0, 0, 0, 0); // SYSTEM_CMD_UPTIME = 16 (100Hz) - return (uint32_t)(ticks * 10); + int fd = sys_open("/proc/uptime", "r"); + if (fd < 0) return 0; + char buf[128]; + int bytes = sys_read(fd, buf, 127); + sys_close(fd); + if (bytes <= 0) return 0; + buf[bytes] = 0; + + char *p = strstr(buf, "Raw_Ticks:"); + if (!p) return 0; + uint32_t ticks = atoi(p + 10); + // 60Hz to ms: ticks * 1000 / 60 = ticks * 50 / 3 + return (ticks * 50) / 3; } void DG_SetWindowTitle(const char * title) { @@ -108,7 +119,7 @@ int DG_GetKey(int* pressed, unsigned char* key) { int main(int argc, char** argv) { (void)argc; (void)argv; - char* fake_argv[] = {"doom", "-iwad", "A:/Library/DOOM/doom1.wad"}; + char* fake_argv[] = {"doom", "-iwad", "/Library/DOOM/doom1.wad"}; doomgeneric_Create(3, fake_argv); while (1) { diff --git a/src/userland/gui/about.c b/src/userland/gui/about.c index 34dbc5a..3a5763e 100644 --- a/src/userland/gui/about.c +++ b/src/userland/gui/about.c @@ -95,36 +95,39 @@ static void about_paint(ui_window_t win) { draw_ascii_logo(win, 14, offset_y); int fh = ui_get_font_height(); - os_info_t os_info; - sys_get_os_info(&os_info); - - char os_name_str[128]; - os_name_str[0] = 0; - strcat(os_name_str, os_info.os_name); - strcat(os_name_str, " '"); - strcat(os_name_str, os_info.os_codename); - strcat(os_name_str, "'"); + int fd_v = sys_open("/proc/version", "r"); + char v_buf[1024]; v_buf[0] = 0; + if (fd_v >= 0) { + int b = sys_read(fd_v, v_buf, 1023); + v_buf[b] = 0; + sys_close(fd_v); + } - char os_version_str[128]; - os_version_str[0] = 0; - strcat(os_version_str, os_info.os_name); - strcat(os_version_str, " Version "); - strcat(os_version_str, os_info.os_version); - - char kernel_version_str[128]; - kernel_version_str[0] = 0; - strcat(kernel_version_str, os_info.kernel_name); - strcat(kernel_version_str, " Version "); - strcat(kernel_version_str, os_info.kernel_version); - strcat(kernel_version_str, " "); - strcat(kernel_version_str, os_info.build_arch); + char os_name_str[128] = "Unknown OS"; + char os_version_str[128] = "Unknown Version"; + char kernel_version_str[128] = "Unknown Kernel"; + char build_date_str[128] = "Unknown Build"; - char build_date_str[128]; - build_date_str[0] = 0; - strcat(build_date_str, "Build Date: "); - strcat(build_date_str, os_info.build_date); - strcat(build_date_str, " "); - strcat(build_date_str, os_info.build_time); + if (v_buf[0]) { + char *line1 = v_buf; + char *line2 = strchr(line1, '\n'); if (line2) { *line2 = 0; line2++; } + char *line3 = line2 ? strchr(line2, '\n') : NULL; if (line3) { *line3 = 0; line3++; } + + strcpy(os_name_str, line1); + if (line2) { + strcpy(os_version_str, line2); + } + if (line3) { + strcpy(kernel_version_str, line3); + char *line4 = strchr(line3, '\n'); + if (line4) { + *line4 = 0; line4++; + strcpy(build_date_str, line4); + char *line5 = strchr(build_date_str, '\n'); + if (line5) *line5 = 0; + } + } + } ui_draw_string(win, offset_x, offset_y + 105, os_name_str, 0xFFFFFFFF); ui_draw_string(win, offset_x, offset_y + 105 + fh, os_version_str, 0xFFFFFFFF); diff --git a/src/userland/gui/browser.c b/src/userland/gui/browser.c index b99177f..ab7aa7f 100644 --- a/src/userland/gui/browser.c +++ b/src/userland/gui/browser.c @@ -32,19 +32,6 @@ static int win_h = 960; static char history_stack[HISTORY_MAX][512]; static int history_count = 0; -static char* strstr(const char* haystack, const char* needle) { - if (!*needle) return (char*)haystack; - for (; *haystack; haystack++) { - const char *h = haystack; - const char *n = needle; - while (*h && *n && *h == *n) { - h++; n++; - } - if (!*n) return (char*)haystack; - } - return NULL; -} - static char* str_istrstr(const char* haystack, const char* needle) { if (!*needle) return (char*)haystack; for (; *haystack; haystack++) { diff --git a/src/userland/gui/notepad.c b/src/userland/gui/notepad.c index 4230300..1e586e3 100644 --- a/src/userland/gui/notepad.c +++ b/src/userland/gui/notepad.c @@ -37,7 +37,7 @@ static void notepad_ensure_cursor_visible(int h) { } static void notepad_load_state() { - int fd = sys_open("A:/tmp/notepad_state.txt", "r"); + int fd = sys_open("/tmp/notepad_state.txt", "r"); if (fd >= 0) { sys_serial_write("Notepad: Loading state...\n"); buf_len = sys_read(fd, buffer, NOTEPAD_BUF_SIZE - 1); @@ -50,8 +50,8 @@ static void notepad_load_state() { static void notepad_save_state() { // Ensure dir exists - sys_mkdir("A:/tmp"); - int fd = sys_open("A:/tmp/notepad_state.txt", "w"); + sys_mkdir("/tmp"); + int fd = sys_open("/tmp/notepad_state.txt", "w"); if (fd >= 0) { sys_write_fs(fd, buffer, buf_len); sys_close(fd); diff --git a/src/userland/gui/paint.c b/src/userland/gui/paint.c index bdbd8d5..db72643 100644 --- a/src/userland/gui/paint.c +++ b/src/userland/gui/paint.c @@ -28,7 +28,7 @@ static uint32_t *canvas_buffer = NULL; static uint32_t current_color = COLOR_BLACK; static int last_mx = -1; static int last_my = -1; -static char current_file_path[256] = "/Desktop/drawing.pnt"; +static char current_file_path[256] = "/root/Desktop/drawing.pnt"; static void paint_strcpy(char *dest, const char *src) { while (*src) *dest++ = *src++; diff --git a/src/userland/gui/screenshot.c b/src/userland/gui/screenshot.c index cc01537..58809a0 100644 --- a/src/userland/gui/screenshot.c +++ b/src/userland/gui/screenshot.c @@ -84,7 +84,7 @@ int main(int argc, char **argv) { uint64_t dt[6] = {0}; syscall2(SYS_GUI, GUI_CMD_GET_DATETIME, (uint64_t)dt); - strcpy(g_filename, "/Desktop/screenshot-"); + strcpy(g_filename, "/root/Desktop/screenshot-"); append_num((int)dt[0], 4); // Year append_num((int)dt[1], 2); // Month append_num((int)dt[2], 2); // Day @@ -110,7 +110,7 @@ int main(int argc, char **argv) { // Show notification char notif[256] = "Saved "; - strcat(notif, g_filename + 9); // Skip "/Desktop/" + strcat(notif, g_filename + 14); // Skip "/root/Desktop/" syscall2(SYS_GUI, GUI_CMD_SHOW_NOTIFICATION, (uint64_t)notif); } else { res = 0; diff --git a/src/userland/gui/taskman.c b/src/userland/gui/taskman.c index c9a7b75..13e4cd9 100644 --- a/src/userland/gui/taskman.c +++ b/src/userland/gui/taskman.c @@ -32,38 +32,111 @@ static uint64_t kernel_ticks_prev = 0; static uint64_t total_mem_system = 0; static uint64_t used_mem_system = 0; static char cpu_model_name[64] = "Unknown CPU"; +static int cpu_cores = 1; -typedef struct { - size_t total_memory; - size_t used_memory; - size_t available_memory; - size_t allocated_blocks; - size_t free_blocks; - size_t largest_free_block; - size_t smallest_free_block; - size_t fragmentation_percent; - size_t peak_memory_used; -} MemStats; +static int find_value(const char *buf, const char *key) { + char *p = (char*)buf; + int key_len = strlen(key); + while (*p) { + if (memcmp(p, key, key_len) == 0 && p[key_len] == ':') { + p += key_len + 1; + while (*p == ' ') p++; + return atoi(p); + } + while (*p && *p != '\n') p++; + if (*p == '\n') p++; + } + return 0; +} + +static void find_string(const char *buf, const char *key, char *out, int max_len) { + char *p = (char*)buf; + int key_len = strlen(key); + while (*p) { + if (memcmp(p, key, key_len) == 0 && p[key_len] == ':') { + p += key_len + 1; + while (*p == ' ') p++; + int i = 0; + while (*p && *p != '\n' && i < max_len - 1) { + out[i++] = *p++; + } + out[i] = 0; + return; + } + while (*p && *p != '\n') p++; + if (*p == '\n') p++; + } + strcpy(out, "Unknown"); +} static void update_proc_list(void) { - proc_count = sys_system(SYSTEM_CMD_PROCESS_LIST, (uint64_t)proc_list, 32, 0, 0); - - uint64_t uptime_now = sys_system(SYSTEM_CMD_UPTIME, 0, 0, 0, 0); + FAT32_FileInfo entries[64]; + int count = sys_list("/proc", entries, 64); + if (count < 0) return; + + proc_count = 0; uint64_t user_ticks_now = 0; - - for (int i = 0; i < proc_count; i++) { - if (proc_list[i].pid != 0) { - user_ticks_now += proc_list[i].ticks; + + for (int i = 0; i < count; i++) { + if (entries[i].is_directory) { + // Check if name is numeric (PID) + bool numeric = true; + for (int j = 0; entries[i].name[j]; j++) { + if (entries[i].name[j] < '0' || entries[i].name[j] > '9') { + numeric = false; + break; + } + } + if (!numeric) continue; + + int pid = atoi(entries[i].name); + char path[64]; + strcpy(path, "/proc/"); + strcat(path, entries[i].name); + strcat(path, "/status"); + + int fd = sys_open(path, "r"); + if (fd >= 0) { + char buf[512]; + int bytes = sys_read(fd, buf, 511); + sys_close(fd); + if (bytes > 0) { + buf[bytes] = 0; + proc_list[proc_count].pid = pid; + find_string(buf, "Name", proc_list[proc_count].name, 64); + proc_list[proc_count].used_memory = (size_t)find_value(buf, "Memory") * 1024; + uint64_t ticks = (uint64_t)find_value(buf, "Ticks"); + proc_list[proc_count].ticks = ticks; + + proc_list[proc_count].is_idle = find_value(buf, "Idle") == 1; + + if (!proc_list[proc_count].is_idle) user_ticks_now += ticks; + proc_count++; + if (proc_count >= 32) break; + } + } } } - + + // Global stats + int fd_u = sys_open("/proc/uptime", "r"); + uint64_t uptime_now = 0; + if (fd_u >= 0) { + char buf[256]; + int bytes = sys_read(fd_u, buf, 255); + sys_close(fd_u); + if (bytes > 0) { + buf[bytes] = 0; + uptime_now = (uint64_t)find_value(buf, "Raw_Ticks"); + } + } + if (uptime_prev > 0) { uint64_t total_delta = uptime_now - uptime_prev; if (total_delta > 0) { - uint64_t used_delta = user_ticks_now - kernel_ticks_prev; // Reusing the global state variable for prev user_ticks - - // On a 4 CPU system, theoretically used_delta can be 4x total_delta - int usage = (int)((used_delta * 100) / (total_delta * 4)); + uint64_t used_delta = user_ticks_now - kernel_ticks_prev; + int cores = cpu_cores > 0 ? cpu_cores : 1; + int usage = (int)((used_delta * 100) / (total_delta * cores)); if (usage > 100) usage = 100; cpu_history[history_idx] = usage; } @@ -72,11 +145,18 @@ static void update_proc_list(void) { uptime_prev = uptime_now; kernel_ticks_prev = user_ticks_now; - MemStats stats; - sys_system(SYSTEM_CMD_MEMINFO, (uint64_t)&stats, 0, 0, 0); - total_mem_system = stats.total_memory; - used_mem_system = stats.used_memory; - mem_history[history_idx] = (int)(stats.used_memory / 1024); + int fd_m = sys_open("/proc/meminfo", "r"); + if (fd_m >= 0) { + char buf[1024]; + int bytes = sys_read(fd_m, buf, 1023); + sys_close(fd_m); + if (bytes > 0) { + buf[bytes] = 0; + total_mem_system = (uint64_t)find_value(buf, "MemTotal") * 1024; + used_mem_system = (uint64_t)find_value(buf, "MemUsed") * 1024; + mem_history[history_idx] = (int)(used_mem_system / 1024); + } + } history_idx = (history_idx + 1) % GRAPH_POINTS; } @@ -168,9 +248,12 @@ static void draw_taskman(void) { // Memory Graph Area ui_draw_string(win_taskman, 205, 10, "MEMORY", COLOR_MEM); char mem_pct_label[16]; - int current_mem_pct = 0; - if (total_mem_system > 0) current_mem_pct = (int)((used_mem_system * 100) / total_mem_system); - itoa(current_mem_pct, mem_pct_label); + int current_mem_pct_x10 = 0; + if (total_mem_system > 0) current_mem_pct_x10 = (int)((used_mem_system * 1000) / total_mem_system); + itoa(current_mem_pct_x10 / 10, mem_pct_label); + strcat(mem_pct_label, "."); + char frac[4]; itoa(current_mem_pct_x10 % 10, frac); + strcat(mem_pct_label, frac); strcat(mem_pct_label, "%"); ui_draw_string(win_taskman, 340, 10, mem_pct_label, COLOR_MEM); @@ -255,8 +338,18 @@ static void draw_taskman(void) { int main(void) { win_taskman = ui_window_create("Task Manager", 100, 100, 400, 480); - // Fetch CPU model - sys_system(SYSTEM_CMD_GET_CPU_MODEL, (uint64_t)cpu_model_name, 0, 0, 0); + int fd_c = sys_open("/proc/cpuinfo", "r"); + if (fd_c >= 0) { + char buf[1024]; + int bytes = sys_read(fd_c, buf, 1023); + sys_close(fd_c); + if (bytes > 0) { + buf[bytes] = 0; + find_string(buf, "Processor", cpu_model_name, 64); + int cores = find_value(buf, "Cores"); + if (cores > 0) cpu_cores = cores; + } + } for(int i=0; icurrent_dir, full_path, normalized_path); cmd_update_dir(normalized_path); cmd_write("Changed to: "); @@ -1071,7 +1071,7 @@ static void internal_cmd_txtedit(char *args) { cmd_write("\n"); cmd_is_waiting_for_process = true; - process_t *proc = process_create_elf("A:/bin/txtedit.elf", normalized_path); + process_t *proc = process_create_elf("/bin/txtedit.elf", normalized_path); if (proc) { proc->is_terminal_proc = true; proc->ui_window = &win_cmd; @@ -1537,7 +1537,7 @@ static void cmd_exec_single(char *cmd) { } } - // Check for executable in Current Directory or A:/bin/ + // Check for executable in Current Directory or /bin/ char search_path[512]; // Check if the command already ends in .elf (case insensitive) @@ -2104,11 +2104,12 @@ void cmd_reset(void) { } static void create_ramfs_files(void) { - if (!fat32_exists("Documents")) fat32_mkdir("Documents"); - if (!fat32_exists("Projects")) fat32_mkdir("Projects"); - if (!fat32_exists("Documents/Important")) fat32_mkdir("Documents/Important"); - if (!fat32_exists("Apps")) fat32_mkdir("Apps"); - if (!fat32_exists("Desktop")) fat32_mkdir("Desktop"); + if (!fat32_exists("root")) fat32_mkdir("root"); + if (!fat32_exists("root/Documents")) fat32_mkdir("root/Documents"); + if (!fat32_exists("root/Documents/Important")) fat32_mkdir("root/Documents/Important"); + if (!fat32_exists("root/Apps")) fat32_mkdir("root/Apps"); + if (!fat32_exists("root/Desktop")) fat32_mkdir("root/Desktop"); + if (!fat32_exists("root/projects")) fat32_mkdir("root/projects"); if (!fat32_exists("RecycleBin")) fat32_mkdir("RecycleBin"); if (!fat32_exists("Library/conf")) fat32_mkdir("Library/conf"); @@ -2156,7 +2157,7 @@ static void create_ramfs_files(void) { "// BoredOS System Fetch Configuration\n" "// ----------------------------------\n" "// To use custom ascii art, uncomment the line below and point it to your file.\n" - "ascii_art_file=A:/Library/art/boredos.txt\n" + "ascii_art_file=/Library/art/boredos.txt\n" "user_host_string=root@boredos\n" "separator=------------\n" "\n" @@ -2192,7 +2193,7 @@ static void create_ramfs_files(void) { - FAT32_FileHandle *fh = fat32_open("Apps/README.md", "w"); + FAT32_FileHandle *fh = fat32_open("root/Apps/README.md", "w"); if (fh) { const char *content = "# All compiled C files in this directory are openable from any other directory by typing in the name of the compiled file by typing in the name of the compiled file.\n\n" @@ -2202,24 +2203,24 @@ static void create_ramfs_files(void) { fat32_close(fh); } - fh = fat32_open("Documents/notes.txt", "w"); + fh = fat32_open("root/Documents/notes.txt", "w"); if (fh) { const char *content = "My Notes\n\n- First note\n- Second note\n"; fat32_write(fh, (void *)content, 39); fat32_close(fh); } - fh = fat32_open("Projects/project1.txt", "w"); + fh = fat32_open("root/projects/project1.txt", "w"); if (fh) { const char *content = "Project 1\n\nStatus: In Progress\n"; fat32_write(fh, (void *)content, 32); fat32_close(fh); } - fat32_open("Desktop/Recycle Bin.shortcut", "w"); + fat32_open("root/Desktop/Recycle Bin.shortcut", "w"); - fh = fat32_open("Apps/wordofgod.c", "w"); + fh = fat32_open("root/Apps/wordofgod.c", "w"); if (fh) { // Buffer the entire file content to write in one go // This prevents issues with multiple small writes causing truncation @@ -2273,7 +2274,7 @@ static void create_ramfs_files(void) { fat32_close(fh); } - fh = fat32_open("Apps/DOOM.c", "w"); + fh = fat32_open("root/Apps/DOOM.c", "w"); if (fh) { const char *content = "int main(){\n" @@ -2324,7 +2325,11 @@ void cmd_init(void) { if (state) { state->current_dir[0] = '/'; - state->current_dir[1] = 0; + state->current_dir[1] = 'r'; + state->current_dir[2] = 'o'; + state->current_dir[3] = 'o'; + state->current_dir[4] = 't'; + state->current_dir[5] = 0; win_cmd.data = state; cmd_state = state; // Set static pointer } diff --git a/src/wm/explorer.c b/src/wm/explorer.c index 4570789..b2a21c7 100644 --- a/src/wm/explorer.c +++ b/src/wm/explorer.c @@ -240,8 +240,8 @@ static void explorer_draw_icon_label(int x, int y, const char *label, uint32_t c static bool check_desktop_limit_explorer(Window *win) { ExplorerState *state = (ExplorerState*)win->data; - if (explorer_str_starts_with(state->current_path, "/Desktop")) { - if (explorer_strcmp(state->current_path, "/Desktop") == 0 || explorer_strcmp(state->current_path, "/Desktop/") == 0) { // Check if root desktop + if (explorer_str_starts_with(state->current_path, "/root/Desktop")) { + if (explorer_strcmp(state->current_path, "/root/Desktop") == 0 || explorer_strcmp(state->current_path, "/root/Desktop/") == 0) { // Check if root desktop if (state->item_count >= desktop_max_cols * (desktop_max_rows_per_col > 1 ? desktop_max_rows_per_col - 1 : 0)) { state->dialog_state = DIALOG_ERROR; explorer_strcpy(state->dialog_input, "Desktop is full!"); diff --git a/src/wm/graphics.c b/src/wm/graphics.c index 0c52643..8315508 100644 --- a/src/wm/graphics.c +++ b/src/wm/graphics.c @@ -108,6 +108,14 @@ int get_screen_height(void) { return g_fb ? g_fb->height : 0; } +uint64_t graphics_get_fb_addr(void) { + return g_fb ? (uint64_t)g_fb->address : 0; +} + +int graphics_get_fb_bpp(void) { + return g_fb ? g_fb->bpp : 0; +} + // Merge new dirty rect with existing one static void merge_dirty_rect(int x, int y, int w, int h) { if (!g_dirty.active) { diff --git a/src/wm/graphics.h b/src/wm/graphics.h index 2d8e09d..e072ef7 100644 --- a/src/wm/graphics.h +++ b/src/wm/graphics.h @@ -42,6 +42,8 @@ void draw_boredos_logo(int x, int y, int scale); // Get screen dimensions int get_screen_width(void); int get_screen_height(void); +uint64_t graphics_get_fb_addr(void); +int graphics_get_fb_bpp(void); void graphics_update_resolution(int width, int height, int bpp, void* fb_addr, int color_mode); // Dirty rectangle management diff --git a/src/wm/wm.c b/src/wm/wm.c index 4c2d677..16764e4 100644 --- a/src/wm/wm.c +++ b/src/wm/wm.c @@ -188,7 +188,7 @@ static void refresh_desktop_icons(void) { FAT32_FileInfo *files = (FAT32_FileInfo*)kmalloc(MAX_DESKTOP_ICONS * sizeof(FAT32_FileInfo)); if (!files) return; - int file_count = fat32_list_directory("/Desktop", files, MAX_DESKTOP_ICONS); + int file_count = fat32_list_directory("/root/Desktop", files, MAX_DESKTOP_ICONS); // Temp array to hold new state DesktopIcon new_icons[MAX_DESKTOP_ICONS]; @@ -310,7 +310,7 @@ void wm_refresh_desktop(void) { } static void create_desktop_shortcut(const char *app_name) { - char path[128] = "/Desktop/"; + char path[128] = "/root/Desktop/"; int p = 9; int n = 0; while(app_name[n]) path[p++] = app_name[n++]; const char *ext = ".shortcut"; @@ -1358,7 +1358,7 @@ static void wm_paint_region(int y_start, int y_end, DirtyRect dirty, int pass) { if (str_ends_with(icon->name, ".elf")) draw_elf_icon(icon->x, icon->y, icon->name); else if (str_ends_with(icon->name, ".pnt")) draw_paint_icon(icon->x, icon->y, icon->name); else if (is_image_file(icon->name)) { - char full_path[128] = "/Desktop/"; int p=9; int n=0; while(icon->name[n] && p < 127) full_path[p++] = icon->name[n++]; full_path[p]=0; + char full_path[128] = "/root/Desktop/"; int p=14; int n=0; while(icon->name[n] && p < 127) full_path[p++] = icon->name[n++]; full_path[p]=0; draw_image_icon(icon->x, icon->y, full_path); draw_icon_label(icon->x, icon->y, icon->name); } @@ -1702,13 +1702,13 @@ void wm_handle_click(int x, int y) { if (item == 0 && desktop_menu_target_icon != -1) { // Cut DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon]; - char path[128] = "/Desktop/"; - int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; explorer_clipboard_cut(path); } else if (item == 1 && desktop_menu_target_icon != -1) { // Copy DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon]; - char path[128] = "/Desktop/"; - int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; explorer_clipboard_copy(path); } else if (item == 0 && desktop_menu_target_icon == -1) { // New File desktop_dialog_state = 1; @@ -1729,13 +1729,13 @@ void wm_handle_click(int x, int y) { int old_count = desktop_icon_count; if (desktop_menu_target_icon != -1 && desktop_icons[desktop_menu_target_icon].type == 1) { // Paste into folder - char path[128] = "/Desktop/"; + char path[128] = "/root/Desktop/"; DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon]; - int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; + int p=14; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; explorer_clipboard_paste(&win_explorer, path); } else { // Paste to desktop - explorer_clipboard_paste(&win_explorer, "/Desktop"); + explorer_clipboard_paste(&win_explorer, "/root/Desktop"); } refresh_desktop_icons(); @@ -1756,8 +1756,8 @@ void wm_handle_click(int x, int y) { } else if (item == 3 && desktop_menu_target_icon != -1) { // Delete DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon]; - char path[128] = "/Desktop/"; - int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; explorer_delete_recursive(path); refresh_desktop_icons(); } @@ -1782,10 +1782,10 @@ void wm_handle_click(int x, int y) { int dlg_x = (sw - 300) / 2; int dlg_y = (sh - 110) / 2; if (rect_contains(dlg_x + 50, dlg_y + 65, 80, 25, x, y)) { // Confirm if (desktop_dialog_state == 8) { // Rename - char old_path[128] = "/Desktop/"; - char new_path[128] = "/Desktop/"; - int p=9; int n=0; while(desktop_icons[desktop_dialog_target].name[n]) old_path[p++] = desktop_icons[desktop_dialog_target].name[n++]; old_path[p]=0; - p=9; n=0; while(desktop_dialog_input[n]) new_path[p++] = desktop_dialog_input[n++]; new_path[p]=0; + char old_path[128] = "/root/Desktop/"; + char new_path[128] = "/root/Desktop/"; + int p=14; int n=0; while(desktop_icons[desktop_dialog_target].name[n]) old_path[p++] = desktop_icons[desktop_dialog_target].name[n++]; old_path[p]=0; + p=14; n=0; while(desktop_dialog_input[n]) new_path[p++] = desktop_dialog_input[n++]; new_path[p]=0; if (fat32_rename(old_path, new_path)) { refresh_desktop_icons(); @@ -1795,8 +1795,8 @@ void wm_handle_click(int x, int y) { if (desktop_icon_count >= desktop_max_cols * desktop_max_rows_per_col) { wm_show_message("Error", "Desktop is full!"); } else if (desktop_dialog_input[0] != 0) { - char path[128] = "/Desktop/"; - int p=9; int n=0; while(desktop_dialog_input[n]) path[p++] = desktop_dialog_input[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(desktop_dialog_input[n]) path[p++] = desktop_dialog_input[n++]; path[p]=0; if (desktop_dialog_state == 1) { FAT32_FileHandle *fh = fat32_open(path, "w"); if (fh) fat32_close(fh); @@ -2130,8 +2130,8 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) { drag_icon_orig_x = icon->x; drag_icon_orig_y = icon->y; // Construct path - char path[128] = "/Desktop/"; - int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; int k=0; while(path[k]) { drag_file_path[k] = path[k]; k++; } drag_file_path[k]=0; } // 2. Check Explorer Items @@ -2184,7 +2184,7 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) { if (start_menu_pending_app) { // Launch App if (str_starts_with(start_menu_pending_app, "Files")) { - explorer_open_directory("/"); + explorer_open_directory("/root"); } else if (str_starts_with(start_menu_pending_app, "Notepad")) { Window *existing = wm_find_window_by_title_locked("Notepad"); if (existing) { @@ -2279,8 +2279,8 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) { if (!handled) { // Generic Shortcut Handling - char path[128] = "/Desktop/"; - int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; if (str_ends_with(icon->name, ".shortcut") && !str_starts_with(icon->name, "Recycle Bin")) { FAT32_FileHandle *fh = fat32_open(path, "r"); @@ -2303,12 +2303,12 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) { } } } else if (icon->type == 1) { // Folder - char path[128] = "/Desktop/"; - int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; explorer_open_directory(path); } else { // File - char path[128] = "/Desktop/"; - int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0; if (str_ends_with(icon->name, ".elf")) { process_create_elf(path, NULL); @@ -2354,7 +2354,7 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) { explorer_import_file(drop_win, drag_file_path); } - if (str_starts_with(drag_file_path, "/Desktop/")) { + if (str_starts_with(drag_file_path, "/root/Desktop/")) { refresh_desktop_icons(); } } else { @@ -2366,15 +2366,15 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) { bool dropped_on_target = false; for (int i = 0; i < desktop_icon_count; i++) { if (from_desktop) { - char path[128] = "/Desktop/"; - int p=9; int n=0; while(desktop_icons[i].name[n]) path[p++] = desktop_icons[i].name[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(desktop_icons[i].name[n]) path[p++] = desktop_icons[i].name[n++]; path[p]=0; if (str_eq(path, drag_file_path) != 0) continue; } if (rect_contains(desktop_icons[i].x + 20, desktop_icons[i].y, 40, 40, mx, my)) { if (desktop_icons[i].type == 1) { - char target_path[256] = "/Desktop/"; - int p=9; int n=0; while(desktop_icons[i].name[n]) target_path[p++] = desktop_icons[i].name[n++]; target_path[p]=0; + char target_path[256] = "/root/Desktop/"; + int p=14; int n=0; while(desktop_icons[i].name[n]) target_path[p++] = desktop_icons[i].name[n++]; target_path[p]=0; explorer_import_file_to(&win_explorer, drag_file_path, target_path); refresh_desktop_icons(); dropped_on_target = true; @@ -2397,7 +2397,7 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) { if (desktop_icon_count >= desktop_max_cols * desktop_max_rows_per_col) { wm_show_message("Error", "Desktop is full!"); } else { - explorer_import_file_to(&win_explorer, drag_file_path, "/Desktop"); + explorer_import_file_to(&win_explorer, drag_file_path, "/root/Desktop"); } // Handle insertion at specific position @@ -2453,8 +2453,8 @@ static void wm_handle_mouse_internal(int dx, int dy, uint8_t buttons, int dz) { } else if (!dropped_on_target) { int dragged_idx = -1; for(int i=0; i= desktop_max_cols * desktop_max_rows_per_col) { wm_show_message("Error", "Desktop is full!"); } else if (desktop_dialog_input[0] != 0) { - char path[128] = "/Desktop/"; - int p=9; int n=0; while(desktop_dialog_input[n]) path[p++] = desktop_dialog_input[n++]; path[p]=0; + char path[128] = "/root/Desktop/"; + int p=14; int n=0; while(desktop_dialog_input[n]) path[p++] = desktop_dialog_input[n++]; path[p]=0; if (desktop_dialog_state == 1) { FAT32_FileHandle *fh = fat32_open(path, "w"); if (fh) fat32_close(fh);