diff --git a/Makefile b/Makefile
index df0de645d..86d692dff 100755
--- a/Makefile
+++ b/Makefile
@@ -18,15 +18,15 @@ $(OBJ_DIRECTORY)/%.o : %.s | $(OBJ_DIRECTORY)
$(OBJ_DIRECTORY)/%.o : %.c | $(OBJ_DIRECTORY)
@echo -e '\x1b[32mC \x1b[0m' $@
- @$(CC) $(CFLAGS) -O0 -c -o $@ $<
+ @$(CC) $(CFLAGS) -c -o $@ $<
$(OBJ_DIRECTORY)/%.o : %.cpp | $(OBJ_DIRECTORY)
@echo -e '\x1b[32mCPP \x1b[0m' $@
@$(CXX) $(CPP_FLAGS) -c -o $@ $<
build_rust:
- @echo -e '\x1b[32mRUST \x1b[0mBuild rust kernel'
- cd $(RUST_DIR) && rustup override set nightly && rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu && cargo build
+ @echo -e '\x1b[32mRUST \x1b[0mBuilding Rust subsystem'
+ cd rust && rustup override set nightly && rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu && cargo +nightly build
# Сборка ядра
build: $(SOURCES)
@@ -50,16 +50,34 @@ run_remote_mon:
run_ahci_sata:
$(QEMU) $(QEMU_FLAGS) -serial mon:stdio \
- -drive id=disk,file=disk.img,if=none \
-device ahci,id=ahci \
- -device ide-hd,drive=disk,bus=ahci.0
+ -drive id=thatdisk,file=disk.img,if=none \
+ -device ide-hd,drive=thatdisk,bus=ahci.0 \
+ -drive id=thatcdrom,file=/dev/cdrom,if=none \
+ -device ide-cd,drive=thatcdrom,bus=ahci.1 \
+ # -trace "ahci*" \
+
+run_disks:
+ $(QEMU) $(QEMU_FLAGS) -serial mon:stdio -hda disk1.img -hdb disk2.img -hdd disk3.img
+
+bra:
+ @$(MAKE)
+ @$(MAKE) RAM
+ @$(MAKE) geniso
+ @$(MAKE) run_ahci_sata
+
+disks:
+ @$(MAKE)
+ @$(MAKE) RAM
+ @$(MAKE) geniso
+ @$(MAKE) run_disks
# Запуск Milla
milla:
- qemu-system-i386 -cdrom kernel.iso -serial file:Qemu.log -serial tcp:127.0.0.1:64552,server,nowait -accel kvm -m 128M -name "SayoriOS Soul" -d guest_errors -rtc base=localtime -soundhw pcspk
+ qemu-system-i386 -cdrom kernel.iso -serial file:Qemu.log -serial telnet:sayorios.piminoff.ru:10000 -accel kvm -m 128M -name "SayoriOS Soul" -d guest_errors -rtc base=localtime -soundhw pcspk
floppy:
- qemu-system-i386 -cdrom kernel.iso -serial file:Qemu.log -m 128M -name "SayoriOS v0.3.x (Dev)" -d guest_errors -rtc base=localtime -fda floppy.img -boot order=dc
+ qemu-system-i386 -cdrom kernel.iso -serial mon:stdio -m 64M -name "SayoriOS v0.3.4 Soul - Scythe" -d guest_errors -rtc base=localtime -fda floppy.img -boot order=dc -accel kvm
# Запуск с логами в консоль
runlive:
@@ -68,48 +86,52 @@ runlive:
# Запуск в режиме UEFI с логами в файл
uefi:
qemu-system-x86_64 -bios /usr/share/qemu/OVMF.fd -cdrom SayoriOS_UEFI.iso -serial file:Qemu.log -accel kvm \
- -m 128M -name "SayoriOS Soul" -d guest_errors -rtc base=localtime
+ -m 128M -name "SayoriOS v0.3.4 Soul - Scythe" -d guest_errors -rtc base=localtime
# Запуск в режиме UEFI с логами в консоль
uefilive:
qemu-system-x86_64 -bios /usr/share/qemu/OVMF.fd -cdrom SayoriOS_UEFI.iso -serial mon:stdio -accel kvm \
- -m 128M -name "SayoriOS Soul" -d guest_errors -rtc base=localtime
+ -m 128M -name "SayoriOS v0.3.4 Soul - Scythe" -d guest_errors -rtc base=localtime
# Генерация ISO-файла
geniso: $(KERNEL)
- grub2-mkrescue -o "kernel.iso" iso/ -V kernel
+ $(shell bash tools/grub.sh) -o "kernel.iso" iso/ -V kernel
# Генерация ISO-файла с поддержкой UEFI
genuefi:
- grub2-mkrescue -d /usr/lib/grub/x86_64-efi -o SayoriOS_UEFI.iso iso/ --locale-directory=/usr/share/locale/ -V "SayoriOS Soul"
+ $(shell bash tools/grub.sh) -d /usr/lib/grub/x86_64-efi -o SayoriOS_UEFI.iso iso/ --locale-directory=/usr/share/locale/ -V "SayoriOS v0.3.4 Soul - Scythe"
# Удаление оригинального файла и *.о файлов
clean:
-rm -f $(KERNEL)
-rm -f $(KERNEL_NEED)
-rm -f $(DEPS)
+ -rm -f iso/boot/ramdisk
-rm -f $(RUST_OBJ_DEBUG)
-rm -f $(RUST_OBJ_RELEASE)
# Линковка файлов
$(KERNEL): $(KERNEL_NEED) $(RUST_SOURCES) rust/Cargo.toml
- @$(MAKE) build_rust
+ # $(MAKE) build_rust
@echo -e '\x1b[32mLINK \x1b[0m' $(KERNEL)
@rm -f $(KERNEL)
- @$(LD) $(LDFLAGS) -o $(KERNEL) $(KERNEL_NEED) $(RUST_OBJ_DEBUG)
- @llvm-strip -s $(KERNEL)
+ @$(LD) $(LDFLAGS) -o $(KERNEL) $(KERNEL_NEED) # $(RUST_OBJ_DEBUG)
+ #@llvm-strip -s $(KERNEL) # I know I strip all symbols so making unwind useless. (Fix it later)
@bash tools/genmap.sh
@bash tools/insertmap.sh
+ @ls -lh $(KERNEL)
@-rm kernel.map
# Быстрая линковка, генерация ISO, запуск
bir:
@$(MAKE)
+ @$(MAKE) RAM
@$(MAKE) geniso
@$(MAKE) run
# Быстрая линковка, генерация ISO, запуск
birl:
@$(MAKE)
+ @$(MAKE) RAM
@$(MAKE) geniso
@$(MAKE) runlive
@@ -131,25 +153,91 @@ bf:
cppcheck:
cppcheck --enable=warning,performance,portability .
-
debug: geniso
$(QEMU) $(QEMU_FLAGS) -s -S &
gdb -ex "target remote localhost:1234" -ex "break kernel" -ex "continue"
ensure_tools:
@echo "C:" $(CC)
- @echo "C++:" $(CXX)
+ @echo "LD:" $(LD)
release:
ADDCFLAGS="-DRELEASE" $(MAKE)
+ @$(MAKE) RAM
+# ВНИМАНИЕ: Данное правило установит SayoriOS на ваш компьютер!
deploy: $(KERNEL)
sudo cp iso/boot/kernel.elf /boot/sayorios_kernel.elf
- sudo cp iso/boot/sayori_sefs.img /boot/
+ sudo cp iso/boot/ramdisk /boot/sayori_ramdisk
sudo cp other/41_sayori /etc/grub.d/
sudo update-grub
+RAM:
+ @-rm ./iso/boot/ramdisk
+ @tar -cvf ./iso/boot/ramdisk ./ramdisk/
+
+VBOX_create_vm:
+ @echo "TODO"
+ @VBoxManage createvm --name=SayoriOS --register
+ @VBoxManage storagectl SayoriOS --name=ide --add=ide --bootable=on
+ @VBoxManage storageattach SayoriOS --type=dvddrive --medium kernel.iso --storagectl=ide --port=0 --device=0
+
+VBOX:
+ @$(MAKE)
+ @$(MAKE) RAM
+ @$(MAKE) geniso
+ @VBoxManage startvm "SayoriOS"
+
+WSL_RUN:
+ "/mnt/c/Program Files/qemu/qemu-system-i386.exe" -cdrom "C:\\SayoriDev\\SayoriOS_DEV_WSL.iso" -serial mon:stdio -m 128M -name "SayoriOS v0.3.4 Soul - Scythe - WSL MODE" -d guest_errors -rtc base=localtime $(QEMU_FLAGS_WSL)
+
+
+WSL:
+ @$(MAKE)
+ @$(MAKE) RAM
+ @$(MAKE) geniso
+ @-mkdir /mnt/c/SayoriDev/
+ mv kernel.iso /mnt/c/SayoriDev/SayoriOS_DEV_WSL.iso
+ "/mnt/c/Program Files/qemu/qemu-system-i386.exe" -cdrom "C:\\SayoriDev\\SayoriOS_DEV_WSL.iso" -serial mon:stdio -m 128M -name "SayoriOS v0.3.4 Soul - Scythe - WSL MODE" -d guest_errors -rtc base=localtime $(QEMU_FLAGS_WSL)
+
+WSL_NAT:
+ @$(MAKE)
+ @$(MAKE) RAM
+ @$(MAKE) geniso
+ @-mkdir /mnt/c/SayoriDev/
+ mv kernel.iso /mnt/c/SayoriDev/SayoriOS_DEV_WSL.iso
+ "/mnt/c/Program Files/qemu/qemu-system-i386.exe" -cdrom "C:\\SayoriDev\\SayoriOS_DEV_WSL.iso" -serial mon:stdio -serial telnet:sayorios.piminoff.ru:10000 -m 128M -name "SayoriOS v0.3.4 Soul - Scythe - WSL MODE" -d guest_errors -rtc base=localtime $(QEMU_FLAGS_WSL)
+
+WSL_DISKS:
+ @$(MAKE)
+ @$(MAKE) RAM
+ @$(MAKE) geniso
+ @-mkdir /mnt/c/SayoriDev/
+ mv kernel.iso /mnt/c/SayoriDev/SayoriOS_DEV_WSL.iso
+ @-mv disk1.img /mnt/c/SayoriDev/disk1.img
+ @-mv disk2.img /mnt/c/SayoriDev/disk2.img
+ @-mv disk3.img /mnt/c/SayoriDev/disk3.img
+ "/mnt/c/Program Files/qemu/qemu-system-i386.exe" -cdrom "C:\\SayoriDev\\SayoriOS_DEV_WSL.iso" -serial mon:stdio -m 128M -name "SayoriOS v0.3.4 Soul - Scythe - WSL MODE" -d guest_errors -rtc base=localtime $(QEMU_FLAGS_WSL) -hda "C:\\SayoriDev\\disk1.img" -hdb "C:\\SayoriDev\\disk2.img" -hdd "C:\\SayoriDev\\disk3.img"
+
+create_fat_disk:
+ fallocate -l 64M disk1.img
+ sudo mkfs.fat -F 32 disk1.img
+
+net_tap_dev: geniso
+ sudo $(QEMU) -cdrom kernel.iso -m $(MEMORY_SIZE) \
+ -name "SayoriOS v0.3.4 Soul - Scythe - [NETWORK ON TAP]" \
+ -rtc base=localtime \
+ -d guest_errors,cpu_reset,int \
+ -smp 1 \
+ -netdev tap,id=net0 \
+ -device rtl8139,netdev=net0,id=mydev0 \
+ -boot d \
+ -cpu core2duo-v1 \
+ -serial mon:stdio \
+ $(KVM_QEMU_FLAGS)
+
+
clangd:
$(MAKE) clean
bear -- $(MAKE) -j2
diff --git a/README.MD b/README.MD
index 206ab7784..69aba51bd 100644
--- a/README.MD
+++ b/README.MD
@@ -10,19 +10,22 @@
Коммиты идут пачками (по одному коммиту на каждый релиз)
Скриншоты
-
-
-
-
+
+
+
+
+
+
+
Примерный план действий:
Прогресс:
- ❤ [Ядро] Выполнено 4 из 7 (57%) [=====-----]
- 💫 [Драйвера] Выполнено 3 из 6 (50%) [=====-----]
- 📂 [Файлы] Выполнено 4 из 8 (50%) [=====-----]
- 🌐 [Сеть] Выполнено 0 из 1 (0%) [----------]
- 🔌 [Прочие] Выполнено 2 из 5 (40%) [====------]
+ ❤ [Ядро] Выполнено 10 из 20 (50%) [=====-----]
+ 💫 [Драйвера] Выполнено 9 из 10 (90%) [=========-]
+ 📂 [Файлы] Выполнено 8 из 10 (80%) [========--]
+ 🌐 [Сеть] Выполнено 1 из 3 (33%) [===-------]
+ 🔌 [Прочие] Выполнено 6 из 9 (66%) [======----]
Нажав сюда, вы увидите изображение, где отображены примерные планы на ядро.
Обновление данного изображения, будет только при следующем релизе. или нажмите сюда, для просмотра на сайте
@@ -88,11 +91,13 @@
make clean-objs - Удаляет все скомпилированные файлы
make link - Линк файлов ядра
make bir - Сборка ISO и запуск ядра
+ make WSL - Сборка ISO и запуск ядра через WSL
Список людей, которые поддерживают ядро:
* Nikita Piminoff (Создатель SayoriOS)
* Drew Pavlenko
+ * Даниил Лебедев
* Коммьюнити SayoriOS в VK
Отказ от ответственности:
diff --git a/README.MD:Zone.Identifier b/README.MD:Zone.Identifier
new file mode 100644
index 000000000..43a1a01e3
--- /dev/null
+++ b/README.MD:Zone.Identifier
@@ -0,0 +1,3 @@
+[ZoneTransfer]
+ZoneId=3
+HostUrl=https://github.com/
diff --git a/config.mk b/config.mk
index 1d3bbc31b..33e8be0a6 100755
--- a/config.mk
+++ b/config.mk
@@ -2,13 +2,19 @@
# SayoriOS Soul
# (c) SayoriOS Team 2022-2023
-# CC=$(shell bash other/compiler.sh cpp)
-CC=$(shell bash other/compiler.sh)
-CXX=$(shell bash other/compiler.sh cpp)
-
+KERNEL = iso/boot/kernel.elf
+DEBUG =# -ggdb3 #-Werror
MEMORY_SIZE=128M
USE_SSE=true
+COMPILER_DETECTOR_FLAGS = ""
+
+ifeq ($(X64),true)
+ COMPILER_DETECTOR_FLAGS := "--64"
+endif
+
+CC=$(shell bash tools/compiler.sh $(COMPILER_DETECTOR_FLAGS))
+
GAMEBOY = $(wildcard kernel/src/ports/gameboy/*.c)
GAMEBOY_OBJS = $(GAMEBOY:.c=.o)
@@ -16,7 +22,12 @@ OBJ_DIRECTORY = objects
DIRECTORIES = objects/kernel/src \
objects/kernel/asm \
objects/kernel/src/lib \
+ objects/kernel/src/lib/libstring/src \
+ objects/kernel/src/lib/libvector/src \
objects/kernel/src/lib/php \
+ objects/kernel/src/lib/elk \
+ objects/kernel/src/lib/elk/ext \
+ objects/kernel/src/lib/freeada \
objects/kernel/src/extra \
objects/kernel/src/sys \
objects/kernel/src/io \
@@ -32,134 +43,169 @@ DIRECTORIES = objects/kernel/src \
objects/kernel/src/lib/math \
objects/kernel/src/toys \
objects/kernel/src/gui \
+ objects/kernel/src/desktop \
objects/kernel/src/user \
objects/kernel/src/ports/gameboy \
- objects/kernel/src/compress/zlib \
+ objects/kernel/src/mem \
+ objects/kernel/src/arch/x86 \
+ # objects/kernel/src/compress/zlib \
# Исходные объектные модули
ASM_SRC=kernel/asm/init.s \
kernel/asm/interrupt.s \
- kernel/asm/switch_task.s \
kernel/asm/sys_calls.s \
kernel/asm/usr.s \
kernel/asm/sse.s \
kernel/asm/gdt.s \
+ kernel/asm/paging.s \
kernel/asm/regs.s \
kernel/src/lib/setjmp.s \
- kernel/src/sys/v8086.s \
+ kernel/asm/switch_task.s \
+# kernel/src/sys/v8086.s \
ASM=$(ASM_SRC:%.s=$(OBJ_DIRECTORY)/%.o)
-SOURCES=kernel/src/sys/bootscreen.c \
- kernel/src/sys/cpu_isr.c \
- $(GAMEBOY) \
- kernel/src/sys/acpi.c \
+SOURCES=\
kernel/src/sys/cpuinfo.c \
+ kernel/src/sys/cpu_isr.c \
kernel/src/sys/gdt.c \
kernel/src/sys/tss.c \
kernel/src/sys/idt.c \
kernel/src/sys/isr.c \
- kernel/src/sys/memory.c \
- kernel/src/sys/scheduler.c \
- kernel/src/sys/sync.c \
- kernel/src/sys/syscalls.c \
- kernel/src/sys/system.c \
+ kernel/src/io/ports.c \
+ kernel/src/io/serial_port.c \
+ kernel/src/lib/string.c \
+ kernel/src/drv/fpu.c \
kernel/src/sys/timer.c \
- kernel/src/sys/elf.c \
- kernel/src/lib/list.c \
- kernel/src/lib/dan.c \
+ kernel/src/sys/logo.c \
+ kernel/src/lib/math/math.c \
+ kernel/src/mem/pmm.c \
+ kernel/src/mem/vmm.c \
+ $(wildcard kernel/src/lib/libvector/src/*.c) \
+ $(wildcard kernel/src/lib/libstring/src/*.c) \
kernel/src/lib/stdio.c \
- kernel/src/lib/string.c \
kernel/src/lib/split.c \
- kernel/src/io/tty.c \
- kernel/src/io/status_sounds.c \
- kernel/src/io/status_loggers.c \
kernel/src/io/screen.c \
- kernel/src/drv/cmos.c \
- kernel/src/drv/vfs_new.c \
+ kernel/src/io/tty.c \
+ kernel/src/fs/tarfs.c \
+ kernel/src/fs/fsm.c \
+ kernel/src/fs/nvfs.c \
+ kernel/src/fs/natfs.c \
+ kernel/src/fs/iso9660.c \
+ kernel/src/lib/php/str_replace.c \
+ kernel/src/sys/scheduler.c \
+ kernel/src/lib/php/explode.c \
+ kernel/src/lib/php/pathinfo.c \
+ kernel/src/lib/elk/elk.c \
+ kernel/src/lib/elk/elk_engine.c \
+ kernel/src/lib/elk/elk_libs.c \
+ kernel/src/lib/elk/jse_func.c \
+ $(wildcard kernel/src/lib/elk/ext/*.c) \
+ kernel/src/lib/freeada/ada.c \
+ kernel/src/drv/psf.c \
+ kernel/src/sys/unwind.c \
+ kernel/src/fs/NatSuki.c \
+ kernel/src/drv/disk/initrd.c \
+ kernel/src/drv/disk/dpm.c \
+ kernel/src/lib/list.c \
+ kernel/src/sys/sync.c \
+ kernel/src/gui/basics.c \
+ kernel/src/lib/pixel.c \
+ kernel/src/sys/bootscreen.c \
+ kernel/src/debug/hexview.c \
kernel/src/drv/video/vbe.c \
kernel/src/drv/input/keyboard.c \
kernel/src/drv/input/mouse.c \
+ kernel/src/sys/syscalls.c \
+ kernel/src/sys/testing.c \
+ kernel/src/sys/trigger.c \
+ kernel/src/lib/rand.c \
+ kernel/src/drv/cmos.c \
kernel/src/drv/beeper.c \
- kernel/src/drv/fpu.c \
- kernel/src/drv/rtl8139.c \
- kernel/src/drv/pci.c \
- kernel/src/io/ports.c \
- kernel/src/fs/sefs.c \
- kernel/src/fs/milla.c \
- kernel/src/fs/NatSuki.c \
kernel/src/user/env.c \
- kernel/src/sys/logo.c \
- kernel/src/io/port_io.c \
+ kernel/src/drv/pci.c \
kernel/src/gui/pointutils.c \
- kernel/src/gui/eki.c \
kernel/src/gui/line.c \
kernel/src/gui/circle.c \
- kernel/src/drv/audio/ac97.c \
- kernel/src/toys/piano.c \
- kernel/src/toys/minesweeper.c \
- kernel/src/toys/diskctl.c \
- kernel/src/toys/danview.c \
- kernel/src/toys/mala.c \
- kernel/src/toys/dino.c \
- kernel/src/toys/calendar.c \
- kernel/src/sys/testing.c \
- kernel/src/sys/trigger.c \
- kernel/src/lib/pixel.c \
- kernel/src/lib/tui.c \
- kernel/src/lib/rand.c \
- kernel/src/lib/sprintf.c \
- kernel/src/lib/php/str_replace.c \
- kernel/src/extra/texplorer.c \
- kernel/src/io/shell.c \
- kernel/src/sys/unwind.c \
- kernel/src/sys/fxsave_region.c \
- kernel/src/net/endianess.c \
- kernel/src/net/cards.c \
- kernel/src/net/ethernet.c \
- kernel/src/net/arp.c \
- kernel/src/drv/disk/mbr.c \
- kernel/src/drv/disk/floppy.c \
- kernel/src/drv/disk/ata.c \
- kernel/src/drv/disk/atapi.c \
- kernel/src/fs/fat12.c \
- kernel/src/fs/smfs.c \
- kernel/src/debug/hexview.c \
- kernel/src/debug/ubsan.c \
- kernel/src/fmt/tga.c \
- kernel/src/fmt/tga_extract.c \
- kernel/src/sys/pixfmt.c \
kernel/src/lib/math/exp.c \
kernel/src/lib/math/log.c \
kernel/src/lib/math/pow.c \
kernel/src/lib/math/acos.c \
kernel/src/lib/math/asin.c \
kernel/src/lib/math/atan.c \
+ kernel/src/lib/math/modf.c \
kernel/src/lib/math/integral.c \
kernel/src/lib/math/sin.c \
kernel/src/lib/math/cos.c \
kernel/src/lib/math/tan.c \
kernel/src/lib/math/sqrt.c \
+ kernel/src/io/rgb_image.c \
+ $(wildcard kernel/src/lib/libstring/*.c) \
kernel/src/lib/math/cbrt.c \
- kernel/src/lib/math/math.c \
- kernel/src/gui/basics.c \
- kernel/src/gui/render.c \
- kernel/src/drv/psf.c \
- kernel/src/gui/window.c \
- kernel/src/gui/widget.c \
- kernel/src/gui/widget_button.c \
- kernel/src/gui/widget_label.c \
- kernel/src/gui/widget_image.c \
- kernel/src/gui/parallel_desktop.c \
- kernel/src/lib/base64.c \
- kernel/src/io/duke_image.c \
kernel/src/sys/cpuid.c \
+ kernel/src/drv/disk/ata.c \
+ kernel/src/drv/disk/atapi.c \
kernel/src/sys/cputemp.c \
- $(wildcard kernel/src/compress/zlib/*.c) \
- kernel/src/zlibtest.c \
+ kernel/src/net/endianess.c \
+ kernel/src/net/cards.c \
+ kernel/src/net/ethernet.c \
+ kernel/src/net/arp.c \
+ kernel/src/net/ipv4.c \
+ kernel/src/net/udp.c \
+ kernel/src/net/dhcp.c \
+ kernel/src/net/icmp.c \
+ kernel/src/sys/system.c \
+ kernel/src/io/status_sounds.c \
+ kernel/src/io/status_loggers.c \
+ kernel/src/extra/cli.c \
+ kernel/src/sys/variable.c \
+ kernel/src/fs/fat32.c \
+ kernel/src/sys/fxsave_region.c \
+ kernel/src/toys/gfxbench.c \
+ kernel/src/toys/miniplay.c \
+ kernel/src/drv/rtl8139.c \
+ kernel/src/fmt/tga.c \
+ kernel/src/lib/sprintf.c \
+ kernel/src/debug/ubsan.c \
+ kernel/src/fmt/tga_extract.c \
+ kernel/src/drv/disk/floppy.c \
+ kernel/src/drv/disk/ata_dma.c \
+ kernel/src/drv/audio/ac97.c \
+ kernel/src/sys/elf.c \
+ kernel/src/sys/acpi.c \
+ kernel/src/sys/pixfmt.c \
+ kernel/src/desktop/render.c \
+ kernel/src/desktop/window.c \
+ kernel/src/desktop/widget.c \
+ kernel/src/desktop/widget_button.c \
+ kernel/src/desktop/widget_progress.c \
+ kernel/src/desktop/widget_image.c \
+ kernel/src/desktop/widget_label.c \
+ kernel/src/desktop/eki.c \
+ kernel/src/desktop/parallel_desktop.c \
+ kernel/src/sys/mtrr.c \
+ kernel/src/net/net_info_cli.c \
+ kernel/src/toys/mala.c \
+ kernel/src/debug/memmeter.c \
+ kernel/src/drv/disk/ahci.c \
+ kernel/src/drv/disk/ndpm.c \
+ kernel/src/toys/minesweeper.c \
+ kernel/src/toys/calendar.c \
+ kernel/src/toys/diskctl.c \
+ kernel/src/lib/utf_conversion.c \
+ kernel/src/lib/base64.c \
kernel/src/kernel.c \
- # kernel/src/fs/lucario/fs.c \
- # kernel/src/drv/ata_dma.c \
+ $(GAMEBOY) \
+# kernel/src/toys/pavi.c \
+ kernel/src/lib/duktape.c \
+ kernel/src/toys/piano.c \
+ $(wildcard kernel/src/compress/zlib/*.c) \
+ kernel/src/toys/dino.c \
+ kernel/src/lib/tui.c \
+ kernel/src/extra/texplorer.c \
+ kernel/src/drv/disk/mbr.c \
+ kernel/src/fs/fat12.c \
+ kernel/src/fs/smfs.c \
RUST_DIR = rust/
RUST_TARGET = i686-unknown-none
@@ -195,19 +241,11 @@ OBJS = $(SOURCES:%.c=$(OBJ_DIRECTORY)/%.o)
DEPS = $(OBJS:%.o=%.d)
-KERNEL = iso/boot/kernel.elf
-
KERNEL_NEED = $(ASM) $(OBJS) $(CPP_CODE)
-DEBUG = #-ggdb3 #-Werror
-
-COMMON_FLAGS = -nostdlib -fno-stack-protector -fno-builtin -m32 -Ikernel/include/ -ffreestanding \
+COMMON_FLAGS = -O0 -nostdlib -fno-stack-protector -fno-builtin -Ikernel/include/ -ffreestanding \
-Wall -Wno-div-by-zero -Wno-address-of-packed-member -Wno-implicit-function-declaration \
- -mno-red-zone -march=i386 -MMD -MP -Wno-everything
-
-ifeq ($(USE_SSE),true)
- COMMON_FLAGS := $(COMMON_FLAGS) -msse2 -DUSE_SSE
-endif
+ -mno-red-zone -MMD -MP
# Флаги компилятора языка C
CFLAGS=$(DEBUG) $(ADDCFLAGS) $(COMMON_FLAGS)
@@ -215,11 +253,23 @@ CPP_FLAGS=$(DEBUG) $(COMMON_FLAGS) -fno-use-cxa-atexit -fno-exceptions -fno-rtti
LD ?= ld.lld
# Флаги компоновщика
-LDFLAGS=-T kernel/asm/link.ld -m elf_i386
+LDFLAGS=-T kernel/asm/link.ld
# Флаги ассемблера
ASFLAGS=--32
+ifeq ($(USE_SSE),true)
+ COMMON_FLAGS := $(COMMON_FLAGS) -msse2 -DUSE_SSE
+endif
+
+ifeq ($(X64),true)
+ COMMON_FLAGS := $(COMMON_FLAGS) -DSAYORI64
+ LDFLAGS := $(LDFLAGS) -m elf_x86_64
+else
+ LDFLAGS := $(LDFLAGS) -m elf_i386
+endif
+
+
QEMU ?= qemu-system-i386
# Memory minimal: 33 MB
@@ -238,15 +288,27 @@ endif
# NOTE: -d int works only when using tcg accelerator (no KVM)
QEMU_FLAGS = -cdrom kernel.iso -m $(MEMORY_SIZE) \
- -name "SayoriOS Soul v0.3.3 (Dev)" \
+ -name "SayoriOS v0.3.4 Soul - Scythe" \
-rtc base=localtime \
-d guest_errors,cpu_reset,int \
-audiodev pa,id=pa0 \
-smp 1 \
- -netdev user,id=net0 \
+ -netdev user,id=net0,net=192.168.111.0,dhcpstart=192.168.111.128 \
-device rtl8139,netdev=net0,id=mydev0 \
-M pcspk-audiodev=pa0 \
-device AC97 \
-boot d \
-cpu core2duo-v1 \
+ -object filter-dump,id=dump0,netdev=net0,file=netdump.pcap \
$(KVM_QEMU_FLAGS)
+
+# NOTE: -d int works only when using tcg accelerator (no KVM)
+QEMU_FLAGS_WSL = -m $(MEMORY_SIZE) \
+ -name "SayoriOS v0.3.4 Soul - Scythe" \
+ -rtc base=localtime \
+ -smp 1 \
+ -netdev user,id=net0,net=192.168.111.0,dhcpstart=192.168.111.128 \
+ -device rtl8139,netdev=net0,id=mydev0 \
+ -device AC97 \
+ -boot d \
+ -cpu core2duo-v1
diff --git a/iso/boot/grub/background.tga b/iso/boot/grub/background.tga
new file mode 100644
index 000000000..6cdec2cc0
Binary files /dev/null and b/iso/boot/grub/background.tga differ
diff --git a/iso/boot/grub/grub.cfg b/iso/boot/grub/grub.cfg
old mode 100755
new mode 100644
index f7c1bc6fb..2f7862f1f
--- a/iso/boot/grub/grub.cfg
+++ b/iso/boot/grub/grub.cfg
@@ -1,47 +1,61 @@
# Импорт модулей
-insmod gfxterm
+
+set timeout=5
+
insmod vbe
insmod vga
+insmod video_bochs
+insmod video_cirrus
+insmod gfxterm
+insmod gfxmenu
+insmod tga
+
+terminal_input console
+terminal_output gfxterm
-timeout=5
+set theme=/boot/grub/theme.txt
+export theme
-menuentry "SayoriOS Soul v0.3.3" {
- multiboot /boot/kernel.elf NatSuki-Login=Test NatSuki-Password="Password"
- module /boot/sayori_sefs.img initrd_sefs;
+menuentry "SayoriOS Soul v0.3.4 Alpha" {
+ multiboot /boot/kernel.elf
+ module /boot/ramdisk initrd_tarfs;
boot
}
-menuentry --hotkey=f "SayoriOS Soul v0.3.3 [No Floppy Support]" {
- multiboot /boot/kernel.elf disable=floppy
- module /boot/sayori_sefs.img initrd_sefs;
+menuentry --hotkey=w "SayoriOS Soul v0.3.4 Alpha [VMWare]" {
+ multiboot /boot/kernel.elf disable=rdsp
+ module /boot/ramdisk initrd_tarfs;
boot
}
+menuentry --hotkey=f "SayoriOS Soul v0.3.4 Alpha [No Floppy Support]" {
+ multiboot /boot/kernel.elf disable=floppy
+ module /boot/ramdisk initrd_tarfs;
+ boot
+}
-menuentry "SayoriOS Soul v0.3.3 [Minimal Bootscreen]" {
+menuentry "SayoriOS Soul v0.3.x Alpha [Minimal Bootscreen]" {
multiboot /boot/kernel.elf bootscreen=minimal disable=network
- module /boot/sayori_sefs.img initrd_sefs;
+ module /boot/ramdisk initrd_tarfs;
boot
}
-menuentry --hotkey=f "SayoriOS Soul v0.3.3 [FAST+]" {
+menuentry --hotkey=f "SayoriOS Soul v0.3.4 Alpha [FAST+]" {
multiboot /boot/kernel.elf disable=coms disable=ac97 disable=pc-speaker disable=floppy disable=network bootscreen=minimal bootscreen=no-logs
- module /boot/sayori_sefs.img initrd_sefs;
+ module /boot/ramdisk initrd_tarfs;
boot
}
-menuentry --hotkey=n "SayoriOS Soul v0.3.3 [NatSuki]" {
+menuentry --hotkey=n "SayoriOS Soul v0.3.4 Alpha [NatSuki]" {
multiboot /boot/kernel.elf
- module /boot/sayori_sefs.img initrd_sefs;
+ module /boot/ramdisk initrd_tarfs;
boot
}
-menuentry --hotkey=p 'List PCI' {
- lspci
-}
menuentry --hotkey=r 'Reboot' {
reboot
}
-menuentry --hotkey=h 'Halt' {
+
+menuentry --hotkey=h 'Power off' {
halt
-}
\ No newline at end of file
+}
diff --git a/iso/boot/grub/theme.txt b/iso/boot/grub/theme.txt
new file mode 100644
index 000000000..2098285c2
--- /dev/null
+++ b/iso/boot/grub/theme.txt
@@ -0,0 +1,25 @@
+desktop-color: "#24282c"
+desktop-image: "background.tga"
+
++ boot_menu {
+ left = 15%
+ width = 70%
+ top = 30%
+ height = 45%
+ item_height = 30
+ item_padding = 5
+ icon_width = 32
+ icon_height = 32
+ item_icon_space = 20
+ item_spacing = 5
+ item_color = "#cccccc"
+ selected_item_color = "#00ff00"
+}
+
++ hbox {
+ left = 50%-250
+ top = 80%
+ width = 500
+ + label { width = 250 height = 20 align = "center" color = "#ffffff" text = "E = Edit Boot Options" }
+ + label { width = 250 height = 20 align = "center" color = "#ffffff" text = "C = GRUB Commandline" }
+}
diff --git a/iso/boot/ramdisk b/iso/boot/ramdisk
new file mode 100644
index 000000000..1ffdf9173
Binary files /dev/null and b/iso/boot/ramdisk differ
diff --git a/iso/boot/sayori_sefs.img b/iso/boot/sayori_sefs.img
deleted file mode 100644
index 3693261aa..000000000
Binary files a/iso/boot/sayori_sefs.img and /dev/null differ
diff --git a/kernel/asm/gdt.s b/kernel/asm/gdt.s
old mode 100755
new mode 100644
diff --git a/kernel/asm/init.s b/kernel/asm/init.s
old mode 100755
new mode 100644
index cca1dddaa..cd2ad1fc1
--- a/kernel/asm/init.s
+++ b/kernel/asm/init.s
@@ -11,7 +11,7 @@
.set INIT_MBOOT_HEADER_FLAGS, ALIGN | MEMINFO | VBE_MODE
.set INIT_MBOOT_CHECKSUM, 0x00000000 - (INIT_MBOOT_HEADER_MAGIC + INIT_MBOOT_HEADER_FLAGS)
-.set STACK_SIZE, 1024 * 16 # 16 KB
+.set STACK_SIZE, 1024 * 64 # 64 KB
.extern kernel
@@ -49,6 +49,7 @@ __pre_init:
push %ebx
xor %ebp, %ebp
+
call kernel
hlt
diff --git a/kernel/asm/interrupt.s b/kernel/asm/interrupt.s
old mode 100755
new mode 100644
diff --git a/kernel/asm/link.ld b/kernel/asm/link.ld
old mode 100755
new mode 100644
diff --git a/kernel/asm/paging.s b/kernel/asm/paging.s
new file mode 100644
index 000000000..ff2f0d1d6
--- /dev/null
+++ b/kernel/asm/paging.s
@@ -0,0 +1,33 @@
+.text
+.globl load_page_directory
+load_page_directory:
+ push %ebp
+ mov %esp, %ebp
+ mov 8(%esp), %eax
+ mov %eax, %cr3
+ mov %ebp, %esp
+ pop %ebp
+ ret
+
+.text
+.globl enable_paging
+enable_paging:
+ push %ebp
+ mov %esp, %ebp
+ mov %cr0, %eax
+ or $0x80000000, %eax
+ mov %eax, %cr0
+ mov %ebp, %esp
+ pop %ebp
+ ret
+
+.text
+.globl flush_tlb_entry
+flush_tlb_entry:
+ push %ebp
+ mov %esp, %ebp
+ mov 8(%esp), %eax
+ invlpg (%eax)
+ mov %ebp, %esp
+ pop %ebp
+ ret
diff --git a/kernel/asm/regs.s b/kernel/asm/regs.s
old mode 100755
new mode 100644
diff --git a/kernel/asm/switch_task.s b/kernel/asm/switch_task.s
old mode 100755
new mode 100644
index 9941cf82b..313e53c80
--- a/kernel/asm/switch_task.s
+++ b/kernel/asm/switch_task.s
@@ -3,32 +3,71 @@
* Переключение задач
*/
.extern current_thread
+.extern current_proc
.extern tss
.global task_switch
task_switch:
+ # push %ebx
+ # push %esi
+ # push %edi
+ push %ebp
- push %ebp
-
pushf
cli
-
+
+ # Save current thread
mov current_thread, %edx
+
+ # Save current thread's stack
mov %esp, 28(%edx)
-
+
+ # current_thread.list_item.next is next entry in list
mov 4(%edx), %ecx
+
+ # Set current_thread to next entry
mov %ecx, current_thread
-
+
+ # Load thread's stack
mov current_thread, %edx
mov 28(%edx), %esp
-
+
+ # Load stack_top to tss
mov 40(%edx), %eax
- mov $tss, %edx
- mov %eax, 4(%edx)
-
- popf
-
- pop %ebp
+ mov $tss, %edx
+ mov %eax, 4(%edx)
+
+ # WARNING: THIS CODE IS MAY BE BUGGY (NOT TESTED)
+ # IF YOU HAVING PROBLEMS WITH THIS CODE, PLEASE, REPORT IT TO NDRAEY
+ # OR REMOVE THESE FOKEN LINES UNTIL THE `popf` INSTRUCTION
+
+ # Load process' page directory
+ # Load our process structure
+ mov current_thread, %edx
+ mov 12(%edx), %eax
+ mov %eax, current_proc
+
+ mov current_proc, %edx
+
+ # Load our page directory address
+ mov 12(%edx), %eax
+ mov %cr3, %ecx
+
+ cmp %eax, %ecx
+ je .no_addr_switch
+
+ mov %eax, %cr3
+
+ .no_addr_switch:
+
+ popf
+ # sti
+
+ pop %ebp
+ # pop %edi
+ # pop %esi
+ # pop %ebx
+
ret
diff --git a/kernel/asm/sys_calls.s b/kernel/asm/sys_calls.s
old mode 100755
new mode 100644
diff --git a/kernel/asm/usr.s b/kernel/asm/usr.s
old mode 100755
new mode 100644
diff --git a/kernel/include/common.h b/kernel/include/common.h
old mode 100755
new mode 100644
index eecd25d09..1563ccd3c
--- a/kernel/include/common.h
+++ b/kernel/include/common.h
@@ -2,7 +2,7 @@
* @file common.h
* @author Пиминов Никита (nikita.piminoff@yandex.ru)
* @brief Основные определения ядра
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-12-07
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
@@ -23,7 +23,14 @@ typedef enum {
#endif
+#define SAYORI_INLINE static inline __attribute__((always_inline))
+
+#define KB (1 << 10)
+#define MB (1 << 20)
+#define GB (1 << 30)
+
#define ALIGN(value, align) ((value) + ((-(value)) & ((align) - 1)))
+#define IS_ALIGNED(value, align) ((value) % (align) == 0)
/* 64-bit types */
typedef unsigned long long uint64_t;
@@ -38,8 +45,16 @@ typedef short int16_t;
typedef unsigned char uint8_t;
typedef char int8_t;
+#ifdef SAYORI64
+typedef uint64_t size_t;
+typedef int64_t ssize_t;
+#else
typedef uint32_t size_t;
typedef int32_t ssize_t;
+#endif
+
+
+
struct registers {
uint32_t ds;
@@ -51,8 +66,14 @@ struct registers {
typedef struct registers registers_t;
// Use ON_NULLPTR macro to tell a user (developer) that he passed a nullptr
-#define ON_NULLPTR(ptr, code) do { if((ptr) == 0) { \
- qemu_err("Mumble, you have an illusion that you see an object but you can't touch it because it's not exist..."); \
- code \
- } \
-} while(0)
+#ifndef RELEASE
+#define ON_NULLPTR(ptr, code) \
+ do { \
+ if((ptr) == 0) { \
+ qemu_err("You have an illusion that you see an object but you can't touch it because it's not exist..."); \
+ code \
+ } \
+ } while(0)
+#else
+#define ON_NULLPTR(ptr, code)
+#endif
diff --git a/kernel/include/debug/hexview.h b/kernel/include/debug/hexview.h
index 3649631d2..06a3e632f 100644
--- a/kernel/include/debug/hexview.h
+++ b/kernel/include/debug/hexview.h
@@ -1,3 +1,3 @@
#pragma once
-void hexview_advanced(char* buffer, size_t length, size_t width, bool relative, void (*printer_func)(const char *, ...));
\ No newline at end of file
+void hexview_advanced(void *buffer, size_t length, size_t width, bool relative, void (*printer_func)(const char *, ...));
\ No newline at end of file
diff --git a/kernel/include/debug/memmeter.h b/kernel/include/debug/memmeter.h
new file mode 100644
index 000000000..51cdeca47
--- /dev/null
+++ b/kernel/include/debug/memmeter.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void memmeter(void (*function)());
\ No newline at end of file
diff --git a/kernel/include/debug/ubsan.h b/kernel/include/debug/ubsan.h
index b59297677..08425d97e 100644
--- a/kernel/include/debug/ubsan.h
+++ b/kernel/include/debug/ubsan.h
@@ -6,7 +6,7 @@
#include "common.h"
-#define is_aligned(value, alignment) !(value & (alignment - 1))
+#define is_aligned(value, alignment) !((value) & ((alignment) - 1))
struct source_location {
const char *file;
diff --git a/kernel/include/gui/parallel_desktop.h b/kernel/include/desktop/parallel_desktop.h
similarity index 100%
rename from kernel/include/gui/parallel_desktop.h
rename to kernel/include/desktop/parallel_desktop.h
diff --git a/kernel/include/gui/render.h b/kernel/include/desktop/render.h
similarity index 77%
rename from kernel/include/gui/render.h
rename to kernel/include/desktop/render.h
index 8fc845872..3566450e0 100644
--- a/kernel/include/gui/render.h
+++ b/kernel/include/desktop/render.h
@@ -1,7 +1,7 @@
#pragma once
-#include "gui/window.h"
-#include "gui/widget.h"
+#include "desktop/window.h"
+#include "desktop/widget.h"
#include "gui/basics.h"
#include "io/tty.h"
@@ -10,6 +10,8 @@
#define WINDOW_TITLEBAR_COLOR 0x909090
#define GUI_BACKGROUND_COLOR 0x505050
+extern vector_t* windows;
+
void gui_render_window(Window_t* window);
// Render GUI
void gui_render();
\ No newline at end of file
diff --git a/kernel/include/gui/widget.h b/kernel/include/desktop/widget.h
similarity index 83%
rename from kernel/include/gui/widget.h
rename to kernel/include/desktop/widget.h
index 717ce8c09..f43e5a445 100644
--- a/kernel/include/gui/widget.h
+++ b/kernel/include/desktop/widget.h
@@ -1,7 +1,7 @@
#pragma once
#include
-#include "gui/window.h"
+#include "desktop/window.h"
#include "gui/pointutils.h"
struct Widget;
@@ -27,5 +27,7 @@ typedef enum WidgetNotifyCode {
} WidgetNotifyCode_t;
Widget_t* new_bare_widget(renderer_func_t renderer, destroyer_func_t destroyer, size_t x, size_t y, size_t width, size_t height);
+void window_add_widget(Window_t* window, struct Widget* widget);
+void window_remove_widget(Window_t* window, struct Widget* widget);
void destroy_widget(Widget_t* widget);
void widget_notify(struct Window* window, struct Widget* widget, WidgetNotifyCode_t code, void* data);
\ No newline at end of file
diff --git a/kernel/include/gui/widget_button.h b/kernel/include/desktop/widget_button.h
similarity index 100%
rename from kernel/include/gui/widget_button.h
rename to kernel/include/desktop/widget_button.h
diff --git a/kernel/include/gui/widget_image.h b/kernel/include/desktop/widget_image.h
similarity index 59%
rename from kernel/include/gui/widget_image.h
rename to kernel/include/desktop/widget_image.h
index b377b9025..80792bcb6 100644
--- a/kernel/include/gui/widget_image.h
+++ b/kernel/include/desktop/widget_image.h
@@ -1,21 +1,23 @@
#pragma once
#include
-#include
#include "widget.h"
+#include "fmt/tga.h"
-typedef enum Widget_Image_Display_Mode {
+typedef enum {
NORMAL,
STRETCH
} Widget_Image_Display_Mode_t;
typedef struct Widget_Image {
- char* path;
+ const char* path;
- struct DukeImageMeta* meta;
+ tga_header_t meta;
void* image_data;
+ bool loaded;
+
Widget_Image_Display_Mode_t display_mode;
} Widget_Image_t;
-Widget_t* new_widget_image(char* path);
\ No newline at end of file
+Widget_t* new_widget_image(const char *path);
\ No newline at end of file
diff --git a/kernel/include/gui/widget_label.h b/kernel/include/desktop/widget_label.h
similarity index 53%
rename from kernel/include/gui/widget_label.h
rename to kernel/include/desktop/widget_label.h
index 6954b417a..b5c0da32c 100644
--- a/kernel/include/gui/widget_label.h
+++ b/kernel/include/desktop/widget_label.h
@@ -1,15 +1,16 @@
#pragma once
-#include "gui/widget.h"
-#include "gui/widget_label.h"
+#include "desktop/widget.h"
+#include "desktop/widget_label.h"
#include "gui/basics.h"
-#include "io/port_io.h"
+#include "io/serial_port.h"
typedef struct Widget_Label {
- char* label;
+ const char* label;
+ size_t length;
uint32_t color;
} Widget_Label_t;
void widget_label_renderer(struct Widget* this, __attribute__((unused)) struct Window* container);
-Widget_t* new_widget_label(char* label, ssize_t x, ssize_t y, uint32_t color);
+Widget_t* new_widget_label(const char *label, ssize_t x, ssize_t y, uint32_t color);
void destroy_widget_label(Widget_t* widget);
\ No newline at end of file
diff --git a/kernel/include/desktop/widget_progress.h b/kernel/include/desktop/widget_progress.h
new file mode 100644
index 000000000..6d42445a5
--- /dev/null
+++ b/kernel/include/desktop/widget_progress.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "desktop/widget.h"
+#include "gui/basics.h"
+#include "io/serial_port.h"
+
+typedef struct Widget_Progress {
+ size_t current;
+} Widget_Progress_t;
+
+void widget_progress_renderer(struct Widget* this, __attribute__((unused)) struct Window* container);
+Widget_t* new_widget_progress();
+void destroy_widget_progress(Widget_t* widget);
\ No newline at end of file
diff --git a/kernel/include/gui/window.h b/kernel/include/desktop/window.h
similarity index 68%
rename from kernel/include/gui/window.h
rename to kernel/include/desktop/window.h
index 886b8a60c..2ee34f6f1 100644
--- a/kernel/include/gui/window.h
+++ b/kernel/include/desktop/window.h
@@ -1,8 +1,10 @@
#pragma once
#include
-// #include "gui/widget.h"
#include "gui/pointutils.h"
+#include "../../src/lib/libvector/include/vector.h"
+
+#define WINDOW(idx) ((Window_t*)(windows->data[idx]))
typedef enum WindowState {
NOT_INITIALIZED,
@@ -16,6 +18,10 @@ typedef enum WindowSignal {
WINDOW_MINIMIZE
} WindowSignal_t;
+struct Window;
+
+typedef void (*on_close_function_t)(struct Window* window);
+
typedef struct Window {
size_t id;
char* title;
@@ -30,16 +36,16 @@ typedef struct Window {
uint32_t canvas_bgcolor;
- size_t widget_count;
- struct Widget** widgets;
+ vector_t* widgets;
+
+ on_close_function_t on_close;
+ void* data; // Data, used by application to unify window's data
} Window_t;
Window_t* window_new(char* title);
-Window_t** get_window_list();
+vector_t * get_window_list();
void _window_add_to_list(Window_t* window);
size_t get_window_count();
void window_destroy(Window_t* win);
-void window_add_widget(Window_t* window, struct Widget* widget);
-void window_remove_widget(Window_t* window, struct Widget* widget);
void window_send_signal(Window_t* window, WindowSignal_t signal, void* data);
void destroy_all_windows();
\ No newline at end of file
diff --git a/kernel/include/drv/atapi.h b/kernel/include/drv/atapi.h
index b9fe26787..ce76f314b 100644
--- a/kernel/include/drv/atapi.h
+++ b/kernel/include/drv/atapi.h
@@ -1,8 +1,9 @@
#pragma once
#include "common.h"
-#include "drv/ata.h"
+#include "drv/disk/ata.h"
#include "io/ports.h"
+#include
#define ATAPI_CMD_READY 0x00
#define ATAPI_CMD_RQ_SENSE 0x03
diff --git a/kernel/include/drv/audio/ac97.h b/kernel/include/drv/audio/ac97.h
index aca052072..8518c1578 100644
--- a/kernel/include/drv/audio/ac97.h
+++ b/kernel/include/drv/audio/ac97.h
@@ -5,7 +5,6 @@
#pragma once
#include
-#include
#include
#define AC97_VENDOR 0x8086
@@ -31,39 +30,26 @@ typedef struct {
#define NABM_GLOBAL_CONTROL 0x2C
#define NABM_GLOBAL_STATUS 0x30
-#define BUFFER_SIZE (64 * 1024)
-
typedef struct {
- uint32_t memory_pos;
+ void* memory_pos;
uint16_t sample_count;
uint16_t flags;
-} __attribute__((packed)) AC97_BDL_t;
-
-static AC97_BDL_t ac97_bdl_buffer[32];
-static uint16_t native_audio_mixer = 0;
-static uint16_t native_audio_bus_master = 0;
-
-#define ac97_clear_status_register() outb(native_audio_bus_master + 0x16, 0x1C)
-#define _ac97_update_bdl(address) outl(native_audio_bus_master + NABM_PCM_OUT, address)
-#define ac97_update_bdl() _ac97_update_bdl((uint32_t)&ac97_bdl_buffer)
-#define ac97_update_lvi(index) outb(native_audio_bus_master + NABM_PCM_OUT + 0x05, (uint8_t)(index))
-#define ac97_clear_bdl() memset(&ac97_bdl_buffer, 0, sizeof(AC97_BDL_t)*31)
+} AC97_BDL_t;
// Volume in dB, not %
void ac97_set_master_volume(uint8_t left, uint8_t right, bool mute);
// Volume in dB, not %
void ac97_set_pcm_volume(uint8_t right, uint8_t left, bool mute);
-void ac97_set_pcm_sample_rate(uint32_t sample_rate);
+void ac97_set_pcm_sample_rate(uint16_t sample_rate);
void ac97_load_data(char* data, uint32_t length);
void ac97_reset_channel();
+void ac97_clear_status_register();
+void ac97_update_bdl();
+void ac97_update_lvi(uint8_t index);
+void ac97_set_play_sound(bool play);
void ac97_init();
-size_t ac97_copy_user_memory_to_dma(char* data, size_t length);
-void ac97_single_page_write(ssize_t page_num);
-void ac97_single_page_write_wait(ssize_t page_num);
+size_t ac97_copy_user_memory_to_dma(const char* data, size_t length);
+void ac97_single_page_write_wait(size_t page_num);
void ac97_destroy_user_buffer();
-bool ac97_is_initialized();
-
-static inline void ac97_set_play_sound(bool play) {
- outb(native_audio_bus_master + 0x1b, inb(native_audio_bus_master + 0x1B) | play);
-}
+bool ac97_is_initialized();
\ No newline at end of file
diff --git a/kernel/include/drv/beeper.h b/kernel/include/drv/beeper.h
old mode 100755
new mode 100644
index 9c921cfda..b336852e3
--- a/kernel/include/drv/beeper.h
+++ b/kernel/include/drv/beeper.h
@@ -60,5 +60,5 @@ typedef struct Note {
unsigned short duration;
} Note;
-void beeperPlay(uint32_t nFrequence);
+void beeperPlay(uint32_t frequency);
void beeperSilent();
\ No newline at end of file
diff --git a/kernel/include/drv/cmos.h b/kernel/include/drv/cmos.h
old mode 100755
new mode 100644
index 5aed7a4a7..f57f389b3
--- a/kernel/include/drv/cmos.h
+++ b/kernel/include/drv/cmos.h
@@ -1,10 +1,6 @@
#pragma once
#include
-/*
-#define uint8_t unsigned char
-#define uint16_t unsigned short
-*/
typedef struct sayori_time {
uint8_t seconds;
diff --git a/kernel/include/drv/disk/ahci.h b/kernel/include/drv/disk/ahci.h
new file mode 100644
index 000000000..376424edc
--- /dev/null
+++ b/kernel/include/drv/disk/ahci.h
@@ -0,0 +1,304 @@
+#pragma once
+
+#include "common.h"
+
+#define AHCI_SIGNATURE_SATAPI 0xEB140101
+#define AHCI_SIGNATURE_SATA 0x00000101
+
+#define AHCI_HBA_ST 0x0001
+#define AHCI_HBA_FRE 0x0010
+#define AHCI_HBA_FR 0x4000
+#define AHCI_HBA_CR 0x8000
+
+#define AHCI_HBA_TFES (1 << 30)
+
+typedef volatile struct {
+ uint32_t command_list_base_address_low; // 1K-byte aligned
+ uint32_t command_list_base_address_high;
+ uint32_t fis_base_address_low; // 256-byte aligned
+ uint32_t fis_base_address_high;
+ uint32_t interrupt_status;
+ uint32_t interrupt_enable;
+ uint32_t command_and_status;
+ uint32_t reserved;
+ uint32_t task_file_data;
+ uint32_t signature;
+ uint32_t sata_status;
+ uint32_t sata_control;
+ uint32_t sata_error;
+ uint32_t sata_active;
+ uint32_t command_issue;
+ uint32_t sata_notification;
+ uint32_t fis_based_switch_control;
+
+ uint32_t reserved1[11];
+ uint32_t vendor[4];
+} __attribute__((packed)) AHCI_HBA_PORT;
+
+typedef volatile struct {
+ uint32_t capability;
+ uint32_t global_host_control;
+ uint32_t interrupt_status;
+ uint32_t port_implemented;
+ uint32_t version;
+ uint32_t command_completion_coalescing_control;
+ uint32_t command_completion_coalescing_ports;
+ uint32_t enclosure_management_location;
+ uint32_t enclosure_management_control;
+ uint32_t host_capabilities_extended;
+ uint32_t handoff_control_and_status;
+
+ char reserved[0xA0 - 0x2C];
+ char vendor[0x100 - 0xA0];
+
+ AHCI_HBA_PORT ports[0];
+} __attribute__((packed)) AHCI_HBA_MEM;
+
+typedef enum {
+ FIS_TYPE_REG_HOST_TO_DEVICE = 0x27, // Register FIS - host to device
+ FIS_TYPE_REG_DEVICE_TO_HOST = 0x34, // Register FIS - device to host
+ FIS_TYPE_DMA_ACTIVATE = 0x39, // DMA activate FIS - device to host
+ FIS_TYPE_DMA_SETUP = 0x41, // DMA setup FIS - bidirectional
+ FIS_TYPE_DATA = 0x46, // Data FIS - bidirectional
+ FIS_TYPE_BIST = 0x58, // BIST activate FIS - bidirectional
+ FIS_TYPE_PIO_SETUP = 0x5F, // PIO setup FIS - device to host
+ FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host
+} AHCI_FIS_TYPE;
+
+typedef struct {
+ uint8_t fis_type; // FIS_TYPE_REG_H2D
+
+ uint8_t pmport:4; // Port multiplier
+ uint8_t rsv0:3; // Reserved
+ uint8_t c:1; // 1: Command, 0: Control
+
+ uint8_t command; // Command register
+ uint8_t featurel; // Feature register, 7:0
+
+ uint8_t lba0; // LBA low register, 7:0
+ uint8_t lba1; // LBA mid register, 15:8
+ uint8_t lba2; // LBA high register, 23:16
+ uint8_t device; // Device register
+
+ uint8_t lba3; // LBA register, 31:24
+ uint8_t lba4; // LBA register, 39:32
+ uint8_t lba5; // LBA register, 47:40
+ uint8_t featureh; // Feature register, 15:8
+
+ uint8_t countl; // Count register, 7:0
+ uint8_t counth; // Count register, 15:8
+ uint8_t icc; // Isochronous command completion
+ uint8_t control; // Control register
+
+ uint8_t rsv1[4]; // Reserved
+} AHCI_FIS_REG_HOST_TO_DEVICE;
+
+typedef struct {
+ uint8_t fis_type; // FIS_TYPE_REG_D2H
+
+ uint8_t pmport:4; // Port multiplier
+ uint8_t rsv0:2; // Reserved
+ uint8_t i:1; // Interrupt bit
+ uint8_t rsv1:1; // Reserved
+
+ uint8_t status; // Status register
+ uint8_t error; // Error register
+
+ uint8_t lba0; // LBA low register, 7:0
+ uint8_t lba1; // LBA mid register, 15:8
+ uint8_t lba2; // LBA high register, 23:16
+ uint8_t device; // Device register
+
+ uint8_t lba3; // LBA register, 31:24
+ uint8_t lba4; // LBA register, 39:32
+ uint8_t lba5; // LBA register, 47:40
+ uint8_t rsv2; // Reserved
+
+ uint8_t countl; // Count register, 7:0
+ uint8_t counth; // Count register, 15:8
+ uint8_t rsv3[2]; // Reserved
+
+ uint8_t rsv4[4]; // Reserved
+} AHCI_FIS_REG_DEVICE_TO_HOST;
+
+typedef struct {
+ // DWORD 0
+ uint8_t fis_type; // FIS_TYPE_DATA
+
+ uint8_t pmport:4; // Port multiplier
+ uint8_t rsv0:4; // Reserved
+
+ uint8_t rsv1[2]; // Reserved
+
+ // DWORD 1 ~ N
+ uint32_t data[1]; // Payload
+} AHCI_FIS_DATA;
+
+typedef struct tagFIS_DMA_SETUP
+{
+ uint8_t fis_type; // FIS_TYPE_DMA_SETUP
+
+ uint8_t pmport:4; // Port multiplier
+ uint8_t rsv0:1; // Reserved
+ uint8_t d:1; // Data transfer direction, 1 - device to host
+ uint8_t i:1; // Interrupt bit
+ uint8_t a:1; // Auto-activate. Specifies if DMA Activate FIS is needed
+
+ uint8_t rsved[2]; // Reserved
+
+ uint32_t DMAbufferID_low; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory.
+ uint32_t DMAbufferID_high; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory.
+
+ uint32_t rsvd; //More reserved
+
+ uint32_t DMAbufOffset; //Byte offset into buffer. First 2 bits must be 0
+ uint32_t TransferCount; //Number of bytes to transfer. Bit 0 must be 0
+
+ uint32_t resvd; //Reserved
+} AHCI_FIS_DMA_SETUP;
+
+typedef struct {
+ uint8_t fis_type; // FIS_TYPE_PIO_SETUP
+
+ uint8_t pmport:4; // Port multiplier
+ uint8_t rsv0:1; // Reserved
+ uint8_t d:1; // Data transfer direction, 1 - device to host
+ uint8_t i:1; // Interrupt bit
+ uint8_t rsv1:1;
+
+ uint8_t status; // Status register
+ uint8_t error; // Error register
+
+ uint8_t lba0; // LBA low register, 7:0
+ uint8_t lba1; // LBA mid register, 15:8
+ uint8_t lba2; // LBA high register, 23:16
+ uint8_t device; // Device register
+
+ uint8_t lba3; // LBA register, 31:24
+ uint8_t lba4; // LBA register, 39:32
+ uint8_t lba5; // LBA register, 47:40
+ uint8_t rsv2; // Reserved
+
+ uint8_t countl; // Count register, 7:0
+ uint8_t counth; // Count register, 15:8
+ uint8_t rsv3; // Reserved
+ uint8_t e_status; // New value of status register
+
+ uint16_t tc; // Transfer count
+ uint8_t rsv4[2]; // Reserved
+} AHCI_FIS_PIO_SETUP;
+
+typedef struct {
+ // 0
+ uint8_t cfl:5; // Command FIS length in DWORDS, 2 ~ 16
+ uint8_t a:1; // ATAPI
+ uint8_t w:1; // Write, 1: H2D, 0: D2H
+ uint8_t p:1; // Prefetchable
+
+ // 1
+ uint8_t r:1; // Reset
+ uint8_t b:1; // BIST
+ uint8_t c:1; // Clear busy upon R_OK
+ uint8_t rsv0:1; // Reserved
+ uint8_t pmp:4; // Port multiplier port
+
+ // 2
+ uint16_t prdtl; // Physical region descriptor table length in entries
+
+ // 4
+ volatile uint32_t prdbc; // Physical region descriptor byte count transferred
+
+ // 8
+ uint32_t ctba; // Command table descriptor base address
+ uint32_t ctbau; // Command table descriptor base address upper 32 bits
+
+ // 16
+ uint32_t rsv1[4]; // Reserved
+} AHCI_HBA_CMD_HEADER;
+
+typedef struct {
+ uint8_t fis_type;
+ uint8_t pmport:4;
+ uint8_t rsvd:2;
+ uint8_t i:1;
+ uint8_t n:1;
+ uint8_t statusl:3;
+ uint8_t rsvd2:1;
+ uint8_t statush:3;
+ uint8_t rsvd3:1;
+ uint8_t error;
+ uint32_t protocol;
+} AHCI_FIS_DEV_BITS;
+
+
+typedef volatile struct {
+ AHCI_FIS_DMA_SETUP dsfis; // DMA Setup FIS
+ uint8_t pad0[4];
+
+ AHCI_FIS_PIO_SETUP psfis; // PIO Setup FIS
+ uint8_t pad1[12];
+
+ AHCI_FIS_REG_DEVICE_TO_HOST rfis; // Register – Device to Host FIS
+ uint8_t pad2[4];
+
+ AHCI_FIS_DEV_BITS sdbfis; // Set Device Bit FIS
+
+ uint8_t ufis[64];
+
+ uint8_t rsv[0x100-0xA0];
+} AHCI_HBA_FIS;
+
+typedef struct {
+ uint32_t dba; // Data base address
+ uint32_t dbau; // Data base address upper 32 bits
+ uint32_t rsv0; // Reserved
+
+ uint32_t dbc:22; // Byte count, 4M max
+ uint32_t rsv1:9; // Reserved
+ uint32_t i:1; // Interrupt on completion
+} AHCI_HBA_PRDT_ENTRY;
+
+#define COMMAND_TABLE_PRDT_ENTRY_COUNT 8
+
+typedef struct {
+ uint8_t cfis[64]; // Command FIS
+ uint8_t acmd[16]; // ATAPI command, 12 or 16 bytes
+ uint8_t rsv[48]; // Reserved
+ AHCI_HBA_PRDT_ENTRY prdt_entry[COMMAND_TABLE_PRDT_ENTRY_COUNT]; // Physical region descriptor table entries, 0 ~ 65535
+} HBA_CMD_TBL;
+
+#define COMMAND_LIST_ENTRY_COUNT 32
+#define COMMAND_LIST_ENTRY_SIZE sizeof(AHCI_HBA_CMD_HEADER)
+#define COMMAND_LIST_SIZE (COMMAND_LIST_ENTRY_COUNT * COMMAND_LIST_ENTRY_SIZE)
+
+#define FIS_SIZE sizeof(AHCI_HBA_FIS)
+
+#define COMMAND_TABLE_ENTRY_SIZE sizeof(HBA_CMD_TBL)
+#define COMMAND_TABLE_ENTRY_COUNT 32
+#define COMMAND_TABLE_SIZE (COMMAND_TABLE_ENTRY_SIZE * COMMAND_LIST_ENTRY_COUNT)
+
+#define MEMORY_PER_AHCI_PORT (COMMAND_LIST_SIZE + FIS_SIZE + COMMAND_TABLE_SIZE)
+
+// Here we using port_num = 0 because we using new memory layout.
+#define AHCI_COMMAND_LIST(mem, port_num) (((size_t)mem) + (MEMORY_PER_AHCI_PORT * port_num))
+#define AHCI_FIS(mem, port_num) (AHCI_COMMAND_LIST(mem, port_num) + COMMAND_LIST_SIZE)
+#define AHCI_COMMAND_TABLE(mem, port_num) (AHCI_FIS(mem, port_num) + FIS_SIZE)
+#define AHCI_COMMAND_TABLE_ENTRY(mem, port_num, i) (AHCI_COMMAND_TABLE(mem, port_num) + (i * COMMAND_TABLE_ENTRY_SIZE))
+
+struct ahci_port_descriptor {
+ AHCI_HBA_CMD_HEADER* command_list_addr_virt;
+ size_t command_list_addr_phys;
+
+ size_t fis_virt;
+ size_t fis_phys;
+};
+
+void ahci_init();
+bool ahci_is_drive_attached(size_t port_num);
+int ahci_free_cmd_slot(size_t port_num);
+void ahci_start_cmd(size_t port_num);
+void ahci_stop_cmd(size_t port_num);
+void ahci_rebase_memory_for(size_t port_num);
+void ahci_identify(size_t port_num);
+void ahci_read_sectors(size_t port_num, size_t location, size_t sector_count, void* buffer);
+void ahci_write_sectors(size_t port_num, size_t location, size_t sector_count, void* buffer);
\ No newline at end of file
diff --git a/kernel/include/drv/ata.h b/kernel/include/drv/disk/ata.h
similarity index 53%
rename from kernel/include/drv/ata.h
rename to kernel/include/drv/disk/ata.h
index 89bc3d01e..5f95873fb 100644
--- a/kernel/include/drv/ata.h
+++ b/kernel/include/drv/disk/ata.h
@@ -1,6 +1,7 @@
#pragma once
-#include "common.h"
+#include "ndpm.h"
+#include "../../common.h"
#define ATA_SR_BSY 0x80
#define ATA_SR_DRDY 0x40
@@ -35,16 +36,16 @@
#define ATA_CMD_IDENTIFY 0xEC
#define ATA_IDENT_DEVICETYPE 0
-#define ATA_IDENT_CYLINDERS 2
-#define ATA_IDENT_HEADS 6
-#define ATA_IDENT_SECTORS 12
-#define ATA_IDENT_SERIAL 20
-#define ATA_IDENT_MODEL 54
-#define ATA_IDENT_CAPABILITIES 98
-#define ATA_IDENT_FIELDVALID 106
-#define ATA_IDENT_MAX_LBA 120
-#define ATA_IDENT_COMMANDSETS 164
-#define ATA_IDENT_MAX_LBA_EXT 200
+#define ATA_IDENT_CYLINDERS 1
+#define ATA_IDENT_HEADS 3
+#define ATA_IDENT_SECTORS 6
+#define ATA_IDENT_SERIAL 10
+#define ATA_IDENT_MODEL 27
+#define ATA_IDENT_CAPABILITIES 49
+#define ATA_IDENT_FIELDVALID 53
+#define ATA_IDENT_MAX_LBA 60
+#define ATA_IDENT_COMMANDSETS 82
+#define ATA_IDENT_MAX_LBA_EXT 100
#define IDE_ATA 0x00
#define IDE_ATAPI 0x01
@@ -97,24 +98,32 @@
#define ATA_SECONDARY_IRQ 15
#define PRIM_SEC(bus) ((bus) == ATA_PRIMARY?"Primary ":"Secondary")
-#define MAST_SLV(drive) ((drive) == ATA_PRIMARY?"master":"slave ")
+#define MAST_SLV(drive) ((drive) == ATA_MASTER?"master":"slave ")
#define DRIVE(bus, drive) ((bus) << 1 | (drive))
#define ATA_PORT(bus) ((bus) == ATA_PRIMARY ? ATA_PRIMARY_IO : ATA_SECONDARY_IO)
+/// Эта структура определяет каждый ATA диск в системе
typedef struct {
- bool online;
- size_t capacity;
+ uint8_t drive;
+ bool online; /// Устройство доступно?
+ size_t capacity; /// Ёмкость диска в секторах
- bool is_packet;
- bool is_chs_addressing;
+ bool is_packet; /// Является ли пакетным устройством?
+ bool is_medium_inserted;
+ bool is_chs_addressing; /// Адресация по CHS?
- uint16_t block_size;
+ uint16_t block_size; /// Размер сектора
- uint16_t cylinders;
- uint16_t heads;
- uint16_t sectors;
+ uint16_t cylinders; /// Цилиндры
+ uint16_t heads; /// Головки
+ uint16_t sectors; /// Сектора
- bool is_sata;
+ bool is_sata; /// Является ли этот диск SATA устройством?
+ bool is_dma; /// Поддерживает ли этот диск DMA?
+
+ char* model_name;
+ char* fwversion;
+ char* serial_number;
} ata_drive_t;
@@ -122,14 +131,14 @@ void ide_select_drive(uint8_t bus, bool slave);
void ide_400ns_delay(uint16_t io);
void ide_poll(uint16_t io);
-uint8_t ata_read_sector(uint8_t drive, uint8_t *buf, uint32_t lba);
-uint8_t ata_write_raw_sector(uint8_t drive, const uint8_t *buf, uint32_t lba);
+uint8_t ata_pio_read_sector(uint8_t drive, uint8_t *buf, uint32_t lba);
+uint8_t ata_pio_write_raw_sector(uint8_t drive, const uint8_t *buf, uint32_t lba);
-void ata_write_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, size_t sectors);
-void ata_read_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, uint32_t numsects);
+void ata_pio_write_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, size_t sectors);
+void ata_pio_read_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, uint32_t numsects);
-void ata_read(uint8_t drive, uint8_t* buf, uint32_t location, uint32_t length) ;
-void ata_write(uint8_t drive, const uint8_t* buf, size_t location, size_t length);
+void ata_pio_read(uint8_t drive, uint8_t* buf, uint32_t location, uint32_t length) ;
+void ata_pio_write(uint8_t drive, const uint8_t* buf, size_t location, size_t length);
void ata_list();
void ata_init();
@@ -137,4 +146,19 @@ void ata_init();
ata_drive_t* ata_get_drives();
void ata_check_all();
-uint8_t ide_identify(uint8_t bus, uint8_t drive);
\ No newline at end of file
+uint8_t ide_identify(uint8_t bus, uint8_t drive);
+
+static inline void ata_set_params(uint8_t drive, uint16_t* io, uint8_t* real_drive) {
+ uint8_t _io = drive >> 1; // PRIMARY / SECONDARY
+ uint8_t _drv = drive & 1; // MASTER / SLAVE
+
+ if(_io == ATA_PRIMARY)
+ *io = ATA_PRIMARY_IO;
+ else if(_io == ATA_SECONDARY)
+ *io = ATA_SECONDARY_IO;
+
+ *real_drive = _drv;
+}
+
+void ata_ndpm_read(const ndpm_drive_t* drive, size_t location, int size, void* buffer);
+void ata_ndpm_write(const ndpm_drive_t* drive, size_t location, int size, void* buffer);
\ No newline at end of file
diff --git a/kernel/include/drv/disk/ata_dma.h b/kernel/include/drv/disk/ata_dma.h
new file mode 100644
index 000000000..0f1411e27
--- /dev/null
+++ b/kernel/include/drv/disk/ata_dma.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "common.h"
+#include "sys/status.h"
+
+#define ATA_DMA_MARK_END 0x8000
+
+typedef struct prdt {
+ uint32_t buffer_phys;
+ uint16_t transfer_size;
+ uint16_t mark_end;
+} __attribute__((packed)) prdt_t;
+
+status_t ata_dma_read(uint8_t drive, char *buf, uint32_t location, uint32_t length);
+status_t ata_dma_write(uint8_t drive, const char *buf, uint32_t location, uint32_t length);
\ No newline at end of file
diff --git a/kernel/include/drv/disk/dpm.h b/kernel/include/drv/disk/dpm.h
new file mode 100644
index 000000000..af65a82fa
--- /dev/null
+++ b/kernel/include/drv/disk/dpm.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include
+
+#define DPM_ERROR_NO_MOUNT (-1) ///< Не удалось примонтировать устройство
+#define DPM_ERROR_NOT_READY (-2) ///< Устройство не готово к работе
+#define DPM_ERROR_NO_READ (-3) ///< Не удалось прочитать файл
+
+// disk, offset, size, buffer
+typedef int (*dpm_disk_rw_cmd)(size_t,size_t,size_t,void*);
+
+typedef struct {
+ bool Ready; ///< Устройство подключено? (1 - да | 0 - нет)
+ char Name[128]; ///< Имя диск
+ char FileSystem[64]; ///< Файловая система
+ int Status; ///< Режим устройства (0 - не обслуживает | 1 - Чтение/Запись | 2 - Только чтение)
+ size_t Size; ///< Размер диска (в байтах)
+ size_t Sectors; ///< Кол-во секторов
+ size_t SectorSize; ///< Размер секторов
+ int AddrMode; ///< Метод адрессации (0 - CHS | 1 - LBA | 2 - RAM | 3 - RW for FNC)
+ char Serial[16]; ///< Серийный номер диска
+ void* Point; ///< Точка входа в оперативной памяти
+ void* Reserved; ///< Можно в ОЗУ дописать доп.данные если требуется.
+ dpm_disk_rw_cmd Read; ///< Команда для чтения данных
+ dpm_disk_rw_cmd Write; ///< Команда для записи данных
+} __attribute__((packed)) DPM_Disk;
+
+
+
+void* dpm_metadata_read(char Letter);
+void dpm_metadata_write(char Letter, uint32_t Addr);
+size_t dpm_read(char Letter, size_t Offset, size_t Size, void *Buffer);
+int dpm_reg(char Letter, char* Name, char* FS, int Status, size_t Size, size_t Sectors, size_t SectorSize, int AddrMode, char* Serial, void *Point);
+DPM_Disk dpm_info(char Letter);
+int dpm_unmount(char Letter, bool FreeReserved);
+void dpm_LabelUpdate(char Letter, char* Label);
\ No newline at end of file
diff --git a/kernel/include/drv/disk/floppy.h b/kernel/include/drv/disk/floppy.h
index d849626a5..b9bb36a5a 100644
--- a/kernel/include/drv/disk/floppy.h
+++ b/kernel/include/drv/disk/floppy.h
@@ -105,7 +105,8 @@ enum FloppyRegisters
FLOPPY_DIGITAL_INPUT_REGISTER = 7, ///< (?) Доступно в режиме только чтения
FLOPPY_CONFIGURATION_CONTROL_REGISTER = 7 ///< [Исп] Регистр для управления конфигурацией, в режиме только записи
};
-typedef int (*FloppyRW_t)(int,char*,uint32_t,uint32_t);
+typedef size_t (*FloppyR_t)(int,char*,uint32_t,uint32_t);
+typedef size_t (*FloppyW_t)(int,const char*,uint32_t,uint32_t);
typedef int (*FloppyCache_t)(int,FloppyMode,uint32_t,uint32_t*,uint32_t*);
typedef struct floppy
{
@@ -118,9 +119,9 @@ typedef struct floppy
int Motor; ///< Статус мотора
char Name[12]; ///< Название дискеты
char FileSystem[12]; ///< Файловая система
- unsigned Cyr; ///< ?
- FloppyRW_t Read; ///< Команда для чтения данных
- FloppyRW_t Write; ///< Команда для записи данных
+ unsigned Cyr; ///< Цилиндры
+ FloppyR_t Read; ///< Команда для чтения данных
+ FloppyW_t Write; ///< Команда для записи данных
FloppyCache_t Cache; ///< Команда для кэша
const char* Buffer; ///< Буфер
} floppy_t;
\ No newline at end of file
diff --git a/kernel/include/drv/disk/ndpm.h b/kernel/include/drv/disk/ndpm.h
new file mode 100644
index 000000000..8cca2b352
--- /dev/null
+++ b/kernel/include/drv/disk/ndpm.h
@@ -0,0 +1,29 @@
+//
+// Created by ndraey on 23.12.23.
+//
+
+#pragma once
+#include "common.h"
+
+typedef struct ndpm_drive ndpm_drive_t;
+
+typedef void (*ndpm_read_fn_t)(const ndpm_drive_t*, size_t location, int size, void* buffer);
+typedef void (*ndpm_write_fn_t)(const ndpm_drive_t*, size_t location, int size, void* buffer);
+
+typedef struct ndpm_drive {
+ void* drive_specific_data;
+ ndpm_read_fn_t read_fn;
+ ndpm_write_fn_t write_fn;
+} ndpm_drive_t;
+
+void ndpm_init();
+void ndpm_add_drive(void* specific_data, ndpm_read_fn_t reader, ndpm_write_fn_t writer);
+ndpm_drive_t* ndpm_get_drive(int index);
+
+SAYORI_INLINE void ndpm_read(const ndpm_drive_t* drive, size_t location, int size, void* buffer) {
+ drive->read_fn(drive, location, size, buffer);
+}
+
+SAYORI_INLINE void ndpm_write(const ndpm_drive_t* drive, size_t location, int size, void* buffer) {
+ drive->write_fn(drive, location, size, buffer);
+}
\ No newline at end of file
diff --git a/kernel/include/drv/input/keyboard.h b/kernel/include/drv/input/keyboard.h
old mode 100755
new mode 100644
index 4595c6307..f7b267f23
--- a/kernel/include/drv/input/keyboard.h
+++ b/kernel/include/drv/input/keyboard.h
@@ -14,4 +14,5 @@ void gets(char *buffer);
bool is_lctrl_key();
int getCharRaw();
int getIntKeyboardWait();
-uint8_t getPressReleaseKeyboard();
\ No newline at end of file
+uint8_t getPressReleaseKeyboard();
+int gets_max(char *buffer, int length);
\ No newline at end of file
diff --git a/kernel/include/drv/pci.h b/kernel/include/drv/pci.h
index 71dc01c2a..db56b654d 100644
--- a/kernel/include/drv/pci.h
+++ b/kernel/include/drv/pci.h
@@ -3,69 +3,68 @@
* @file drv/pci.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru), Арен Елчинян (SynapseOS)
* @brief Драйвер PCI (Peripheral Component Interconnect)
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-01-14
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
#pragma once
-#include
#include
#define CLASS_DEVICE_TOO_OLD 0x00 ///! Устройство не имеет идентификатора класса, возможно, оно было сделано до его определения
-#define CLASS_MASS_STORAGE 0x01 ///< Контроллер запоминающего устройства
-#define CLASS_NETWORK_CTRLR 0x02 ///< Сетевой контроллер
-#define CLASS_DISPLAY 0x03 ///< Контроллер дисплея
-#define CLASS_MULTIMEDIA 0x04 ///< Мультимедийный контроллер
-#define CLASS_MEMORY 0x05 ///< Контроллер памяти
-#define CLASS_BRIDGE 0x06 ///< Мост
-#define CLASS_SCC 0x07 ///< Простой коммуникационный контроллер
-#define CLASS_SYSTEM 0x08 ///< Периферийное устройство базовой системы
-#define CLASS_INPUT 0x09 ///< Контроллер устройства ввода
-#define CLASS_DOCK 0x0A ///< Док-станция
-#define CLASS_PROCESSOR 0x0B ///< Процессор
-#define CLASS_SERIAL_BUS 0x0C ///< Контроллер последовательной шины
-#define CLASS_WIRELESS 0x0D ///< Беспроводной контроллер
-#define CLASS_INTELLIGENTIO 0x0E ///< Интеллектуальный контроллер
-#define CLASS_SATELLITE 0x0F ///< Контроллер спутниковой связи
-#define CLASS_ENCRYPT 0x10 ///< Контроллер шифрования
-#define CLASS_SIGNAL_PROC 0x11 ///< Контроллер обработки сигналов
-#define CLASS_PROC_ACCEL 0x12 ///< Ускоритель обработки
-#define CLASS_NO_ESS_INS 0x13 ///< Второстепенная аппаратура
-#define CLASS_CO_CPU 0x40 ///< Со-Процессор
+#define CLASS_MASS_STORAGE 0x01 /// Контроллер запоминающего устройства
+#define CLASS_NETWORK_CTRLR 0x02 /// Сетевой контроллер
+#define CLASS_DISPLAY 0x03 /// Контроллер дисплея
+#define CLASS_MULTIMEDIA 0x04 /// Мультимедийный контроллер
+#define CLASS_MEMORY 0x05 /// Контроллер памяти
+#define CLASS_BRIDGE 0x06 /// Мост
+#define CLASS_SCC 0x07 /// Простой коммуникационный контроллер
+#define CLASS_SYSTEM 0x08 /// Периферийное устройство базовой системы
+#define CLASS_INPUT 0x09 /// Контроллер устройства ввода
+#define CLASS_DOCK 0x0A /// Док-станция
+#define CLASS_PROCESSOR 0x0B /// Процессор
+#define CLASS_SERIAL_BUS 0x0C /// Контроллер последовательной шины
+#define CLASS_WIRELESS 0x0D /// Беспроводной контроллер
+#define CLASS_INTELLIGENTIO 0x0E /// Интеллектуальный контроллер
+#define CLASS_SATELLITE 0x0F /// Контроллер спутниковой связи
+#define CLASS_ENCRYPT 0x10 /// Контроллер шифрования
+#define CLASS_SIGNAL_PROC 0x11 /// Контроллер обработки сигналов
+#define CLASS_PROC_ACCEL 0x12 /// Ускоритель обработки
+#define CLASS_NO_ESS_INS 0x13 /// Второстепенная аппаратура
+#define CLASS_CO_CPU 0x40 /// Со-Процессор
-#define PCI_ADDRESS_PORT 0xCF8 ///< Точка входа || Адрес конфигурации, который требуется для доступа
-#define PCI_DATA_PORT 0xCFC ///< Пароль входа || Генерирует доступ к конфигурации и будет передавать данные в или из регистра
+#define PCI_ADDRESS_PORT 0xCF8 /// Точка входа || Адрес конфигурации, который требуется для доступа
+#define PCI_DATA_PORT 0xCFC /// Пароль входа || Генерирует доступ к конфигурации и будет передавать данные в или из регистра
-#define PCI_VENDOR_NO_DEVICE 0xFFFF ///< Устройство не найдено
+#define PCI_VENDOR_NO_DEVICE 0xFFFF /// Устройство не найдено
/**
* @brief Структура устройства
*/
typedef struct pci_header_t {
- uint16_t vendor_id; ///< ID-Поставщика
- uint16_t device_id; ///< ID-Устройства
- uint8_t revision; ///< ID-Реверсии
- uint8_t prog_if; ///< Положение дел (???) Prog IF
- uint8_t subclass_id; ///< Подкатегория устройства
- uint8_t class_id; ///< Категория устройства
- uint8_t cache_line_size; ///< Размер строки кэша
- uint8_t latency_timer; ///< Таймер задержки
- uint8_t hdr_type; ///< Тип заголовка (???)
- uint8_t bist; ///< БИСТ (???) BIST
- uint32_t bar[6]; ///< ???
- uint32_t cardbus_cis_ptr; ///< Базовый адрес CardBus Socket/ExCa
- uint16_t subsys_vendor; ///< ???
- uint16_t subsys_id; ///< ???
- uint32_t expansion_rom; ///< ???
- uint8_t capatibilities; ///< ???
- uint8_t reserved[3]; ///< Зарезервированный
- uint32_t reserved2; ///< Зарезервированный
- uint8_t int_line; ///< Линия прерывания
- uint8_t int_pin; ///< ПИН-код прерывания
- uint8_t min_grant; ///< ???
- uint8_t max_latency; ///< ???
+ uint16_t vendor_id; /// ID-Поставщика
+ uint16_t device_id; /// ID-Устройства
+ uint8_t revision; /// ID-Реверсии
+ uint8_t prog_if; /// Положение дел (???) Prog IF
+ uint8_t subclass_id; /// Подкатегория устройства
+ uint8_t class_id; /// Категория устройства
+ uint8_t cache_line_size; /// Размер строки кэша
+ uint8_t latency_timer; /// Таймер задержки
+ uint8_t hdr_type; /// Тип заголовка (???)
+ uint8_t bist; /// БИСТ (???) BIST
+ uint32_t bar[6]; /// ???
+ uint32_t cardbus_cis_ptr; /// Базовый адрес CardBus Socket/ExCa
+ uint16_t subsys_vendor; /// ???
+ uint16_t subsys_id; /// ???
+ uint32_t expansion_rom; /// ???
+ uint8_t capatibilities; /// ???
+ uint8_t reserved[3]; /// Зарезервированный
+ uint32_t reserved2; /// Зарезервированный
+ uint8_t int_line; /// Линия прерывания
+ uint8_t int_pin; /// ПИН-код прерывания
+ uint8_t min_grant; /// ???
+ uint8_t max_latency; /// ???
} pci_header_t;
uint16_t pci_read_confspc_word(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset);
@@ -80,4 +79,6 @@ uint32_t pci_get_bar(uint8_t hdrtype, uint8_t bus, uint8_t slot, uint8_t func, u
void pci_find_device(uint16_t vendor, uint16_t device, uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret);
void pci_print_list();
void pci_write(uint8_t bus, uint8_t slot, uint8_t func, uint32_t offset, uint32_t value);
-
+void pci_find_device_by_class_and_subclass(uint16_t class, uint16_t subclass, uint16_t *vendor_ret, uint16_t *deviceid_ret,
+ uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret);
+uint32_t pci_read32(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset);
\ No newline at end of file
diff --git a/kernel/include/drv/psf.h b/kernel/include/drv/psf.h
index 778ada4ee..4a8aa977f 100644
--- a/kernel/include/drv/psf.h
+++ b/kernel/include/drv/psf.h
@@ -22,6 +22,7 @@ typedef struct __attribute__((packed)) {
uint8_t charHeight;
} psf_t;
+bool text_init(char* psf);
void draw_vga_ch(uint16_t c, uint16_t c2, size_t pos_x, size_t pos_y, size_t color);
void draw_vga_str(const char* text, size_t len, int x, int y, uint32_t color);
size_t psf1_get_w();
diff --git a/kernel/include/drv/ramdisk.h b/kernel/include/drv/ramdisk.h
deleted file mode 100755
index ed2a4c2a9..000000000
--- a/kernel/include/drv/ramdisk.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#pragma once
-#include
-
-#define USTAR_NORMAL_FILE '0'
-#define USTAR_HARD_LINK '1'
-#define USTAR_SYMBOLIC_LINK '2'
-#define USTAR_CHARACTER_DEVICE '3'
-#define USTAR_BLOCK_DEVICE '4'
-#define USTAR_DIRECTORY '5'
-#define USTAR_NAMED_PIPE '6'
-
-/**
- * @brief Структура файла
- */
-typedef struct {
- char fname[100];
- char fmode[8];
-
- char uid[8];
- char gid[8];
-
- char size[12];
- char mtime[12];
-
- char checksum[8];
- char type;
-
- char linkname[100];
- char signature[6];
- char version[2];
-
- char user_name[32];
- char group_name[32];
-
- char device_major_number[8];
- char device_minor_number[8];
-
- char fprefix[155];
-
- char reserved[12];
-} __attribute__((packed)) ustar_file_t;
-
-int32_t oct2bin(unsigned char *str, int32_t size);
-
-uint32_t tar_getsize(const char *in);
-int32_t tar_lookup(unsigned char *archive, char *filename);
-
-uint32_t initrd_read(char *filename, int32_t offset, int32_t size, vfs_filesystem_t *u, void *buffer);
-
-uint32_t initrd_file_exists(char *filename, vfs_filesystem_t *u);
-uint32_t initrd_get_filesize(char *filename);
-
-uint32_t initrd_is_dir(char *filename);
-
-void initrd_list(int32_t argc, char **arg);
-void initrd_init(uint32_t begin, uint32_t end);
diff --git a/kernel/include/drv/rtl8139.h b/kernel/include/drv/rtl8139.h
index 2f49e9b8c..d273344ae 100644
--- a/kernel/include/drv/rtl8139.h
+++ b/kernel/include/drv/rtl8139.h
@@ -1,5 +1,7 @@
#pragma once
+#include
+
#define RTL8139_VENDOR 0x10EC
#define RTL8139_DEVICE 0x8139
@@ -20,6 +22,15 @@ enum RTL8139_regs {
#define CAPR 0x38
#define RX_READ_POINTER_MASK (~3)
+// Ethernet II header (w/o VLAN 802.11Q tag)
+typedef struct {
+ uint16_t Header; ///< Заголовок (?)
+ uint16_t Size; ///< Размер пакета
+ char MAC_DEVICE[6]; ///< Куда (на какой мак-устройства)
+ char MAC_SOURCE[6]; ///< Источник (от какого мак-устройства)
+ uint16_t Type; ///< Тип источника
+} __attribute__((packed)) EthernetPacked;
+
void rtl8139_init();
void rtl8139_wake_up();
void rtl8139_sw_reset();
@@ -28,4 +39,5 @@ void rtl8139_init_interrupts();
void rtl8139_read_mac();
void rtl8139_setup_rcr();
void rtl8139_enable_rx_tx();
-void rtl8139_send_packet(void* data, size_t length);
\ No newline at end of file
+void rtl8139_send_packet(void* data, size_t length);
+void rtl8139_end_interrupt();
\ No newline at end of file
diff --git a/kernel/include/drv/vfs.h b/kernel/include/drv/vfs.h
deleted file mode 100755
index 081acd1b1..000000000
--- a/kernel/include/drv/vfs.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#pragma once
-/*
- 0 - диск не используется,
- 1 - AHCI,
- 2 - ATA,
- 3 - Устройство хранения,
- 4 - Другое
-*/
-typedef struct vfs_storage_dev_t {
- int32_t type;
-
- int32_t disk_id;
- int32_t partition_id;
-
- int32_t lba_start;
- int32_t lba_end;
-
- char *name;
-
- uint32_t (*read) (int*, unsigned long long, unsigned long long, uint16_t*);
- uint32_t (*write) (int*, unsigned long long, unsigned long long, uint16_t*);
-} vfs_storage_dev_t;
-
-// Некоторые файловые системы
-typedef struct vfs_filesystem_t {
- int32_t fs_type; // 0 - tar-fs, 1 - ext2, 2 - ext3, 3 - ext4, 4 - fat32
- int32_t block_size;
-
- vfs_storage_dev_t *dev;
-} vfs_filesystem_t;
-
-// Содержит указатели на некоторые методы файловой системы.
-typedef struct vfs_filesystem_handles_t {
- uint32_t (*read) (char *fn, int, int, vfs_filesystem_t*, void*);
- uint32_t (*write) (char *fn, int, int, vfs_filesystem_t*, void*);
-
- uint32_t (*readdir) (char*, vfs_filesystem_t*, void*);
-
- uint32_t (*mkfile) (char *fn, char*, vfs_filesystem_t*, uint16_t);
- uint32_t (*mkdir) (char *fn, char*, vfs_filesystem_t*, uint16_t);
-
- uint32_t (*rm) (char *fn, vfs_filesystem_t*);
- uint32_t (*ls) (char *fn, vfs_filesystem_t*);
-
- uint32_t (*get_size) (char *fn, vfs_filesystem_t*);
- uint32_t (*exists) (char *fn, vfs_filesystem_t*);
- uint32_t (*is_dir) (char *fn, vfs_filesystem_t*);
-} vfs_filesystem_handles_t;
-
-// Точка монтирования VFS
-typedef struct vfs_mount_info_t {
- char *location;
- vfs_filesystem_t *fs;
- vfs_filesystem_handles_t *fs_handles;
-} vfs_mount_info_t;
-
-void vfs_init();
-
-void vfs_mount_list();
-int32_t vfs_mount(vfs_storage_dev_t *dev, vfs_filesystem_handles_t *fs_handles, int32_t type, char *location, int32_t block_size);
-int32_t vfs_mount_find(char *path, int32_t *filename_add);
-
-int32_t vfs_read(const char *filename, int32_t offset, int32_t size, void *buf);
-int32_t vfs_get_size(const char *filename);
-int32_t vfs_write(char *filename, int32_t offset, int32_t size, void *buf);
-
-int32_t vfs_mkdir(char *filename, char *path, uint16_t perms);
-int32_t vfs_mkfile(char *filename, char *path, uint16_t perms);
-
-int32_t vfs_list(char *path, void *buf);
-int32_t vfs_rm(char *filename);
-
-int32_t vfs_exists(const char *filename);
-int32_t vfs_is_dir(char *filename);
-
-void vfs_get_file_name_from_path(char *fpath, char *buf);
diff --git a/kernel/include/drv/vfs_new.h b/kernel/include/drv/vfs_new.h
old mode 100755
new mode 100644
diff --git a/kernel/include/elf/elf.h b/kernel/include/elf/elf.h
old mode 100755
new mode 100644
index 390aabb5f..20c6932a6
--- a/kernel/include/elf/elf.h
+++ b/kernel/include/elf/elf.h
@@ -1,4 +1,8 @@
#pragma once
+
+#include "mem/vmm.h"
+#include "lib/stdio.h"
+
#define EI_NIDENT 16
/*-----------------------------------------------------------------------------
@@ -134,18 +138,19 @@ typedef struct
typedef struct elf_sections
{
- Elf32_Ehdr* elf_header; ///< ELF заголовок
+ Elf32_Ehdr elf_header; ///< ELF заголовок
Elf32_Shdr* section; ///< Секции
Elf32_Phdr* p_header; ///< Программный заголовок
FILE* file; ///< Ссылка на файл
+} elf_t;
-} elf_sections_t;
-
-elf_sections_t* load_elf(const char* name);
+elf_t* load_elf(const char* name);
+void unload_elf(elf_t* elf);
+int32_t run_elf_file(const char *name, int argc, char* eargv[]);
static inline bool is_elf_file(FILE* fp) {
- char* temp = (char*)kmalloc(4);
+ char* temp = kmalloc(4);
size_t orig = ftell(fp);
fseek(fp, 0, SEEK_SET);
diff --git a/kernel/include/fmt/tga.h b/kernel/include/fmt/tga.h
index 10e572c00..aa94fd114 100644
--- a/kernel/include/fmt/tga.h
+++ b/kernel/include/fmt/tga.h
@@ -30,4 +30,5 @@ typedef struct {
} __attribute__((packed)) tga_header_t;
bool tga_extract_info(const char* path, tga_header_t* out_meta);
-int tga_extract_pixels(const char* path, uint32_t* pixel_buf);
\ No newline at end of file
+int tga_extract_pixels(const char* path, uint32_t* pixel_buf);
+int tga_extract_pixels_from_data(const char* raw_data, uint32_t* pixel_buf);
\ No newline at end of file
diff --git a/kernel/include/fmt/wav.h b/kernel/include/fmt/wav.h
index 71bd0e352..5f63a3048 100644
--- a/kernel/include/fmt/wav.h
+++ b/kernel/include/fmt/wav.h
@@ -1,3 +1,7 @@
+#pragma once
+
+#include "common.h"
+
typedef struct __attribute__((packed)) {
char chunkID[4];
uint32_t chunkSize;
@@ -10,6 +14,9 @@ typedef struct __attribute__((packed)) {
uint32_t byteRate;
uint16_t blockAlign;
uint16_t bitsPerSample;
- char subchunk2ID[4];
- uint32_t subchunk2Size;
} WAVHeader;
+
+struct WAVInfoChunk {
+ char name[4];
+ uint32_t size;
+} __attribute__((packed));
diff --git a/kernel/include/fs/fat32.h b/kernel/include/fs/fat32.h
new file mode 100644
index 000000000..d3f5ac6a7
--- /dev/null
+++ b/kernel/include/fs/fat32.h
@@ -0,0 +1,110 @@
+/**
+ * @file drv/fs/fat32.c
+ * @author Павленко Андрей (pikachu_andrey@vk.com)
+ * @brief Файловая система FAT32
+ * @version 0.3.4
+ * @date 2023-11-04
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+#pragma once
+
+#include
+#include
+#include
+#include "../../src/lib/libvector/include/vector.h"
+
+typedef struct {
+ char bootcode[3];
+ char OEM[8];
+ uint16_t bytes_per_sector;
+ uint8_t sectors_per_cluster;
+ uint16_t reserved_sectors;
+ uint8_t copies;
+ uint16_t root_entries;
+ uint16_t small_sectors_number;
+ uint8_t descriptor;
+ uint16_t sectors_per_fat;
+ uint16_t sectors_per_track;
+ uint16_t heads;
+ uint32_t hidden_sectors;
+ uint32_t sectors_in_partition;
+ uint32_t fat_size_in_sectors;
+ uint16_t flags;
+ uint16_t version_num;
+ uint32_t root_directory_offset_in_clusters;
+ uint16_t fsinfo_sector;
+ uint16_t _;
+ char reserved1[12];
+ uint8_t disk_number;
+ uint8_t flags1;
+ uint8_t extended_boot_signature;
+ uint32_t volume_serial_number;
+ char volume_label[11];
+ char fs_type[8];
+} __attribute__((packed)) fat_info_t;
+
+typedef struct {
+ char short_file_name[11]; // 8.3
+ uint8_t attributes;
+ uint8_t register_sign;
+
+ uint8_t create_millis;
+ uint16_t create_time;
+ uint16_t create_date;
+ uint16_t last_access_date;
+
+ uint16_t first_cluster_high;
+ uint16_t last_modif_time;
+ uint16_t last_modif_date;
+ uint16_t first_cluster_low;
+ uint32_t file_size_in_bytes;
+} __attribute__((packed)) fat_object_info_t;
+
+typedef struct {
+ uint8_t attr_number;
+ uint16_t first_name_chunk[5];
+ uint8_t attribute;
+ uint8_t reserved;
+ uint8_t checksum;
+ uint16_t second_name_chunk[6];
+ uint16_t reserved2;
+ uint16_t third_name_chunk[2];
+} __attribute__((packed)) LFN_t;
+
+typedef struct {
+ fat_info_t info;
+
+ uint32_t cluster_size;
+ uint32_t fat_offset;
+ uint32_t fat_size;
+ uint32_t reserved_fat_offset;
+ uint32_t root_directory_offset;
+} fat_description_t; // This structure never used in data parsing and represents all needed data for FAT32 driver.
+
+#define LFN_LAST_ENTRY 0x40
+
+struct fat32_lfn_result {
+ char* filename;
+ size_t encoded_characters_count;
+};
+
+typedef struct {
+ char filename[256];
+ size_t size;
+
+ size_t starting_cluster;
+
+ fat_object_info_t advanced_info;
+
+ bool is_lfn;
+} fat_file_info_t;
+
+size_t fs_fat32_read(char Disk,const char* Path, size_t Offset, size_t Size,void* Buffer);
+size_t fs_fat32_write(char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer);
+FSM_FILE fs_fat32_info(char Disk,const char* Path);
+FSM_DIR* fs_fat32_dir(char Disk,const char* Path);
+int fs_fat32_create(char Disk,const char* Path,int Mode);
+int fs_fat32_delete(char Disk,const char* Path,int Mode);
+void fs_fat32_label(char Disk, char* Label);
+int fs_fat32_detect(char Disk);
+vector_t* fs_fat32_get_clusters(char Disk, size_t cluster_number);
\ No newline at end of file
diff --git a/kernel/include/fs/fsm.h b/kernel/include/fs/fsm.h
new file mode 100644
index 000000000..27805f71a
--- /dev/null
+++ b/kernel/include/fs/fsm.h
@@ -0,0 +1,89 @@
+#pragma once
+
+#include
+
+
+typedef struct {
+ uint16_t year; ///< Год
+ uint8_t month; ///< Месяц
+ uint8_t day; ///< День
+ uint8_t hour; ///< Час
+ uint8_t minute; ///< Минуты
+ uint8_t second; ///< Секунды
+} __attribute__((packed)) FSM_TIME;
+
+typedef struct {
+ int Ready; ///< Существует ли файл?
+ char Name[1024]; ///< Имя файла
+ char Path[1024]; ///< Путь файла
+ int Mode; ///< Режим файла
+ size_t Size; ///< Размер файла в байтах (oсt2bin)
+ FSM_TIME LastTime; ///< Время последнего изменения файла
+ int Type; ///< Тип элемента
+} __attribute__((packed)) FSM_FILE;
+
+typedef struct {
+ int Ready; ///< Существует ли файл?
+ size_t Count; ///< Количество всего
+ size_t CountFiles; ///< Количество файлов
+ size_t CountDir; ///< Количество папок
+ size_t CountOther; ///< Количество неизвестного типа файлов
+ FSM_FILE* Files; ///< Файлы и папки
+} __attribute__((packed)) FSM_DIR;
+
+///! Буква, Название, откуда, сколько, буфер
+typedef size_t (*fsm_cmd_read_t)(const char,const char*,size_t,size_t,void*);
+
+///! Буква, Название, куда, сколько, буфер
+typedef size_t (*fsm_cmd_write_t)(const char,const char*,size_t,size_t,void*);
+
+///! Буква, Название
+typedef FSM_FILE (*fsm_cmd_info_t)(const char,const char*);
+
+///! Буква, Название
+typedef FSM_DIR* (*fsm_cmd_dir_t)(const char,const char*);
+
+///! Буква, Название, Тип (0 - файл | 1 - папка)
+typedef int (*fsm_cmd_create_t)(const char,const char*,int);
+
+///! Буква, Название, Тип (0 - файл | 1 - папка)
+typedef int (*fsm_cmd_delete_t)(const char,const char*,int);
+
+///! Буква, Буфер
+typedef void (*fsm_cmd_label_t)(const char,char*);
+
+
+///! Буква, Буфер
+typedef int (*fsm_cmd_detect_t)(const char);
+
+typedef struct {
+ int Ready; ///< Загружена ли фс?
+ char Name[64]; ///< Наименование драйвера
+ int Splash; ///< В какую сторону кинута палка?
+ fsm_cmd_read_t Read; ///< Команда для чтения
+ fsm_cmd_write_t Write; ///< Команда для записи
+ fsm_cmd_info_t Info; ///< Команда для получения информации
+ fsm_cmd_dir_t Dir; ///< Команда для получения информации о папке
+ fsm_cmd_create_t Create; ///< Команда для создания файла или папка
+ fsm_cmd_delete_t Delete; ///< Команда для удаления файла или папка
+
+ fsm_cmd_label_t Label; ///< Команда для получения имени диска
+ fsm_cmd_detect_t Detect; ///< Команда для определения, предналежит ли диск к фс
+ void* Reserved; ///< Можно в ОЗУ дописать доп.данные если требуется.
+} __attribute__((packed)) FSM;
+
+
+int fsm_getIDbyName(const char* Name);
+size_t fsm_read(int FIndex, char DIndex, const char* Name, size_t Offset, size_t Count, void* Buffer);
+size_t fsm_write(int FIndex, char DIndex, const char* Name, size_t Offset, size_t Count, void* Buffer);
+FSM_FILE fsm_info(int FIndex, char DIndex, const char* Name);
+void fsm_reg(const char* Name,int Splash,fsm_cmd_read_t Read, fsm_cmd_write_t Write, fsm_cmd_info_t Info, fsm_cmd_create_t Create, fsm_cmd_delete_t Delete, fsm_cmd_dir_t Dir, fsm_cmd_label_t Label, fsm_cmd_detect_t Detect);
+int fsm_delete(int FIndex, char DIndex, const char* Name, int Mode);
+int fsm_create(int FIndex, char DIndex, const char* Name, int Mode);
+void fsm_dump(FSM_FILE file);
+int fsm_getMode(int FIndex);
+FSM_DIR* fsm_dir(int FIndex, char DIndex, const char* Name);
+void fsm_convertUnix(uint32_t unix_time, FSM_TIME* time);
+int fsm_isPathToFile(const char* Path,const char* Name);
+char* fsm_timePrintable(FSM_TIME time);
+void fsm_dpm_update(char Letter);
\ No newline at end of file
diff --git a/kernel/include/fs/iso9660.h b/kernel/include/fs/iso9660.h
new file mode 100644
index 000000000..e0a371999
--- /dev/null
+++ b/kernel/include/fs/iso9660.h
@@ -0,0 +1,67 @@
+#ifndef SAYORI_ISO9660_H
+#define SAYORI_ISO9660_H
+
+#include
+#include
+#include
+
+typedef struct {
+ uint8_t Zero; ///< [0+1] Указывает на загрузочную запись?
+ char ID[5]; ///< [1+5] ОЕМ-идентификатор (Всегда CD001)
+ uint8_t Version; ///< [6+1] Версия файловой системы
+ uint8_t UnUsed00; ///< [7+1] [!] Все нули
+ char SystemName[32]; ///< [8+32] Имя системы, которая может работать с секторами 0x00–0x0F тома.
+ char Label[32]; ///< [40+32] Метка диска
+ char UnUsed01[8]; ///< [72] [!] Все нули
+ int32_t VolumeSpaceSize[2]; ///< [80] Количество логических блоков, в которых записан том.
+ char UnUsed02[32]; ///< [88] [!] Все нули
+ int32_t VolumeSetSize; ///< [120] Количество логических блоков, в которых записан том.
+ int32_t VolumeSequenceNumber; ///< [124] Номер этого диска в наборе томов.
+ int32_t LogicalBlockSize; ///< [128] Размер логического блока в байтах. NB: Это означает, что логический блок на компакт-диске может иметь размер, отличный от 2 КиБ!
+ int32_t PathTableSize[2]; ///< [132] Размер таблицы путей в байтах.
+ int32_t LocOfType_L_PathTable; ///< [140] Расположение LBA таблицы путей. Таблица путей, на которую указывает, содержит только значения с прямым порядком байтов.
+ int32_t LocOfOpti_L_PathTable; ///< [144] Местоположение LBA дополнительной таблицы путей. Таблица путей, на которую указывает, содержит только значения с прямым порядком байтов. Ноль означает, что дополнительная таблица путей не существует.
+ int32_t LocOfType_M_PathTable; ///< [148] Расположение LBA таблицы путей. Таблица путей, на которую указывает, содержит только значения с прямым порядком байтов.
+ int32_t LocOfOpti_M_PathTable; ///< [152] Местоположение LBA дополнительной таблицы путей. Таблица путей, на которую указывает, содержит только значения с прямым порядком байтов. Ноль означает, что дополнительная таблица путей не существует.
+ char DirectoryEntry[34]; ///< [156] Обратите внимание, что это не адрес LBA, а фактическая запись каталога, которая содержит однобайтовый идентификатор каталога (0x00), отсюда и фиксированный размер в 34 байта.
+ char VolumeSetID[128]; ///< [190] Идентификатор набора томов, членом которого является этот том.
+ char PublisherID[128]; ///< [318] Издательство тома. Для расширенной информации об издателе первый байт должен быть 0x5F, за которым следует имя файла в корневом каталоге. Если не указано, все байты должны быть 0x20.
+ char DataPreparerID[128]; ///< [446] Идентификатор лица(ов), подготовившего данные для этого тома. Для расширенной информации о подготовке первый байт должен быть 0x5F, за которым следует имя файла в корневом каталоге. Если не указано, все байты должны быть 0x20.
+ char ApplicationID[128]; ///< [574] Определяет, как данные записываются на этот том. Для расширенной информации первый байт должен быть 0x5F, за которым следует имя файла в корневом каталоге. Если не указано, все байты должны быть 0x20.
+ char CopyrightFileID[37]; ///< [702] Имя файла в корневом каталоге, который содержит информацию об авторских правах для этого набора томов. Если не указано, все байты должны быть 0x20
+ char AbstractFileID[37]; ///< [739] Имя файла в корневом каталоге, который содержит абстрактную информацию для этого набора томов. Если не указано, все байты должны быть 0x20.
+ char BibliographicFileID[37]; ///< [776] Имя файла в корневом каталоге, содержащего библиографическую информацию для этого набора томов. Если не указано, все байты должны быть 0x20.
+ char VolumeCreationDate[17]; ///< [813] Дата и время создания тома.
+ char VolumeModificationDate[17]; ///< [830] Дата и время изменения тома.
+ char VolumeExpirationDate[17]; ///< [847] Дата и время, после которых этот том считается устаревшим. Если не указано, том никогда не считается устаревшим.
+ char VolumeEffectiveDate[17]; ///< [864] Дата и время, после которых том можно будет использовать. Если не указано иное, том можно использовать немедленно.
+ int8_t FileStructureVersion; ///< [881] Записи каталога и версия таблицы путей (всегда 0x01).
+ int8_t UnUsed03; ///< [882] [!] Всегда 0x00.
+ char ApplicationUsed[512]; ///< [883] Содержание не определено ISO 9660.
+ char Reserved[653]; ///< [1395] Зарезервировано ISO.
+} ISO9660_PVD; ///< Primary Volume Descriptor || Дескриптор основного тома
+
+typedef struct {
+ int8_t LengthDirectoryRecord; ///< [0] Длина записи каталога.
+ int8_t ExtendedAttributeRecord; ///< [1] Длина расширенной записи атрибутов.
+ uint32_t LBA[2]; ///< [2] Местоположение экстента (LBA) в формате с прямым порядком байтов.
+ uint32_t Lenght[2]; ///< [10] Длина данных (размер экстента) в формате с прямым порядком байтов.
+ char Date[7]; ///< [18] Дата и время записи.
+ int8_t Flags; ///< [25] Флаги файлов.
+ int8_t Mode; ///< [26] Размер файловой единицы для файлов, записанных в чередующемся режиме, в противном случае — ноль.
+ int8_t Interval; ///< [27] Размер интервала чередования для файлов, записанных в режиме чередования, в противном случае — ноль.
+ uint32_t VolumeSequenceNumber; ///< [28] Порядковый номер тома — том, на котором записан этот экстент, в 16-битном формате с прямым порядком байтов.
+ int8_t ID; ///< [32] Длина идентификатора файла (имя файла). Это заканчивается знаком ';' символ, за которым следует идентификационный номер файла в десятичном формате ASCII («1»).
+ char* FileID; ///< [33] Идентификатор файла.
+
+} ISO9660_Entity; ///< Сущность файла или папки
+
+size_t fs_iso9660_read(char Disk,const char* Path, size_t Offset, size_t Size,void* Buffer);
+size_t fs_iso9660_write(char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer);
+FSM_FILE fs_iso9660_info(char Disk,const char* Path);
+FSM_DIR* fs_iso9660_dir(char Disk,const char* Path);
+int fs_iso9660_create(char Disk,const char* Path,int Mode);
+int fs_iso9660_delete(char Disk,const char* Path,int Mode);
+void fs_iso9660_label(char Disk, char* Label);
+int fs_iso9660_detect(char Disk);
+#endif //SAYORI_ISO9660_H
diff --git a/kernel/include/fs/lucario/fs.h b/kernel/include/fs/lucario/fs.h
deleted file mode 100644
index 254e5f22a..000000000
--- a/kernel/include/fs/lucario/fs.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-
-#include
-
-#define LUCARIO_DIVISOR (8192)
-
-LucarioDescriptor_t* lucario_fs_build_descriptor();
-bool lucario_fs_init(LucarioDescriptor_t* descr, uint8_t ata_drive);
-void lucario_fs_destroy_descriptor(LucarioDescriptor_t* descr);
-void lucario_fs_read_file_entry(LucarioDescriptor_t* descr, size_t index, LucarioFileEntry_t* out);
-void lucario_fs_get_file_entry(LucarioDescriptor_t* descr, char name[], size_t folder_id, LucarioFileEntry_t* out);
-bool lucario_fs_file_exists(LucarioDescriptor_t* descr, char name[], size_t folder_id);
-size_t lucario_fs_file_size(LucarioDescriptor_t* descr, char name[], size_t folder_id);
-
-static inline size_t lucario_fs_sector_list_pos_byte(LucarioDescriptor_t* descr, LucarioFileEntry_t* entry) {
- return entry->sector_list_lba * 512;
-}
-
-bool lucario_fs_read_file(LucarioDescriptor_t* descr, char name[], size_t folder_id, size_t offset, size_t length, char* out);
\ No newline at end of file
diff --git a/kernel/include/fs/lucario/structures.h b/kernel/include/fs/lucario/structures.h
deleted file mode 100644
index 06c7bbac3..000000000
--- a/kernel/include/fs/lucario/structures.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-
-#include
-
-#define LUCARIOFS_MAGIC "LUCARIO"
-
-typedef enum {
- E_NONE = 0x00,
- E_FILE = 0xF1,
- E_FOLDER = 0xF0
-} LucarioFileEntryType_t;
-
-typedef struct {
- char magic[7]; // LUCARIO
- char version_major;
- char version_minor;
- char version_patch;
-} __attribute__((packed)) LucarioHeader_t;
-
-typedef struct {
- uint8_t type;
- char name[256];
- uint32_t folder_target_id;
- uint32_t folder_id;
- uint32_t sector_list_lba;
- uint32_t sector_list_size;
- uint32_t file_size;
-} __attribute__((packed)) LucarioFileEntry_t;
-
-typedef struct {
- bool ok;
- uint8_t ata_drive;
- size_t disk_capacity;
-
- LucarioHeader_t header;
- size_t max_entries;
-} LucarioDescriptor_t;
diff --git a/kernel/include/fs/milla.h b/kernel/include/fs/milla.h
index ad20298a4..12d316732 100644
--- a/kernel/include/fs/milla.h
+++ b/kernel/include/fs/milla.h
@@ -3,16 +3,15 @@
* @file fs/milla.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru), NDRAEY >_ (pikachu_andrey@vk.com)
* @brief Проект Милла
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-01-23
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-#include
void __milla_sendcmd(char* msg);
char* __milla_getcmd();
int __milla_cleanState();
-char* __milla_getFile(char* path);
+char* __milla_getFile(const char *path);
int __milla_writeFile(char* path, char* data);
int __milla_delete(char* path);
int __milla_mkdir(char* path);
diff --git a/kernel/include/fs/natfs.h b/kernel/include/fs/natfs.h
new file mode 100644
index 000000000..ddfc471ef
--- /dev/null
+++ b/kernel/include/fs/natfs.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include
+
+int fs_natfs_detect(const char Disk);
+void fs_natfs_label(const char Disk, char* Label);
+int fs_natfs_delete(const char Disk,const char* Path,int Mode);
+int fs_natfs_create(const char Disk,const char* Path,int Mode);
+FSM_DIR* fs_natfs_dir(const char Disk,const char* Path);
+FSM_FILE fs_natfs_info(const char Disk,const char* Path);
+size_t fs_natfs_write(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer);
+size_t fs_natfs_read(const char Disk,const char* Path, size_t Offset, size_t Size,void* Buffer);
+int fs_natfs_init();
\ No newline at end of file
diff --git a/kernel/include/fs/nvfs.h b/kernel/include/fs/nvfs.h
new file mode 100644
index 000000000..ef3a59952
--- /dev/null
+++ b/kernel/include/fs/nvfs.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include
+#include "fs/fsm.h"
+
+typedef struct {
+ bool Ready; ///< Готов к работе?
+ char Disk; ///< Индекс диска (который надо подставить)
+ char Path[1024]; ///< Путь
+ bool Online; ///< В сети ли диск?
+ char FileSystem[64]; ///< Название драйвера на диске
+ int DriverFS; ///< Загружен ли драйвер фс?
+} __attribute__((packed)) NVFS_DECINFO;
+
+NVFS_DECINFO nvfs_decode(const char* Name);
+size_t nvfs_read(const char* Name, size_t Offset, size_t Count, void* Buffer);
+int nvfs_create(const char* Name, int Mode);
+int nvfs_delete(const char* Name, int Mode);
+size_t nvfs_write(const char* Name, size_t Offset, size_t Count, const void *Buffer);
+FSM_FILE nvfs_info(const char* Name);
+FSM_DIR* nvfs_dir(const char* Name);
\ No newline at end of file
diff --git a/kernel/include/fs/sefs.h b/kernel/include/fs/sefs.h
deleted file mode 100755
index c532b5861..000000000
--- a/kernel/include/fs/sefs.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-/**
- * @brief Структура кол-ва файлов
- */
-typedef struct {
- uint32_t nfiles; // Число файлов в ramdisk.
-} sefs_header_t;
-
-/**
- * @brief Структура файлов
- */
-typedef struct {
- uint32_t index; ///< Индекс
- uint32_t magic; ///< Магическое число для проверки ошибок.
- char name[128]; ///< Имя файла
- uint32_t offset; ///< Смещение в sefs, указывающее откуда начинается файл.
- uint32_t length; ///< Длина файла
- uint8_t types; ///< Тип (0 - файл/1 - Папка)
- uint8_t parentDir; ///< Родительская папка (0 - значит root)
-} sefs_file_header_t;
-
-fs_node_t *sefs_initrd(uint32_t location, uint32_t end);
-
diff --git a/kernel/include/fs/smfs.h b/kernel/include/fs/smfs.h
index ba34d69d6..9994f68e9 100644
--- a/kernel/include/fs/smfs.h
+++ b/kernel/include/fs/smfs.h
@@ -49,4 +49,19 @@ typedef struct {
uint8_t Length; ///< Длина пакета
char Data[33]; ///< Пакет данных
uint32_t Next; ///< Следующий пакет данных
-} __attribute__((__packed__)) SMFS_PACKAGE_BIG; // Получится 39 байт
\ No newline at end of file
+} __attribute__((__packed__)) SMFS_PACKAGE_BIG; // Получится 39 байт
+
+
+int fs_smfs_format(const char Disk);
+
+size_t fs_smfs_read(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer);
+size_t fs_smfs_write(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer);
+FSM_FILE fs_smfs_info(const char Disk,const char* Path);
+int fs_smfs_create(const char Disk,const char* Path,int Mode);
+int fs_smfs_delete(const char Disk,const char* Path,int Mode);
+
+TarFS_ROOT* fs_smfs_init(uint32_t in, uint32_t size, int Mode);
+FSM_DIR* fs_smfs_dir(const char Disk,const char* Path);
+
+int fs_smfs_detect(const char Disk);
+void fs_smfs_label(const char Disk, char* Label);
\ No newline at end of file
diff --git a/kernel/include/fs/tarfs.h b/kernel/include/fs/tarfs.h
new file mode 100644
index 000000000..1461244be
--- /dev/null
+++ b/kernel/include/fs/tarfs.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#include
+#define TARFS_ELEM_TYPE_FILE 48 ///< Обычный файл
+#define TARFS_ELEM_TYPE_HARD_LINK 49 ///< Жесткая ссылка
+#define TARFS_ELEM_TYPE_SYMB_LINK 50 ///< Символическая ссылка
+#define TARFS_ELEM_TYPE_CHR_DEV 51 ///< Символьное устройство
+#define TARFS_ELEM_TYPE_BLK_DEV 52 ///< Блочное-устройство
+#define TARFS_ELEM_TYPE_DIR 53 ///< Папка
+#define TARFS_ELEM_TYPE_PIPE 54 ///< Канал (FIFO)
+
+/**
+ * @brief Структура файла
+ */
+typedef struct {
+ char Name[100]; /// Имя файла
+ char Mode[8]; /// Режим файла
+
+ char UID[8]; /// Числовой идентификатор пользователя владельца
+ char GID[8]; /// Числовой идентификатор пользователя группы
+
+ char Size[12]; /// Размер файла в байтах (oсt2bin)
+ char LastTime[12]; /// Время последнего изменения файла
+
+ char CheckSum[8]; /// Контрольная сумма для записи заголовка
+ char Type; /// Тип элемента
+
+ char Link[100]; /// Имя связанного файла
+ char Signature[6]; /// Индикатор UStar
+ char Version[2]; /// Версия Ustar
+
+ char OwnerUser[32]; /// Имя владельца
+ char OwnerGroup[32]; /// Имя группы
+
+ char DM1[8]; /// Основной номер устройства
+ char DM2[8]; /// Младший номер устройства
+
+ char Prefix[155]; /// Префикс имени файла
+} __attribute__((packed, aligned(512))) TarFS_Elem;
+
+typedef struct {
+ int Ready; /// Существует ли файл?
+ char Name[100]; /// Имя файла
+ char Mode[8]; /// Режим файла
+ size_t Size; /// Размер файла в байтах (oсt2bin)
+ char LastTime[12]; /// Время последнего изменения файла
+ int Type; /// Тип элемента
+ uint32_t Addr; /// Адрес размещения файла
+ uint32_t Real; /// Адрес размещения файла
+} __attribute__((packed)) TarFS_File;
+
+typedef struct {
+ int Ready; /// Инициализировано?
+ size_t Count; /// Кол-во файлов и элементов
+ TarFS_File* Files; /// Файлы
+} __attribute__((packed)) TarFS_ROOT;
+
+int oct2bin(char *str, int size);
+TarFS_File tarfs_infoFile(TarFS_ROOT* r,const char* name);
+char* tarfs_readFile(TarFS_ROOT* r,const char* name);
+size_t tarfs_getCountFiles(const uint32_t in);
+TarFS_ROOT* tarfs_init(const uint32_t in);
+
+size_t fs_tarfs_read(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer);
+size_t fs_tarfs_write(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer);
+FSM_FILE fs_tarfs_info(const char Disk,const char* Path);
+int fs_tarfs_create(const char Disk,const char* Path,int Mode);
+int fs_tarfs_delete(const char Disk,const char* Path,int Mode);
+
+TarFS_ROOT* fs_tarfs_init(uint32_t in, uint32_t size, int Mode);
+FSM_DIR* fs_tarfs_dir(const char Disk,const char* Path);
+
+int fs_tarfs_detect(const char Disk);
+void fs_tarfs_label(const char Disk, char* Label);
\ No newline at end of file
diff --git a/kernel/include/gui/circle.h b/kernel/include/gui/circle.h
index 57f7966db..ffd19b265 100644
--- a/kernel/include/gui/circle.h
+++ b/kernel/include/gui/circle.h
@@ -1,4 +1,4 @@
#pragma once
-#include
+#include
void draw_circle(int32_t xc, int32_t yc, int32_t radius, uint32_t color);
diff --git a/kernel/include/gui/line.h b/kernel/include/gui/line.h
index f04643019..6b0b1e5c3 100644
--- a/kernel/include/gui/line.h
+++ b/kernel/include/gui/line.h
@@ -3,4 +3,4 @@
#include
void draw_line(int x0, int y0, int x1, int y1, int thickness, int color);
-void draw_line_extern(char* buffer, size_t width, size_t height, int x0, int y0, int x1, int y1, int thickness, int color);
\ No newline at end of file
+void draw_line_extern(uint8_t *buffer, size_t width, size_t height, int x0, int y0, int x1, int y1, int thickness, int color);
\ No newline at end of file
diff --git a/kernel/include/gui/sayori_font_file.h b/kernel/include/gui/sayori_font_file.h
deleted file mode 100644
index 79fdb39fc..000000000
--- a/kernel/include/gui/sayori_font_file.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#pragma once
-
-#include
-#include
-/*
- * SFF1 File Specification
- *
- * SFF Common (Global) header:
- * |- Identifier: "SFF"
- * |- Version: 1 (uint8_t)
- *
- * SFF1 Header:
- * |- Glyph Width (uint8_t)
- * |- Glyph Height (uint8_t)
- * |- Duke identifier: "DUKE"
- */
-
-#define ARRAY_CHARACTER_COUNT 148
-#define IS_IN_SFF1(chr) (is_in_sff1_alphabet_array(chr, alphabet_sff1, ARRAY_CHARACTER_COUNT) != 0xffff)
-#define UTF8_GLOBAL_SHIFT 0xcc80
-#define UTF8_GLOBAL_SHIFT_2 0xcd41
-
-typedef struct {
- uint8_t identifier[3];
- uint8_t version;
-} __attribute__((packed)) SFF_Global_Header_t;
-
-typedef struct {
- uint8_t glyph_width;
- uint8_t glyph_height;
-
- uint8_t DUKE_identifier[4];
-} __attribute__((packed)) SFF1_Header_t;
-
-typedef struct {
- SFF_Global_Header_t* global;
-
- // Data for SFF1
- SFF1_Header_t* sff1;
- uint8_t* image_data;
- struct DukeImageMeta* image_metadata;
-
- FILE* file_descriptor;
-} SFF_Descriptor_t;
-
-SFF_Descriptor_t* load_sff_font(const char* path);
-uint16_t is_in_sff1_alphabet_array(uint16_t character, uint16_t* array, uint16_t length);
-void _draw_sff1_char_screen(SFF_Descriptor_t* descriptor, uint16_t character,
- size_t x, size_t y, uint32_t color);
-void _draw_sff1_string_screen(SFF_Descriptor_t* descriptor, uint8_t* string,
- size_t x, size_t y, uint32_t color);
-void scale_sff1_font(SFF_Descriptor_t* descriptor, size_t w, size_t h);
-void destroy_sff_font(SFF_Descriptor_t* descriptor);
\ No newline at end of file
diff --git a/kernel/include/io/duke_image.h b/kernel/include/io/duke_image.h
deleted file mode 100755
index f9af2b925..000000000
--- a/kernel/include/io/duke_image.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * @file imaging.h
- * @brief Описания функций imaging.h
- * @version 0.3.3
- * @author NDRAEY >_ (pikachu_andrey@vk.com)
- */
-
-#pragma once
-
-#include
-
-#define RGB_TO_UINT32(r, g, b) ((r&0xff)<<16)|((g&0xff)<<8)|(b&0xff)
-#define DUKE_MAGIC "DUKE"
-
-#define PIXIDX(w, x, y) ((w) * (y) + (x))
-
-/**
- * @brief Структура изображения Duke.
- * @param width - ширина
- * @param height - высота
- * @param data_length - длина всех "сырых" пикселей
- * @param alpha - указывает на наличие альфа слоя
- */
-
-// Duke Image Header struct is 13 bytes long.
-struct DukeImageMeta {
- uint8_t magic[4];
- uint16_t width;
- uint16_t height;
- uint32_t data_length;
- uint8_t alpha;
-} __attribute__((packed));
-
-typedef struct DukeImageMeta DukeHeader_t;
-
-// Returns 0 if OK, 1 if ERR
-bool duke_draw_from_file(const char *filename, size_t sx, size_t sy);
-char duke_get_image_metadata(char *filename, struct DukeImageMeta* meta);
-void duke_get_image_data(char* filename, struct DukeImageMeta meta, void* buf);
-unsigned int duke_calculate_bufsize(unsigned int width, unsigned int height, unsigned int alpha);
-void duke_rawdraw(const char *data, struct DukeImageMeta* meta, int sx, int sy);
-void duke_scale(const char* pixels, unsigned int w1, unsigned int h1, int w2, int h2, char alpha, char* out);
-char duke_draw_scaled(char* filename, int width, int height, int x, int y);
-void duke_rawdraw2(const char *data, int width, int height, int bpp, int sx, int sy);
\ No newline at end of file
diff --git a/kernel/include/io/ports.h b/kernel/include/io/ports.h
old mode 100755
new mode 100644
index 0ea5b2f4b..cdd479983
--- a/kernel/include/io/ports.h
+++ b/kernel/include/io/ports.h
@@ -1,6 +1,7 @@
#pragma once
#include
+#include
#define PORT_COM1 0x3f8
#define PORT_COM2 0x2F8
@@ -13,19 +14,27 @@
#define LOG_WITH_TIME 0
+extern void (*default_qemu_printf)(const char *text, ...);
+
#ifndef RELEASE
- #if LOG_WITH_TIME==0
- #define qemu_log(M, ...) qemu_printf("[LOG] (%s:%s:%d) " M "\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
- #define qemu_warn(M, ...) qemu_printf("[\033[33;1mWARN\033[33;0m] (%s:%s:%d) \033[33;1m" M "\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
- #define qemu_err(M, ...) qemu_printf("[\033[31;1mERROR\033[33;0m] (%s:%s:%d) \033[31;1m" M "\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #if LOG_WITH_TIME == 0
+ #define qemu_log(M, ...) default_qemu_printf("[LOG] (%s:%s:%d) " M "\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #define qemu_note(M, ...) default_qemu_printf("[\033[36;1mNOTE\033[33;0m] (%s:%s:%d) \033[36;1m" M "\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #define qemu_warn(M, ...) default_qemu_printf("[\033[33;1mWARN\033[33;0m] (%s:%s:%d) \033[33;1m" M "\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #define qemu_ok(M, ...) default_qemu_printf("[\033[32;1mOK\033[33;0m] (%s:%s:%d) \033[32;1m" M "\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #define qemu_err(M, ...) default_qemu_printf("[\033[31;1mERROR\033[33;0m] (%s:%s:%d) \033[31;1m" M "\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
- #define qemu_log(M, ...) qemu_printf("[LOG] [%f] (%s:%s:%d) " M "\033[0m\n", getUptime(), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
- #define qemu_warn(M, ...) qemu_printf("[\033[33;1mWARN\033[33;0m] [%f] (%s:%s:%d) \033[33;1m" M "\033[0m\n", getUptime(), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
- #define qemu_err(M, ...) qemu_printf("[\033[31;1mERR\033[33;0m] [%f] (%s:%s:%d) \033[31;1m" M "\033[0m\n", getUptime(), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #define qemu_log(M, ...) qemu_printf("[LOG] [%d] (%s:%s:%d) " M "\033[0m\n", timestamp(), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #define qemu_note(M, ...) qemu_printf("[\033[36;1mWARN\033[33;0m] [%d] (%s:%s:%d) \033[36;1m" M "\033[0m\n", timestamp(), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #define qemu_warn(M, ...) qemu_printf("[\033[33;1mWARN\033[33;0m] [%d] (%s:%s:%d) \033[33;1m" M "\033[0m\n", timestamp(), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #define qemu_ok(M, ...) qemu_printf("[\033[32;1mOK\033[33;0m] [%d] (%s:%s:%d) \033[32;1m" M "\033[0m\n", timestamp(), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+ #define qemu_err(M, ...) qemu_printf("[\033[31;1mERR\033[33;0m] [%d] (%s:%s:%d) \033[31;1m" M "\033[0m\n", timestamp(), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
#else
- #define qemu_log(M, ...)
+ #define qemu_note(M, ...)
+ #define qemu_log(M, ...)
#define qemu_warn(M, ...)
+ #define qemu_ok(M, ...)
#define qemu_err(M, ...)
#endif
@@ -34,53 +43,78 @@
qemu_printf("ASSERT FAILED: " format "\n", ##__VA_ARGS__); \
qemu_printf("======================================\n"); \
bsod_screen((registers_t){}, "ASSERT_FAIL", "See additional information on COM1 port. (Or Qemu.log if you're using QEMU)", 0xFFFF); \
-}\
-} while(0)
+} } while(0)
// Check if character received.
#define is_signal_received(port) (inb(port + 5) & 1)
-#define outb(port, val) __asm__ volatile("outb %b0, %w1" : : "a"(val), "Nd"(port))
-#define outw(port, val) outs(port, val)
-
-#define fast_inb(port, ret) __asm__ volatile( "inb %1, %0" : "=a"(ret) : "Nd"((uint16_t)(port)) )
-#define fast_ins(port, ret) __asm__ volatile( "inw %1, %0" : "=a"(ret) : "Nd"((uint16_t)(port)) )
+/**
+ * @brief Отправка одного байта в порт
+ *
+ * @param port - порт
+ * @param val - данные
+ */
+SAYORI_INLINE void outb(uint16_t port, uint8_t val) {
+ __asm__ volatile("outb %b0, %w1" : : "a"(val), "Nd"(port));
+}
/**
* @brief Получение одного байта из порта
*
* @param port - порт
- * @return uint8_t - данные
+ * @return Байт из порта
*/
-static inline uint8_t inb(uint16_t port) {
+SAYORI_INLINE uint8_t inb(uint16_t port) {
uint8_t ret;
- asm volatile ( "inb %1, %0"
+ __asm__ volatile ( "inb %1, %0"
: "=a"(ret)
: "Nd"(port) );
return ret;
}
+
+/**
+ * @brief Запись 32-битного слова в порт
+ *
+ * @param port - порт
+ * @param val - число
+ */
+SAYORI_INLINE void outl(uint16_t port, uint32_t val) {
+ __asm__ volatile ( "outl %0, %1" : : "a"(val), "Nd"(port) );
+}
+
/**
- * @brief Чтение word из порта
+ * @brief Чтение 32-битного слова
*
* @param port - порт
- * @return uint16_t - word
+ * @return Слово из порта
*/
-static inline uint16_t ins(uint16_t port) {
- uint16_t rv;
- asm volatile ("inw %1, %0" : "=a" (rv) : "Nd" (port));
- return rv;
+SAYORI_INLINE uint32_t inl(uint16_t port) {
+ uint32_t ret;
+ __asm__ volatile( "inl %1, %0" : "=a"(ret) : "Nd"(port) );
+ return ret;
}
+/**
+ * @brief Чтение 16-битного слова из порта
+ *
+ * @param port - порт
+ * @return Слово из порта
+ */
+SAYORI_INLINE uint16_t inw(uint16_t port) {
+ uint16_t ret;
+ __asm__ volatile ("inw %1, %0" : "=a" (ret) : "Nd" (port));
+ return ret;
+}
/**
- * @brief Запись word в порт
+ * @brief Запись 16-битного слова в порт
*
* @param port - порт
* @param data - данные
*/
-static inline void outs(uint16_t port, uint16_t data) {
- asm volatile ("outw %1, %0" :: "Nd" (port), "a" (data));
+SAYORI_INLINE void outw(uint16_t port, uint16_t data) {
+ __asm__ volatile ("outw %1, %0" :: "Nd" (port), "a" (data));
}
void insw(uint16_t __port, void *__buf, unsigned long __n);
@@ -97,7 +131,6 @@ void com1_write_char(char a);
void qemu_printf(const char *text, ...);
int32_t is_transmit_empty(uint16_t port);
-// int32_t is_signal_received(uint16_t port);
uint8_t serial_readchar(uint16_t port);
void io_wait();
diff --git a/kernel/include/io/rgb_image.h b/kernel/include/io/rgb_image.h
new file mode 100644
index 000000000..0c4529135
--- /dev/null
+++ b/kernel/include/io/rgb_image.h
@@ -0,0 +1,12 @@
+//
+// Created by ndraey on 25.10.23.
+//
+
+#pragma once
+
+#include "common.h"
+
+#define PIXIDX(w, x, y) ((w) * (y) + (x))
+
+void draw_rgb_image(const char *data, size_t width, size_t height, size_t bpp, int sx, int sy);
+void scale_rgb_image(const char* pixels, uint32_t w1, uint32_t h1, int w2, int h2, char alpha, char* out);
\ No newline at end of file
diff --git a/kernel/include/io/screen.h b/kernel/include/io/screen.h
index e58fe620c..5d620b1f6 100644
--- a/kernel/include/io/screen.h
+++ b/kernel/include/io/screen.h
@@ -1,10 +1,13 @@
#pragma once
#include
+#include "lib/string.h"
extern uint8_t* framebuffer_addr;
+extern uint32_t framebuffer_bpp;
+extern uint32_t framebuffer_pitch;
extern uint8_t* back_framebuffer_addr;
-extern size_t framebuffer_size;
+extern uint32_t framebuffer_size;
#define VESA_WIDTH (getScreenWidth())
#define VESA_HEIGHT (getScreenHeight())
@@ -27,10 +30,6 @@ typedef struct rgb_struct {
uint8_t b;
} rgb_color;
-typedef struct screen_pixel {
- rgb_color color;
- uint32_t x, y;
-} screen_pixel;
enum colors {
VESA_BLACK = 0x000000,
@@ -78,15 +77,47 @@ typedef struct svga_mode_info {
uint8_t reserved1[206];
} __attribute__ ((packed)) svga_mode_info_t;
-#define punch() memcpy(framebuffer_addr, back_framebuffer_addr, framebuffer_size);
+#define punch() memcpy(framebuffer_addr, back_framebuffer_addr, framebuffer_size)
//#define punch() rect_copy(0, 0, VESA_WIDTH, VESA_HEIGHT)
uint32_t getDisplayPitch();
uint32_t getScreenWidth();
uint32_t getScreenHeight();
-uint32_t getDisplaySize();
size_t getDisplayAddr();
+uint32_t getDisplayBpp();
size_t getFrameBufferAddr();
size_t getPixel(int32_t x, int32_t y);
-void set_pixel(uint32_t x, uint32_t y, uint32_t color);
+
+
+/**
+ * @brief Вывод одного пикселя на экран
+ *
+ * @param x - позиция по x
+ * @param y - позиция по y
+ * @param color - цвет
+ */
+inline static __attribute__((always_inline)) void set_pixel(uint32_t x, uint32_t y, uint32_t color) {
+ #ifndef RELEASE
+ if (x >= VESA_WIDTH ||
+ y >= VESA_HEIGHT) {
+ return;
+ }
+ #endif
+ uint8_t* pixels = back_framebuffer_addr + (x * (framebuffer_bpp >> 3)) + y * framebuffer_pitch;
+
+ pixels[0] = color & 255;
+ pixels[1] = (color >> 8) & 255;
+ pixels[2] = (color >> 16) & 255;
+}
+
+/**
+ * @brief Получение размера буфера экрана
+ *
+ * @return uint32_t - Размер буфера экрана
+ */
+inline static __attribute__((always_inline)) uint32_t getDisplaySize(){
+ return framebuffer_size;
+}
+
+void setPixelAlpha(uint32_t x, uint32_t y, rgba_color color);
void rect_copy(int x, int y, int width, int height);
\ No newline at end of file
diff --git a/kernel/include/io/port_io.h b/kernel/include/io/serial_port.h
similarity index 100%
rename from kernel/include/io/port_io.h
rename to kernel/include/io/serial_port.h
diff --git a/kernel/include/io/status_loggers.h b/kernel/include/io/status_loggers.h
index 6543222b4..b19bb039a 100644
--- a/kernel/include/io/status_loggers.h
+++ b/kernel/include/io/status_loggers.h
@@ -1,18 +1,10 @@
#pragma once
-#define COLOR_TEXT 0xFFFFFF
-#define COLOR_SYS_TEXT 0x92D7D4
-#define COLOR_SYS_PATH 0x335190
#define COLOR_ERROR 0xA5383B
#define COLOR_ALERT 0xA66938
#define COLOR_ATENTION 0xDBF03E
#define COLOR_BG 0x000000
-#include
-#include
-#include
-#include
-#include
#include
void tty_error(char* format, ...);
diff --git a/kernel/include/io/status_sounds.h b/kernel/include/io/status_sounds.h
old mode 100755
new mode 100644
diff --git a/kernel/include/io/tty.h b/kernel/include/io/tty.h
old mode 100755
new mode 100644
index 3059255e8..55d68cbf8
--- a/kernel/include/io/tty.h
+++ b/kernel/include/io/tty.h
@@ -1,9 +1,15 @@
#pragma once
-#include
+#include
+#include "io/screen.h"
+#include
+
+#define NEW_TTY_PRINTF 1
extern bool stateTTY;
+void tty_fontConfigurate();
+
void _tty_puts(const char str[]);
void _tty_print(const char *format, va_list args);
void _tty_printf(char *text, ...);
@@ -38,4 +44,6 @@ void _tty_putchar(char c, char c1);
void tty_putchar(char c, char c1);
void clean_screen();
-void buffer_set_pixel4(uint8_t *buffer, size_t width, size_t height, size_t x, size_t y, size_t color);
\ No newline at end of file
+void clean_tty_screen();
+void buffer_set_pixel4(uint8_t *buffer, size_t width, size_t height, size_t x, size_t y, size_t color);
+void clean_tty_screen_no_update();
\ No newline at end of file
diff --git a/kernel/include/io/vgafnt.h b/kernel/include/io/vgafnt.h
deleted file mode 100755
index 377e26300..000000000
--- a/kernel/include/io/vgafnt.h
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file was generated by bintoc utility
-// Binary data from file "a_vga_font.fon"
-
-#pragma once
-
-
-extern uint8_t vgafnt[4096];
-extern int32_t vgafnt_size;
diff --git a/kernel/include/kernel.h b/kernel/include/kernel.h
old mode 100755
new mode 100644
index 2609c71c5..845e4a827
--- a/kernel/include/kernel.h
+++ b/kernel/include/kernel.h
@@ -1,11 +1,6 @@
#pragma once
-#define VERSION_MAJOR 0 // Версия ядра
-#define VERSION_MINOR 3 // Пре-релиз
-#define VERSION_PATCH 3 // Патч
-#define ARCH_TYPE "i386" // Архитектура
-#define VERNAME "Soul" // Имя версии (изменяется вместе с минорной части версии)
-#define SUBVERSIONNAME "Flight" // Вторичное имя версии (изменяется вместе с каждым глобальным релизом)
+#include
#include
@@ -15,7 +10,7 @@
#include "common.h"
#include "config.h"
-#include "rust_header.h"
+#include "rust_headers.h"
#include "lib/string.h"
#include "lib/stdlib.h"
@@ -24,11 +19,12 @@
#include "lib/split.h"
#include "lib/math.h"
#include "lib/setjmp.h"
-#include "lib/dan.h"
+
+#include "mem/pmm.h"
+#include "mem/vmm.h"
#include "sys/acpi.h"
#include "sys/timer.h"
-#include "sys/memory.h"
#include "sys/scheduler.h"
#include "sys/cpu_isr.h"
#include "sys/bootscreen.h"
@@ -38,9 +34,8 @@
#include "sys/v8086.h"
#include "sys/system.h"
-#include
#include
-#include
+#include
#include
#include
#include
@@ -48,18 +43,27 @@
#include
#include
#include
+
+#include
+#include
+#include
+
#include
#include
#include
#include
#include
-#include
+#include "drv/disk/ata.h"
#include
#include
-#include
+#include
+
#include
-#include
+#include
+#include
+#include
+#include
#include
#include
@@ -73,4 +77,4 @@
#include "net/arp.h"
#include "debug/hexview.h"
-#include "debug/ubsan.h"
\ No newline at end of file
+#include "debug/ubsan.h"
diff --git a/kernel/include/lib/dan.h b/kernel/include/lib/dan.h
deleted file mode 100644
index fce59794b..000000000
--- a/kernel/include/lib/dan.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include
-
-typedef struct DANHeader {
- unsigned char magic[3];
- uint32_t frame_count;
- uint16_t width;
- uint16_t height;
- uint8_t alpha;
-} __attribute__((packed)) DANHeader_t;
-
-typedef struct DANDescriptor {
- DANHeader_t header;
- uint32_t framesize;
- char* data;
-
- bool stream;
- FILE* fd;
-} DANDescriptor_t;
-
-DANDescriptor_t* alloc_dan(const char* filename, bool stream);
-void read_frame_dan(DANDescriptor_t* dan, size_t index, char* out);
-void free_dan(DANDescriptor_t* dan);
\ No newline at end of file
diff --git a/kernel/include/lib/libstring/string.h b/kernel/include/lib/libstring/string.h
new file mode 100644
index 000000000..6b547e716
--- /dev/null
+++ b/kernel/include/lib/libstring/string.h
@@ -0,0 +1,30 @@
+//
+// Created by ndraey on 04.10.23.
+//
+
+#pragma once
+
+#include "common.h"
+#include "../../../src/lib/libvector/include/vector.h"
+
+typedef struct string {
+ char* data;
+
+ size_t length;
+} string_t;
+
+#define ADDR2STRING(addr) ((string_t*)(addr))
+
+string_t* string_new();
+void string_append_charptr(string_t* string, const char* concatenable);
+void string_append(string_t* string, const string_t* concatenable);
+void string_crop(string_t* string, size_t start, size_t end);
+void string_append_char(string_t* string, char ch);
+string_t* string_from_charptr(const char* chars);
+string_t* string_from_sized_charptr(const char* chars, size_t length);
+vector_t* string_split(string_t* string, const char* delimiter);
+void string_split_free(vector_t* vec);
+string_t* string_clone(string_t* str);
+void string_reverse(string_t* str);
+string_t* string_from_integer(int number);
+void string_destroy(string_t *string);
diff --git a/kernel/include/lib/list.h b/kernel/include/lib/list.h
old mode 100755
new mode 100644
diff --git a/kernel/include/lib/math.h b/kernel/include/lib/math.h
index 33a62c6fc..746bb5dbc 100644
--- a/kernel/include/lib/math.h
+++ b/kernel/include/lib/math.h
@@ -2,8 +2,6 @@
#include "common.h"
-// #define MIN(a, b) (a > b ? b : a)
-// #define MAX(a, b) (a < b ? b : a)
#define ABS(a) ((a) >= 0 ? (a) : -(a))
#define MIN(a, b) \
@@ -105,7 +103,7 @@ double atan(double x);
double sqrt(double x);
double cbrt(double x);
-
+double modf(double value, double* intPart);
// static inline double sqrt(double x) {
// return pow(x, 0.5);
// }
diff --git a/kernel/include/lib/php/explode.h b/kernel/include/lib/php/explode.h
new file mode 100644
index 000000000..3b1a6705d
--- /dev/null
+++ b/kernel/include/lib/php/explode.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include
+
+uint32_t str_cdsp2(const char a_str[], char del);
+char** explode(const char str[], char delimiter);
\ No newline at end of file
diff --git a/kernel/include/lib/php/pathinfo.h b/kernel/include/lib/php/pathinfo.h
new file mode 100644
index 000000000..119454de3
--- /dev/null
+++ b/kernel/include/lib/php/pathinfo.h
@@ -0,0 +1,9 @@
+
+#include
+
+#define PATHINFO_DIRNAME 0
+#define PATHINFO_BASENAME 1
+#define PATHINFO_EXTENSION 2
+#define PATHINFO_FILENAME 3
+
+char* pathinfo(const char* Path, int Mode);
\ No newline at end of file
diff --git a/kernel/include/lib/php/str_contains.h b/kernel/include/lib/php/str_contains.h
new file mode 100644
index 000000000..ddd23a840
--- /dev/null
+++ b/kernel/include/lib/php/str_contains.h
@@ -0,0 +1,17 @@
+/**
+ * @file lib/php/pathinfo.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru)
+ * @brief Функция замены строк
+ * @version 0.3.4
+ * @date 2023-07-30
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+ */
+#pragma once
+
+#include "lib/string.h"
+
+static inline bool str_contains(const char* haystack, const char* needle) {
+ const char* result = strstr(haystack, needle);
+
+ return result != NULL;
+}
\ No newline at end of file
diff --git a/kernel/include/lib/php/str_replace.h b/kernel/include/lib/php/str_replace.h
new file mode 100644
index 000000000..d9e50a169
--- /dev/null
+++ b/kernel/include/lib/php/str_replace.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "common.h"
+
+uint32_t char_replace(char search, char replace, char* subject);
\ No newline at end of file
diff --git a/kernel/include/lib/pixel.h b/kernel/include/lib/pixel.h
new file mode 100644
index 000000000..1947988a8
--- /dev/null
+++ b/kernel/include/lib/pixel.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#ifndef SAYORI_PIXEL_H
+#define SAYORI_PIXEL_H
+
+void drawRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color);
+void drawRectLine(int x,int y,int w, int h,int color,int color2, int c);
+void drawRectBorder(int x, int y, int w, int h, int color);
+void drawHorizontalLine(int x1, int x2, int y, uint32_t color);
+void drawVerticalLine(int y1, int y2, int x, uint32_t color);
+void drawCirclePoints(int cx, int cy, int x, int y, uint32_t color);
+void drawCircle(int cx, int cy, int radius, uint32_t color);
+void drawFilledCircle(int x0, int y0, int radius, uint32_t color);
+void drawFilledRectBorder(int x0, int y0, int radius, int w, int mode, uint32_t color);
+void drawRoundedSquare(int x, int y, int size, int radius, uint32_t fill_color, uint32_t border_color);
+void drawRoundedRectangle(int x, int y, int width, int height, int radius, uint32_t fill_color, uint32_t border_color);
+
+
+#endif //SAYORI_PIXEL_H
diff --git a/kernel/include/lib/split.h b/kernel/include/lib/split.h
index 9aa4eb799..5b7e24486 100644
--- a/kernel/include/lib/split.h
+++ b/kernel/include/lib/split.h
@@ -2,5 +2,5 @@
#include "common.h"
-uint32_t str_cdsp(char* a_str, char* del);
-void str_split(char a_str[], char *out[], char* dec);
\ No newline at end of file
+uint32_t str_cdsp(const char *a_str, const char* del);
+void str_split(const char a_str[], char *out[], char* dec);
\ No newline at end of file
diff --git a/kernel/include/lib/sprintf.h b/kernel/include/lib/sprintf.h
index 6fb1256a4..0115c8006 100644
--- a/kernel/include/lib/sprintf.h
+++ b/kernel/include/lib/sprintf.h
@@ -1,6 +1,5 @@
#pragma once
-#include
#include
size_t measure_vsprintf(const char *format, va_list args);
diff --git a/kernel/include/lib/stdarg.h b/kernel/include/lib/stdarg.h
old mode 100755
new mode 100644
diff --git a/kernel/include/lib/stdio.h b/kernel/include/lib/stdio.h
old mode 100755
new mode 100644
index a0357923f..b53099db1
--- a/kernel/include/lib/stdio.h
+++ b/kernel/include/lib/stdio.h
@@ -1,7 +1,7 @@
#pragma once
#include "common.h"
-
+#include
#define EOF (-1)
#define SEEK_SET 0
#define SEEK_CUR 1
@@ -44,9 +44,5 @@ ssize_t fseek(FILE* stream, ssize_t offset, uint8_t whence);
void rewind(FILE *stream);
void perror(FILE* stream,char* s);
uint32_t ferror(FILE* stream);
-void fsetpos(FILE* stream, ssize_t pos);
-ssize_t fgetpos(FILE* stream);
-void fdebuginfo(FILE* stream);
-//size_t fread(FILE* stream, char* ptr, size_t size, size_t nmemb);
size_t fwrite(FILE *stream, size_t size, size_t count, const void *ptr);
diff --git a/kernel/include/lib/stdlib.h b/kernel/include/lib/stdlib.h
old mode 100755
new mode 100644
index f2d027a3a..986a75cc2
--- a/kernel/include/lib/stdlib.h
+++ b/kernel/include/lib/stdlib.h
@@ -1,6 +1,5 @@
#pragma once
#include
-void* calloc(size_t nmemb, size_t size);
-int32_t itoa(int32_t n, char *buffer);
-uint32_t atoi(char s[]);
\ No newline at end of file
+size_t itoa(int32_t n, char *buffer);
+uint32_t atoi(const char s[]);
\ No newline at end of file
diff --git a/kernel/include/lib/string.h b/kernel/include/lib/string.h
index 97ef2895d..d04ee46ab 100644
--- a/kernel/include/lib/string.h
+++ b/kernel/include/lib/string.h
@@ -3,8 +3,8 @@
#include "common.h"
int32_t memcmp(const char *s1, const char *s2, size_t n);
-void memcpy(void* destination, const void* source, size_t n);
-void* memset(void* ptr, int value, size_t num);
+void* memcpy(void *restrict destination, const void *restrict source, size_t n);
+void* memset(void* ptr, char value, size_t num);
void* memmove(void *dest, void *src, size_t count);
void strver(char *str);
@@ -15,13 +15,12 @@ char *strtok(char *s, const char *delim);
size_t strlen(const char *str);
bool strcmpn(const char *str1, const char *str2);
size_t mb_strlen(const char *str);
-void substr(char *dest, const char *source, int from, int length);
+void substr(char* restrict dest, const char* restrict source, int from, int length);
int strcmp(const char *s1, const char *s2);
int32_t strncmp(const char *s1, const char *s2, size_t num);
char digit_count(size_t num);
char hex_count(size_t num);
-bool isdigit(char a);
size_t itoh(size_t n, char *buffer);
size_t itou(size_t n, char *buffer);
char *strchr(const char *_s, char _c);
@@ -30,8 +29,14 @@ bool isnumberstr(char* a);
bool isUTF(char c);
-#if USE_SSE
void sse_memcpy(void* restrict dest, const void* restrict src, size_t size);
-#endif
size_t strcount(const char* string, char character);
+char* strstr(const char* haystack, const char* needle);
+char *strncpy(char *dest, const char *src, size_t n);
+
+uint32_t atoi(const char s[]);
+
+SAYORI_INLINE bool isdigit(char a) {
+ return a >= '0' && a <= '9';
+}
\ No newline at end of file
diff --git a/kernel/include/lib/utf_conversion.h b/kernel/include/lib/utf_conversion.h
new file mode 100644
index 000000000..45fadd467
--- /dev/null
+++ b/kernel/include/lib/utf_conversion.h
@@ -0,0 +1,7 @@
+//
+// Created by maractus on 27.12.23.
+//
+
+#pragma once
+
+void utf16_to_utf8(const unsigned short *utf16, int utf16_length, char *utf8);
diff --git a/kernel/include/mem/pmm.h b/kernel/include/mem/pmm.h
new file mode 100644
index 000000000..0570495cb
--- /dev/null
+++ b/kernel/include/mem/pmm.h
@@ -0,0 +1,66 @@
+#pragma once
+
+// Scyther Physical Memory Manager by NDRAEY (c) 2023
+// for SayoriOS
+
+#include "common.h"
+#include "multiboot.h"
+
+typedef uint32_t pt_entry;
+typedef uint32_t pd_entry;
+
+extern size_t phys_memory_size;
+extern size_t used_phys_memory_size;
+
+extern size_t kernel_start;
+extern size_t kernel_end;
+
+#define PAGE_SIZE 0x1000
+#define PAGE_OFFSET_MASK 0xFFF
+#define PAGE_TABLE_INDEX_BITS 10
+#define PAGE_TABLE_INDEX_MASK 0x3FF
+
+#define PAGE_PRESENT (1 << 0)
+#define PAGE_WRITEABLE (1 << 1)
+#define PAGE_USER (1 << 2)
+#define PAGE_WRITE_THROUGH (1 << 3)
+#define PAGE_CACHE_DISABLE (1 << 4)
+#define PAGE_ACCESSED (1 << 5)
+#define PAGE_DIRTY (1 << 6)
+#define PAGE_GLOBAL (1 << 8)
+
+#define PAGE_BITMAP_SIZE (131072)
+
+#define PD_INDEX(virt_addr) ((virt_addr) >> 22)
+#define PT_INDEX(virt_addr) (((virt_addr) >> 12) & 0x3ff)
+
+typedef uint32_t virtual_addr_t;
+typedef uint32_t physical_addr_t;
+
+// The space where first page table starts
+/// Начало где расположены все таблицы страниц
+static uint32_t* page_directory_start = (uint32_t*)(0xffffffff - (4 * MB) + 1);
+
+// The space where we can modify page directory
+/// Начало директории таблиц для страниц
+static uint32_t* page_directory_virt = (uint32_t*)(0xffffffff - (4 * KB) + 1);
+
+
+extern void load_page_directory(size_t addr);
+extern void enable_paging();
+
+physical_addr_t phys_alloc_single_page();
+physical_addr_t phys_alloc_multi_pages(size_t count);
+void phys_free_single_page(physical_addr_t addr);
+void phys_free_multi_pages(physical_addr_t addr, size_t count);
+void map_single_page(physical_addr_t* page_dir, physical_addr_t physical, virtual_addr_t virtual, uint32_t flags);
+void unmap_single_page(uint32_t* page_dir, virtual_addr_t virtual);
+void map_pages(uint32_t* page_dir, physical_addr_t physical, virtual_addr_t virtual, size_t size, uint32_t flags);
+void phys_not_enough_memory();
+void blank_page_directory(uint32_t* pagedir_addr);
+bool phys_is_used_page(physical_addr_t addr);
+void phys_mark_page_entry(physical_addr_t addr, uint8_t used);
+uint32_t phys_get_page_data(uint32_t* page_dir, virtual_addr_t virtual);
+uint32_t virt2phys(uint32_t* page_dir, virtual_addr_t virtual);
+void init_paging();
+uint32_t* get_kernel_page_directory();
\ No newline at end of file
diff --git a/kernel/include/mem/vmm.h b/kernel/include/mem/vmm.h
new file mode 100644
index 000000000..7dfc8a166
--- /dev/null
+++ b/kernel/include/mem/vmm.h
@@ -0,0 +1,51 @@
+// Charmander - a new virtual memory manager by NDRAEY (c) 2023
+// for SayoriOS
+//
+// Created by ndraey on 05.11.23.
+//
+
+#pragma once
+
+#include
+#include "lib/string.h"
+
+// #define kfree_debug(ptr) do { qemu_note("FREE BLOCK (%x) at %s:%d", ptr, __FILE__, __LINE__); kfree(ptr); } while(0);
+
+struct heap_entry {
+ size_t address;
+ size_t length;
+};
+
+typedef struct heap {
+ size_t allocated_count;
+ size_t capacity; // Entries
+ size_t start;
+ size_t used_memory;
+ struct heap_entry* memory;
+} heap_t;
+
+extern heap_t system_heap;
+
+void vmm_init();
+void *alloc_no_map(size_t size, size_t align);
+void free_no_map(void* ptr);
+bool vmm_is_page_used_by_entries(size_t address);
+void* kmalloc_common(size_t size, size_t align);
+
+SAYORI_INLINE void* kmalloc(size_t size) {
+ return kmalloc_common(size, 0);
+}
+
+void* krealloc(void* ptr, size_t memory_size);
+void kfree(void* ptr);
+void* clone_kernel_page_directory();
+
+void vmm_debug_switch(bool enable);
+
+SAYORI_INLINE void* kcalloc(size_t size, size_t amount) {
+ void* x = kmalloc(size * amount);
+
+ memset(x, 0, size * amount);
+
+ return x;
+}
diff --git a/kernel/include/multiboot.h b/kernel/include/multiboot.h
old mode 100755
new mode 100644
diff --git a/kernel/include/net/arp.h b/kernel/include/net/arp.h
index efafa147d..bda171ee3 100644
--- a/kernel/include/net/arp.h
+++ b/kernel/include/net/arp.h
@@ -1,6 +1,7 @@
#pragma once
-#include "kernel.h"
+#include "common.h"
+#include "cards.h"
#define ARP_REQUEST 1
#define ARP_REPLY 2
diff --git a/kernel/include/net/cards.h b/kernel/include/net/cards.h
index 698d92bac..7122df257 100644
--- a/kernel/include/net/cards.h
+++ b/kernel/include/net/cards.h
@@ -4,12 +4,13 @@
typedef struct {
char name[64];
+ uint8_t ipv4_addr[4];
void (*get_mac_addr)(uint8_t[6]);
void (*send_packet)(void*, size_t);
} netcard_entry_t;
void netcards_list_init();
-void netcard_add(netcard_entry_t card);
+void netcard_add(netcard_entry_t *card);
size_t netcards_get_count();
netcard_entry_t* netcard_get(size_t index);
\ No newline at end of file
diff --git a/kernel/include/net/dhcp.h b/kernel/include/net/dhcp.h
new file mode 100644
index 000000000..03ca60c6f
--- /dev/null
+++ b/kernel/include/net/dhcp.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "common.h"
+
+#define DHCP_REQUEST 1
+#define DHCP_REPLY 2
+
+typedef struct dhcp_packet {
+ uint8_t op;
+ uint8_t hardware_type;
+ uint8_t hardware_addr_len;
+ uint8_t hops;
+ uint32_t xid;
+ uint16_t seconds;
+ uint16_t flags;
+ uint32_t client_ip;
+ uint32_t your_ip;
+ uint32_t server_ip;
+ uint32_t gateway_ip;
+ uint8_t client_hardware_addr[16];
+ uint8_t server_name[64];
+ uint8_t file[128];
+ uint8_t options[340];
+} __attribute__ ((packed)) dhcp_packet_t;
+
+void dhcp_discover(netcard_entry_t* card);
+void dhcp_handle_packet(netcard_entry_t* card, dhcp_packet_t* packet);
+void dhcp_request(netcard_entry_t* card, const uint8_t req_ip[4]);
\ No newline at end of file
diff --git a/kernel/include/net/ethernet.h b/kernel/include/net/ethernet.h
index 6b9b1b27b..924eb0a6d 100644
--- a/kernel/include/net/ethernet.h
+++ b/kernel/include/net/ethernet.h
@@ -1,9 +1,74 @@
#pragma once
#include "common.h"
+#include "net/cards.h"
-#define ETHERNET_TYPE_ARP 0x0806
-#define ETHERNET_TYPE_IP 0x0800
+#define ETHERNET_TYPE_IPV4 0x0800 ///< Internet Protocol v4
+#define ETHERNET_TYPE_ARP 0x0806 ///< Address Resolution Protocol
+#define ETHERNET_TYPE_WoL 0x0842 ///< Wake-on-LAN
+#define ETHERNET_TYPE_SRP 0x22EA ///< Stream Reservation Protocol
+#define ETHERNET_TYPE_AVTP 0x22F0 ///< Audio Video Transport Protocol
+#define ETHERNET_TYPE_IETF 0x22F3 ///< IETF TRILL Protocol
+#define ETHERNET_TYPE_DECMOP 0x6002 ///< DEC MOP RC
+#define ETHERNET_TYPE_DECNET 0x6003 ///< DECnet Phase Iv, DNA Routing
+#define ETHERNET_TYPE_DECLAT 0x6004 ///< DEC LAT
+#define ETHERNET_TYPE_RASP 0x8035 ///< Reverse Address Resolution Protocol
+#define ETHERNET_TYPE_ATE 0x809B ///< AppleTalk (Ethertalk)
+#define ETHERNET_TYPE_ATARP 0x80F3 ///< AppleTalk Address Resolution Protocol
+#define ETHERNET_TYPE_VLAN 0x8100 ///< VLAN-tagged frame (IEEE 802.1Q)
+#define ETHERNET_TYPE_SLPP 0x8102 ///< Simple Loop Prevention Protocol
+#define ETHERNET_TYPE_VLACP 0x8103 ///< Virtual Link Aggregation Control Protocol
+#define ETHERNET_TYPE_IPX 0x8137 ////< IPX
+#define ETHERNET_TYPE_QNX 0x8204 ///< QNX Qnet
+#define ETHERNET_TYPE_IPV6 0x86DD ///< Internet Protocol v6
+#define ETHERNET_TYPE_EFC 0x8808 ///< Ethernet flow control
+#define ETHERNET_TYPE_ESP 0x8809
+///< Ethernet Slow Protocols
+#define ETHERNET_TYPE_COBRA 0x8819 ///< CobraNet
+#define ETHERNET_TYPE_MPLSU 0x8847 ///< MPLS unicast
+#define ETHERNET_TYPE_MPLSM 0x8848 ///< MPLS multicast
+#define ETHERNET_TYPE_PPPoEDS 0x8863 ////< PPPoE Discovery State
+#define ETHERNET_TYPE_PPPoESS 0x8864 ///< PPPoE Session Stage
+#define ETHERNET_TYPE_HP1MME 0x887B ///< HomePlug 1.0 MME
+#define ETHERNET_TYPE_EAPoLAN 0x888E ///< EAP over LAN (IEEE 802.1X)
+#define ETHERNET_TYPE_PROFINET 0x8892 ///< PROFINET Protocol
+#define ETHERNET_TYPE_HYPERSCSI 0x889A ///< HyperSCSI (SCSI over Ethernet)
+#define ETHERNET_TYPE_ATAoE 0x88A2 ///< ATA over Ethernet
+#define ETHERNET_TYPE_ECAT 0x88A4 ///< EtherCAT Protocol
+#define ETHERNET_TYPE_SVLAN 0x88A8 ///< Service VLAN tag identifier
+#define ETHERNET_TYPE_POWLINK 0x88AB ///< Ethernet Powerlink
+#define ETHERNET_TYPE_GOOSE 0x88B8 ////< Generic Object Oriented Substatuion event
+#define ETHERNET_TYPE_GSE 0x88B9 ///< Generic Substation Events
+#define ETHERNET_TYPE_SV 0x88BA ///< Sampled Value Transmission
+#define ETHERNET_TYPE_MTRMN 0x88BA ///< MikroTik RoMON (unofficial)
+#define ETHERNET_TYPE_LLDP 0x88CC ///< Link Layer Discovery Protocol
+#define ETHERNET_TYPE_SCSIII 0x88CD ///< SECOS III
+#define ETHERNET_TYPE_HPGPHY 0x88E1 ///< HomePlug Green PHY
+#define ETHERNET_TYPE_MRP 0x88E3 ///< Media Redundancy Protocol
+#define ETHERNET_TYPE_MACSEC 0x88E5 ///< IEEE 802.1AE MAC Security
+#define ETHERNET_TYPE_PBB 0x88E7 ///< Provider Backbone Bridges
+#define ETHERNET_TYPE_PTP 0x88F7 ///< Precison Time Protocol
+#define ETHERNET_TYPE_NCSI 0x88F8 ///< NC-SI
+#define ETHERNET_TYPE_PRP 0x88FB ///< Parallel Redundancy Protocol
+#define ETHERNET_TYPE_CFM 0x8902 ///< IEEE 802.1ag Connectivy Fault Management
+#define ETHERNET_TYPE_FCoE 0x8906 ///< Fible Channel over Ethenet
+#define ETHERNET_TYPE_FCoEI 0x8914 ///< FCoE Initialization Protocol
+#define ETHERNET_TYPE_RoCE 0x8915 ///< RDMA over Converted Ethernet
+#define ETHERNET_TYPE_TTE 0x891D ///< TTEthernet Protocol Control Flame
+#define ETHERNET_TYPE_1905 0x893A ///< 1905.1 IEEE Protocol
+#define ETHERNET_TYPE_HSR 0x892F ///< High-availability Seamless Redundancy
+#define ETHERNET_TYPE_ECTP 0x9000 ///< ethernet Configuration Testing Protocol
+#define ETHERNET_TYPE_RT 0xF1C1 ///< Redundancy Tag
+
+#define ETH_IPv6_HEAD_ICMPv6 0x3a ///< ICMPv6 (IPv6 заголовок)
+#define ETH_IPv6_HEAD_UDP 0x11 ///< UDP (IPv6 заголовок)
+
+#define ETH_IPv4_HEAD_ICMPv4 1 ///< ICMPv4 (IPv4 заголовок)
+#define ETH_IPv4_HEAD_UDP 0x11 ///< UDP (IPv4 заголовок) еще как вариант 17
+#define ETH_IPv4_HEAD_TCP 6 ///< TCP (IPv4 заголовок)
+
+#define ETH_ICMPv4_TYPE_PING 8 ///< Нас пингуют через ICMPv4 > IPv4
+#define ETH_ICMPv6_TYPE_PING 128 ///< Нас пингуют через ICMPv6 > IPv6
#define HARDWARE_TYPE_ETHERNET 0x01
@@ -12,7 +77,65 @@ typedef struct ethernet_frame {
uint8_t src_mac[6];
uint16_t type;
uint8_t data[];
-} __attribute__((packed)) ethernet_frame_t;
+} __attribute__((packed)) ethernet_frame_t; ///< 14+
+
+typedef struct {
+ uint8_t Type;
+ uint8_t Size;
+ uint8_t MAC[6];
+} __attribute__((packed)) ETH_IPv6_OPT_PKG; ///< 8 байт
+
+typedef struct {
+ uint8_t Version;
+ uint8_t Flow[3];
+ uint16_t PayLoad;
+ uint8_t NextHead;
+ uint8_t HopLimit;
+ uint16_t Source[8];
+ uint16_t Destination[8];
+} __attribute__((packed)) ETH_IPv6_PKG; ///< 40 байт + 8 байт
+
+
+typedef struct {
+ uint8_t Type;
+ uint8_t Code;
+ uint16_t CheckSum;
+ uint32_t Reserved;
+ ETH_IPv6_OPT_PKG Opt;
+} __attribute__((packed)) ETH_ICMPv6_PKG; ///< 16 байт
+
+typedef struct {
+ uint8_t HeaderLength : 4;
+ uint8_t Version : 4;
+ uint8_t DSF;
+ uint16_t TotalLength;
+ uint16_t ID;
+ uint16_t Flags;
+ uint8_t TimeLife;
+ uint8_t Protocol;
+ uint16_t Checksum;
+ uint8_t Source[4];
+ uint8_t Destination[4];
+} __attribute__((packed)) ETH_IPv4_PKG; ///< 20 байт // NDRAEY: PKT is not PKG!
+
+
+typedef struct {
+ uint16_t SourcePort;
+ uint16_t DestinationPort;
+ uint16_t Length;
+ uint16_t CheckSum;
+} __attribute__((packed)) ETH_UDP_PKG; ///< 8 байт
+
+
+typedef struct {
+ uint8_t Type;
+ uint8_t Code;
+ uint16_t CheckSum;
+ uint16_t IDBE;
+ uint16_t SNBE;
+ uint8_t Timestamp[8];
+} __attribute__((packed)) ETH_ICMPv4_PKG; ///< 16 байт
+
void ethernet_send_packet(netcard_entry_t* card, uint8_t* dest_mac, uint8_t* data, size_t len, uint16_t type);
-void ethernet_handle_packet(ethernet_frame_t* packet, size_t len);
\ No newline at end of file
+void ethernet_handle_packet(netcard_entry_t *card, ethernet_frame_t *packet, size_t len);
\ No newline at end of file
diff --git a/kernel/include/net/icmp.h b/kernel/include/net/icmp.h
new file mode 100644
index 000000000..9a33c2578
--- /dev/null
+++ b/kernel/include/net/icmp.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "net/cards.h"
+
+void icmp_handle_packet(netcard_entry_t* card, char* packet_data);
\ No newline at end of file
diff --git a/kernel/include/net/ipv4.h b/kernel/include/net/ipv4.h
new file mode 100644
index 000000000..f637618f4
--- /dev/null
+++ b/kernel/include/net/ipv4.h
@@ -0,0 +1,13 @@
+//
+// Created by ndraey on 01.11.23.
+//
+
+#pragma once
+
+#include
+#include "net/cards.h"
+
+#define IP_PROTOCOL_UDP 17
+
+void ipv4_handle_packet(netcard_entry_t *card, char *packet, size_t packet_size);
+void ipv4_send_packet(netcard_entry_t *card, uint8_t dest_ip[4], const void *data, size_t size, uint8_t protocol);
\ No newline at end of file
diff --git a/kernel/include/net/udp.h b/kernel/include/net/udp.h
new file mode 100644
index 000000000..80566d5ee
--- /dev/null
+++ b/kernel/include/net/udp.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "common.h"
+#include "net/cards.h"
+
+typedef struct udp_packet {
+ uint16_t src_port;
+ uint16_t dst_port;
+ uint16_t length;
+ uint16_t checksum;
+} __attribute__((packed)) udp_packet_t;
+
+void udp_send_packet(netcard_entry_t* card, uint8_t * dst_ip, uint16_t src_port, uint16_t dst_port, void * data, int len);
+void udp_handle_packet(netcard_entry_t *card, udp_packet_t *packet);
\ No newline at end of file
diff --git a/kernel/include/portability.h b/kernel/include/portability.h
new file mode 100644
index 000000000..0b916369c
--- /dev/null
+++ b/kernel/include/portability.h
@@ -0,0 +1,112 @@
+#pragma once
+
+#include "mem/vmm.h"
+#include "lib/stdlib.h"
+
+#define malloc(a) kmalloc(a)
+#define calloc(a, b) kcalloc(a, b)
+#define realloc(a, b) krealloc(a, b)
+#define free(a) kfree(a)
+#define printf(a, ...) qemu_printf(a, ##__VA_ARGS__)
+
+
+#define passert(expression) \
+ if (!(expression)) { \
+ qemu_warn("Assertion failed: file %s, line %d\n", __FILE__, __LINE__); \
+ }
+
+// stdint.h
+
+#define INT_FAST16_MIN (-2147483647-1)
+#define INT_FAST32_MIN (-2147483647-1)
+#define INT_FAST16_MAX (2147483647)
+#define INT_FAST32_MAX (2147483647)
+#define UINT_FAST16_MAX (4294967295U)
+#define UINT_FAST32_MAX (4294967295U)
+#define SIZE_MAX (4294967295U)
+
+#define INT32_MIN (-INT32_MAX-1)
+#define INT32_MAX 2147483647
+
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+#define UINT_MAX 4294967295U
+
+#define UINT32_MAX (4294967295U)
+
+
+// bits/types.h
+
+typedef signed char __int8_t;
+typedef unsigned char __uint8_t;
+typedef signed short int __int16_t;
+typedef unsigned short int __uint16_t;
+typedef signed int __int32_t;
+typedef unsigned int __uint32_t;
+typedef unsigned long long __uint64_t;
+typedef long long __int64_t;
+
+typedef __int8_t __int_least8_t;
+typedef __uint8_t __uint_least8_t;
+typedef __int16_t __int_least16_t;
+typedef __uint16_t __uint_least16_t;
+typedef __int32_t __int_least32_t;
+typedef __uint32_t __uint_least32_t;
+typedef __int64_t __int_least64_t;
+typedef __uint64_t __uint_least64_t;
+
+// stdint.h
+typedef __int_least8_t int_least8_t;
+typedef __int_least16_t int_least16_t;
+typedef __int_least32_t int_least32_t;
+typedef __int_least64_t int_least64_t;
+
+
+typedef __uint_least8_t uint_least8_t;
+typedef __uint_least16_t uint_least16_t;
+typedef __uint_least32_t uint_least32_t;
+typedef __uint_least64_t uint_least64_t;
+
+typedef signed char int_fast8_t;
+typedef int int_fast16_t;
+typedef int int_fast32_t;
+
+typedef uint8_t uint_fast8_t;
+typedef uint32_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+
+typedef int intptr_t;
+typedef unsigned int uintptr_t;
+
+__extension__ typedef long long int __intmax_t;
+__extension__ typedef unsigned long long int __uintmax_t;
+
+typedef __intmax_t intmax_t;
+typedef __uintmax_t uintmax_t;
+
+
+typedef __uint_least64_t uint_least64_t;
+typedef __int_least64_t int_least64_t;
+
+typedef long long int int_fast64_t;
+typedef unsigned long long int uint_fast64_t;
+
+// bits/types/struct_tm.h
+
+struct tm {
+ int tm_sec; /* Seconds. [0-60] (1 leap second) */
+ int tm_min; /* Minutes. [0-59] */
+ int tm_hour; /* Hours. [0-23] */
+ int tm_mday; /* Day. [1-31] */
+ int tm_mon; /* Month. [0-11] */
+ int tm_year; /* Year - 1900. */
+ int tm_wday; /* Day of week. [0-6] */
+ int tm_yday; /* Days in year.[0-365] */
+ int tm_isdst; /* DST. [-1/0/1]*/
+
+ long int __tm_gmtoff; /* Seconds east of UTC. */
+ const char *__tm_zone; /* Timezone abbreviation. */
+};
+
+typedef int32_t time_t;
diff --git a/kernel/include/rust_header.h b/kernel/include/rust_header.h
deleted file mode 100644
index aef54a8f6..000000000
--- a/kernel/include/rust_header.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef RUST_H
-#define RUST_H
-
-extern void rust_main();
-extern void rust_command(uint32_t argc, char *argv[]);
-
-#endif
\ No newline at end of file
diff --git a/kernel/include/rust_headers.h b/kernel/include/rust_headers.h
new file mode 100644
index 000000000..cc3c63683
--- /dev/null
+++ b/kernel/include/rust_headers.h
@@ -0,0 +1,6 @@
+#ifndef RUST_H
+#define RUST_H
+
+extern void rust_main();
+
+#endif
diff --git a/kernel/include/sys/acpi.h b/kernel/include/sys/acpi.h
index 15ddc3549..a7ecd353a 100644
--- a/kernel/include/sys/acpi.h
+++ b/kernel/include/sys/acpi.h
@@ -1,6 +1,6 @@
#pragma once
-#include "kernel.h"
+#include "common.h"
#include "sys/rsdp.h"
#include "sys/rsdt.h"
diff --git a/kernel/include/sys/cpu_isr.h b/kernel/include/sys/cpu_isr.h
old mode 100755
new mode 100644
diff --git a/kernel/include/sys/cpuid.h b/kernel/include/sys/cpuid.h
index a327d9e33..fe1199df6 100644
--- a/kernel/include/sys/cpuid.h
+++ b/kernel/include/sys/cpuid.h
@@ -80,9 +80,10 @@ struct cpu_info {
size_t l2_size;
size_t l3_size;
- size_t feature_flags_ecx;
- size_t feature_flags_edx;
+ uint32_t feature_flags_ecx;
+ uint32_t feature_flags_edx;
};
size_t cpu_get_id();
-struct cpu_info cpu_get_basic_info();
\ No newline at end of file
+struct cpu_info cpu_get_basic_info();
+bool is_long_mode_supported();
diff --git a/kernel/include/sys/cpuinfo.h b/kernel/include/sys/cpuinfo.h
old mode 100755
new mode 100644
diff --git a/kernel/include/sys/descriptor_tables.h b/kernel/include/sys/descriptor_tables.h
old mode 100755
new mode 100644
diff --git a/kernel/include/sys/isr.h b/kernel/include/sys/isr.h
old mode 100755
new mode 100644
diff --git a/kernel/include/sys/memory.h b/kernel/include/sys/memory.h
deleted file mode 100755
index e5e508904..000000000
--- a/kernel/include/sys/memory.h
+++ /dev/null
@@ -1,156 +0,0 @@
-#ifndef MEMORY_H
-#define MEMORY_H
-
-#include "common.h"
-#include "multiboot.h"
-#include "sys/sync.h"
-#include "lib/string.h"
-
-#define PAGE_SIZE 0x1000 /* Memory page size */
-#define PAGE_OFFSET_BITS 12 /* */
-#define PAGE_OFFSET_MASK 0xFFF
-#define PAGE_TABLE_INDEX_BITS 10
-#define PAGE_TABLE_INDEX_MASK 0x3FF
-
-#define PHYSADDR_BITS 32
-
-/*------------------------------------------------------------------------------
-// Page flags
-//----------------------------------------------------------------------------*/
-#define PAGE_PRESENT (1 << 0)
-#define PAGE_WRITEABLE (1 << 1)
-#define PAGE_USER (1 << 2)
-#define PAGE_WRITE_THROUGH (1 << 3)
-#define PAGE_CACHE_DISABLE (1 << 4)
-#define PAGE_ACCESSED (1 << 5)
-#define PAGE_DIRTY (1 << 6)
-#define PAGE_GLOBAL (1 << 8)
-
-// #define KERNEL_BASE 0x200000 /* Kernel start address in physical memory */ // There was 0x200000 before SB16 driver
-// #define KERNEL_SIZE 0x1800000 /* Size of area for kernel */
-
-/*------------------------------------------------------------------------------
-// Kernel virtual address space
-//----------------------------------------------------------------------------*/
-#define KERNEL_MEMORY_END (0x80000000)
-
-/* Kernel heap params */
-#define KERNEL_HEAP_SIZE 0x20000000
-#define KERNEL_HEAP_BASE ((void*) (KERNEL_MEMORY_END - KERNEL_HEAP_SIZE))
-#define KERNEL_HEAP_BLOCK_INFO_SIZE 0x400000
-
-/*------------------------------------------------------------------------------
-// Any types redefinition
-//----------------------------------------------------------------------------*/
-typedef uint32_t physaddr_t;
-typedef uint32_t virtual_addr_t;
-//typedef uint32_t physical_addres_t;
-/*------------------------------------------------------------------------------
-// Memory pages block
-//----------------------------------------------------------------------------*/
-typedef struct
-{
- physaddr_t prev; /* Previous block pointer */
- physaddr_t next; /* Next block pointer */
- size_t size; /* Block size */
-
-}__attribute__((packed)) physmemory_pages_block_t;
-
-/*------------------------------------------------------------------------------
-// Memory block structure
-//----------------------------------------------------------------------------*/
-typedef struct
-{
- void* base; /* Base address */
- size_t size; /* Memory block size */
-
-}__attribute__((packed)) memory_block_t;
-
-/*------------------------------------------------------------------------------
-// Kernel heap
-//----------------------------------------------------------------------------*/
-typedef struct
-{
- memory_block_t* blocks; /* Memory blocks info array */
- void* start; /* Heap start virtual address */
- void* end; /* Heap end virtual address */
- size_t size; /* Heap size */
- size_t count; /* Number of allocated memory blocks */
- mutex_t heap_mutex; /* Sinchonization for heap access */
-
-}__attribute__((packed)) heap_t;
-
-#define LAST_ADDR 0xFFFFFFFF /* Last virtual address in x86 address space*/
-
-#define TEMP_PAGE (KERNEL_BASE + KERNEL_SIZE - PAGE_SIZE) /* Temporary page for */
-// #define TEMP_PAGE (0xFFA00000) /* Temporary page for */
- /* physical memory access */
-
-#define TEMP_TABLE_IDX (TEMP_PAGE >> 22) /* Temporary page table index == PAGE_DIRECTORY_INDEX*/
-#define TEMP_PAGE_IDX ((TEMP_PAGE >> PAGE_OFFSET_BITS) & PAGE_TABLE_INDEX_MASK) /* Temporary page index == PAGE_TABLE_INDEX*/
-
-#define PAGE_ALIGN_DOWN(x) ((x) & -PAGE_SIZE)
-#define PAGE_ALIGN_UP(address) (((address) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1) )
-
-#define PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3FF)
-#define PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3FF)
-
-#define PAGE_GET_TABLE_ADDRESS(x) (*x & ~0xFFF)
-
-#define GET_PDE(v) (page_dir_entry*) (0xFFFFF000 + (v >> 22) * 4)
-#define GET_PTE(v) (page_table_entry*) (0xFFC00000 + (v >> 12) * 4)
-
-#define GET_PT() (size_t*)(kernel_page_dir + PAGE_SIZE)
-
-extern size_t memory_size;
-extern size_t KERNEL_BASE;
-extern size_t KERNEL_SIZE;
-
-// #define REAL_HEAP_SIZE (memory_size - (KERNEL_BASE + KERNEL_SIZE + KERNEL_HEAP_BLOCK_INFO_SIZE - (8 << 20)))
-#define REAL_HEAP_SIZE KERNEL_HEAP_SIZE
-
-/* Switch processor to page mode */
-void switch_page_mode(void);
-/* Check memory map from GRUB2 Multiboot header */
-void check_memory_map(memory_map_entry_t* mmap_addr, uint32_t length);
-
-void init_memory_manager(uint32_t stack);
-
-uint8_t map_pages(physaddr_t page_dir, /* Page directory*/
- virtual_addr_t vaddr, /* Start virtual address */
- physaddr_t paddr, /* Start physical address */
- size_t count, /* Size of memory space */
- uint32_t flags); /* Page's flags */
-
-physaddr_t alloc_phys_pages(size_t count);
-void vmm_free_page(virtual_addr_t vaddr);
-physaddr_t get_kernel_dir(void);
-
-void* kmalloc_common(size_t size, bool align);
-void kfree(void* vaddr);
-void* krealloc(void* vaddr, size_t size);
-size_t memory_get_used_kernel();
-size_t virt2phys(physaddr_t page_directory, virtual_addr_t virtual_address);
-uint8_t unmap_pages(physaddr_t page_dir, virtual_addr_t vaddr, size_t count);
-
-/**
- * @brief Выделение памяти
- *
- * @param size_t size - Размер
- *
- * @return void* - ???
- */
-static inline void* kmalloc(size_t size){
- return kmalloc_common(size, false);
-}
-
-/**
- * @brief Выделение памяти
- */
-void* kcalloc(size_t count, size_t size);
-
-void* kmalloc_a(size_t size);
-
-bool is_suitable_phys_region(physaddr_t address);
-
-#endif
\ No newline at end of file
diff --git a/kernel/include/sys/mtrr.h b/kernel/include/sys/mtrr.h
new file mode 100644
index 000000000..f1c3f30f3
--- /dev/null
+++ b/kernel/include/sys/mtrr.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "common.h"
+
+void mtrr_init();
+void read_mtrr(size_t index, uint32_t* base, uint32_t* mask);
+void write_mtrr(size_t index, uint32_t base, uint32_t mask);
+void write_mtrr_size(size_t index, uint32_t base, uint32_t size, size_t type);
+size_t find_free_mtrr();
\ No newline at end of file
diff --git a/kernel/include/sys/scheduler.h b/kernel/include/sys/scheduler.h
old mode 100755
new mode 100644
index 5a3763c33..8c0703d28
--- a/kernel/include/sys/scheduler.h
+++ b/kernel/include/sys/scheduler.h
@@ -3,7 +3,7 @@
#include "common.h"
#include "lib/list.h"
-#include "sys/memory.h"
+#include "mem/pmm.h"
#define DEFAULT_STACK_SIZE 0x4000
@@ -13,12 +13,12 @@
typedef struct
{
list_item_t list_item; /* List item */
- physaddr_t page_dir; /* Page directory */
+ physical_addr_t page_dir; /* Page directory */
size_t threads_count; /* Count of threads */
bool suspend; /* Suspend flag */
uint32_t pid; /* Process ID (PID) */
char name[256]; /* Process name */
-
+ // Every process should have a path that process operates
}__attribute__((packed)) process_t;
/*-----------------------------------------------------------------------------
@@ -41,9 +41,6 @@ typedef struct
/* Initialization */
void init_task_manager(void);
-/* Switching of tasks */
-void switch_task(void);
-
extern void task_switch(void);
/* Create new thread */
@@ -62,6 +59,8 @@ void thread_suspend(thread_t* thread, bool suspend);
/* Exit from thread */
void thread_exit(thread_t* thread);
+void create_process(void* entry_point, char* name, bool suspend, bool is_kernel);
+
/* Check multitask flag */
bool is_multitask(void);
diff --git a/kernel/include/sys/status.h b/kernel/include/sys/status.h
new file mode 100644
index 000000000..a76fc94a5
--- /dev/null
+++ b/kernel/include/sys/status.h
@@ -0,0 +1,16 @@
+#pragma once
+
+typedef enum {
+ OK = 0,
+ E_NO_MEMORY,
+ E_INVALID_BUFFER,
+ E_NO_DEVICE,
+ E_DEVICE_NOT_ONLINE,
+ E_IO_ERROR,
+ E_TIMEOUT,
+ E_INVALID_SIZE,
+ E_INVALID_SIGNATURE,
+ E_NOT_SUPPORTED,
+ E_PIKACHU, // Tsssss it's an easteregg
+ E_UNKNOWN
+} status_t;
diff --git a/kernel/include/sys/sync.h b/kernel/include/sys/sync.h
old mode 100755
new mode 100644
diff --git a/kernel/include/sys/syscalls.h b/kernel/include/sys/syscalls.h
old mode 100755
new mode 100644
index d3695c833..896aeaec1
--- a/kernel/include/sys/syscalls.h
+++ b/kernel/include/sys/syscalls.h
@@ -1,39 +1,21 @@
-#ifndef SYSCALLS_H
-#define SYSCALLS_H
+#pragma once
#include "common.h"
#include "sys/isr.h"
-#define NUM_CALLS 9
-
-/*-----------------------------------------------------------------------------
- * Syscall interrupt number
- *---------------------------------------------------------------------------*/
#define SYSCALL 0x50
-/*-----------------------------------------------------------------------------
- * System functions
- *---------------------------------------------------------------------------*/
-#define PORT_INPUT_BYTE 0x00
-#define PORT_OUTPUT_BYTE 0x01
-#define TTYCTL 0x02
-#define SH_ENV 0x03
-#define SH_ENV_DEBUG 0x04
-#define SCREENCTL 0x05
-#define MEMCTL 0x06
-#define KBDCTL 0x07
+typedef size_t syscall_fn_t (size_t, size_t, size_t);
-/*-----------------------------------------------------------------------------
- * Macro for system call declaration
- *---------------------------------------------------------------------------*/
+#define NUM_CALLS 4
/* No params */
#define DECL_SYSCALL0(func) int syscall_##func()
#define DEFN_SYSCALL0(func, num)\
\
-int syscall_##func()\
-{ int ret = 0;\
+int syscall_##func() { \
+ int ret = 0;\
asm volatile ("int $0x50":"=a"(ret):"a"(num));\
return ret;\
}
@@ -79,13 +61,3 @@ int syscall_##func(P1 p1, P2 p2, P3 p3)\
void init_syscalls(void);
extern size_t syscall_entry_call(void* entry_point, void* param1, void* param2, void* param3);
void syscall_handler(registers_t regs);
-int get_digit(int dig);
-
-/*-----------------------------------------------------------------------------
- * System calls declaration
- *---------------------------------------------------------------------------*/
-DECL_SYSCALL2(tty_ctl, void*, void*);
-// ...
-DECL_SYSCALL2(screen_ctl, size_t, size_t);
-
-#endif
diff --git a/kernel/include/sys/timer.h b/kernel/include/sys/timer.h
old mode 100755
new mode 100644
index 9dc941785..6212fea80
--- a/kernel/include/sys/timer.h
+++ b/kernel/include/sys/timer.h
@@ -1,11 +1,11 @@
-#ifndef TIMER_H
-#define TIMER_H
+#pragma once
-#define BASE_FREQ 1000
+#define BASE_FREQ 1193180
+#define CLOCK_FREQ 1000
#include "common.h"
-#define sleep(_d) sleep_ms((_d) * 1000);
+#define sleep(_d) sleep_ms((_d) * CLOCK_FREQ);
#define timestamp() (getTicks() / (getFrequency() / 1000))
size_t getTicks();
@@ -13,9 +13,4 @@ double getUptime();
size_t getFrequency();
void sleep_ticks(uint32_t delay);
void sleep_ms(uint32_t milliseconds);
-
-
void init_timer(uint32_t f);
-
-
-#endif
diff --git a/kernel/include/sys/v8086.h b/kernel/include/sys/v8086.h
index 62f8a16e3..0de14e600 100644
--- a/kernel/include/sys/v8086.h
+++ b/kernel/include/sys/v8086.h
@@ -1,6 +1,4 @@
// v8086 by NDRAEY (c) 2023
// For SayoriOS
-#include "kernel.h"
-
extern void v8086_enable();
\ No newline at end of file
diff --git a/kernel/include/sys/variable.h b/kernel/include/sys/variable.h
new file mode 100644
index 000000000..ea50b29d0
--- /dev/null
+++ b/kernel/include/sys/variable.h
@@ -0,0 +1,11 @@
+#pragma once
+
+typedef struct {
+ bool Ready;
+ char Key[512];
+ char Value[2048];
+} VARIABLE;
+
+char* variable_read(char* Key);
+int variable_write(char* Key, char* Value);
+VARIABLE* variable_list(char* Search);
\ No newline at end of file
diff --git a/kernel/include/user/env.h b/kernel/include/user/env.h
index 6b7c75b3a..9edadae31 100644
--- a/kernel/include/user/env.h
+++ b/kernel/include/user/env.h
@@ -1,29 +1,23 @@
#pragma once
-typedef struct env
-{
- char Username[128]; ///< Имя пользователя
- char Hostname[128]; ///< Имя устройства
- char CPU_Name[128]; ///< Имя процессора
- char OS_Name[128]; ///< Имя ОС
- char OS_CodeName[128]; ///< Кодовое название ОС
- char OS_Build[128]; ///< Дата компиляции
- char OS_Arch[128]; ///< Архитектура ядра
- int OS_VERSION_ENV; ///< Версия ENV
- int OS_VERSION_MAJOR; ///< Версия ядра
- int OS_VERSION_MINOR; ///< Пре-Релиз
- int OS_VERSION_PATCH; ///< Патч
- size_t Link_Display; ///< Ссылка на виртуальный экран
- size_t Link_Time; ///< Ссылка на время
- size_t Display_W; ///< Длина экрана
- size_t Display_H; ///< Высота экрана
- int Display_B; ///< Смещение экрана
- size_t Display_P; ///< Глубина экрана
- size_t Display_S; ///< Размер буфера
- size_t Ticks; ///< Количество текущих тиков
- size_t RAM_Install; ///< Установлено ОЗУ
- size_t RAM_Used; ///< Использовано ОЗУ
- size_t RAM_Free; ///< Свободно ОЗУ
+typedef struct env {
+ int OS_VERSION_ENV; ///< Версия ENV
+ int OS_VERSION_MAJOR; ///< Версия ядра
+ int OS_VERSION_MINOR; ///< Пре-Релиз
+ int OS_VERSION_PATCH; ///< Патч
+ size_t DisplayFrameBuffer_Address; ///< Ссылка на виртуальный экран
+ size_t Link_Time; ///< Ссылка на время
+ size_t Display_W; ///< Длина экрана
+ size_t Display_H; ///< Высота экрана
+ size_t Display_B; ///< Бит / пиксель
+ size_t Display_P; ///< Глубина экрана
+ size_t Display_S; ///< Размер буфера
+ size_t Ticks; ///< Количество текущих тиков
+ size_t RAM_Install; ///< Установлено ОЗУ
+ size_t RAM_Used; ///< Использовано ОЗУ
+ size_t RAM_Free; ///< Свободно ОЗУ
} env_t;
-struct env* printEnv();
+extern env_t system_environment;
+
+void configure_env();
\ No newline at end of file
diff --git a/kernel/include/version.h b/kernel/include/version.h
new file mode 100644
index 000000000..074aeb123
--- /dev/null
+++ b/kernel/include/version.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#define VERSION_MAJOR 0 /// Версия ядра
+#define VERSION_MINOR 3 /// Пре-релиз
+#define VERSION_PATCH 4 /// Патч
+#ifdef SAYORI64
+#define ARCH_TYPE "x86_64" /// Архитектура
+#else
+#define ARCH_TYPE "i386" /// Архитектура
+#endif
+#define VERNAME "Soul" /// Имя версии (изменяется вместе с минорной части версии)
+#define SUBVERSIONNAME "Scythe" /// Вторичное имя версии (изменяется вместе с каждым глобальным релизом)
diff --git a/kernel/src/compress/zlib/README_IMPORTANT.txt b/kernel/src/compress/zlib/README_IMPORTANT.txt
deleted file mode 100644
index 68fd69f56..000000000
--- a/kernel/src/compress/zlib/README_IMPORTANT.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Zlib PORTED from following GitHub repository: https://github.com/madler/zlib.
-
-This code doesn't belong to me! Code belongs to it's original authors!!!1
-
-See kernel/include/compress/zlib/zlib.h for more information.
-
-Sources - kernel/src/compress/zlib
-
-Include files - kernel/include/compress/zlib
-
-Ported to SayoriOS by NDRAEY.
\ No newline at end of file
diff --git a/kernel/src/compress/zlib/adler32.c b/kernel/src/compress/zlib/adler32.c
deleted file mode 100644
index 05178e0f0..000000000
--- a/kernel/src/compress/zlib/adler32.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-2011, 2016 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#include "../../../include/compress/zlib/zutil.h"
-
-#define BASE 65521U /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
-#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf) DO8(buf,0); DO8(buf,8);
-
-/* use NO_DIVIDE if your processor does not do division in hardware --
- try it both ways to see which is faster */
-#ifdef NO_DIVIDE
-/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
- (thank you to John Reiser for pointing this out) */
-# define CHOP(a) \
- do { \
- unsigned long tmp = a >> 16; \
- a &= 0xffffUL; \
- a += (tmp << 4) - tmp; \
- } while (0)
-# define MOD28(a) \
- do { \
- CHOP(a); \
- if (a >= BASE) a -= BASE; \
- } while (0)
-# define MOD(a) \
- do { \
- CHOP(a); \
- MOD28(a); \
- } while (0)
-# define MOD63(a) \
- do { /* this assumes a is not negative */ \
- z_off64_t tmp = a >> 32; \
- a &= 0xffffffffL; \
- a += (tmp << 8) - (tmp << 5) + tmp; \
- tmp = a >> 16; \
- a &= 0xffffL; \
- a += (tmp << 4) - tmp; \
- tmp = a >> 16; \
- a &= 0xffffL; \
- a += (tmp << 4) - tmp; \
- if (a >= BASE) a -= BASE; \
- } while (0)
-#else
-# define MOD(a) a %= BASE
-# define MOD28(a) a %= BASE
-# define MOD63(a) a %= BASE
-#endif
-
-/* ========================================================================= */
-uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
- unsigned long sum2;
- unsigned n;
-
- /* split Adler-32 into component sums */
- sum2 = (adler >> 16) & 0xffff;
- adler &= 0xffff;
-
- /* in case user likes doing a byte at a time, keep it fast */
- if (len == 1) {
- adler += buf[0];
- if (adler >= BASE)
- adler -= BASE;
- sum2 += adler;
- if (sum2 >= BASE)
- sum2 -= BASE;
- return adler | (sum2 << 16);
- }
-
- /* initial Adler-32 value (deferred check for len == 1 speed) */
- if (buf == Z_NULL)
- return 1L;
-
- /* in case short lengths are provided, keep it somewhat fast */
- if (len < 16) {
- while (len--) {
- adler += *buf++;
- sum2 += adler;
- }
- if (adler >= BASE)
- adler -= BASE;
- MOD28(sum2); /* only added so many BASE's */
- return adler | (sum2 << 16);
- }
-
- /* do length NMAX blocks -- requires just one modulo operation */
- while (len >= NMAX) {
- len -= NMAX;
- n = NMAX / 16; /* NMAX is divisible by 16 */
- do {
- DO16(buf); /* 16 sums unrolled */
- buf += 16;
- } while (--n);
- MOD(adler);
- MOD(sum2);
- }
-
- /* do remaining bytes (less than NMAX, still just one modulo) */
- if (len) { /* avoid modulos if none remaining */
- while (len >= 16) {
- len -= 16;
- DO16(buf);
- buf += 16;
- }
- while (len--) {
- adler += *buf++;
- sum2 += adler;
- }
- MOD(adler);
- MOD(sum2);
- }
-
- /* return recombined sums */
- return adler | (sum2 << 16);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) {
- return adler32_z(adler, buf, len);
-}
-
-/* ========================================================================= */
-local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
- unsigned long sum1;
- unsigned long sum2;
- unsigned rem;
-
- /* for negative len, return invalid adler32 as a clue for debugging */
- if (len2 < 0)
- return 0xffffffffUL;
-
- /* the derivation of this formula is left as an exercise for the reader */
- MOD63(len2); /* assumes len2 >= 0 */
- rem = (unsigned)len2;
- sum1 = adler1 & 0xffff;
- sum2 = rem * sum1;
- MOD(sum2);
- sum1 += (adler2 & 0xffff) + BASE - 1;
- sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
- if (sum1 >= BASE) sum1 -= BASE;
- if (sum1 >= BASE) sum1 -= BASE;
- if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
- if (sum2 >= BASE) sum2 -= BASE;
- return sum1 | (sum2 << 16);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
- return adler32_combine_(adler1, adler2, len2);
-}
-
-uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
- return adler32_combine_(adler1, adler2, len2);
-}
diff --git a/kernel/src/compress/zlib/compress.c b/kernel/src/compress/zlib/compress.c
deleted file mode 100644
index 741b9b7e7..000000000
--- a/kernel/src/compress/zlib/compress.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* compress.c -- compress a memory buffer
- * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#define ZLIB_INTERNAL
-#include "../../../include/compress/zlib/zlib.h"
-
-/* ===========================================================================
- Compresses the source buffer into the destination buffer. The level
- parameter has the same meaning as in deflateInit. sourceLen is the byte
- length of the source buffer. Upon entry, destLen is the total size of the
- destination buffer, which must be at least 0.1% larger than sourceLen plus
- 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
-
- compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
- memory, Z_BUF_ERROR if there was not enough room in the output buffer,
- Z_STREAM_ERROR if the level parameter is invalid.
-*/
-int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source,
- uLong sourceLen, int level) {
- z_stream stream;
- int err;
- const uInt max = (uInt)-1;
- uLong left;
-
- left = *destLen;
- *destLen = 0;
-
- stream.zalloc = (alloc_func)0;
- stream.zfree = (free_func)0;
- stream.opaque = (voidpf)0;
-
- err = deflateInit(&stream, level);
- if (err != Z_OK) return err;
-
- stream.next_out = dest;
- stream.avail_out = 0;
- stream.next_in = (z_const Bytef *)source;
- stream.avail_in = 0;
-
- do {
- if (stream.avail_out == 0) {
- stream.avail_out = left > (uLong)max ? max : (uInt)left;
- left -= stream.avail_out;
- }
- if (stream.avail_in == 0) {
- stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
- sourceLen -= stream.avail_in;
- }
- err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
- } while (err == Z_OK);
-
- *destLen = stream.total_out;
- deflateEnd(&stream);
- return err == Z_STREAM_END ? Z_OK : err;
-}
-
-/* ===========================================================================
- */
-int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source,
- uLong sourceLen) {
- return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
-}
-
-/* ===========================================================================
- If the default memLevel or windowBits for deflateInit() is changed, then
- this function needs to be updated.
- */
-uLong ZEXPORT compressBound(uLong sourceLen) {
- return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
- (sourceLen >> 25) + 13;
-}
diff --git a/kernel/src/compress/zlib/crc32.c b/kernel/src/compress/zlib/crc32.c
deleted file mode 100644
index e25ad3ff5..000000000
--- a/kernel/src/compress/zlib/crc32.c
+++ /dev/null
@@ -1,1049 +0,0 @@
-/* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-2022 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- *
- * This interleaved implementation of a CRC makes use of pipelined multiple
- * arithmetic-logic units, commonly found in modern CPU cores. It is due to
- * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.
- */
-
-/* @(#) $Id$ */
-
-/*
- Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
- protection on the static variables used to control the first-use generation
- of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
- first call get_crc_table() to initialize the tables before allowing more than
- one thread to use crc32().
-
- MAKECRCH can be #defined to write out crc32.h. A main() routine is also
- produced, so that this one source file can be compiled to an executable.
- */
-
-#ifdef MAKECRCH
-# include
-# ifndef DYNAMIC_CRC_TABLE
-# define DYNAMIC_CRC_TABLE
-# endif /* !DYNAMIC_CRC_TABLE */
-#endif /* MAKECRCH */
-
-#include "../../../include/compress/zlib/zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */
-
- /*
- A CRC of a message is computed on N braids of words in the message, where
- each word consists of W bytes (4 or 8). If N is 3, for example, then three
- running sparse CRCs are calculated respectively on each braid, at these
- indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...
- This is done starting at a word boundary, and continues until as many blocks
- of N * W bytes as are available have been processed. The results are combined
- into a single CRC at the end. For this code, N must be in the range 1..6 and
- W must be 4 or 8. The upper limit on N can be increased if desired by adding
- more #if blocks, extending the patterns apparent in the code. In addition,
- crc32.h would need to be regenerated, if the maximum N value is increased.
-
- N and W are chosen empirically by benchmarking the execution time on a given
- processor. The choices for N and W below were based on testing on Intel Kaby
- Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64
- Octeon II processors. The Intel, AMD, and ARM processors were all fastest
- with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.
- They were all tested with either gcc or clang, all using the -O3 optimization
- level. Your mileage may vary.
- */
-
-/* Define N */
-#ifdef Z_TESTN
-# define N Z_TESTN
-#else
-# define N 5
-#endif
-#if N < 1 || N > 6
-# error N must be in 1..6
-#endif
-
-/*
- z_crc_t must be at least 32 bits. z_word_t must be at least as long as
- z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and
- that bytes are eight bits.
- */
-
-/*
- Define W and the associated z_word_t type. If W is not defined, then a
- braided calculation is not used, and the associated tables and code are not
- compiled.
- */
-#ifdef Z_TESTW
-# if Z_TESTW-1 != -1
-# define W Z_TESTW
-# endif
-#else
-# ifdef MAKECRCH
-# define W 8 /* required for MAKECRCH */
-# else
-# if defined(__x86_64__) || defined(__aarch64__)
-# define W 8
-# else
-# define W 4
-# endif
-# endif
-#endif
-#ifdef W
-# if W == 8 && defined(Z_U8)
- typedef Z_U8 z_word_t;
-# elif defined(Z_U4)
-# undef W
-# define W 4
- typedef Z_U4 z_word_t;
-# else
-# undef W
-# endif
-#endif
-
-/* If available, use the ARM processor CRC32 instruction. */
-#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
-# define ARMCRC32
-#endif
-
-#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
-/*
- Swap the bytes in a z_word_t to convert between little and big endian. Any
- self-respecting compiler will optimize this to a single machine byte-swap
- instruction, if one is available. This assumes that word_t is either 32 bits
- or 64 bits.
- */
-local z_word_t byte_swap(z_word_t word) {
-# if W == 8
- return
- (word & 0xff00000000000000) >> 56 |
- (word & 0xff000000000000) >> 40 |
- (word & 0xff0000000000) >> 24 |
- (word & 0xff00000000) >> 8 |
- (word & 0xff000000) << 8 |
- (word & 0xff0000) << 24 |
- (word & 0xff00) << 40 |
- (word & 0xff) << 56;
-# else /* W == 4 */
- return
- (word & 0xff000000) >> 24 |
- (word & 0xff0000) >> 8 |
- (word & 0xff00) << 8 |
- (word & 0xff) << 24;
-# endif
-}
-#endif
-
-#ifdef DYNAMIC_CRC_TABLE
-/* =========================================================================
- * Table of powers of x for combining CRC-32s, filled in by make_crc_table()
- * below.
- */
- local z_crc_t FAR x2n_table[32];
-#else
-/* =========================================================================
- * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
- * of x for combining CRC-32s, all made by make_crc_table().
- */
-# include "../../../include/compress/zlib/crc32.h"
-#endif
-
-/* CRC polynomial. */
-#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */
-
-/*
- Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
- reflected. For speed, this requires that a not be zero.
- */
-local z_crc_t multmodp(z_crc_t a, z_crc_t b) {
- z_crc_t m, p;
-
- m = (z_crc_t)1 << 31;
- p = 0;
- for (;;) {
- if (a & m) {
- p ^= b;
- if ((a & (m - 1)) == 0)
- break;
- }
- m >>= 1;
- b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
- }
- return p;
-}
-
-/*
- Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
- initialized.
- */
-local z_crc_t x2nmodp(z_off64_t n, unsigned k) {
- z_crc_t p;
-
- p = (z_crc_t)1 << 31; /* x^0 == 1 */
- while (n) {
- if (n & 1)
- p = multmodp(x2n_table[k & 31], p);
- n >>= 1;
- k++;
- }
- return p;
-}
-
-#ifdef DYNAMIC_CRC_TABLE
-/* =========================================================================
- * Build the tables for byte-wise and braided CRC-32 calculations, and a table
- * of powers of x for combining CRC-32s.
- */
-local z_crc_t FAR crc_table[256];
-#ifdef W
- local z_word_t FAR crc_big_table[256];
- local z_crc_t FAR crc_braid_table[W][256];
- local z_word_t FAR crc_braid_big_table[W][256];
- local void braid(z_crc_t [][256], z_word_t [][256], int, int);
-#endif
-#ifdef MAKECRCH
- local void write_table(FILE *, const z_crc_t FAR *, int);
- local void write_table32hi(FILE *, const z_word_t FAR *, int);
- local void write_table64(FILE *, const z_word_t FAR *, int);
-#endif /* MAKECRCH */
-
-/*
- Define a once() function depending on the availability of atomics. If this is
- compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in
- multiple threads, and if atomics are not available, then get_crc_table() must
- be called to initialize the tables and must return before any threads are
- allowed to compute or combine CRCs.
- */
-
-/* Definition of once functionality. */
-typedef struct once_s once_t;
-
-/* Check for the availability of atomics. */
-#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
- !defined(__STDC_NO_ATOMICS__)
-
-#include
-
-/* Structure for once(), which must be initialized with ONCE_INIT. */
-struct once_s {
- atomic_flag begun;
- atomic_int done;
-};
-#define ONCE_INIT {ATOMIC_FLAG_INIT, 0}
-
-/*
- Run the provided init() function exactly once, even if multiple threads
- invoke once() at the same time. The state must be a once_t initialized with
- ONCE_INIT.
- */
-local void once(once_t *state, void (*init)(void)) {
- if (!atomic_load(&state->done)) {
- if (atomic_flag_test_and_set(&state->begun))
- while (!atomic_load(&state->done))
- ;
- else {
- init();
- atomic_store(&state->done, 1);
- }
- }
-}
-
-#else /* no atomics */
-
-/* Structure for once(), which must be initialized with ONCE_INIT. */
-struct once_s {
- volatile int begun;
- volatile int done;
-};
-#define ONCE_INIT {0, 0}
-
-/* Test and set. Alas, not atomic, but tries to minimize the period of
- vulnerability. */
-local int test_and_set(int volatile *flag) {
- int was;
-
- was = *flag;
- *flag = 1;
- return was;
-}
-
-/* Run the provided init() function once. This is not thread-safe. */
-local void once(once_t *state, void (*init)(void)) {
- if (!state->done) {
- if (test_and_set(&state->begun))
- while (!state->done)
- ;
- else {
- init();
- state->done = 1;
- }
- }
-}
-
-#endif
-
-/* State for once(). */
-local once_t made = ONCE_INIT;
-
-/*
- Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
- x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
-
- Polynomials over GF(2) are represented in binary, one bit per coefficient,
- with the lowest powers in the most significant bit. Then adding polynomials
- is just exclusive-or, and multiplying a polynomial by x is a right shift by
- one. If we call the above polynomial p, and represent a byte as the
- polynomial q, also with the lowest power in the most significant bit (so the
- byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,
- where a mod b means the remainder after dividing a by b.
-
- This calculation is done using the shift-register method of multiplying and
- taking the remainder. The register is initialized to zero, and for each
- incoming bit, x^32 is added mod p to the register if the bit is a one (where
- x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x
- (which is shifting right by one and adding x^32 mod p if the bit shifted out
- is a one). We start with the highest power (least significant bit) of q and
- repeat for all eight bits of q.
-
- The table is simply the CRC of all possible eight bit values. This is all the
- information needed to generate CRCs on data a byte at a time for all
- combinations of CRC register values and incoming bytes.
- */
-
-local void make_crc_table(void) {
- unsigned i, j, n;
- z_crc_t p;
-
- /* initialize the CRC of bytes tables */
- for (i = 0; i < 256; i++) {
- p = i;
- for (j = 0; j < 8; j++)
- p = p & 1 ? (p >> 1) ^ POLY : p >> 1;
- crc_table[i] = p;
-#ifdef W
- crc_big_table[i] = byte_swap(p);
-#endif
- }
-
- /* initialize the x^2^n mod p(x) table */
- p = (z_crc_t)1 << 30; /* x^1 */
- x2n_table[0] = p;
- for (n = 1; n < 32; n++)
- x2n_table[n] = p = multmodp(p, p);
-
-#ifdef W
- /* initialize the braiding tables -- needs x2n_table[] */
- braid(crc_braid_table, crc_braid_big_table, N, W);
-#endif
-
-#ifdef MAKECRCH
- {
- /*
- The crc32.h header file contains tables for both 32-bit and 64-bit
- z_word_t's, and so requires a 64-bit type be available. In that case,
- z_word_t must be defined to be 64-bits. This code then also generates
- and writes out the tables for the case that z_word_t is 32 bits.
- */
-#if !defined(W) || W != 8
-# error Need a 64-bit integer type in order to generate crc32.h.
-#endif
- FILE *out;
- int k, n;
- z_crc_t ltl[8][256];
- z_word_t big[8][256];
-
- out = fopen("crc32.h", "w");
- if (out == NULL) return;
-
- /* write out little-endian CRC table to crc32.h */
- fprintf(out,
- "/* crc32.h -- tables for rapid CRC calculation\n"
- " * Generated automatically by crc32.c\n */\n"
- "\n"
- "local const z_crc_t FAR crc_table[] = {\n"
- " ");
- write_table(out, crc_table, 256);
- fprintf(out,
- "};\n");
-
- /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */
- fprintf(out,
- "\n"
- "#ifdef W\n"
- "\n"
- "#if W == 8\n"
- "\n"
- "local const z_word_t FAR crc_big_table[] = {\n"
- " ");
- write_table64(out, crc_big_table, 256);
- fprintf(out,
- "};\n");
-
- /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */
- fprintf(out,
- "\n"
- "#else /* W == 4 */\n"
- "\n"
- "local const z_word_t FAR crc_big_table[] = {\n"
- " ");
- write_table32hi(out, crc_big_table, 256);
- fprintf(out,
- "};\n"
- "\n"
- "#endif\n");
-
- /* write out braid tables for each value of N */
- for (n = 1; n <= 6; n++) {
- fprintf(out,
- "\n"
- "#if N == %d\n", n);
-
- /* compute braid tables for this N and 64-bit word_t */
- braid(ltl, big, n, 8);
-
- /* write out braid tables for 64-bit z_word_t to crc32.h */
- fprintf(out,
- "\n"
- "#if W == 8\n"
- "\n"
- "local const z_crc_t FAR crc_braid_table[][256] = {\n");
- for (k = 0; k < 8; k++) {
- fprintf(out, " {");
- write_table(out, ltl[k], 256);
- fprintf(out, "}%s", k < 7 ? ",\n" : "");
- }
- fprintf(out,
- "};\n"
- "\n"
- "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
- for (k = 0; k < 8; k++) {
- fprintf(out, " {");
- write_table64(out, big[k], 256);
- fprintf(out, "}%s", k < 7 ? ",\n" : "");
- }
- fprintf(out,
- "};\n");
-
- /* compute braid tables for this N and 32-bit word_t */
- braid(ltl, big, n, 4);
-
- /* write out braid tables for 32-bit z_word_t to crc32.h */
- fprintf(out,
- "\n"
- "#else /* W == 4 */\n"
- "\n"
- "local const z_crc_t FAR crc_braid_table[][256] = {\n");
- for (k = 0; k < 4; k++) {
- fprintf(out, " {");
- write_table(out, ltl[k], 256);
- fprintf(out, "}%s", k < 3 ? ",\n" : "");
- }
- fprintf(out,
- "};\n"
- "\n"
- "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
- for (k = 0; k < 4; k++) {
- fprintf(out, " {");
- write_table32hi(out, big[k], 256);
- fprintf(out, "}%s", k < 3 ? ",\n" : "");
- }
- fprintf(out,
- "};\n"
- "\n"
- "#endif\n"
- "\n"
- "#endif\n");
- }
- fprintf(out,
- "\n"
- "#endif\n");
-
- /* write out zeros operator table to crc32.h */
- fprintf(out,
- "\n"
- "local const z_crc_t FAR x2n_table[] = {\n"
- " ");
- write_table(out, x2n_table, 32);
- fprintf(out,
- "};\n");
- fclose(out);
- }
-#endif /* MAKECRCH */
-}
-
-#ifdef MAKECRCH
-
-/*
- Write the 32-bit values in table[0..k-1] to out, five per line in
- hexadecimal separated by commas.
- */
-local void write_table(FILE *out, const z_crc_t FAR *table, int k) {
- int n;
-
- for (n = 0; n < k; n++)
- fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
- (unsigned long)(table[n]),
- n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
-}
-
-/*
- Write the high 32-bits of each value in table[0..k-1] to out, five per line
- in hexadecimal separated by commas.
- */
-local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) {
- int n;
-
- for (n = 0; n < k; n++)
- fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
- (unsigned long)(table[n] >> 32),
- n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
-}
-
-/*
- Write the 64-bit values in table[0..k-1] to out, three per line in
- hexadecimal separated by commas. This assumes that if there is a 64-bit
- type, then there is also a long long integer type, and it is at least 64
- bits. If not, then the type cast and format string can be adjusted
- accordingly.
- */
-local void write_table64(FILE *out, const z_word_t FAR *table, int k) {
- int n;
-
- for (n = 0; n < k; n++)
- fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ",
- (unsigned long long)(table[n]),
- n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", "));
-}
-
-/* Actually do the deed. */
-int main(void) {
- make_crc_table();
- return 0;
-}
-
-#endif /* MAKECRCH */
-
-#ifdef W
-/*
- Generate the little and big-endian braid tables for the given n and z_word_t
- size w. Each array must have room for w blocks of 256 elements.
- */
-local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) {
- int k;
- z_crc_t i, p, q;
- for (k = 0; k < w; k++) {
- p = x2nmodp((n * w + 3 - k) << 3, 0);
- ltl[k][0] = 0;
- big[w - 1 - k][0] = 0;
- for (i = 1; i < 256; i++) {
- ltl[k][i] = q = multmodp(i << 24, p);
- big[w - 1 - k][i] = byte_swap(q);
- }
- }
-}
-#endif
-
-#endif /* DYNAMIC_CRC_TABLE */
-
-/* =========================================================================
- * This function can be used by asm versions of crc32(), and to force the
- * generation of the CRC tables in a threaded application.
- */
-const z_crc_t FAR * ZEXPORT get_crc_table(void) {
-#ifdef DYNAMIC_CRC_TABLE
- once(&made, make_crc_table);
-#endif /* DYNAMIC_CRC_TABLE */
- return (const z_crc_t FAR *)crc_table;
-}
-
-/* =========================================================================
- * Use ARM machine instructions if available. This will compute the CRC about
- * ten times faster than the braided calculation. This code does not check for
- * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will
- * only be defined if the compilation specifies an ARM processor architecture
- * that has the instructions. For example, compiling with -march=armv8.1-a or
- * -march=armv8-a+crc, or -march=native if the compile machine has the crc32
- * instructions.
- */
-#ifdef ARMCRC32
-
-/*
- Constants empirically determined to maximize speed. These values are from
- measurements on a Cortex-A57. Your mileage may vary.
- */
-#define Z_BATCH 3990 /* number of words in a batch */
-#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */
-#define Z_BATCH_MIN 800 /* fewest words in a final batch */
-
-unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
- z_size_t len) {
- z_crc_t val;
- z_word_t crc1, crc2;
- const z_word_t *word;
- z_word_t val0, val1, val2;
- z_size_t last, last2, i;
- z_size_t num;
-
- /* Return initial CRC, if requested. */
- if (buf == Z_NULL) return 0;
-
-#ifdef DYNAMIC_CRC_TABLE
- once(&made, make_crc_table);
-#endif /* DYNAMIC_CRC_TABLE */
-
- /* Pre-condition the CRC */
- crc = (~crc) & 0xffffffff;
-
- /* Compute the CRC up to a word boundary. */
- while (len && ((z_size_t)buf & 7) != 0) {
- len--;
- val = *buf++;
- __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
- }
-
- /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */
- word = (z_word_t const *)buf;
- num = len >> 3;
- len &= 7;
-
- /* Do three interleaved CRCs to realize the throughput of one crc32x
- instruction per cycle. Each CRC is calculated on Z_BATCH words. The
- three CRCs are combined into a single CRC after each set of batches. */
- while (num >= 3 * Z_BATCH) {
- crc1 = 0;
- crc2 = 0;
- for (i = 0; i < Z_BATCH; i++) {
- val0 = word[i];
- val1 = word[i + Z_BATCH];
- val2 = word[i + 2 * Z_BATCH];
- __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
- __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
- __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
- }
- word += 3 * Z_BATCH;
- num -= 3 * Z_BATCH;
- crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;
- crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;
- }
-
- /* Do one last smaller batch with the remaining words, if there are enough
- to pay for the combination of CRCs. */
- last = num / 3;
- if (last >= Z_BATCH_MIN) {
- last2 = last << 1;
- crc1 = 0;
- crc2 = 0;
- for (i = 0; i < last; i++) {
- val0 = word[i];
- val1 = word[i + last];
- val2 = word[i + last2];
- __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
- __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
- __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
- }
- word += 3 * last;
- num -= 3 * last;
- val = x2nmodp(last, 6);
- crc = multmodp(val, crc) ^ crc1;
- crc = multmodp(val, crc) ^ crc2;
- }
-
- /* Compute the CRC on any remaining words. */
- for (i = 0; i < num; i++) {
- val0 = word[i];
- __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
- }
- word += num;
-
- /* Complete the CRC on any remaining bytes. */
- buf = (const unsigned char FAR *)word;
- while (len) {
- len--;
- val = *buf++;
- __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
- }
-
- /* Return the CRC, post-conditioned. */
- return crc ^ 0xffffffff;
-}
-
-#else
-
-#ifdef W
-
-/*
- Return the CRC of the W bytes in the word_t data, taking the
- least-significant byte of the word as the first byte of data, without any pre
- or post conditioning. This is used to combine the CRCs of each braid.
- */
-local z_crc_t crc_word(z_word_t data) {
- int k;
- for (k = 0; k < W; k++)
- data = (data >> 8) ^ crc_table[data & 0xff];
- return (z_crc_t)data;
-}
-
-local z_word_t crc_word_big(z_word_t data) {
- int k;
- for (k = 0; k < W; k++)
- data = (data << 8) ^
- crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
- return data;
-}
-
-#endif
-
-/* ========================================================================= */
-unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
- z_size_t len) {
- /* Return initial CRC, if requested. */
- if (buf == Z_NULL) return 0;
-
-#ifdef DYNAMIC_CRC_TABLE
- once(&made, make_crc_table);
-#endif /* DYNAMIC_CRC_TABLE */
-
- /* Pre-condition the CRC */
- crc = (~crc) & 0xffffffff;
-
-#ifdef W
-
- /* If provided enough bytes, do a braided CRC calculation. */
- if (len >= N * W + W - 1) {
- z_size_t blks;
- z_word_t const *words;
- unsigned endian;
- int k;
-
- /* Compute the CRC up to a z_word_t boundary. */
- while (len && ((z_size_t)buf & (W - 1)) != 0) {
- len--;
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- }
-
- /* Compute the CRC on as many N z_word_t blocks as are available. */
- blks = len / (N * W);
- len -= blks * N * W;
- words = (z_word_t const *)buf;
-
- /* Do endian check at execution time instead of compile time, since ARM
- processors can change the endianness at execution time. If the
- compiler knows what the endianness will be, it can optimize out the
- check and the unused branch. */
- endian = 1;
- if (*(unsigned char *)&endian) {
- /* Little endian. */
-
- z_crc_t crc0;
- z_word_t word0;
-#if N > 1
- z_crc_t crc1;
- z_word_t word1;
-#if N > 2
- z_crc_t crc2;
- z_word_t word2;
-#if N > 3
- z_crc_t crc3;
- z_word_t word3;
-#if N > 4
- z_crc_t crc4;
- z_word_t word4;
-#if N > 5
- z_crc_t crc5;
- z_word_t word5;
-#endif
-#endif
-#endif
-#endif
-#endif
-
- /* Initialize the CRC for each braid. */
- crc0 = crc;
-#if N > 1
- crc1 = 0;
-#if N > 2
- crc2 = 0;
-#if N > 3
- crc3 = 0;
-#if N > 4
- crc4 = 0;
-#if N > 5
- crc5 = 0;
-#endif
-#endif
-#endif
-#endif
-#endif
-
- /*
- Process the first blks-1 blocks, computing the CRCs on each braid
- independently.
- */
- while (--blks) {
- /* Load the word for each braid into registers. */
- word0 = crc0 ^ words[0];
-#if N > 1
- word1 = crc1 ^ words[1];
-#if N > 2
- word2 = crc2 ^ words[2];
-#if N > 3
- word3 = crc3 ^ words[3];
-#if N > 4
- word4 = crc4 ^ words[4];
-#if N > 5
- word5 = crc5 ^ words[5];
-#endif
-#endif
-#endif
-#endif
-#endif
- words += N;
-
- /* Compute and update the CRC for each word. The loop should
- get unrolled. */
- crc0 = crc_braid_table[0][word0 & 0xff];
-#if N > 1
- crc1 = crc_braid_table[0][word1 & 0xff];
-#if N > 2
- crc2 = crc_braid_table[0][word2 & 0xff];
-#if N > 3
- crc3 = crc_braid_table[0][word3 & 0xff];
-#if N > 4
- crc4 = crc_braid_table[0][word4 & 0xff];
-#if N > 5
- crc5 = crc_braid_table[0][word5 & 0xff];
-#endif
-#endif
-#endif
-#endif
-#endif
- for (k = 1; k < W; k++) {
- crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];
-#if N > 1
- crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];
-#if N > 2
- crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];
-#if N > 3
- crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];
-#if N > 4
- crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];
-#if N > 5
- crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];
-#endif
-#endif
-#endif
-#endif
-#endif
- }
- }
-
- /*
- Process the last block, combining the CRCs of the N braids at the
- same time.
- */
- crc = crc_word(crc0 ^ words[0]);
-#if N > 1
- crc = crc_word(crc1 ^ words[1] ^ crc);
-#if N > 2
- crc = crc_word(crc2 ^ words[2] ^ crc);
-#if N > 3
- crc = crc_word(crc3 ^ words[3] ^ crc);
-#if N > 4
- crc = crc_word(crc4 ^ words[4] ^ crc);
-#if N > 5
- crc = crc_word(crc5 ^ words[5] ^ crc);
-#endif
-#endif
-#endif
-#endif
-#endif
- words += N;
- }
- else {
- /* Big endian. */
-
- z_word_t crc0, word0, comb;
-#if N > 1
- z_word_t crc1, word1;
-#if N > 2
- z_word_t crc2, word2;
-#if N > 3
- z_word_t crc3, word3;
-#if N > 4
- z_word_t crc4, word4;
-#if N > 5
- z_word_t crc5, word5;
-#endif
-#endif
-#endif
-#endif
-#endif
-
- /* Initialize the CRC for each braid. */
- crc0 = byte_swap(crc);
-#if N > 1
- crc1 = 0;
-#if N > 2
- crc2 = 0;
-#if N > 3
- crc3 = 0;
-#if N > 4
- crc4 = 0;
-#if N > 5
- crc5 = 0;
-#endif
-#endif
-#endif
-#endif
-#endif
-
- /*
- Process the first blks-1 blocks, computing the CRCs on each braid
- independently.
- */
- while (--blks) {
- /* Load the word for each braid into registers. */
- word0 = crc0 ^ words[0];
-#if N > 1
- word1 = crc1 ^ words[1];
-#if N > 2
- word2 = crc2 ^ words[2];
-#if N > 3
- word3 = crc3 ^ words[3];
-#if N > 4
- word4 = crc4 ^ words[4];
-#if N > 5
- word5 = crc5 ^ words[5];
-#endif
-#endif
-#endif
-#endif
-#endif
- words += N;
-
- /* Compute and update the CRC for each word. The loop should
- get unrolled. */
- crc0 = crc_braid_big_table[0][word0 & 0xff];
-#if N > 1
- crc1 = crc_braid_big_table[0][word1 & 0xff];
-#if N > 2
- crc2 = crc_braid_big_table[0][word2 & 0xff];
-#if N > 3
- crc3 = crc_braid_big_table[0][word3 & 0xff];
-#if N > 4
- crc4 = crc_braid_big_table[0][word4 & 0xff];
-#if N > 5
- crc5 = crc_braid_big_table[0][word5 & 0xff];
-#endif
-#endif
-#endif
-#endif
-#endif
- for (k = 1; k < W; k++) {
- crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];
-#if N > 1
- crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];
-#if N > 2
- crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];
-#if N > 3
- crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];
-#if N > 4
- crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];
-#if N > 5
- crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];
-#endif
-#endif
-#endif
-#endif
-#endif
- }
- }
-
- /*
- Process the last block, combining the CRCs of the N braids at the
- same time.
- */
- comb = crc_word_big(crc0 ^ words[0]);
-#if N > 1
- comb = crc_word_big(crc1 ^ words[1] ^ comb);
-#if N > 2
- comb = crc_word_big(crc2 ^ words[2] ^ comb);
-#if N > 3
- comb = crc_word_big(crc3 ^ words[3] ^ comb);
-#if N > 4
- comb = crc_word_big(crc4 ^ words[4] ^ comb);
-#if N > 5
- comb = crc_word_big(crc5 ^ words[5] ^ comb);
-#endif
-#endif
-#endif
-#endif
-#endif
- words += N;
- crc = byte_swap(comb);
- }
-
- /*
- Update the pointer to the remaining bytes to process.
- */
- buf = (unsigned char const *)words;
- }
-
-#endif /* W */
-
- /* Complete the computation of the CRC on any remaining bytes. */
- while (len >= 8) {
- len -= 8;
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- }
- while (len) {
- len--;
- crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
- }
-
- /* Return the CRC, post-conditioned. */
- return crc ^ 0xffffffff;
-}
-
-#endif
-
-/* ========================================================================= */
-unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf,
- uInt len) {
- return crc32_z(crc, buf, len);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) {
-#ifdef DYNAMIC_CRC_TABLE
- once(&made, make_crc_table);
-#endif /* DYNAMIC_CRC_TABLE */
- return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) {
- return crc32_combine64(crc1, crc2, (z_off64_t)len2);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) {
-#ifdef DYNAMIC_CRC_TABLE
- once(&made, make_crc_table);
-#endif /* DYNAMIC_CRC_TABLE */
- return x2nmodp(len2, 3);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT crc32_combine_gen(z_off_t len2) {
- return crc32_combine_gen64((z_off64_t)len2);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) {
- return multmodp(op, crc1) ^ (crc2 & 0xffffffff);
-}
diff --git a/kernel/src/compress/zlib/deflate.c b/kernel/src/compress/zlib/deflate.c
deleted file mode 100644
index 7958a638c..000000000
--- a/kernel/src/compress/zlib/deflate.c
+++ /dev/null
@@ -1,2135 +0,0 @@
-/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- * ALGORITHM
- *
- * The "deflation" process depends on being able to identify portions
- * of the input text which are identical to earlier input (within a
- * sliding window trailing behind the input currently being processed).
- *
- * The most straightforward technique turns out to be the fastest for
- * most input files: try all possible matches and select the longest.
- * The key feature of this algorithm is that insertions into the string
- * dictionary are very simple and thus fast, and deletions are avoided
- * completely. Insertions are performed at each input character, whereas
- * string matches are performed only when the previous match ends. So it
- * is preferable to spend more time in matches to allow very fast string
- * insertions and avoid deletions. The matching algorithm for small
- * strings is inspired from that of Rabin & Karp. A brute force approach
- * is used to find longer strings when a small match has been found.
- * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
- * (by Leonid Broukhis).
- * A previous version of this file used a more sophisticated algorithm
- * (by Fiala and Greene) which is guaranteed to run in linear amortized
- * time, but has a larger average cost, uses more memory and is patented.
- * However the F&G algorithm may be faster for some highly redundant
- * files if the parameter max_chain_length (described below) is too large.
- *
- * ACKNOWLEDGEMENTS
- *
- * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
- * I found it in 'freeze' written by Leonid Broukhis.
- * Thanks to many people for bug reports and testing.
- *
- * REFERENCES
- *
- * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
- * Available in http://tools.ietf.org/html/rfc1951
- *
- * A description of the Rabin and Karp algorithm is given in the book
- * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
- *
- * Fiala,E.R., and Greene,D.H.
- * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
- *
- */
-
-/* @(#) $Id$ */
-
-#include "../../../include/compress/zlib/deflate.h"
-
-const char deflate_copyright[] =
- " deflate 1.3.0.1 Copyright 1995-2023 Jean-loup Gailly and Mark Adler ";
-/*
- If you use the zlib library in a product, an acknowledgment is welcome
- in the documentation of your product. If for some reason you cannot
- include such an acknowledgment, I would appreciate that you keep this
- copyright string in the executable of your product.
- */
-
-typedef enum {
- need_more, /* block not completed, need more input or more output */
- block_done, /* block flush performed */
- finish_started, /* finish started, need only more output at next deflate */
- finish_done /* finish done, accept no more input or output */
-} block_state;
-
-typedef block_state (*compress_func)(deflate_state *s, int flush);
-/* Compression function. Returns the block state after the call. */
-
-local block_state deflate_stored(deflate_state *s, int flush);
-local block_state deflate_fast(deflate_state *s, int flush);
-#ifndef FASTEST
-local block_state deflate_slow(deflate_state *s, int flush);
-#endif
-local block_state deflate_rle(deflate_state *s, int flush);
-local block_state deflate_huff(deflate_state *s, int flush);
-
-/* ===========================================================================
- * Local data
- */
-
-#define NIL 0
-/* Tail of hash chains */
-
-#ifndef TOO_FAR
-# define TOO_FAR 4096
-#endif
-/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
-
-/* Values for max_lazy_match, good_match and max_chain_length, depending on
- * the desired pack level (0..9). The values given below have been tuned to
- * exclude worst case performance for pathological files. Better values may be
- * found for specific files.
- */
-typedef struct config_s {
- ush good_length; /* reduce lazy search above this match length */
- ush max_lazy; /* do not perform lazy search above this match length */
- ush nice_length; /* quit search above this match length */
- ush max_chain;
- compress_func func;
-} config;
-
-#ifdef FASTEST
-local const config configuration_table[2] = {
-/* good lazy nice chain */
-/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
-/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
-#else
-local const config configuration_table[10] = {
-/* good lazy nice chain */
-/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
-/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
-/* 2 */ {4, 5, 16, 8, deflate_fast},
-/* 3 */ {4, 6, 32, 32, deflate_fast},
-
-/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
-/* 5 */ {8, 16, 32, 32, deflate_slow},
-/* 6 */ {8, 16, 128, 128, deflate_slow},
-/* 7 */ {8, 32, 128, 256, deflate_slow},
-/* 8 */ {32, 128, 258, 1024, deflate_slow},
-/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
-#endif
-
-/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
- * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
- * meaning.
- */
-
-/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
-#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0))
-
-/* ===========================================================================
- * Update a hash value with the given input byte
- * IN assertion: all calls to UPDATE_HASH are made with consecutive input
- * characters, so that a running hash key can be computed from the previous
- * key instead of complete recalculation each time.
- */
-#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)
-
-
-/* ===========================================================================
- * Insert string str in the dictionary and set match_head to the previous head
- * of the hash chain (the most recent string with same hash key). Return
- * the previous length of the hash chain.
- * If this file is compiled with -DFASTEST, the compression level is forced
- * to 1, and no hash chains are maintained.
- * IN assertion: all calls to INSERT_STRING are made with consecutive input
- * characters and the first MIN_MATCH bytes of str are valid (except for
- * the last MIN_MATCH-1 bytes of the input file).
- */
-#ifdef FASTEST
-#define INSERT_STRING(s, str, match_head) \
- (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
- match_head = s->head[s->ins_h], \
- s->head[s->ins_h] = (Pos)(str))
-#else
-#define INSERT_STRING(s, str, match_head) \
- (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
- match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
- s->head[s->ins_h] = (Pos)(str))
-#endif
-
-/* ===========================================================================
- * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
- * prev[] will be initialized on the fly.
- */
-#define CLEAR_HASH(s) \
- do { \
- s->head[s->hash_size - 1] = NIL; \
- zmemzero((Bytef *)s->head, \
- (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \
- } while (0)
-
-/* ===========================================================================
- * Slide the hash table when sliding the window down (could be avoided with 32
- * bit values at the expense of memory usage). We slide even when level == 0 to
- * keep the hash table consistent if we switch back to level > 0 later.
- */
-#if defined(__has_feature)
-# if __has_feature(memory_sanitizer)
- __attribute__((no_sanitize("memory")))
-# endif
-#endif
-local void slide_hash(deflate_state *s) {
- unsigned n, m;
- Posf *p;
- uInt wsize = s->w_size;
-
- n = s->hash_size;
- p = &s->head[n];
- do {
- m = *--p;
- *p = (Pos)(m >= wsize ? m - wsize : NIL);
- } while (--n);
- n = wsize;
-#ifndef FASTEST
- p = &s->prev[n];
- do {
- m = *--p;
- *p = (Pos)(m >= wsize ? m - wsize : NIL);
- /* If n is not on any hash chain, prev[n] is garbage but
- * its value will never be used.
- */
- } while (--n);
-#endif
-}
-
-/* ===========================================================================
- * Read a new buffer from the current input stream, update the adler32
- * and total number of bytes read. All deflate() input goes through
- * this function so some applications may wish to modify it to avoid
- * allocating a large strm->next_in buffer and copying from it.
- * (See also flush_pending()).
- */
-local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) {
- unsigned len = strm->avail_in;
-
- if (len > size) len = size;
- if (len == 0) return 0;
-
- strm->avail_in -= len;
-
- zmemcpy(buf, strm->next_in, len);
- if (strm->state->wrap == 1) {
- strm->adler = adler32(strm->adler, buf, len);
- }
-#ifdef GZIP
- else if (strm->state->wrap == 2) {
- strm->adler = crc32(strm->adler, buf, len);
- }
-#endif
- strm->next_in += len;
- strm->total_in += len;
-
- return len;
-}
-
-/* ===========================================================================
- * Fill the window when the lookahead becomes insufficient.
- * Updates strstart and lookahead.
- *
- * IN assertion: lookahead < MIN_LOOKAHEAD
- * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
- * At least one byte has been read, or avail_in == 0; reads are
- * performed for at least two bytes (required for the zip translate_eol
- * option -- not supported here).
- */
-local void fill_window(deflate_state *s) {
- unsigned n;
- unsigned more; /* Amount of free space at the end of the window. */
- uInt wsize = s->w_size;
-
- Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
-
- do {
- more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
-
- /* Deal with !@#$% 64K limit: */
- if (sizeof(int) <= 2) {
- if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
- more = wsize;
-
- } else if (more == (unsigned)(-1)) {
- /* Very unlikely, but possible on 16 bit machine if
- * strstart == 0 && lookahead == 1 (input done a byte at time)
- */
- more--;
- }
- }
-
- /* If the window is almost full and there is insufficient lookahead,
- * move the upper half to the lower one to make room in the upper half.
- */
- if (s->strstart >= wsize + MAX_DIST(s)) {
-
- zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more);
- s->match_start -= wsize;
- s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
- s->block_start -= (long) wsize;
- if (s->insert > s->strstart)
- s->insert = s->strstart;
- slide_hash(s);
- more += wsize;
- }
- if (s->strm->avail_in == 0) break;
-
- /* If there was no sliding:
- * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
- * more == window_size - lookahead - strstart
- * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
- * => more >= window_size - 2*WSIZE + 2
- * In the BIG_MEM or MMAP case (not yet supported),
- * window_size == input_size + MIN_LOOKAHEAD &&
- * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
- * Otherwise, window_size == 2*WSIZE so more >= 2.
- * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
- */
- Assert(more >= 2, "more < 2");
-
- n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
- s->lookahead += n;
-
- /* Initialize the hash value now that we have some input: */
- if (s->lookahead + s->insert >= MIN_MATCH) {
- uInt str = s->strstart - s->insert;
- s->ins_h = s->window[str];
- UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
-#if MIN_MATCH != 3
- Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
- while (s->insert) {
- UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
-#ifndef FASTEST
- s->prev[str & s->w_mask] = s->head[s->ins_h];
-#endif
- s->head[s->ins_h] = (Pos)str;
- str++;
- s->insert--;
- if (s->lookahead + s->insert < MIN_MATCH)
- break;
- }
- }
- /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
- * but this is not important since only literal bytes will be emitted.
- */
-
- } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
-
- /* If the WIN_INIT bytes after the end of the current data have never been
- * written, then zero those bytes in order to avoid memory check reports of
- * the use of uninitialized (or uninitialised as Julian writes) bytes by
- * the longest match routines. Update the high water mark for the next
- * time through here. WIN_INIT is set to MAX_MATCH since the longest match
- * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
- */
- if (s->high_water < s->window_size) {
- ulg curr = s->strstart + (ulg)(s->lookahead);
- ulg init;
-
- if (s->high_water < curr) {
- /* Previous high water mark below current data -- zero WIN_INIT
- * bytes or up to end of window, whichever is less.
- */
- init = s->window_size - curr;
- if (init > WIN_INIT)
- init = WIN_INIT;
- zmemzero(s->window + curr, (unsigned)init);
- s->high_water = curr + init;
- }
- else if (s->high_water < (ulg)curr + WIN_INIT) {
- /* High water mark at or above current data, but below current data
- * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
- * to end of window, whichever is less.
- */
- init = (ulg)curr + WIN_INIT - s->high_water;
- if (init > s->window_size - s->high_water)
- init = s->window_size - s->high_water;
- zmemzero(s->window + s->high_water, (unsigned)init);
- s->high_water += init;
- }
- }
-
- Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
- "not enough room for search");
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version,
- int stream_size) {
- return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
- Z_DEFAULT_STRATEGY, version, stream_size);
- /* To do: ignore strm->next_in if we use it as window */
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
- int windowBits, int memLevel, int strategy,
- const char *version, int stream_size) {
- deflate_state *s;
- int wrap = 1;
- static const char my_version[] = ZLIB_VERSION;
-
- if (version == Z_NULL || version[0] != my_version[0] ||
- stream_size != sizeof(z_stream)) {
- return Z_VERSION_ERROR;
- }
- if (strm == Z_NULL) return Z_STREAM_ERROR;
-
- strm->msg = Z_NULL;
- if (strm->zalloc == (alloc_func)0) {
-#ifdef Z_SOLO
- return Z_STREAM_ERROR;
-#else
- strm->zalloc = zcalloc;
- strm->opaque = (voidpf)0;
-#endif
- }
- if (strm->zfree == (free_func)0)
-#ifdef Z_SOLO
- return Z_STREAM_ERROR;
-#else
- strm->zfree = zcfree;
-#endif
-
-#ifdef FASTEST
- if (level != 0) level = 1;
-#else
- if (level == Z_DEFAULT_COMPRESSION) level = 6;
-#endif
-
- if (windowBits < 0) { /* suppress zlib wrapper */
- wrap = 0;
- if (windowBits < -15)
- return Z_STREAM_ERROR;
- windowBits = -windowBits;
- }
-#ifdef GZIP
- else if (windowBits > 15) {
- wrap = 2; /* write gzip wrapper instead */
- windowBits -= 16;
- }
-#endif
- if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
- windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
- strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) {
- return Z_STREAM_ERROR;
- }
- if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
- s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
- if (s == Z_NULL) return Z_MEM_ERROR;
- strm->state = (struct internal_state FAR *)s;
- s->strm = strm;
- s->status = INIT_STATE; /* to pass state test in deflateReset() */
-
- s->wrap = wrap;
- s->gzhead = Z_NULL;
- s->w_bits = (uInt)windowBits;
- s->w_size = 1 << s->w_bits;
- s->w_mask = s->w_size - 1;
-
- s->hash_bits = (uInt)memLevel + 7;
- s->hash_size = 1 << s->hash_bits;
- s->hash_mask = s->hash_size - 1;
- s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH);
-
- s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
- s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
- s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
-
- s->high_water = 0; /* nothing written to s->window yet */
-
- s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
-
- /* We overlay pending_buf and sym_buf. This works since the average size
- * for length/distance pairs over any compressed block is assured to be 31
- * bits or less.
- *
- * Analysis: The longest fixed codes are a length code of 8 bits plus 5
- * extra bits, for lengths 131 to 257. The longest fixed distance codes are
- * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
- * possible fixed-codes length/distance pair is then 31 bits total.
- *
- * sym_buf starts one-fourth of the way into pending_buf. So there are
- * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
- * in sym_buf is three bytes -- two for the distance and one for the
- * literal/length. As each symbol is consumed, the pointer to the next
- * sym_buf value to read moves forward three bytes. From that symbol, up to
- * 31 bits are written to pending_buf. The closest the written pending_buf
- * bits gets to the next sym_buf symbol to read is just before the last
- * code is written. At that time, 31*(n - 2) bits have been written, just
- * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at
- * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1
- * symbols are written.) The closest the writing gets to what is unread is
- * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and
- * can range from 128 to 32768.
- *
- * Therefore, at a minimum, there are 142 bits of space between what is
- * written and what is read in the overlain buffers, so the symbols cannot
- * be overwritten by the compressed data. That space is actually 139 bits,
- * due to the three-bit fixed-code block header.
- *
- * That covers the case where either Z_FIXED is specified, forcing fixed
- * codes, or when the use of fixed codes is chosen, because that choice
- * results in a smaller compressed block than dynamic codes. That latter
- * condition then assures that the above analysis also covers all dynamic
- * blocks. A dynamic-code block will only be chosen to be emitted if it has
- * fewer bits than a fixed-code block would for the same set of symbols.
- * Therefore its average symbol length is assured to be less than 31. So
- * the compressed data for a dynamic block also cannot overwrite the
- * symbols from which it is being constructed.
- */
-
-#ifdef LIT_MEM
- s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 5);
-#else
- s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
-#endif
- s->pending_buf_size = (ulg)s->lit_bufsize * 4;
-
- if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
- s->pending_buf == Z_NULL) {
- s->status = FINISH_STATE;
- strm->msg = ERR_MSG(Z_MEM_ERROR);
- deflateEnd (strm);
- return Z_MEM_ERROR;
- }
-#ifdef LIT_MEM
- s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1));
- s->l_buf = s->pending_buf + (s->lit_bufsize << 2);
- s->sym_end = s->lit_bufsize - 1;
-#else
- s->sym_buf = s->pending_buf + s->lit_bufsize;
- s->sym_end = (s->lit_bufsize - 1) * 3;
-#endif
- /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
- * on 16 bit machines and because stored blocks are restricted to
- * 64K-1 bytes.
- */
-
- s->level = level;
- s->strategy = strategy;
- s->method = (Byte)method;
-
- return deflateReset(strm);
-}
-
-/* =========================================================================
- * Check for a valid deflate stream state. Return 0 if ok, 1 if not.
- */
-local int deflateStateCheck(z_streamp strm) {
- deflate_state *s;
- if (strm == Z_NULL ||
- strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
- return 1;
- s = strm->state;
- if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE &&
-#ifdef GZIP
- s->status != GZIP_STATE &&
-#endif
- s->status != EXTRA_STATE &&
- s->status != NAME_STATE &&
- s->status != COMMENT_STATE &&
- s->status != HCRC_STATE &&
- s->status != BUSY_STATE &&
- s->status != FINISH_STATE))
- return 1;
- return 0;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary,
- uInt dictLength) {
- deflate_state *s;
- uInt str, n;
- int wrap;
- unsigned avail;
- z_const unsigned char *next;
-
- if (deflateStateCheck(strm) || dictionary == Z_NULL)
- return Z_STREAM_ERROR;
- s = strm->state;
- wrap = s->wrap;
- if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
- return Z_STREAM_ERROR;
-
- /* when using zlib wrappers, compute Adler-32 for provided dictionary */
- if (wrap == 1)
- strm->adler = adler32(strm->adler, dictionary, dictLength);
- s->wrap = 0; /* avoid computing Adler-32 in read_buf */
-
- /* if dictionary would fill window, just replace the history */
- if (dictLength >= s->w_size) {
- if (wrap == 0) { /* already empty otherwise */
- CLEAR_HASH(s);
- s->strstart = 0;
- s->block_start = 0L;
- s->insert = 0;
- }
- dictionary += dictLength - s->w_size; /* use the tail */
- dictLength = s->w_size;
- }
-
- /* insert dictionary into window and hash */
- avail = strm->avail_in;
- next = strm->next_in;
- strm->avail_in = dictLength;
- strm->next_in = (z_const Bytef *)dictionary;
- fill_window(s);
- while (s->lookahead >= MIN_MATCH) {
- str = s->strstart;
- n = s->lookahead - (MIN_MATCH-1);
- do {
- UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
-#ifndef FASTEST
- s->prev[str & s->w_mask] = s->head[s->ins_h];
-#endif
- s->head[s->ins_h] = (Pos)str;
- str++;
- } while (--n);
- s->strstart = str;
- s->lookahead = MIN_MATCH-1;
- fill_window(s);
- }
- s->strstart += s->lookahead;
- s->block_start = (long)s->strstart;
- s->insert = s->lookahead;
- s->lookahead = 0;
- s->match_length = s->prev_length = MIN_MATCH-1;
- s->match_available = 0;
- strm->next_in = next;
- strm->avail_in = avail;
- s->wrap = wrap;
- return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary,
- uInt *dictLength) {
- deflate_state *s;
- uInt len;
-
- if (deflateStateCheck(strm))
- return Z_STREAM_ERROR;
- s = strm->state;
- len = s->strstart + s->lookahead;
- if (len > s->w_size)
- len = s->w_size;
- if (dictionary != Z_NULL && len)
- zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len);
- if (dictLength != Z_NULL)
- *dictLength = len;
- return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateResetKeep(z_streamp strm) {
- deflate_state *s;
-
- if (deflateStateCheck(strm)) {
- return Z_STREAM_ERROR;
- }
-
- strm->total_in = strm->total_out = 0;
- strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
- strm->data_type = Z_UNKNOWN;
-
- s = (deflate_state *)strm->state;
- s->pending = 0;
- s->pending_out = s->pending_buf;
-
- if (s->wrap < 0) {
- s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
- }
- s->status =
-#ifdef GZIP
- s->wrap == 2 ? GZIP_STATE :
-#endif
- INIT_STATE;
- strm->adler =
-#ifdef GZIP
- s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
-#endif
- adler32(0L, Z_NULL, 0);
- s->last_flush = -2;
-
- _tr_init(s);
-
- return Z_OK;
-}
-
-/* ===========================================================================
- * Initialize the "longest match" routines for a new zlib stream
- */
-local void lm_init(deflate_state *s) {
- s->window_size = (ulg)2L*s->w_size;
-
- CLEAR_HASH(s);
-
- /* Set the default configuration parameters:
- */
- s->max_lazy_match = configuration_table[s->level].max_lazy;
- s->good_match = configuration_table[s->level].good_length;
- s->nice_match = configuration_table[s->level].nice_length;
- s->max_chain_length = configuration_table[s->level].max_chain;
-
- s->strstart = 0;
- s->block_start = 0L;
- s->lookahead = 0;
- s->insert = 0;
- s->match_length = s->prev_length = MIN_MATCH-1;
- s->match_available = 0;
- s->ins_h = 0;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateReset(z_streamp strm) {
- int ret;
-
- ret = deflateResetKeep(strm);
- if (ret == Z_OK)
- lm_init(strm->state);
- return ret;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) {
- if (deflateStateCheck(strm) || strm->state->wrap != 2)
- return Z_STREAM_ERROR;
- strm->state->gzhead = head;
- return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) {
- if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
- if (pending != Z_NULL)
- *pending = strm->state->pending;
- if (bits != Z_NULL)
- *bits = strm->state->bi_valid;
- return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) {
- deflate_state *s;
- int put;
-
- if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
- s = strm->state;
-#ifdef LIT_MEM
- if (bits < 0 || bits > 16 ||
- (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3))
- return Z_BUF_ERROR;
-#else
- if (bits < 0 || bits > 16 ||
- s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
- return Z_BUF_ERROR;
-#endif
- do {
- put = Buf_size - s->bi_valid;
- if (put > bits)
- put = bits;
- s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
- s->bi_valid += put;
- _tr_flush_bits(s);
- value >>= put;
- bits -= put;
- } while (bits);
- return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) {
- deflate_state *s;
- compress_func func;
-
- if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
- s = strm->state;
-
-#ifdef FASTEST
- if (level != 0) level = 1;
-#else
- if (level == Z_DEFAULT_COMPRESSION) level = 6;
-#endif
- if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
- return Z_STREAM_ERROR;
- }
- func = configuration_table[s->level].func;
-
- if ((strategy != s->strategy || func != configuration_table[level].func) &&
- s->last_flush != -2) {
- /* Flush the last buffer: */
- int err = deflate(strm, Z_BLOCK);
- if (err == Z_STREAM_ERROR)
- return err;
- if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
- return Z_BUF_ERROR;
- }
- if (s->level != level) {
- if (s->level == 0 && s->matches != 0) {
- if (s->matches == 1)
- slide_hash(s);
- else
- CLEAR_HASH(s);
- s->matches = 0;
- }
- s->level = level;
- s->max_lazy_match = configuration_table[level].max_lazy;
- s->good_match = configuration_table[level].good_length;
- s->nice_match = configuration_table[level].nice_length;
- s->max_chain_length = configuration_table[level].max_chain;
- }
- s->strategy = strategy;
- return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy,
- int nice_length, int max_chain) {
- deflate_state *s;
-
- if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
- s = strm->state;
- s->good_match = (uInt)good_length;
- s->max_lazy_match = (uInt)max_lazy;
- s->nice_match = nice_length;
- s->max_chain_length = (uInt)max_chain;
- return Z_OK;
-}
-
-/* =========================================================================
- * For the default windowBits of 15 and memLevel of 8, this function returns a
- * close to exact, as well as small, upper bound on the compressed size. This
- * is an expansion of ~0.03%, plus a small constant.
- *
- * For any setting other than those defaults for windowBits and memLevel, one
- * of two worst case bounds is returned. This is at most an expansion of ~4% or
- * ~13%, plus a small constant.
- *
- * Both the 0.03% and 4% derive from the overhead of stored blocks. The first
- * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second
- * is for stored blocks of 127 bytes (the worst case memLevel == 1). The
- * expansion results from five bytes of header for each stored block.
- *
- * The larger expansion of 13% results from a window size less than or equal to
- * the symbols buffer size (windowBits <= memLevel + 7). In that case some of
- * the data being compressed may have slid out of the sliding window, impeding
- * a stored block from being emitted. Then the only choice is a fixed or
- * dynamic block, where a fixed block limits the maximum expansion to 9 bits
- * per 8-bit byte, plus 10 bits for every block. The smallest block size for
- * which this can occur is 255 (memLevel == 2).
- *
- * Shifts are used to approximate divisions, for speed.
- */
-uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) {
- deflate_state *s;
- uLong fixedlen, storelen, wraplen;
-
- /* upper bound for fixed blocks with 9-bit literals and length 255
- (memLevel == 2, which is the lowest that may not use stored blocks) --
- ~13% overhead plus a small constant */
- fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +
- (sourceLen >> 9) + 4;
-
- /* upper bound for stored blocks with length 127 (memLevel == 1) --
- ~4% overhead plus a small constant */
- storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) +
- (sourceLen >> 11) + 7;
-
- /* if can't get parameters, return larger bound plus a zlib wrapper */
- if (deflateStateCheck(strm))
- return (fixedlen > storelen ? fixedlen : storelen) + 6;
-
- /* compute wrapper length */
- s = strm->state;
- switch (s->wrap) {
- case 0: /* raw deflate */
- wraplen = 0;
- break;
- case 1: /* zlib wrapper */
- wraplen = 6 + (s->strstart ? 4 : 0);
- break;
-#ifdef GZIP
- case 2: /* gzip wrapper */
- wraplen = 18;
- if (s->gzhead != Z_NULL) { /* user-supplied gzip header */
- Bytef *str;
- if (s->gzhead->extra != Z_NULL)
- wraplen += 2 + s->gzhead->extra_len;
- str = s->gzhead->name;
- if (str != Z_NULL)
- do {
- wraplen++;
- } while (*str++);
- str = s->gzhead->comment;
- if (str != Z_NULL)
- do {
- wraplen++;
- } while (*str++);
- if (s->gzhead->hcrc)
- wraplen += 2;
- }
- break;
-#endif
- default: /* for compiler happiness */
- wraplen = 6;
- }
-
- /* if not default parameters, return one of the conservative bounds */
- if (s->w_bits != 15 || s->hash_bits != 8 + 7)
- return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) +
- wraplen;
-
- /* default settings: return tight bound for that case -- ~0.03% overhead
- plus a small constant */
- return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
- (sourceLen >> 25) + 13 - 6 + wraplen;
-}
-
-/* =========================================================================
- * Put a short in the pending buffer. The 16-bit value is put in MSB order.
- * IN assertion: the stream state is correct and there is enough room in
- * pending_buf.
- */
-local void putShortMSB(deflate_state *s, uInt b) {
- put_byte(s, (Byte)(b >> 8));
- put_byte(s, (Byte)(b & 0xff));
-}
-
-/* =========================================================================
- * Flush as much pending output as possible. All deflate() output, except for
- * some deflate_stored() output, goes through this function so some
- * applications may wish to modify it to avoid allocating a large
- * strm->next_out buffer and copying into it. (See also read_buf()).
- */
-local void flush_pending(z_streamp strm) {
- unsigned len;
- deflate_state *s = strm->state;
-
- _tr_flush_bits(s);
- len = s->pending;
- if (len > strm->avail_out) len = strm->avail_out;
- if (len == 0) return;
-
- zmemcpy(strm->next_out, s->pending_out, len);
- strm->next_out += len;
- s->pending_out += len;
- strm->total_out += len;
- strm->avail_out -= len;
- s->pending -= len;
- if (s->pending == 0) {
- s->pending_out = s->pending_buf;
- }
-}
-
-/* ===========================================================================
- * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1].
- */
-#define HCRC_UPDATE(beg) \
- do { \
- if (s->gzhead->hcrc && s->pending > (beg)) \
- strm->adler = crc32(strm->adler, s->pending_buf + (beg), \
- s->pending - (beg)); \
- } while (0)
-
-/* ========================================================================= */
-int ZEXPORT deflate(z_streamp strm, int flush) {
- int old_flush; /* value of flush param for previous deflate call */
- deflate_state *s;
-
- if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {
- return Z_STREAM_ERROR;
- }
- s = strm->state;
-
- if (strm->next_out == Z_NULL ||
- (strm->avail_in != 0 && strm->next_in == Z_NULL) ||
- (s->status == FINISH_STATE && flush != Z_FINISH)) {
- ERR_RETURN(strm, Z_STREAM_ERROR);
- }
- if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
-
- old_flush = s->last_flush;
- s->last_flush = flush;
-
- /* Flush as much pending output as possible */
- if (s->pending != 0) {
- flush_pending(strm);
- if (strm->avail_out == 0) {
- /* Since avail_out is 0, deflate will be called again with
- * more output space, but possibly with both pending and
- * avail_in equal to zero. There won't be anything to do,
- * but this is not an error situation so make sure we
- * return OK instead of BUF_ERROR at next call of deflate:
- */
- s->last_flush = -1;
- return Z_OK;
- }
-
- /* Make sure there is something to do and avoid duplicate consecutive
- * flushes. For repeated and useless calls with Z_FINISH, we keep
- * returning Z_STREAM_END instead of Z_BUF_ERROR.
- */
- } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
- flush != Z_FINISH) {
- ERR_RETURN(strm, Z_BUF_ERROR);
- }
-
- /* User must not provide more input after the first FINISH: */
- if (s->status == FINISH_STATE && strm->avail_in != 0) {
- ERR_RETURN(strm, Z_BUF_ERROR);
- }
-
- /* Write the header */
- if (s->status == INIT_STATE && s->wrap == 0)
- s->status = BUSY_STATE;
- if (s->status == INIT_STATE) {
- /* zlib header */
- uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8;
- uInt level_flags;
-
- if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
- level_flags = 0;
- else if (s->level < 6)
- level_flags = 1;
- else if (s->level == 6)
- level_flags = 2;
- else
- level_flags = 3;
- header |= (level_flags << 6);
- if (s->strstart != 0) header |= PRESET_DICT;
- header += 31 - (header % 31);
-
- putShortMSB(s, header);
-
- /* Save the adler32 of the preset dictionary: */
- if (s->strstart != 0) {
- putShortMSB(s, (uInt)(strm->adler >> 16));
- putShortMSB(s, (uInt)(strm->adler & 0xffff));
- }
- strm->adler = adler32(0L, Z_NULL, 0);
- s->status = BUSY_STATE;
-
- /* Compression must start with an empty pending buffer */
- flush_pending(strm);
- if (s->pending != 0) {
- s->last_flush = -1;
- return Z_OK;
- }
- }
-#ifdef GZIP
- if (s->status == GZIP_STATE) {
- /* gzip header */
- strm->adler = crc32(0L, Z_NULL, 0);
- put_byte(s, 31);
- put_byte(s, 139);
- put_byte(s, 8);
- if (s->gzhead == Z_NULL) {
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, s->level == 9 ? 2 :
- (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
- 4 : 0));
- put_byte(s, OS_CODE);
- s->status = BUSY_STATE;
-
- /* Compression must start with an empty pending buffer */
- flush_pending(strm);
- if (s->pending != 0) {
- s->last_flush = -1;
- return Z_OK;
- }
- }
- else {
- put_byte(s, (s->gzhead->text ? 1 : 0) +
- (s->gzhead->hcrc ? 2 : 0) +
- (s->gzhead->extra == Z_NULL ? 0 : 4) +
- (s->gzhead->name == Z_NULL ? 0 : 8) +
- (s->gzhead->comment == Z_NULL ? 0 : 16)
- );
- put_byte(s, (Byte)(s->gzhead->time & 0xff));
- put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
- put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
- put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
- put_byte(s, s->level == 9 ? 2 :
- (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
- 4 : 0));
- put_byte(s, s->gzhead->os & 0xff);
- if (s->gzhead->extra != Z_NULL) {
- put_byte(s, s->gzhead->extra_len & 0xff);
- put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
- }
- if (s->gzhead->hcrc)
- strm->adler = crc32(strm->adler, s->pending_buf,
- s->pending);
- s->gzindex = 0;
- s->status = EXTRA_STATE;
- }
- }
- if (s->status == EXTRA_STATE) {
- if (s->gzhead->extra != Z_NULL) {
- ulg beg = s->pending; /* start of bytes to update crc */
- uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex;
- while (s->pending + left > s->pending_buf_size) {
- uInt copy = s->pending_buf_size - s->pending;
- zmemcpy(s->pending_buf + s->pending,
- s->gzhead->extra + s->gzindex, copy);
- s->pending = s->pending_buf_size;
- HCRC_UPDATE(beg);
- s->gzindex += copy;
- flush_pending(strm);
- if (s->pending != 0) {
- s->last_flush = -1;
- return Z_OK;
- }
- beg = 0;
- left -= copy;
- }
- zmemcpy(s->pending_buf + s->pending,
- s->gzhead->extra + s->gzindex, left);
- s->pending += left;
- HCRC_UPDATE(beg);
- s->gzindex = 0;
- }
- s->status = NAME_STATE;
- }
- if (s->status == NAME_STATE) {
- if (s->gzhead->name != Z_NULL) {
- ulg beg = s->pending; /* start of bytes to update crc */
- int val;
- do {
- if (s->pending == s->pending_buf_size) {
- HCRC_UPDATE(beg);
- flush_pending(strm);
- if (s->pending != 0) {
- s->last_flush = -1;
- return Z_OK;
- }
- beg = 0;
- }
- val = s->gzhead->name[s->gzindex++];
- put_byte(s, val);
- } while (val != 0);
- HCRC_UPDATE(beg);
- s->gzindex = 0;
- }
- s->status = COMMENT_STATE;
- }
- if (s->status == COMMENT_STATE) {
- if (s->gzhead->comment != Z_NULL) {
- ulg beg = s->pending; /* start of bytes to update crc */
- int val;
- do {
- if (s->pending == s->pending_buf_size) {
- HCRC_UPDATE(beg);
- flush_pending(strm);
- if (s->pending != 0) {
- s->last_flush = -1;
- return Z_OK;
- }
- beg = 0;
- }
- val = s->gzhead->comment[s->gzindex++];
- put_byte(s, val);
- } while (val != 0);
- HCRC_UPDATE(beg);
- }
- s->status = HCRC_STATE;
- }
- if (s->status == HCRC_STATE) {
- if (s->gzhead->hcrc) {
- if (s->pending + 2 > s->pending_buf_size) {
- flush_pending(strm);
- if (s->pending != 0) {
- s->last_flush = -1;
- return Z_OK;
- }
- }
- put_byte(s, (Byte)(strm->adler & 0xff));
- put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
- strm->adler = crc32(0L, Z_NULL, 0);
- }
- s->status = BUSY_STATE;
-
- /* Compression must start with an empty pending buffer */
- flush_pending(strm);
- if (s->pending != 0) {
- s->last_flush = -1;
- return Z_OK;
- }
- }
-#endif
-
- /* Start a new block or continue the current one.
- */
- if (strm->avail_in != 0 || s->lookahead != 0 ||
- (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
- block_state bstate;
-
- bstate = s->level == 0 ? deflate_stored(s, flush) :
- s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
- s->strategy == Z_RLE ? deflate_rle(s, flush) :
- (*(configuration_table[s->level].func))(s, flush);
-
- if (bstate == finish_started || bstate == finish_done) {
- s->status = FINISH_STATE;
- }
- if (bstate == need_more || bstate == finish_started) {
- if (strm->avail_out == 0) {
- s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
- }
- return Z_OK;
- /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
- * of deflate should use the same flush parameter to make sure
- * that the flush is complete. So we don't have to output an
- * empty block here, this will be done at next call. This also
- * ensures that for a very small output buffer, we emit at most
- * one empty block.
- */
- }
- if (bstate == block_done) {
- if (flush == Z_PARTIAL_FLUSH) {
- _tr_align(s);
- } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
- _tr_stored_block(s, (char*)0, 0L, 0);
- /* For a full flush, this empty block will be recognized
- * as a special marker by inflate_sync().
- */
- if (flush == Z_FULL_FLUSH) {
- CLEAR_HASH(s); /* forget history */
- if (s->lookahead == 0) {
- s->strstart = 0;
- s->block_start = 0L;
- s->insert = 0;
- }
- }
- }
- flush_pending(strm);
- if (strm->avail_out == 0) {
- s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
- return Z_OK;
- }
- }
- }
-
- if (flush != Z_FINISH) return Z_OK;
- if (s->wrap <= 0) return Z_STREAM_END;
-
- /* Write the trailer */
-#ifdef GZIP
- if (s->wrap == 2) {
- put_byte(s, (Byte)(strm->adler & 0xff));
- put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
- put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
- put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
- put_byte(s, (Byte)(strm->total_in & 0xff));
- put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
- put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
- put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
- }
- else
-#endif
- {
- putShortMSB(s, (uInt)(strm->adler >> 16));
- putShortMSB(s, (uInt)(strm->adler & 0xffff));
- }
- flush_pending(strm);
- /* If avail_out is zero, the application will call deflate again
- * to flush the rest.
- */
- if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
- return s->pending != 0 ? Z_OK : Z_STREAM_END;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateEnd(z_streamp strm) {
- int status;
-
- if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
-
- status = strm->state->status;
-
- /* Deallocate in reverse order of allocations: */
- TRY_FREE(strm, strm->state->pending_buf);
- TRY_FREE(strm, strm->state->head);
- TRY_FREE(strm, strm->state->prev);
- TRY_FREE(strm, strm->state->window);
-
- ZFREE(strm, strm->state);
- strm->state = Z_NULL;
-
- return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
-}
-
-/* =========================================================================
- * Copy the source state to the destination state.
- * To simplify the source, this is not supported for 16-bit MSDOS (which
- * doesn't have enough memory anyway to duplicate compression states).
- */
-int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
-#ifdef MAXSEG_64K
- (void)dest;
- (void)source;
- return Z_STREAM_ERROR;
-#else
- deflate_state *ds;
- deflate_state *ss;
-
-
- if (deflateStateCheck(source) || dest == Z_NULL) {
- return Z_STREAM_ERROR;
- }
-
- ss = source->state;
-
- zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
-
- ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
- if (ds == Z_NULL) return Z_MEM_ERROR;
- dest->state = (struct internal_state FAR *) ds;
- zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
- ds->strm = dest;
-
- ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
- ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
- ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
- ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
-
- if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
- ds->pending_buf == Z_NULL) {
- deflateEnd (dest);
- return Z_MEM_ERROR;
- }
- /* following zmemcpy do not work for 16-bit MSDOS */
- zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
- zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
- zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
- zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
-
- ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
-#ifdef LIT_MEM
- ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1));
- ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2);
-#else
- ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
-#endif
-
- ds->l_desc.dyn_tree = ds->dyn_ltree;
- ds->d_desc.dyn_tree = ds->dyn_dtree;
- ds->bl_desc.dyn_tree = ds->bl_tree;
-
- return Z_OK;
-#endif /* MAXSEG_64K */
-}
-
-#ifndef FASTEST
-/* ===========================================================================
- * Set match_start to the longest match starting at the given string and
- * return its length. Matches shorter or equal to prev_length are discarded,
- * in which case the result is equal to prev_length and match_start is
- * garbage.
- * IN assertions: cur_match is the head of the hash chain for the current
- * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
- * OUT assertion: the match length is not greater than s->lookahead.
- */
-local uInt longest_match(deflate_state *s, IPos cur_match) {
- unsigned chain_length = s->max_chain_length;/* max hash chain length */
- register Bytef *scan = s->window + s->strstart; /* current string */
- register Bytef *match; /* matched string */
- register int len; /* length of current match */
- int best_len = (int)s->prev_length; /* best match length so far */
- int nice_match = s->nice_match; /* stop if match long enough */
- IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
- s->strstart - (IPos)MAX_DIST(s) : NIL;
- /* Stop when cur_match becomes <= limit. To simplify the code,
- * we prevent matches with the string of window index 0.
- */
- Posf *prev = s->prev;
- uInt wmask = s->w_mask;
-
-#ifdef UNALIGNED_OK
- /* Compare two bytes at a time. Note: this is not always beneficial.
- * Try with and without -DUNALIGNED_OK to check.
- */
- register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
- register ush scan_start = *(ushf*)scan;
- register ush scan_end = *(ushf*)(scan + best_len - 1);
-#else
- register Bytef *strend = s->window + s->strstart + MAX_MATCH;
- register Byte scan_end1 = scan[best_len - 1];
- register Byte scan_end = scan[best_len];
-#endif
-
- /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
- * It is easy to get rid of this optimization if necessary.
- */
- Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
- /* Do not waste too much time if we already have a good match: */
- if (s->prev_length >= s->good_match) {
- chain_length >>= 2;
- }
- /* Do not look for matches beyond the end of the input. This is necessary
- * to make deflate deterministic.
- */
- if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;
-
- Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
- "need lookahead");
-
- do {
- Assert(cur_match < s->strstart, "no future");
- match = s->window + cur_match;
-
- /* Skip to next match if the match length cannot increase
- * or if the match length is less than 2. Note that the checks below
- * for insufficient lookahead only occur occasionally for performance
- * reasons. Therefore uninitialized memory will be accessed, and
- * conditional jumps will be made that depend on those values.
- * However the length of the match is limited to the lookahead, so
- * the output of deflate is not affected by the uninitialized values.
- */
-#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
- /* This code assumes sizeof(unsigned short) == 2. Do not use
- * UNALIGNED_OK if your compiler uses a different size.
- */
- if (*(ushf*)(match + best_len - 1) != scan_end ||
- *(ushf*)match != scan_start) continue;
-
- /* It is not necessary to compare scan[2] and match[2] since they are
- * always equal when the other bytes match, given that the hash keys
- * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
- * strstart + 3, + 5, up to strstart + 257. We check for insufficient
- * lookahead only every 4th comparison; the 128th check will be made
- * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is
- * necessary to put more guard bytes at the end of the window, or
- * to check more often for insufficient lookahead.
- */
- Assert(scan[2] == match[2], "scan[2]?");
- scan++, match++;
- do {
- } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
- *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
- *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
- *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
- scan < strend);
- /* The funny "do {}" generates better code on most compilers */
-
- /* Here, scan <= window + strstart + 257 */
- Assert(scan <= s->window + (unsigned)(s->window_size - 1),
- "wild scan");
- if (*scan == *match) scan++;
-
- len = (MAX_MATCH - 1) - (int)(strend - scan);
- scan = strend - (MAX_MATCH-1);
-
-#else /* UNALIGNED_OK */
-
- if (match[best_len] != scan_end ||
- match[best_len - 1] != scan_end1 ||
- *match != *scan ||
- *++match != scan[1]) continue;
-
- /* The check at best_len - 1 can be removed because it will be made
- * again later. (This heuristic is not always a win.)
- * It is not necessary to compare scan[2] and match[2] since they
- * are always equal when the other bytes match, given that
- * the hash keys are equal and that HASH_BITS >= 8.
- */
- scan += 2, match++;
- Assert(*scan == *match, "match[2]?");
-
- /* We check for insufficient lookahead only every 8th comparison;
- * the 256th check will be made at strstart + 258.
- */
- do {
- } while (*++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- scan < strend);
-
- Assert(scan <= s->window + (unsigned)(s->window_size - 1),
- "wild scan");
-
- len = MAX_MATCH - (int)(strend - scan);
- scan = strend - MAX_MATCH;
-
-#endif /* UNALIGNED_OK */
-
- if (len > best_len) {
- s->match_start = cur_match;
- best_len = len;
- if (len >= nice_match) break;
-#ifdef UNALIGNED_OK
- scan_end = *(ushf*)(scan + best_len - 1);
-#else
- scan_end1 = scan[best_len - 1];
- scan_end = scan[best_len];
-#endif
- }
- } while ((cur_match = prev[cur_match & wmask]) > limit
- && --chain_length != 0);
-
- if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
- return s->lookahead;
-}
-
-#else /* FASTEST */
-
-/* ---------------------------------------------------------------------------
- * Optimized version for FASTEST only
- */
-local uInt longest_match(deflate_state *s, IPos cur_match) {
- register Bytef *scan = s->window + s->strstart; /* current string */
- register Bytef *match; /* matched string */
- register int len; /* length of current match */
- register Bytef *strend = s->window + s->strstart + MAX_MATCH;
-
- /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
- * It is easy to get rid of this optimization if necessary.
- */
- Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
- Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
- "need lookahead");
-
- Assert(cur_match < s->strstart, "no future");
-
- match = s->window + cur_match;
-
- /* Return failure if the match length is less than 2:
- */
- if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
-
- /* The check at best_len - 1 can be removed because it will be made
- * again later. (This heuristic is not always a win.)
- * It is not necessary to compare scan[2] and match[2] since they
- * are always equal when the other bytes match, given that
- * the hash keys are equal and that HASH_BITS >= 8.
- */
- scan += 2, match += 2;
- Assert(*scan == *match, "match[2]?");
-
- /* We check for insufficient lookahead only every 8th comparison;
- * the 256th check will be made at strstart + 258.
- */
- do {
- } while (*++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- scan < strend);
-
- Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan");
-
- len = MAX_MATCH - (int)(strend - scan);
-
- if (len < MIN_MATCH) return MIN_MATCH - 1;
-
- s->match_start = cur_match;
- return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
-}
-
-#endif /* FASTEST */
-
-#ifdef ZLIB_DEBUG
-
-#define EQUAL 0
-/* result of memcmp for equal strings */
-
-/* ===========================================================================
- * Check that the match at match_start is indeed a match.
- */
-local void check_match(deflate_state *s, IPos start, IPos match, int length) {
- /* check that the match is indeed a match */
- if (zmemcmp(s->window + match,
- s->window + start, length) != EQUAL) {
- fprintf(stderr, " start %u, match %u, length %d\n",
- start, match, length);
- do {
- fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
- } while (--length != 0);
- z_error("invalid match");
- }
- if (z_verbose > 1) {
- fprintf(stderr,"\\[%d,%d]", start - match, length);
- do { putc(s->window[start++], stderr); } while (--length != 0);
- }
-}
-#else
-# define check_match(s, start, match, length)
-#endif /* ZLIB_DEBUG */
-
-/* ===========================================================================
- * Flush the current block, with given end-of-file flag.
- * IN assertion: strstart is set to the end of the current match.
- */
-#define FLUSH_BLOCK_ONLY(s, last) { \
- _tr_flush_block(s, (s->block_start >= 0L ? \
- (charf *)&s->window[(unsigned)s->block_start] : \
- (charf *)Z_NULL), \
- (ulg)((long)s->strstart - s->block_start), \
- (last)); \
- s->block_start = s->strstart; \
- flush_pending(s->strm); \
- Tracev((stderr,"[FLUSH]")); \
-}
-
-/* Same but force premature exit if necessary. */
-#define FLUSH_BLOCK(s, last) { \
- FLUSH_BLOCK_ONLY(s, last); \
- if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
-}
-
-/* Maximum stored block length in deflate format (not including header). */
-#define MAX_STORED 65535
-
-/* Minimum of a and b. */
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
-/* ===========================================================================
- * Copy without compression as much as possible from the input stream, return
- * the current block state.
- *
- * In case deflateParams() is used to later switch to a non-zero compression
- * level, s->matches (otherwise unused when storing) keeps track of the number
- * of hash table slides to perform. If s->matches is 1, then one hash table
- * slide will be done when switching. If s->matches is 2, the maximum value
- * allowed here, then the hash table will be cleared, since two or more slides
- * is the same as a clear.
- *
- * deflate_stored() is written to minimize the number of times an input byte is
- * copied. It is most efficient with large input and output buffers, which
- * maximizes the opportunities to have a single copy from next_in to next_out.
- */
-local block_state deflate_stored(deflate_state *s, int flush) {
- /* Smallest worthy block size when not flushing or finishing. By default
- * this is 32K. This can be as small as 507 bytes for memLevel == 1. For
- * large input and output buffers, the stored block size will be larger.
- */
- unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size);
-
- /* Copy as many min_block or larger stored blocks directly to next_out as
- * possible. If flushing, copy the remaining available input to next_out as
- * stored blocks, if there is enough space.
- */
- unsigned len, left, have, last = 0;
- unsigned used = s->strm->avail_in;
- do {
- /* Set len to the maximum size block that we can copy directly with the
- * available input data and output space. Set left to how much of that
- * would be copied from what's left in the window.
- */
- len = MAX_STORED; /* maximum deflate stored block length */
- have = (s->bi_valid + 42) >> 3; /* number of header bytes */
- if (s->strm->avail_out < have) /* need room for header */
- break;
- /* maximum stored block length that will fit in avail_out: */
- have = s->strm->avail_out - have;
- left = s->strstart - s->block_start; /* bytes left in window */
- if (len > (ulg)left + s->strm->avail_in)
- len = left + s->strm->avail_in; /* limit len to the input */
- if (len > have)
- len = have; /* limit len to the output */
-
- /* If the stored block would be less than min_block in length, or if
- * unable to copy all of the available input when flushing, then try
- * copying to the window and the pending buffer instead. Also don't
- * write an empty block when flushing -- deflate() does that.
- */
- if (len < min_block && ((len == 0 && flush != Z_FINISH) ||
- flush == Z_NO_FLUSH ||
- len != left + s->strm->avail_in))
- break;
-
- /* Make a dummy stored block in pending to get the header bytes,
- * including any pending bits. This also updates the debugging counts.
- */
- last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0;
- _tr_stored_block(s, (char *)0, 0L, last);
-
- /* Replace the lengths in the dummy stored block with len. */
- s->pending_buf[s->pending - 4] = len;
- s->pending_buf[s->pending - 3] = len >> 8;
- s->pending_buf[s->pending - 2] = ~len;
- s->pending_buf[s->pending - 1] = ~len >> 8;
-
- /* Write the stored block header bytes. */
- flush_pending(s->strm);
-
-#ifdef ZLIB_DEBUG
- /* Update debugging counts for the data about to be copied. */
- s->compressed_len += len << 3;
- s->bits_sent += len << 3;
-#endif
-
- /* Copy uncompressed bytes from the window to next_out. */
- if (left) {
- if (left > len)
- left = len;
- zmemcpy(s->strm->next_out, s->window + s->block_start, left);
- s->strm->next_out += left;
- s->strm->avail_out -= left;
- s->strm->total_out += left;
- s->block_start += left;
- len -= left;
- }
-
- /* Copy uncompressed bytes directly from next_in to next_out, updating
- * the check value.
- */
- if (len) {
- read_buf(s->strm, s->strm->next_out, len);
- s->strm->next_out += len;
- s->strm->avail_out -= len;
- s->strm->total_out += len;
- }
- } while (last == 0);
-
- /* Update the sliding window with the last s->w_size bytes of the copied
- * data, or append all of the copied data to the existing window if less
- * than s->w_size bytes were copied. Also update the number of bytes to
- * insert in the hash tables, in the event that deflateParams() switches to
- * a non-zero compression level.
- */
- used -= s->strm->avail_in; /* number of input bytes directly copied */
- if (used) {
- /* If any input was used, then no unused input remains in the window,
- * therefore s->block_start == s->strstart.
- */
- if (used >= s->w_size) { /* supplant the previous history */
- s->matches = 2; /* clear hash */
- zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
- s->strstart = s->w_size;
- s->insert = s->strstart;
- }
- else {
- if (s->window_size - s->strstart <= used) {
- /* Slide the window down. */
- s->strstart -= s->w_size;
- zmemcpy(s->window, s->window + s->w_size, s->strstart);
- if (s->matches < 2)
- s->matches++; /* add a pending slide_hash() */
- if (s->insert > s->strstart)
- s->insert = s->strstart;
- }
- zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
- s->strstart += used;
- s->insert += MIN(used, s->w_size - s->insert);
- }
- s->block_start = s->strstart;
- }
- if (s->high_water < s->strstart)
- s->high_water = s->strstart;
-
- /* If the last block was written to next_out, then done. */
- if (last)
- return finish_done;
-
- /* If flushing and all input has been consumed, then done. */
- if (flush != Z_NO_FLUSH && flush != Z_FINISH &&
- s->strm->avail_in == 0 && (long)s->strstart == s->block_start)
- return block_done;
-
- /* Fill the window with any remaining input. */
- have = s->window_size - s->strstart;
- if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
- /* Slide the window down. */
- s->block_start -= s->w_size;
- s->strstart -= s->w_size;
- zmemcpy(s->window, s->window + s->w_size, s->strstart);
- if (s->matches < 2)
- s->matches++; /* add a pending slide_hash() */
- have += s->w_size; /* more space now */
- if (s->insert > s->strstart)
- s->insert = s->strstart;
- }
- if (have > s->strm->avail_in)
- have = s->strm->avail_in;
- if (have) {
- read_buf(s->strm, s->window + s->strstart, have);
- s->strstart += have;
- s->insert += MIN(have, s->w_size - s->insert);
- }
- if (s->high_water < s->strstart)
- s->high_water = s->strstart;
-
- /* There was not enough avail_out to write a complete worthy or flushed
- * stored block to next_out. Write a stored block to pending instead, if we
- * have enough input for a worthy block, or if flushing and there is enough
- * room for the remaining input as a stored block in the pending buffer.
- */
- have = (s->bi_valid + 42) >> 3; /* number of header bytes */
- /* maximum stored block length that will fit in pending: */
- have = MIN(s->pending_buf_size - have, MAX_STORED);
- min_block = MIN(have, s->w_size);
- left = s->strstart - s->block_start;
- if (left >= min_block ||
- ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH &&
- s->strm->avail_in == 0 && left <= have)) {
- len = MIN(left, have);
- last = flush == Z_FINISH && s->strm->avail_in == 0 &&
- len == left ? 1 : 0;
- _tr_stored_block(s, (charf *)s->window + s->block_start, len, last);
- s->block_start += len;
- flush_pending(s->strm);
- }
-
- /* We've done all we can with the available input and output. */
- return last ? finish_started : need_more;
-}
-
-/* ===========================================================================
- * Compress as much as possible from the input stream, return the current
- * block state.
- * This function does not perform lazy evaluation of matches and inserts
- * new strings in the dictionary only for unmatched strings or for short
- * matches. It is used only for the fast compression options.
- */
-local block_state deflate_fast(deflate_state *s, int flush) {
- IPos hash_head; /* head of the hash chain */
- int bflush; /* set if current block must be flushed */
-
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- if (s->lookahead < MIN_LOOKAHEAD) {
- fill_window(s);
- if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
- return need_more;
- }
- if (s->lookahead == 0) break; /* flush the current block */
- }
-
- /* Insert the string window[strstart .. strstart + 2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- hash_head = NIL;
- if (s->lookahead >= MIN_MATCH) {
- INSERT_STRING(s, s->strstart, hash_head);
- }
-
- /* Find the longest match, discarding those <= prev_length.
- * At this point we have always match_length < MIN_MATCH
- */
- if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- s->match_length = longest_match (s, hash_head);
- /* longest_match() sets match_start */
- }
- if (s->match_length >= MIN_MATCH) {
- check_match(s, s->strstart, s->match_start, s->match_length);
-
- _tr_tally_dist(s, s->strstart - s->match_start,
- s->match_length - MIN_MATCH, bflush);
-
- s->lookahead -= s->match_length;
-
- /* Insert new strings in the hash table only if the match length
- * is not too large. This saves time but degrades compression.
- */
-#ifndef FASTEST
- if (s->match_length <= s->max_insert_length &&
- s->lookahead >= MIN_MATCH) {
- s->match_length--; /* string at strstart already in table */
- do {
- s->strstart++;
- INSERT_STRING(s, s->strstart, hash_head);
- /* strstart never exceeds WSIZE-MAX_MATCH, so there are
- * always MIN_MATCH bytes ahead.
- */
- } while (--s->match_length != 0);
- s->strstart++;
- } else
-#endif
- {
- s->strstart += s->match_length;
- s->match_length = 0;
- s->ins_h = s->window[s->strstart];
- UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]);
-#if MIN_MATCH != 3
- Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
- /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
- * matter since it will be recomputed at next deflate call.
- */
- }
- } else {
- /* No match, output a literal byte */
- Tracevv((stderr,"%c", s->window[s->strstart]));
- _tr_tally_lit(s, s->window[s->strstart], bflush);
- s->lookahead--;
- s->strstart++;
- }
- if (bflush) FLUSH_BLOCK(s, 0);
- }
- s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
- if (flush == Z_FINISH) {
- FLUSH_BLOCK(s, 1);
- return finish_done;
- }
- if (s->sym_next)
- FLUSH_BLOCK(s, 0);
- return block_done;
-}
-
-#ifndef FASTEST
-/* ===========================================================================
- * Same as above, but achieves better compression. We use a lazy
- * evaluation for matches: a match is finally adopted only if there is
- * no better match at the next window position.
- */
-local block_state deflate_slow(deflate_state *s, int flush) {
- IPos hash_head; /* head of hash chain */
- int bflush; /* set if current block must be flushed */
-
- /* Process the input block. */
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- if (s->lookahead < MIN_LOOKAHEAD) {
- fill_window(s);
- if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
- return need_more;
- }
- if (s->lookahead == 0) break; /* flush the current block */
- }
-
- /* Insert the string window[strstart .. strstart + 2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- hash_head = NIL;
- if (s->lookahead >= MIN_MATCH) {
- INSERT_STRING(s, s->strstart, hash_head);
- }
-
- /* Find the longest match, discarding those <= prev_length.
- */
- s->prev_length = s->match_length, s->prev_match = s->match_start;
- s->match_length = MIN_MATCH-1;
-
- if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
- s->strstart - hash_head <= MAX_DIST(s)) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- s->match_length = longest_match (s, hash_head);
- /* longest_match() sets match_start */
-
- if (s->match_length <= 5 && (s->strategy == Z_FILTERED
-#if TOO_FAR <= 32767
- || (s->match_length == MIN_MATCH &&
- s->strstart - s->match_start > TOO_FAR)
-#endif
- )) {
-
- /* If prev_match is also MIN_MATCH, match_start is garbage
- * but we will ignore the current match anyway.
- */
- s->match_length = MIN_MATCH-1;
- }
- }
- /* If there was a match at the previous step and the current
- * match is not better, output the previous match:
- */
- if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
- uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
- /* Do not insert strings in hash table beyond this. */
-
- check_match(s, s->strstart - 1, s->prev_match, s->prev_length);
-
- _tr_tally_dist(s, s->strstart - 1 - s->prev_match,
- s->prev_length - MIN_MATCH, bflush);
-
- /* Insert in hash table all strings up to the end of the match.
- * strstart - 1 and strstart are already inserted. If there is not
- * enough lookahead, the last two strings are not inserted in
- * the hash table.
- */
- s->lookahead -= s->prev_length - 1;
- s->prev_length -= 2;
- do {
- if (++s->strstart <= max_insert) {
- INSERT_STRING(s, s->strstart, hash_head);
- }
- } while (--s->prev_length != 0);
- s->match_available = 0;
- s->match_length = MIN_MATCH-1;
- s->strstart++;
-
- if (bflush) FLUSH_BLOCK(s, 0);
-
- } else if (s->match_available) {
- /* If there was no match at the previous position, output a
- * single literal. If there was a match but the current match
- * is longer, truncate the previous match to a single literal.
- */
- Tracevv((stderr,"%c", s->window[s->strstart - 1]));
- _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
- if (bflush) {
- FLUSH_BLOCK_ONLY(s, 0);
- }
- s->strstart++;
- s->lookahead--;
- if (s->strm->avail_out == 0) return need_more;
- } else {
- /* There is no previous match to compare with, wait for
- * the next step to decide.
- */
- s->match_available = 1;
- s->strstart++;
- s->lookahead--;
- }
- }
- Assert (flush != Z_NO_FLUSH, "no flush?");
- if (s->match_available) {
- Tracevv((stderr,"%c", s->window[s->strstart - 1]));
- _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
- s->match_available = 0;
- }
- s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
- if (flush == Z_FINISH) {
- FLUSH_BLOCK(s, 1);
- return finish_done;
- }
- if (s->sym_next)
- FLUSH_BLOCK(s, 0);
- return block_done;
-}
-#endif /* FASTEST */
-
-/* ===========================================================================
- * For Z_RLE, simply look for runs of bytes, generate matches only of distance
- * one. Do not maintain a hash table. (It will be regenerated if this run of
- * deflate switches away from Z_RLE.)
- */
-local block_state deflate_rle(deflate_state *s, int flush) {
- int bflush; /* set if current block must be flushed */
- uInt prev; /* byte at distance one to match */
- Bytef *scan, *strend; /* scan goes up to strend for length of run */
-
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the longest run, plus one for the unrolled loop.
- */
- if (s->lookahead <= MAX_MATCH) {
- fill_window(s);
- if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
- return need_more;
- }
- if (s->lookahead == 0) break; /* flush the current block */
- }
-
- /* See how many times the previous byte repeats */
- s->match_length = 0;
- if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
- scan = s->window + s->strstart - 1;
- prev = *scan;
- if (prev == *++scan && prev == *++scan && prev == *++scan) {
- strend = s->window + s->strstart + MAX_MATCH;
- do {
- } while (prev == *++scan && prev == *++scan &&
- prev == *++scan && prev == *++scan &&
- prev == *++scan && prev == *++scan &&
- prev == *++scan && prev == *++scan &&
- scan < strend);
- s->match_length = MAX_MATCH - (uInt)(strend - scan);
- if (s->match_length > s->lookahead)
- s->match_length = s->lookahead;
- }
- Assert(scan <= s->window + (uInt)(s->window_size - 1),
- "wild scan");
- }
-
- /* Emit match if have run of MIN_MATCH or longer, else emit literal */
- if (s->match_length >= MIN_MATCH) {
- check_match(s, s->strstart, s->strstart - 1, s->match_length);
-
- _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
-
- s->lookahead -= s->match_length;
- s->strstart += s->match_length;
- s->match_length = 0;
- } else {
- /* No match, output a literal byte */
- Tracevv((stderr,"%c", s->window[s->strstart]));
- _tr_tally_lit(s, s->window[s->strstart], bflush);
- s->lookahead--;
- s->strstart++;
- }
- if (bflush) FLUSH_BLOCK(s, 0);
- }
- s->insert = 0;
- if (flush == Z_FINISH) {
- FLUSH_BLOCK(s, 1);
- return finish_done;
- }
- if (s->sym_next)
- FLUSH_BLOCK(s, 0);
- return block_done;
-}
-
-/* ===========================================================================
- * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
- * (It will be regenerated if this run of deflate switches away from Huffman.)
- */
-local block_state deflate_huff(deflate_state *s, int flush) {
- int bflush; /* set if current block must be flushed */
-
- for (;;) {
- /* Make sure that we have a literal to write. */
- if (s->lookahead == 0) {
- fill_window(s);
- if (s->lookahead == 0) {
- if (flush == Z_NO_FLUSH)
- return need_more;
- break; /* flush the current block */
- }
- }
-
- /* Output a literal byte */
- s->match_length = 0;
- Tracevv((stderr,"%c", s->window[s->strstart]));
- _tr_tally_lit(s, s->window[s->strstart], bflush);
- s->lookahead--;
- s->strstart++;
- if (bflush) FLUSH_BLOCK(s, 0);
- }
- s->insert = 0;
- if (flush == Z_FINISH) {
- FLUSH_BLOCK(s, 1);
- return finish_done;
- }
- if (s->sym_next)
- FLUSH_BLOCK(s, 0);
- return block_done;
-}
diff --git a/kernel/src/compress/zlib/inffast.c b/kernel/src/compress/zlib/inffast.c
deleted file mode 100644
index 6b990952b..000000000
--- a/kernel/src/compress/zlib/inffast.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/* inffast.c -- fast decoding
- * Copyright (C) 1995-2017 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "../../../include/compress/zlib/zutil.h"
-#include "../../../include/compress/zlib/inftrees.h"
-#include "../../../include/compress/zlib/inflate.h"
-#include "../../../include/compress/zlib/inffast.h"
-
-#ifdef ASMINF
-# pragma message("Assembler code may have bugs -- use at your own risk")
-#else
-
-/*
- Decode literal, length, and distance codes and write out the resulting
- literal and match bytes until either not enough input or output is
- available, an end-of-block is encountered, or a data error is encountered.
- When large enough input and output buffers are supplied to inflate(), for
- example, a 16K input buffer and a 64K output buffer, more than 95% of the
- inflate execution time is spent in this routine.
-
- Entry assumptions:
-
- state->mode == LEN
- strm->avail_in >= 6
- strm->avail_out >= 258
- start >= strm->avail_out
- state->bits < 8
-
- On return, state->mode is one of:
-
- LEN -- ran out of enough output space or enough available input
- TYPE -- reached end of block code, inflate() to interpret next block
- BAD -- error in block data
-
- Notes:
-
- - The maximum input bits used by a length/distance pair is 15 bits for the
- length code, 5 bits for the length extra, 15 bits for the distance code,
- and 13 bits for the distance extra. This totals 48 bits, or six bytes.
- Therefore if strm->avail_in >= 6, then there is enough input to avoid
- checking for available input while decoding.
-
- - The maximum bytes that a single length/distance pair can output is 258
- bytes, which is the maximum length that can be coded. inflate_fast()
- requires strm->avail_out >= 258 for each loop to avoid checking for
- output space.
- */
-void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
- struct inflate_state FAR *state;
- z_const unsigned char FAR *in; /* local strm->next_in */
- z_const unsigned char FAR *last; /* have enough input while in < last */
- unsigned char FAR *out; /* local strm->next_out */
- unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
- unsigned char FAR *end; /* while out < end, enough space available */
-#ifdef INFLATE_STRICT
- unsigned dmax; /* maximum distance from zlib header */
-#endif
- unsigned wsize; /* window size or zero if not using window */
- unsigned whave; /* valid bytes in the window */
- unsigned wnext; /* window write index */
- unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
- unsigned long hold; /* local strm->hold */
- unsigned bits; /* local strm->bits */
- code const FAR *lcode; /* local strm->lencode */
- code const FAR *dcode; /* local strm->distcode */
- unsigned lmask; /* mask for first level of length codes */
- unsigned dmask; /* mask for first level of distance codes */
- code const *here; /* retrieved table entry */
- unsigned op; /* code bits, operation, extra bits, or */
- /* window position, window bytes to copy */
- unsigned len; /* match length, unused bytes */
- unsigned dist; /* match distance */
- unsigned char FAR *from; /* where to copy match from */
-
- /* copy state to local variables */
- state = (struct inflate_state FAR *)strm->state;
- in = strm->next_in;
- last = in + (strm->avail_in - 5);
- out = strm->next_out;
- beg = out - (start - strm->avail_out);
- end = out + (strm->avail_out - 257);
-#ifdef INFLATE_STRICT
- dmax = state->dmax;
-#endif
- wsize = state->wsize;
- whave = state->whave;
- wnext = state->wnext;
- window = state->window;
- hold = state->hold;
- bits = state->bits;
- lcode = state->lencode;
- dcode = state->distcode;
- lmask = (1U << state->lenbits) - 1;
- dmask = (1U << state->distbits) - 1;
-
- /* decode literals and length/distances until end-of-block or not enough
- input data or output space */
- do {
- if (bits < 15) {
- hold += (unsigned long)(*in++) << bits;
- bits += 8;
- hold += (unsigned long)(*in++) << bits;
- bits += 8;
- }
- here = lcode + (hold & lmask);
- dolen:
- op = (unsigned)(here->bits);
- hold >>= op;
- bits -= op;
- op = (unsigned)(here->op);
- if (op == 0) { /* literal */
- Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
- "inflate: literal '%c'\n" :
- "inflate: literal 0x%02x\n", here->val));
- *out++ = (unsigned char)(here->val);
- }
- else if (op & 16) { /* length base */
- len = (unsigned)(here->val);
- op &= 15; /* number of extra bits */
- if (op) {
- if (bits < op) {
- hold += (unsigned long)(*in++) << bits;
- bits += 8;
- }
- len += (unsigned)hold & ((1U << op) - 1);
- hold >>= op;
- bits -= op;
- }
- Tracevv((stderr, "inflate: length %u\n", len));
- if (bits < 15) {
- hold += (unsigned long)(*in++) << bits;
- bits += 8;
- hold += (unsigned long)(*in++) << bits;
- bits += 8;
- }
- here = dcode + (hold & dmask);
- dodist:
- op = (unsigned)(here->bits);
- hold >>= op;
- bits -= op;
- op = (unsigned)(here->op);
- if (op & 16) { /* distance base */
- dist = (unsigned)(here->val);
- op &= 15; /* number of extra bits */
- if (bits < op) {
- hold += (unsigned long)(*in++) << bits;
- bits += 8;
- if (bits < op) {
- hold += (unsigned long)(*in++) << bits;
- bits += 8;
- }
- }
- dist += (unsigned)hold & ((1U << op) - 1);
-#ifdef INFLATE_STRICT
- if (dist > dmax) {
- strm->msg = (char *)"invalid distance too far back";
- state->mode = BAD;
- break;
- }
-#endif
- hold >>= op;
- bits -= op;
- Tracevv((stderr, "inflate: distance %u\n", dist));
- op = (unsigned)(out - beg); /* max distance in output */
- if (dist > op) { /* see if copy from window */
- op = dist - op; /* distance back in window */
- if (op > whave) {
- if (state->sane) {
- strm->msg =
- (char *)"invalid distance too far back";
- state->mode = BAD;
- break;
- }
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
- if (len <= op - whave) {
- do {
- *out++ = 0;
- } while (--len);
- continue;
- }
- len -= op - whave;
- do {
- *out++ = 0;
- } while (--op > whave);
- if (op == 0) {
- from = out - dist;
- do {
- *out++ = *from++;
- } while (--len);
- continue;
- }
-#endif
- }
- from = window;
- if (wnext == 0) { /* very common case */
- from += wsize - op;
- if (op < len) { /* some from window */
- len -= op;
- do {
- *out++ = *from++;
- } while (--op);
- from = out - dist; /* rest from output */
- }
- }
- else if (wnext < op) { /* wrap around window */
- from += wsize + wnext - op;
- op -= wnext;
- if (op < len) { /* some from end of window */
- len -= op;
- do {
- *out++ = *from++;
- } while (--op);
- from = window;
- if (wnext < len) { /* some from start of window */
- op = wnext;
- len -= op;
- do {
- *out++ = *from++;
- } while (--op);
- from = out - dist; /* rest from output */
- }
- }
- }
- else { /* contiguous in window */
- from += wnext - op;
- if (op < len) { /* some from window */
- len -= op;
- do {
- *out++ = *from++;
- } while (--op);
- from = out - dist; /* rest from output */
- }
- }
- while (len > 2) {
- *out++ = *from++;
- *out++ = *from++;
- *out++ = *from++;
- len -= 3;
- }
- if (len) {
- *out++ = *from++;
- if (len > 1)
- *out++ = *from++;
- }
- }
- else {
- from = out - dist; /* copy direct from output */
- do { /* minimum length is three */
- *out++ = *from++;
- *out++ = *from++;
- *out++ = *from++;
- len -= 3;
- } while (len > 2);
- if (len) {
- *out++ = *from++;
- if (len > 1)
- *out++ = *from++;
- }
- }
- }
- else if ((op & 64) == 0) { /* 2nd level distance code */
- here = dcode + here->val + (hold & ((1U << op) - 1));
- goto dodist;
- }
- else {
- strm->msg = (char *)"invalid distance code";
- state->mode = BAD;
- break;
- }
- }
- else if ((op & 64) == 0) { /* 2nd level length code */
- here = lcode + here->val + (hold & ((1U << op) - 1));
- goto dolen;
- }
- else if (op & 32) { /* end-of-block */
- Tracevv((stderr, "inflate: end of block\n"));
- state->mode = TYPE;
- break;
- }
- else {
- strm->msg = (char *)"invalid literal/length code";
- state->mode = BAD;
- break;
- }
- } while (in < last && out < end);
-
- /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
- len = bits >> 3;
- in -= len;
- bits -= len << 3;
- hold &= (1U << bits) - 1;
-
- /* update state and return */
- strm->next_in = in;
- strm->next_out = out;
- strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
- strm->avail_out = (unsigned)(out < end ?
- 257 + (end - out) : 257 - (out - end));
- state->hold = hold;
- state->bits = bits;
- return;
-}
-
-/*
- inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
- - Using bit fields for code structure
- - Different op definition to avoid & for extra bits (do & for table bits)
- - Three separate decoding do-loops for direct, window, and wnext == 0
- - Special case for distance > 1 copies to do overlapped load and store copy
- - Explicit branch predictions (based on measured branch probabilities)
- - Deferring match copy and interspersed it with decoding subsequent codes
- - Swapping literal/length else
- - Swapping window/direct else
- - Larger unrolled copy loops (three is about right)
- - Moving len -= 3 statement into middle of loop
- */
-
-#endif /* !ASMINF */
diff --git a/kernel/src/compress/zlib/inflate.c b/kernel/src/compress/zlib/inflate.c
deleted file mode 100644
index cb35ff237..000000000
--- a/kernel/src/compress/zlib/inflate.c
+++ /dev/null
@@ -1,1527 +0,0 @@
-/* inflate.c -- zlib decompression
- * Copyright (C) 1995-2022 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- * Change history:
- *
- * 1.2.beta0 24 Nov 2002
- * - First version -- complete rewrite of inflate to simplify code, avoid
- * creation of window when not needed, minimize use of window when it is
- * needed, make inffast.c even faster, implement gzip decoding, and to
- * improve code readability and style over the previous zlib inflate code
- *
- * 1.2.beta1 25 Nov 2002
- * - Use pointers for available input and output checking in inffast.c
- * - Remove input and output counters in inffast.c
- * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
- * - Remove unnecessary second byte pull from length extra in inffast.c
- * - Unroll direct copy to three copies per loop in inffast.c
- *
- * 1.2.beta2 4 Dec 2002
- * - Change external routine names to reduce potential conflicts
- * - Correct filename to inffixed.h for fixed tables in inflate.c
- * - Make hbuf[] unsigned char to match parameter type in inflate.c
- * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
- * to avoid negation problem on Alphas (64 bit) in inflate.c
- *
- * 1.2.beta3 22 Dec 2002
- * - Add comments on state->bits assertion in inffast.c
- * - Add comments on op field in inftrees.h
- * - Fix bug in reuse of allocated window after inflateReset()
- * - Remove bit fields--back to byte structure for speed
- * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
- * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
- * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
- * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
- * - Use local copies of stream next and avail values, as well as local bit
- * buffer and bit count in inflate()--for speed when inflate_fast() not used
- *
- * 1.2.beta4 1 Jan 2003
- * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
- * - Move a comment on output buffer sizes from inffast.c to inflate.c
- * - Add comments in inffast.c to introduce the inflate_fast() routine
- * - Rearrange window copies in inflate_fast() for speed and simplification
- * - Unroll last copy for window match in inflate_fast()
- * - Use local copies of window variables in inflate_fast() for speed
- * - Pull out common wnext == 0 case for speed in inflate_fast()
- * - Make op and len in inflate_fast() unsigned for consistency
- * - Add FAR to lcode and dcode declarations in inflate_fast()
- * - Simplified bad distance check in inflate_fast()
- * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
- * source file infback.c to provide a call-back interface to inflate for
- * programs like gzip and unzip -- uses window as output buffer to avoid
- * window copying
- *
- * 1.2.beta5 1 Jan 2003
- * - Improved inflateBack() interface to allow the caller to provide initial
- * input in strm.
- * - Fixed stored blocks bug in inflateBack()
- *
- * 1.2.beta6 4 Jan 2003
- * - Added comments in inffast.c on effectiveness of POSTINC
- * - Typecasting all around to reduce compiler warnings
- * - Changed loops from while (1) or do {} while (1) to for (;;), again to
- * make compilers happy
- * - Changed type of window in inflateBackInit() to unsigned char *
- *
- * 1.2.beta7 27 Jan 2003
- * - Changed many types to unsigned or unsigned short to avoid warnings
- * - Added inflateCopy() function
- *
- * 1.2.0 9 Mar 2003
- * - Changed inflateBack() interface to provide separate opaque descriptors
- * for the in() and out() functions
- * - Changed inflateBack() argument and in_func typedef to swap the length
- * and buffer address return values for the input function
- * - Check next_in and next_out for Z_NULL on entry to inflate()
- *
- * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
- */
-
-#include "../../../include/compress/zlib/zutil.h"
-#include "../../../include/compress/zlib/inftrees.h"
-#include "../../../include/compress/zlib/inflate.h"
-#include "../../../include/compress/zlib/inffast.h"
-
-#ifdef MAKEFIXED
-# ifndef BUILDFIXED
-# define BUILDFIXED
-# endif
-#endif
-
-local int inflateStateCheck(z_streamp strm) {
- struct inflate_state FAR *state;
- if (strm == Z_NULL ||
- strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
- return 1;
- state = (struct inflate_state FAR *)strm->state;
- if (state == Z_NULL || state->strm != strm ||
- state->mode < HEAD || state->mode > SYNC)
- return 1;
- return 0;
-}
-
-int ZEXPORT inflateResetKeep(z_streamp strm) {
- struct inflate_state FAR *state;
-
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
- strm->total_in = strm->total_out = state->total = 0;
- strm->msg = Z_NULL;
- if (state->wrap) /* to support ill-conceived Java test suite */
- strm->adler = state->wrap & 1;
- state->mode = HEAD;
- state->last = 0;
- state->havedict = 0;
- state->flags = -1;
- state->dmax = 32768U;
- state->head = Z_NULL;
- state->hold = 0;
- state->bits = 0;
- state->lencode = state->distcode = state->next = state->codes;
- state->sane = 1;
- state->back = -1;
- Tracev((stderr, "inflate: reset\n"));
- return Z_OK;
-}
-
-int ZEXPORT inflateReset(z_streamp strm) {
- struct inflate_state FAR *state;
-
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
- state->wsize = 0;
- state->whave = 0;
- state->wnext = 0;
- return inflateResetKeep(strm);
-}
-
-int ZEXPORT inflateReset2(z_streamp strm, int windowBits) {
- int wrap;
- struct inflate_state FAR *state;
-
- /* get the state */
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
-
- /* extract wrap request from windowBits parameter */
- if (windowBits < 0) {
- if (windowBits < -15)
- return Z_STREAM_ERROR;
- wrap = 0;
- windowBits = -windowBits;
- }
- else {
- wrap = (windowBits >> 4) + 5;
-#ifdef GUNZIP
- if (windowBits < 48)
- windowBits &= 15;
-#endif
- }
-
- /* set number of window bits, free window if different */
- if (windowBits && (windowBits < 8 || windowBits > 15))
- return Z_STREAM_ERROR;
- if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
- ZFREE(strm, state->window);
- state->window = Z_NULL;
- }
-
- /* update state and reset the rest of it */
- state->wrap = wrap;
- state->wbits = (unsigned)windowBits;
- return inflateReset(strm);
-}
-
-int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
- const char *version, int stream_size) {
- int ret;
- struct inflate_state FAR *state;
-
- if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
- stream_size != (int)(sizeof(z_stream)))
- return Z_VERSION_ERROR;
- if (strm == Z_NULL) return Z_STREAM_ERROR;
- strm->msg = Z_NULL; /* in case we return an error */
- if (strm->zalloc == (alloc_func)0) {
-#ifdef Z_SOLO
- return Z_STREAM_ERROR;
-#else
- strm->zalloc = zcalloc;
- strm->opaque = (voidpf)0;
-#endif
- }
- if (strm->zfree == (free_func)0)
-#ifdef Z_SOLO
- return Z_STREAM_ERROR;
-#else
- strm->zfree = zcfree;
-#endif
- state = (struct inflate_state FAR *)
- ZALLOC(strm, 1, sizeof(struct inflate_state));
- if (state == Z_NULL) return Z_MEM_ERROR;
- Tracev((stderr, "inflate: allocated\n"));
- strm->state = (struct internal_state FAR *)state;
- state->strm = strm;
- state->window = Z_NULL;
- state->mode = HEAD; /* to pass state test in inflateReset2() */
- ret = inflateReset2(strm, windowBits);
- if (ret != Z_OK) {
- ZFREE(strm, state);
- strm->state = Z_NULL;
- }
- return ret;
-}
-
-int ZEXPORT inflateInit_(z_streamp strm, const char *version,
- int stream_size) {
- return inflateInit2_(strm, DEF_WBITS, version, stream_size);
-}
-
-int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) {
- struct inflate_state FAR *state;
-
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- if (bits == 0)
- return Z_OK;
- state = (struct inflate_state FAR *)strm->state;
- if (bits < 0) {
- state->hold = 0;
- state->bits = 0;
- return Z_OK;
- }
- if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
- value &= (1L << bits) - 1;
- state->hold += (unsigned)value << state->bits;
- state->bits += (uInt)bits;
- return Z_OK;
-}
-
-/*
- Return state with length and distance decoding tables and index sizes set to
- fixed code decoding. Normally this returns fixed tables from inffixed.h.
- If BUILDFIXED is defined, then instead this routine builds the tables the
- first time it's called, and returns those tables the first time and
- thereafter. This reduces the size of the code by about 2K bytes, in
- exchange for a little execution time. However, BUILDFIXED should not be
- used for threaded applications, since the rewriting of the tables and virgin
- may not be thread-safe.
- */
-local void fixedtables(struct inflate_state FAR *state) {
-#ifdef BUILDFIXED
- static int virgin = 1;
- static code *lenfix, *distfix;
- static code fixed[544];
-
- /* build fixed huffman tables if first call (may not be thread safe) */
- if (virgin) {
- unsigned sym, bits;
- static code *next;
-
- /* literal/length table */
- sym = 0;
- while (sym < 144) state->lens[sym++] = 8;
- while (sym < 256) state->lens[sym++] = 9;
- while (sym < 280) state->lens[sym++] = 7;
- while (sym < 288) state->lens[sym++] = 8;
- next = fixed;
- lenfix = next;
- bits = 9;
- inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
-
- /* distance table */
- sym = 0;
- while (sym < 32) state->lens[sym++] = 5;
- distfix = next;
- bits = 5;
- inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
-
- /* do this just once */
- virgin = 0;
- }
-#else /* !BUILDFIXED */
-# include "../../../include/compress/zlib/inffixed.h"
-
-#endif /* BUILDFIXED */
- state->lencode = lenfix;
- state->lenbits = 9;
- state->distcode = distfix;
- state->distbits = 5;
-}
-
-#ifdef MAKEFIXED
-#include
-
-/*
- Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
- defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
- those tables to stdout, which would be piped to inffixed.h. A small program
- can simply call makefixed to do this:
-
- void makefixed(void);
-
- int main(void)
- {
- makefixed();
- return 0;
- }
-
- Then that can be linked with zlib built with MAKEFIXED defined and run:
-
- a.out > inffixed.h
- */
-void makefixed(void)
-{
- unsigned low, size;
- struct inflate_state state;
-
- fixedtables(&state);
- puts(" /* inffixed.h -- table for decoding fixed codes");
- puts(" * Generated automatically by makefixed().");
- puts(" */");
- puts("");
- puts(" /* WARNING: this file should *not* be used by applications.");
- puts(" It is part of the implementation of this library and is");
- puts(" subject to change. Applications should only use zlib.h.");
- puts(" */");
- puts("");
- size = 1U << 9;
- printf(" static const code lenfix[%u] = {", size);
- low = 0;
- for (;;) {
- if ((low % 7) == 0) printf("\n ");
- printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
- state.lencode[low].bits, state.lencode[low].val);
- if (++low == size) break;
- putchar(',');
- }
- puts("\n };");
- size = 1U << 5;
- printf("\n static const code distfix[%u] = {", size);
- low = 0;
- for (;;) {
- if ((low % 6) == 0) printf("\n ");
- printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
- state.distcode[low].val);
- if (++low == size) break;
- putchar(',');
- }
- puts("\n };");
-}
-#endif /* MAKEFIXED */
-
-/*
- Update the window with the last wsize (normally 32K) bytes written before
- returning. If window does not exist yet, create it. This is only called
- when a window is already in use, or when output has been written during this
- inflate call, but the end of the deflate stream has not been reached yet.
- It is also called to create a window for dictionary data when a dictionary
- is loaded.
-
- Providing output buffers larger than 32K to inflate() should provide a speed
- advantage, since only the last 32K of output is copied to the sliding window
- upon return from inflate(), and since all distances after the first 32K of
- output will fall in the output data, making match copies simpler and faster.
- The advantage may be dependent on the size of the processor's data caches.
- */
-local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) {
- struct inflate_state FAR *state;
- unsigned dist;
-
- state = (struct inflate_state FAR *)strm->state;
-
- /* if it hasn't been done already, allocate space for the window */
- if (state->window == Z_NULL) {
- state->window = (unsigned char FAR *)
- ZALLOC(strm, 1U << state->wbits,
- sizeof(unsigned char));
- if (state->window == Z_NULL) return 1;
- }
-
- /* if window not in use yet, initialize */
- if (state->wsize == 0) {
- state->wsize = 1U << state->wbits;
- state->wnext = 0;
- state->whave = 0;
- }
-
- /* copy state->wsize or less output bytes into the circular window */
- if (copy >= state->wsize) {
- zmemcpy(state->window, end - state->wsize, state->wsize);
- state->wnext = 0;
- state->whave = state->wsize;
- }
- else {
- dist = state->wsize - state->wnext;
- if (dist > copy) dist = copy;
- zmemcpy(state->window + state->wnext, end - copy, dist);
- copy -= dist;
- if (copy) {
- zmemcpy(state->window, end - copy, copy);
- state->wnext = copy;
- state->whave = state->wsize;
- }
- else {
- state->wnext += dist;
- if (state->wnext == state->wsize) state->wnext = 0;
- if (state->whave < state->wsize) state->whave += dist;
- }
- }
- return 0;
-}
-
-/* Macros for inflate(): */
-
-/* check function to use adler32() for zlib or crc32() for gzip */
-#ifdef GUNZIP
-# define UPDATE_CHECK(check, buf, len) \
- (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
-#else
-# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
-#endif
-
-/* check macros for header crc */
-#ifdef GUNZIP
-# define CRC2(check, word) \
- do { \
- hbuf[0] = (unsigned char)(word); \
- hbuf[1] = (unsigned char)((word) >> 8); \
- check = crc32(check, hbuf, 2); \
- } while (0)
-
-# define CRC4(check, word) \
- do { \
- hbuf[0] = (unsigned char)(word); \
- hbuf[1] = (unsigned char)((word) >> 8); \
- hbuf[2] = (unsigned char)((word) >> 16); \
- hbuf[3] = (unsigned char)((word) >> 24); \
- check = crc32(check, hbuf, 4); \
- } while (0)
-#endif
-
-/* Load registers with state in inflate() for speed */
-#define LOAD() \
- do { \
- put = strm->next_out; \
- left = strm->avail_out; \
- next = strm->next_in; \
- have = strm->avail_in; \
- hold = state->hold; \
- bits = state->bits; \
- } while (0)
-
-/* Restore state from registers in inflate() */
-#define RESTORE() \
- do { \
- strm->next_out = put; \
- strm->avail_out = left; \
- strm->next_in = next; \
- strm->avail_in = have; \
- state->hold = hold; \
- state->bits = bits; \
- } while (0)
-
-/* Clear the input bit accumulator */
-#define INITBITS() \
- do { \
- hold = 0; \
- bits = 0; \
- } while (0)
-
-/* Get a byte of input into the bit accumulator, or return from inflate()
- if there is no input available. */
-#define PULLBYTE() \
- do { \
- if (have == 0) goto inf_leave; \
- have--; \
- hold += (unsigned long)(*next++) << bits; \
- bits += 8; \
- } while (0)
-
-/* Assure that there are at least n bits in the bit accumulator. If there is
- not enough available input to do that, then return from inflate(). */
-#define NEEDBITS(n) \
- do { \
- while (bits < (unsigned)(n)) \
- PULLBYTE(); \
- } while (0)
-
-/* Return the low n bits of the bit accumulator (n < 16) */
-#define BITS(n) \
- ((unsigned)hold & ((1U << (n)) - 1))
-
-/* Remove n bits from the bit accumulator */
-#define DROPBITS(n) \
- do { \
- hold >>= (n); \
- bits -= (unsigned)(n); \
- } while (0)
-
-/* Remove zero to seven bits as needed to go to a byte boundary */
-#define BYTEBITS() \
- do { \
- hold >>= bits & 7; \
- bits -= bits & 7; \
- } while (0)
-
-/*
- inflate() uses a state machine to process as much input data and generate as
- much output data as possible before returning. The state machine is
- structured roughly as follows:
-
- for (;;) switch (state) {
- ...
- case STATEn:
- if (not enough input data or output space to make progress)
- return;
- ... make progress ...
- state = STATEm;
- break;
- ...
- }
-
- so when inflate() is called again, the same case is attempted again, and
- if the appropriate resources are provided, the machine proceeds to the
- next state. The NEEDBITS() macro is usually the way the state evaluates
- whether it can proceed or should return. NEEDBITS() does the return if
- the requested bits are not available. The typical use of the BITS macros
- is:
-
- NEEDBITS(n);
- ... do something with BITS(n) ...
- DROPBITS(n);
-
- where NEEDBITS(n) either returns from inflate() if there isn't enough
- input left to load n bits into the accumulator, or it continues. BITS(n)
- gives the low n bits in the accumulator. When done, DROPBITS(n) drops
- the low n bits off the accumulator. INITBITS() clears the accumulator
- and sets the number of available bits to zero. BYTEBITS() discards just
- enough bits to put the accumulator on a byte boundary. After BYTEBITS()
- and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
-
- NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
- if there is no input available. The decoding of variable length codes uses
- PULLBYTE() directly in order to pull just enough bytes to decode the next
- code, and no more.
-
- Some states loop until they get enough input, making sure that enough
- state information is maintained to continue the loop where it left off
- if NEEDBITS() returns in the loop. For example, want, need, and keep
- would all have to actually be part of the saved state in case NEEDBITS()
- returns:
-
- case STATEw:
- while (want < need) {
- NEEDBITS(n);
- keep[want++] = BITS(n);
- DROPBITS(n);
- }
- state = STATEx;
- case STATEx:
-
- As shown above, if the next state is also the next case, then the break
- is omitted.
-
- A state may also return if there is not enough output space available to
- complete that state. Those states are copying stored data, writing a
- literal byte, and copying a matching string.
-
- When returning, a "goto inf_leave" is used to update the total counters,
- update the check value, and determine whether any progress has been made
- during that inflate() call in order to return the proper return code.
- Progress is defined as a change in either strm->avail_in or strm->avail_out.
- When there is a window, goto inf_leave will update the window with the last
- output written. If a goto inf_leave occurs in the middle of decompression
- and there is no window currently, goto inf_leave will create one and copy
- output to the window for the next call of inflate().
-
- In this implementation, the flush parameter of inflate() only affects the
- return code (per zlib.h). inflate() always writes as much as possible to
- strm->next_out, given the space available and the provided input--the effect
- documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
- the allocation of and copying into a sliding window until necessary, which
- provides the effect documented in zlib.h for Z_FINISH when the entire input
- stream available. So the only thing the flush parameter actually does is:
- when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
- will return Z_BUF_ERROR if it has not reached the end of the stream.
- */
-
-int ZEXPORT inflate(z_streamp strm, int flush) {
- struct inflate_state FAR *state;
- z_const unsigned char FAR *next; /* next input */
- unsigned char FAR *put; /* next output */
- unsigned have, left; /* available input and output */
- unsigned long hold; /* bit buffer */
- unsigned bits; /* bits in bit buffer */
- unsigned in, out; /* save starting available input and output */
- unsigned copy; /* number of stored or match bytes to copy */
- unsigned char FAR *from; /* where to copy match bytes from */
- code here; /* current decoding table entry */
- code last; /* parent table entry */
- unsigned len; /* length to copy for repeats, bits to drop */
- int ret; /* return code */
-#ifdef GUNZIP
- unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
-#endif
- static const unsigned short order[19] = /* permutation of code lengths */
- {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
- if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
- (strm->next_in == Z_NULL && strm->avail_in != 0))
- return Z_STREAM_ERROR;
-
- state = (struct inflate_state FAR *)strm->state;
- if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
- LOAD();
- in = have;
- out = left;
- ret = Z_OK;
- for (;;)
- switch (state->mode) {
- case HEAD:
- if (state->wrap == 0) {
- state->mode = TYPEDO;
- break;
- }
- NEEDBITS(16);
-#ifdef GUNZIP
- if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
- if (state->wbits == 0)
- state->wbits = 15;
- state->check = crc32(0L, Z_NULL, 0);
- CRC2(state->check, hold);
- INITBITS();
- state->mode = FLAGS;
- break;
- }
- if (state->head != Z_NULL)
- state->head->done = -1;
- if (!(state->wrap & 1) || /* check if zlib header allowed */
-#else
- if (
-#endif
- ((BITS(8) << 8) + (hold >> 8)) % 31) {
- strm->msg = (char *)"incorrect header check";
- state->mode = BAD;
- break;
- }
- if (BITS(4) != Z_DEFLATED) {
- strm->msg = (char *)"unknown compression method";
- state->mode = BAD;
- break;
- }
- DROPBITS(4);
- len = BITS(4) + 8;
- if (state->wbits == 0)
- state->wbits = len;
- if (len > 15 || len > state->wbits) {
- strm->msg = (char *)"invalid window size";
- state->mode = BAD;
- break;
- }
- state->dmax = 1U << len;
- state->flags = 0; /* indicate zlib header */
- Tracev((stderr, "inflate: zlib header ok\n"));
- strm->adler = state->check = adler32(0L, Z_NULL, 0);
- state->mode = hold & 0x200 ? DICTID : TYPE;
- INITBITS();
- break;
-#ifdef GUNZIP
- case FLAGS:
- NEEDBITS(16);
- state->flags = (int)(hold);
- if ((state->flags & 0xff) != Z_DEFLATED) {
- strm->msg = (char *)"unknown compression method";
- state->mode = BAD;
- break;
- }
- if (state->flags & 0xe000) {
- strm->msg = (char *)"unknown header flags set";
- state->mode = BAD;
- break;
- }
- if (state->head != Z_NULL)
- state->head->text = (int)((hold >> 8) & 1);
- if ((state->flags & 0x0200) && (state->wrap & 4))
- CRC2(state->check, hold);
- INITBITS();
- state->mode = TIME;
- /* fallthrough */
- case TIME:
- NEEDBITS(32);
- if (state->head != Z_NULL)
- state->head->time = hold;
- if ((state->flags & 0x0200) && (state->wrap & 4))
- CRC4(state->check, hold);
- INITBITS();
- state->mode = OS;
- /* fallthrough */
- case OS:
- NEEDBITS(16);
- if (state->head != Z_NULL) {
- state->head->xflags = (int)(hold & 0xff);
- state->head->os = (int)(hold >> 8);
- }
- if ((state->flags & 0x0200) && (state->wrap & 4))
- CRC2(state->check, hold);
- INITBITS();
- state->mode = EXLEN;
- /* fallthrough */
- case EXLEN:
- if (state->flags & 0x0400) {
- NEEDBITS(16);
- state->length = (unsigned)(hold);
- if (state->head != Z_NULL)
- state->head->extra_len = (unsigned)hold;
- if ((state->flags & 0x0200) && (state->wrap & 4))
- CRC2(state->check, hold);
- INITBITS();
- }
- else if (state->head != Z_NULL)
- state->head->extra = Z_NULL;
- state->mode = EXTRA;
- /* fallthrough */
- case EXTRA:
- if (state->flags & 0x0400) {
- copy = state->length;
- if (copy > have) copy = have;
- if (copy) {
- if (state->head != Z_NULL &&
- state->head->extra != Z_NULL &&
- (len = state->head->extra_len - state->length) <
- state->head->extra_max) {
- zmemcpy(state->head->extra + len, next,
- len + copy > state->head->extra_max ?
- state->head->extra_max - len : copy);
- }
- if ((state->flags & 0x0200) && (state->wrap & 4))
- state->check = crc32(state->check, next, copy);
- have -= copy;
- next += copy;
- state->length -= copy;
- }
- if (state->length) goto inf_leave;
- }
- state->length = 0;
- state->mode = NAME;
- /* fallthrough */
- case NAME:
- if (state->flags & 0x0800) {
- if (have == 0) goto inf_leave;
- copy = 0;
- do {
- len = (unsigned)(next[copy++]);
- if (state->head != Z_NULL &&
- state->head->name != Z_NULL &&
- state->length < state->head->name_max)
- state->head->name[state->length++] = (Bytef)len;
- } while (len && copy < have);
- if ((state->flags & 0x0200) && (state->wrap & 4))
- state->check = crc32(state->check, next, copy);
- have -= copy;
- next += copy;
- if (len) goto inf_leave;
- }
- else if (state->head != Z_NULL)
- state->head->name = Z_NULL;
- state->length = 0;
- state->mode = COMMENT;
- /* fallthrough */
- case COMMENT:
- if (state->flags & 0x1000) {
- if (have == 0) goto inf_leave;
- copy = 0;
- do {
- len = (unsigned)(next[copy++]);
- if (state->head != Z_NULL &&
- state->head->comment != Z_NULL &&
- state->length < state->head->comm_max)
- state->head->comment[state->length++] = (Bytef)len;
- } while (len && copy < have);
- if ((state->flags & 0x0200) && (state->wrap & 4))
- state->check = crc32(state->check, next, copy);
- have -= copy;
- next += copy;
- if (len) goto inf_leave;
- }
- else if (state->head != Z_NULL)
- state->head->comment = Z_NULL;
- state->mode = HCRC;
- /* fallthrough */
- case HCRC:
- if (state->flags & 0x0200) {
- NEEDBITS(16);
- if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
- strm->msg = (char *)"header crc mismatch";
- state->mode = BAD;
- break;
- }
- INITBITS();
- }
- if (state->head != Z_NULL) {
- state->head->hcrc = (int)((state->flags >> 9) & 1);
- state->head->done = 1;
- }
- strm->adler = state->check = crc32(0L, Z_NULL, 0);
- state->mode = TYPE;
- break;
-#endif
- case DICTID:
- NEEDBITS(32);
- strm->adler = state->check = ZSWAP32(hold);
- INITBITS();
- state->mode = DICT;
- /* fallthrough */
- case DICT:
- if (state->havedict == 0) {
- RESTORE();
- return Z_NEED_DICT;
- }
- strm->adler = state->check = adler32(0L, Z_NULL, 0);
- state->mode = TYPE;
- /* fallthrough */
- case TYPE:
- if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
- /* fallthrough */
- case TYPEDO:
- if (state->last) {
- BYTEBITS();
- state->mode = CHECK;
- break;
- }
- NEEDBITS(3);
- state->last = BITS(1);
- DROPBITS(1);
- switch (BITS(2)) {
- case 0: /* stored block */
- Tracev((stderr, "inflate: stored block%s\n",
- state->last ? " (last)" : ""));
- state->mode = STORED;
- break;
- case 1: /* fixed block */
- fixedtables(state);
- Tracev((stderr, "inflate: fixed codes block%s\n",
- state->last ? " (last)" : ""));
- state->mode = LEN_; /* decode codes */
- if (flush == Z_TREES) {
- DROPBITS(2);
- goto inf_leave;
- }
- break;
- case 2: /* dynamic block */
- Tracev((stderr, "inflate: dynamic codes block%s\n",
- state->last ? " (last)" : ""));
- state->mode = TABLE;
- break;
- case 3:
- strm->msg = (char *)"invalid block type";
- state->mode = BAD;
- }
- DROPBITS(2);
- break;
- case STORED:
- BYTEBITS(); /* go to byte boundary */
- NEEDBITS(32);
- if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
- strm->msg = (char *)"invalid stored block lengths";
- state->mode = BAD;
- break;
- }
- state->length = (unsigned)hold & 0xffff;
- Tracev((stderr, "inflate: stored length %u\n",
- state->length));
- INITBITS();
- state->mode = COPY_;
- if (flush == Z_TREES) goto inf_leave;
- /* fallthrough */
- case COPY_:
- state->mode = COPY;
- /* fallthrough */
- case COPY:
- copy = state->length;
- if (copy) {
- if (copy > have) copy = have;
- if (copy > left) copy = left;
- if (copy == 0) goto inf_leave;
- zmemcpy(put, next, copy);
- have -= copy;
- next += copy;
- left -= copy;
- put += copy;
- state->length -= copy;
- break;
- }
- Tracev((stderr, "inflate: stored end\n"));
- state->mode = TYPE;
- break;
- case TABLE:
- NEEDBITS(14);
- state->nlen = BITS(5) + 257;
- DROPBITS(5);
- state->ndist = BITS(5) + 1;
- DROPBITS(5);
- state->ncode = BITS(4) + 4;
- DROPBITS(4);
-#ifndef PKZIP_BUG_WORKAROUND
- if (state->nlen > 286 || state->ndist > 30) {
- strm->msg = (char *)"too many length or distance symbols";
- state->mode = BAD;
- break;
- }
-#endif
- Tracev((stderr, "inflate: table sizes ok\n"));
- state->have = 0;
- state->mode = LENLENS;
- /* fallthrough */
- case LENLENS:
- while (state->have < state->ncode) {
- NEEDBITS(3);
- state->lens[order[state->have++]] = (unsigned short)BITS(3);
- DROPBITS(3);
- }
- while (state->have < 19)
- state->lens[order[state->have++]] = 0;
- state->next = state->codes;
- state->lencode = (const code FAR *)(state->next);
- state->lenbits = 7;
- ret = inflate_table(CODES, state->lens, 19, &(state->next),
- &(state->lenbits), state->work);
- if (ret) {
- strm->msg = (char *)"invalid code lengths set";
- state->mode = BAD;
- break;
- }
- Tracev((stderr, "inflate: code lengths ok\n"));
- state->have = 0;
- state->mode = CODELENS;
- /* fallthrough */
- case CODELENS:
- while (state->have < state->nlen + state->ndist) {
- for (;;) {
- here = state->lencode[BITS(state->lenbits)];
- if ((unsigned)(here.bits) <= bits) break;
- PULLBYTE();
- }
- if (here.val < 16) {
- DROPBITS(here.bits);
- state->lens[state->have++] = here.val;
- }
- else {
- if (here.val == 16) {
- NEEDBITS(here.bits + 2);
- DROPBITS(here.bits);
- if (state->have == 0) {
- strm->msg = (char *)"invalid bit length repeat";
- state->mode = BAD;
- break;
- }
- len = state->lens[state->have - 1];
- copy = 3 + BITS(2);
- DROPBITS(2);
- }
- else if (here.val == 17) {
- NEEDBITS(here.bits + 3);
- DROPBITS(here.bits);
- len = 0;
- copy = 3 + BITS(3);
- DROPBITS(3);
- }
- else {
- NEEDBITS(here.bits + 7);
- DROPBITS(here.bits);
- len = 0;
- copy = 11 + BITS(7);
- DROPBITS(7);
- }
- if (state->have + copy > state->nlen + state->ndist) {
- strm->msg = (char *)"invalid bit length repeat";
- state->mode = BAD;
- break;
- }
- while (copy--)
- state->lens[state->have++] = (unsigned short)len;
- }
- }
-
- /* handle error breaks in while */
- if (state->mode == BAD) break;
-
- /* check for end-of-block code (better have one) */
- if (state->lens[256] == 0) {
- strm->msg = (char *)"invalid code -- missing end-of-block";
- state->mode = BAD;
- break;
- }
-
- /* build code tables -- note: do not change the lenbits or distbits
- values here (9 and 6) without reading the comments in inftrees.h
- concerning the ENOUGH constants, which depend on those values */
- state->next = state->codes;
- state->lencode = (const code FAR *)(state->next);
- state->lenbits = 9;
- ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
- &(state->lenbits), state->work);
- if (ret) {
- strm->msg = (char *)"invalid literal/lengths set";
- state->mode = BAD;
- break;
- }
- state->distcode = (const code FAR *)(state->next);
- state->distbits = 6;
- ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
- &(state->next), &(state->distbits), state->work);
- if (ret) {
- strm->msg = (char *)"invalid distances set";
- state->mode = BAD;
- break;
- }
- Tracev((stderr, "inflate: codes ok\n"));
- state->mode = LEN_;
- if (flush == Z_TREES) goto inf_leave;
- /* fallthrough */
- case LEN_:
- state->mode = LEN;
- /* fallthrough */
- case LEN:
- if (have >= 6 && left >= 258) {
- RESTORE();
- inflate_fast(strm, out);
- LOAD();
- if (state->mode == TYPE)
- state->back = -1;
- break;
- }
- state->back = 0;
- for (;;) {
- here = state->lencode[BITS(state->lenbits)];
- if ((unsigned)(here.bits) <= bits) break;
- PULLBYTE();
- }
- if (here.op && (here.op & 0xf0) == 0) {
- last = here;
- for (;;) {
- here = state->lencode[last.val +
- (BITS(last.bits + last.op) >> last.bits)];
- if ((unsigned)(last.bits + here.bits) <= bits) break;
- PULLBYTE();
- }
- DROPBITS(last.bits);
- state->back += last.bits;
- }
- DROPBITS(here.bits);
- state->back += here.bits;
- state->length = (unsigned)here.val;
- if ((int)(here.op) == 0) {
- Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
- "inflate: literal '%c'\n" :
- "inflate: literal 0x%02x\n", here.val));
- state->mode = LIT;
- break;
- }
- if (here.op & 32) {
- Tracevv((stderr, "inflate: end of block\n"));
- state->back = -1;
- state->mode = TYPE;
- break;
- }
- if (here.op & 64) {
- strm->msg = (char *)"invalid literal/length code";
- state->mode = BAD;
- break;
- }
- state->extra = (unsigned)(here.op) & 15;
- state->mode = LENEXT;
- /* fallthrough */
- case LENEXT:
- if (state->extra) {
- NEEDBITS(state->extra);
- state->length += BITS(state->extra);
- DROPBITS(state->extra);
- state->back += state->extra;
- }
- Tracevv((stderr, "inflate: length %u\n", state->length));
- state->was = state->length;
- state->mode = DIST;
- /* fallthrough */
- case DIST:
- for (;;) {
- here = state->distcode[BITS(state->distbits)];
- if ((unsigned)(here.bits) <= bits) break;
- PULLBYTE();
- }
- if ((here.op & 0xf0) == 0) {
- last = here;
- for (;;) {
- here = state->distcode[last.val +
- (BITS(last.bits + last.op) >> last.bits)];
- if ((unsigned)(last.bits + here.bits) <= bits) break;
- PULLBYTE();
- }
- DROPBITS(last.bits);
- state->back += last.bits;
- }
- DROPBITS(here.bits);
- state->back += here.bits;
- if (here.op & 64) {
- strm->msg = (char *)"invalid distance code";
- state->mode = BAD;
- break;
- }
- state->offset = (unsigned)here.val;
- state->extra = (unsigned)(here.op) & 15;
- state->mode = DISTEXT;
- /* fallthrough */
- case DISTEXT:
- if (state->extra) {
- NEEDBITS(state->extra);
- state->offset += BITS(state->extra);
- DROPBITS(state->extra);
- state->back += state->extra;
- }
-#ifdef INFLATE_STRICT
- if (state->offset > state->dmax) {
- strm->msg = (char *)"invalid distance too far back";
- state->mode = BAD;
- break;
- }
-#endif
- Tracevv((stderr, "inflate: distance %u\n", state->offset));
- state->mode = MATCH;
- /* fallthrough */
- case MATCH:
- if (left == 0) goto inf_leave;
- copy = out - left;
- if (state->offset > copy) { /* copy from window */
- copy = state->offset - copy;
- if (copy > state->whave) {
- if (state->sane) {
- strm->msg = (char *)"invalid distance too far back";
- state->mode = BAD;
- break;
- }
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
- Trace((stderr, "inflate.c too far\n"));
- copy -= state->whave;
- if (copy > state->length) copy = state->length;
- if (copy > left) copy = left;
- left -= copy;
- state->length -= copy;
- do {
- *put++ = 0;
- } while (--copy);
- if (state->length == 0) state->mode = LEN;
- break;
-#endif
- }
- if (copy > state->wnext) {
- copy -= state->wnext;
- from = state->window + (state->wsize - copy);
- }
- else
- from = state->window + (state->wnext - copy);
- if (copy > state->length) copy = state->length;
- }
- else { /* copy from output */
- from = put - state->offset;
- copy = state->length;
- }
- if (copy > left) copy = left;
- left -= copy;
- state->length -= copy;
- do {
- *put++ = *from++;
- } while (--copy);
- if (state->length == 0) state->mode = LEN;
- break;
- case LIT:
- if (left == 0) goto inf_leave;
- *put++ = (unsigned char)(state->length);
- left--;
- state->mode = LEN;
- break;
- case CHECK:
- if (state->wrap) {
- NEEDBITS(32);
- out -= left;
- strm->total_out += out;
- state->total += out;
- if ((state->wrap & 4) && out)
- strm->adler = state->check =
- UPDATE_CHECK(state->check, put - out, out);
- out = left;
- if ((state->wrap & 4) && (
-#ifdef GUNZIP
- state->flags ? hold :
-#endif
- ZSWAP32(hold)) != state->check) {
- strm->msg = (char *)"incorrect data check";
- state->mode = BAD;
- break;
- }
- INITBITS();
- Tracev((stderr, "inflate: check matches trailer\n"));
- }
-#ifdef GUNZIP
- state->mode = LENGTH;
- /* fallthrough */
- case LENGTH:
- if (state->wrap && state->flags) {
- NEEDBITS(32);
- if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
- strm->msg = (char *)"incorrect length check";
- state->mode = BAD;
- break;
- }
- INITBITS();
- Tracev((stderr, "inflate: length matches trailer\n"));
- }
-#endif
- state->mode = DONE;
- /* fallthrough */
- case DONE:
- ret = Z_STREAM_END;
- goto inf_leave;
- case BAD:
- ret = Z_DATA_ERROR;
- goto inf_leave;
- case MEM:
- return Z_MEM_ERROR;
- case SYNC:
- /* fallthrough */
- default:
- return Z_STREAM_ERROR;
- }
-
- /*
- Return from inflate(), updating the total counts and the check value.
- If there was no progress during the inflate() call, return a buffer
- error. Call updatewindow() to create and/or update the window state.
- Note: a memory error from inflate() is non-recoverable.
- */
- inf_leave:
- RESTORE();
- if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
- (state->mode < CHECK || flush != Z_FINISH)))
- if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
- state->mode = MEM;
- return Z_MEM_ERROR;
- }
- in -= strm->avail_in;
- out -= strm->avail_out;
- strm->total_in += in;
- strm->total_out += out;
- state->total += out;
- if ((state->wrap & 4) && out)
- strm->adler = state->check =
- UPDATE_CHECK(state->check, strm->next_out - out, out);
- strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
- (state->mode == TYPE ? 128 : 0) +
- (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
- if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
- ret = Z_BUF_ERROR;
- return ret;
-}
-
-int ZEXPORT inflateEnd(z_streamp strm) {
- struct inflate_state FAR *state;
- if (inflateStateCheck(strm))
- return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
- if (state->window != Z_NULL) ZFREE(strm, state->window);
- ZFREE(strm, strm->state);
- strm->state = Z_NULL;
- Tracev((stderr, "inflate: end\n"));
- return Z_OK;
-}
-
-int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
- uInt *dictLength) {
- struct inflate_state FAR *state;
-
- /* check state */
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
-
- /* copy dictionary */
- if (state->whave && dictionary != Z_NULL) {
- zmemcpy(dictionary, state->window + state->wnext,
- state->whave - state->wnext);
- zmemcpy(dictionary + state->whave - state->wnext,
- state->window, state->wnext);
- }
- if (dictLength != Z_NULL)
- *dictLength = state->whave;
- return Z_OK;
-}
-
-int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
- uInt dictLength) {
- struct inflate_state FAR *state;
- unsigned long dictid;
- int ret;
-
- /* check state */
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
- if (state->wrap != 0 && state->mode != DICT)
- return Z_STREAM_ERROR;
-
- /* check for correct dictionary identifier */
- if (state->mode == DICT) {
- dictid = adler32(0L, Z_NULL, 0);
- dictid = adler32(dictid, dictionary, dictLength);
- if (dictid != state->check)
- return Z_DATA_ERROR;
- }
-
- /* copy dictionary to window using updatewindow(), which will amend the
- existing dictionary if appropriate */
- ret = updatewindow(strm, dictionary + dictLength, dictLength);
- if (ret) {
- state->mode = MEM;
- return Z_MEM_ERROR;
- }
- state->havedict = 1;
- Tracev((stderr, "inflate: dictionary set\n"));
- return Z_OK;
-}
-
-int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) {
- struct inflate_state FAR *state;
-
- /* check state */
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
- if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
-
- /* save header structure */
- state->head = head;
- head->done = 0;
- return Z_OK;
-}
-
-/*
- Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
- or when out of input. When called, *have is the number of pattern bytes
- found in order so far, in 0..3. On return *have is updated to the new
- state. If on return *have equals four, then the pattern was found and the
- return value is how many bytes were read including the last byte of the
- pattern. If *have is less than four, then the pattern has not been found
- yet and the return value is len. In the latter case, syncsearch() can be
- called again with more data and the *have state. *have is initialized to
- zero for the first call.
- */
-local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf,
- unsigned len) {
- unsigned got;
- unsigned next;
-
- got = *have;
- next = 0;
- while (next < len && got < 4) {
- if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
- got++;
- else if (buf[next])
- got = 0;
- else
- got = 4 - got;
- next++;
- }
- *have = got;
- return next;
-}
-
-int ZEXPORT inflateSync(z_streamp strm) {
- unsigned len; /* number of bytes to look at or looked at */
- int flags; /* temporary to save header status */
- unsigned long in, out; /* temporary to save total_in and total_out */
- unsigned char buf[4]; /* to restore bit buffer to byte string */
- struct inflate_state FAR *state;
-
- /* check parameters */
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
- if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
-
- /* if first time, start search in bit buffer */
- if (state->mode != SYNC) {
- state->mode = SYNC;
- state->hold >>= state->bits & 7;
- state->bits -= state->bits & 7;
- len = 0;
- while (state->bits >= 8) {
- buf[len++] = (unsigned char)(state->hold);
- state->hold >>= 8;
- state->bits -= 8;
- }
- state->have = 0;
- syncsearch(&(state->have), buf, len);
- }
-
- /* search available input */
- len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
- strm->avail_in -= len;
- strm->next_in += len;
- strm->total_in += len;
-
- /* return no joy or set up to restart inflate() on a new block */
- if (state->have != 4) return Z_DATA_ERROR;
- if (state->flags == -1)
- state->wrap = 0; /* if no header yet, treat as raw */
- else
- state->wrap &= ~4; /* no point in computing a check value now */
- flags = state->flags;
- in = strm->total_in; out = strm->total_out;
- inflateReset(strm);
- strm->total_in = in; strm->total_out = out;
- state->flags = flags;
- state->mode = TYPE;
- return Z_OK;
-}
-
-/*
- Returns true if inflate is currently at the end of a block generated by
- Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
- implementation to provide an additional safety check. PPP uses
- Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
- block. When decompressing, PPP checks that at the end of input packet,
- inflate is waiting for these length bytes.
- */
-int ZEXPORT inflateSyncPoint(z_streamp strm) {
- struct inflate_state FAR *state;
-
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
- return state->mode == STORED && state->bits == 0;
-}
-
-int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
- struct inflate_state FAR *state;
- struct inflate_state FAR *copy;
- unsigned char FAR *window;
- unsigned wsize;
-
- /* check input */
- if (inflateStateCheck(source) || dest == Z_NULL)
- return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)source->state;
-
- /* allocate space */
- copy = (struct inflate_state FAR *)
- ZALLOC(source, 1, sizeof(struct inflate_state));
- if (copy == Z_NULL) return Z_MEM_ERROR;
- window = Z_NULL;
- if (state->window != Z_NULL) {
- window = (unsigned char FAR *)
- ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
- if (window == Z_NULL) {
- ZFREE(source, copy);
- return Z_MEM_ERROR;
- }
- }
-
- /* copy state */
- zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
- zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
- copy->strm = dest;
- if (state->lencode >= state->codes &&
- state->lencode <= state->codes + ENOUGH - 1) {
- copy->lencode = copy->codes + (state->lencode - state->codes);
- copy->distcode = copy->codes + (state->distcode - state->codes);
- }
- copy->next = copy->codes + (state->next - state->codes);
- if (window != Z_NULL) {
- wsize = 1U << state->wbits;
- zmemcpy(window, state->window, wsize);
- }
- copy->window = window;
- dest->state = (struct internal_state FAR *)copy;
- return Z_OK;
-}
-
-int ZEXPORT inflateUndermine(z_streamp strm, int subvert) {
- struct inflate_state FAR *state;
-
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
- state->sane = !subvert;
- return Z_OK;
-#else
- (void)subvert;
- state->sane = 1;
- return Z_DATA_ERROR;
-#endif
-}
-
-int ZEXPORT inflateValidate(z_streamp strm, int check) {
- struct inflate_state FAR *state;
-
- if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
- state = (struct inflate_state FAR *)strm->state;
- if (check && state->wrap)
- state->wrap |= 4;
- else
- state->wrap &= ~4;
- return Z_OK;
-}
-
-long ZEXPORT inflateMark(z_streamp strm) {
- struct inflate_state FAR *state;
-
- if (inflateStateCheck(strm))
- return -(1L << 16);
- state = (struct inflate_state FAR *)strm->state;
- return (long)(((unsigned long)((long)state->back)) << 16) +
- (state->mode == COPY ? state->length :
- (state->mode == MATCH ? state->was - state->length : 0));
-}
-
-unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) {
- struct inflate_state FAR *state;
- if (inflateStateCheck(strm)) return (unsigned long)-1;
- state = (struct inflate_state FAR *)strm->state;
- return (unsigned long)(state->next - state->codes);
-}
diff --git a/kernel/src/compress/zlib/inftrees.c b/kernel/src/compress/zlib/inftrees.c
deleted file mode 100644
index e4203cf09..000000000
--- a/kernel/src/compress/zlib/inftrees.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2023 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "../../../include/compress/zlib/zutil.h"
-#include "../../../include/compress/zlib/inftrees.h"
-
-#define MAXBITS 15
-
-const char inflate_copyright[] =
- " inflate 1.3.0.1 Copyright 1995-2023 Mark Adler ";
-/*
- If you use the zlib library in a product, an acknowledgment is welcome
- in the documentation of your product. If for some reason you cannot
- include such an acknowledgment, I would appreciate that you keep this
- copyright string in the executable of your product.
- */
-
-/*
- Build a set of tables to decode the provided canonical Huffman code.
- The code lengths are lens[0..codes-1]. The result starts at *table,
- whose indices are 0..2^bits-1. work is a writable array of at least
- lens shorts, which is used as a work area. type is the type of code
- to be generated, CODES, LENS, or DISTS. On return, zero is success,
- -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
- on return points to the next available entry's address. bits is the
- requested root table index bits, and on return it is the actual root
- table index bits. It will differ if the request is greater than the
- longest code or if it is less than the shortest code.
- */
-int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
- unsigned codes, code FAR * FAR *table,
- unsigned FAR *bits, unsigned short FAR *work) {
- unsigned len; /* a code's length in bits */
- unsigned sym; /* index of code symbols */
- unsigned min, max; /* minimum and maximum code lengths */
- unsigned root; /* number of index bits for root table */
- unsigned curr; /* number of index bits for current table */
- unsigned drop; /* code bits to drop for sub-table */
- int left; /* number of prefix codes available */
- unsigned used; /* code entries in table used */
- unsigned huff; /* Huffman code */
- unsigned incr; /* for incrementing code, index */
- unsigned fill; /* index for replicating entries */
- unsigned low; /* low bits for current root entry */
- unsigned mask; /* mask for low root bits */
- code here; /* table entry for duplication */
- code FAR *next; /* next available space in table */
- const unsigned short FAR *base; /* base value table to use */
- const unsigned short FAR *extra; /* extra bits table to use */
- unsigned match; /* use base and extra for symbol >= match */
- unsigned short count[MAXBITS+1]; /* number of codes of each length */
- unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
- static const unsigned short lbase[31] = { /* Length codes 257..285 base */
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
- static const unsigned short lext[31] = { /* Length codes 257..285 extra */
- 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 70, 200};
- static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
- 8193, 12289, 16385, 24577, 0, 0};
- static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
- 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
- 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
- 28, 28, 29, 29, 64, 64};
-
- /*
- Process a set of code lengths to create a canonical Huffman code. The
- code lengths are lens[0..codes-1]. Each length corresponds to the
- symbols 0..codes-1. The Huffman code is generated by first sorting the
- symbols by length from short to long, and retaining the symbol order
- for codes with equal lengths. Then the code starts with all zero bits
- for the first code of the shortest length, and the codes are integer
- increments for the same length, and zeros are appended as the length
- increases. For the deflate format, these bits are stored backwards
- from their more natural integer increment ordering, and so when the
- decoding tables are built in the large loop below, the integer codes
- are incremented backwards.
-
- This routine assumes, but does not check, that all of the entries in
- lens[] are in the range 0..MAXBITS. The caller must assure this.
- 1..MAXBITS is interpreted as that code length. zero means that that
- symbol does not occur in this code.
-
- The codes are sorted by computing a count of codes for each length,
- creating from that a table of starting indices for each length in the
- sorted table, and then entering the symbols in order in the sorted
- table. The sorted table is work[], with that space being provided by
- the caller.
-
- The length counts are used for other purposes as well, i.e. finding
- the minimum and maximum length codes, determining if there are any
- codes at all, checking for a valid set of lengths, and looking ahead
- at length counts to determine sub-table sizes when building the
- decoding tables.
- */
-
- /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
- for (len = 0; len <= MAXBITS; len++)
- count[len] = 0;
- for (sym = 0; sym < codes; sym++)
- count[lens[sym]]++;
-
- /* bound code lengths, force root to be within code lengths */
- root = *bits;
- for (max = MAXBITS; max >= 1; max--)
- if (count[max] != 0) break;
- if (root > max) root = max;
- if (max == 0) { /* no symbols to code at all */
- here.op = (unsigned char)64; /* invalid code marker */
- here.bits = (unsigned char)1;
- here.val = (unsigned short)0;
- *(*table)++ = here; /* make a table to force an error */
- *(*table)++ = here;
- *bits = 1;
- return 0; /* no symbols, but wait for decoding to report error */
- }
- for (min = 1; min < max; min++)
- if (count[min] != 0) break;
- if (root < min) root = min;
-
- /* check for an over-subscribed or incomplete set of lengths */
- left = 1;
- for (len = 1; len <= MAXBITS; len++) {
- left <<= 1;
- left -= count[len];
- if (left < 0) return -1; /* over-subscribed */
- }
- if (left > 0 && (type == CODES || max != 1))
- return -1; /* incomplete set */
-
- /* generate offsets into symbol table for each length for sorting */
- offs[1] = 0;
- for (len = 1; len < MAXBITS; len++)
- offs[len + 1] = offs[len] + count[len];
-
- /* sort symbols by length, by symbol order within each length */
- for (sym = 0; sym < codes; sym++)
- if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
-
- /*
- Create and fill in decoding tables. In this loop, the table being
- filled is at next and has curr index bits. The code being used is huff
- with length len. That code is converted to an index by dropping drop
- bits off of the bottom. For codes where len is less than drop + curr,
- those top drop + curr - len bits are incremented through all values to
- fill the table with replicated entries.
-
- root is the number of index bits for the root table. When len exceeds
- root, sub-tables are created pointed to by the root entry with an index
- of the low root bits of huff. This is saved in low to check for when a
- new sub-table should be started. drop is zero when the root table is
- being filled, and drop is root when sub-tables are being filled.
-
- When a new sub-table is needed, it is necessary to look ahead in the
- code lengths to determine what size sub-table is needed. The length
- counts are used for this, and so count[] is decremented as codes are
- entered in the tables.
-
- used keeps track of how many table entries have been allocated from the
- provided *table space. It is checked for LENS and DIST tables against
- the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
- the initial root table size constants. See the comments in inftrees.h
- for more information.
-
- sym increments through all symbols, and the loop terminates when
- all codes of length max, i.e. all codes, have been processed. This
- routine permits incomplete codes, so another loop after this one fills
- in the rest of the decoding tables with invalid code markers.
- */
-
- /* set up for code type */
- switch (type) {
- case CODES:
- base = extra = work; /* dummy value--not used */
- match = 20;
- break;
- case LENS:
- base = lbase;
- extra = lext;
- match = 257;
- break;
- default: /* DISTS */
- base = dbase;
- extra = dext;
- match = 0;
- }
-
- /* initialize state for loop */
- huff = 0; /* starting code */
- sym = 0; /* starting code symbol */
- len = min; /* starting code length */
- next = *table; /* current table to fill in */
- curr = root; /* current table index bits */
- drop = 0; /* current bits to drop from code for index */
- low = (unsigned)(-1); /* trigger new sub-table when len > root */
- used = 1U << root; /* use root table entries */
- mask = used - 1; /* mask for comparing low */
-
- /* check available table space */
- if ((type == LENS && used > ENOUGH_LENS) ||
- (type == DISTS && used > ENOUGH_DISTS))
- return 1;
-
- /* process all codes and make table entries */
- for (;;) {
- /* create table entry */
- here.bits = (unsigned char)(len - drop);
- if (work[sym] + 1U < match) {
- here.op = (unsigned char)0;
- here.val = work[sym];
- }
- else if (work[sym] >= match) {
- here.op = (unsigned char)(extra[work[sym] - match]);
- here.val = base[work[sym] - match];
- }
- else {
- here.op = (unsigned char)(32 + 64); /* end of block */
- here.val = 0;
- }
-
- /* replicate for those indices with low len bits equal to huff */
- incr = 1U << (len - drop);
- fill = 1U << curr;
- min = fill; /* save offset to next table */
- do {
- fill -= incr;
- next[(huff >> drop) + fill] = here;
- } while (fill != 0);
-
- /* backwards increment the len-bit code huff */
- incr = 1U << (len - 1);
- while (huff & incr)
- incr >>= 1;
- if (incr != 0) {
- huff &= incr - 1;
- huff += incr;
- }
- else
- huff = 0;
-
- /* go to next symbol, update count, len */
- sym++;
- if (--(count[len]) == 0) {
- if (len == max) break;
- len = lens[work[sym]];
- }
-
- /* create new sub-table if needed */
- if (len > root && (huff & mask) != low) {
- /* if first time, transition to sub-tables */
- if (drop == 0)
- drop = root;
-
- /* increment past last table */
- next += min; /* here min is 1 << curr */
-
- /* determine length of next table */
- curr = len - drop;
- left = (int)(1 << curr);
- while (curr + drop < max) {
- left -= count[curr + drop];
- if (left <= 0) break;
- curr++;
- left <<= 1;
- }
-
- /* check for enough space */
- used += 1U << curr;
- if ((type == LENS && used > ENOUGH_LENS) ||
- (type == DISTS && used > ENOUGH_DISTS))
- return 1;
-
- /* point entry in root table to sub-table */
- low = huff & mask;
- (*table)[low].op = (unsigned char)curr;
- (*table)[low].bits = (unsigned char)root;
- (*table)[low].val = (unsigned short)(next - *table);
- }
- }
-
- /* fill in remaining table entry if code is incomplete (guaranteed to have
- at most one remaining entry, since if the code is incomplete, the
- maximum code length that was allowed to get this far is one bit) */
- if (huff != 0) {
- here.op = (unsigned char)64; /* invalid code marker */
- here.bits = (unsigned char)(len - drop);
- here.val = (unsigned short)0;
- next[huff] = here;
- }
-
- /* set return parameters */
- *table += used;
- *bits = root;
- return 0;
-}
diff --git a/kernel/src/compress/zlib/trees.c b/kernel/src/compress/zlib/trees.c
deleted file mode 100644
index ef0b65543..000000000
--- a/kernel/src/compress/zlib/trees.c
+++ /dev/null
@@ -1,1117 +0,0 @@
-/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2021 Jean-loup Gailly
- * detect_data_type() function provided freely by Cosmin Truta, 2006
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- * ALGORITHM
- *
- * The "deflation" process uses several Huffman trees. The more
- * common source values are represented by shorter bit sequences.
- *
- * Each code tree is stored in a compressed form which is itself
- * a Huffman encoding of the lengths of all the code strings (in
- * ascending order by source values). The actual code strings are
- * reconstructed from the lengths in the inflate process, as described
- * in the deflate specification.
- *
- * REFERENCES
- *
- * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
- * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
- *
- * Storer, James A.
- * Data Compression: Methods and Theory, pp. 49-50.
- * Computer Science Press, 1988. ISBN 0-7167-8156-5.
- *
- * Sedgewick, R.
- * Algorithms, p290.
- * Addison-Wesley, 1983. ISBN 0-201-06672-6.
- */
-
-/* @(#) $Id$ */
-
-/* #define GEN_TREES_H */
-
-#include "../../../include/compress/zlib/deflate.h"
-
-#ifdef ZLIB_DEBUG
-# include
-#endif
-
-/* ===========================================================================
- * Constants
- */
-
-#define MAX_BL_BITS 7
-/* Bit length codes must not exceed MAX_BL_BITS bits */
-
-#define END_BLOCK 256
-/* end of block literal code */
-
-#define REP_3_6 16
-/* repeat previous bit length 3-6 times (2 bits of repeat count) */
-
-#define REPZ_3_10 17
-/* repeat a zero length 3-10 times (3 bits of repeat count) */
-
-#define REPZ_11_138 18
-/* repeat a zero length 11-138 times (7 bits of repeat count) */
-
-local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
- = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
-
-local const int extra_dbits[D_CODES] /* extra bits for each distance code */
- = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
-
-local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
- = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
-
-local const uch bl_order[BL_CODES]
- = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
-/* The lengths of the bit length codes are sent in order of decreasing
- * probability, to avoid transmitting the lengths for unused bit length codes.
- */
-
-/* ===========================================================================
- * Local data. These are initialized only once.
- */
-
-#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
-
-#if defined(GEN_TREES_H) || !defined(STDC)
-/* non ANSI compilers may not accept trees.h */
-
-local ct_data static_ltree[L_CODES+2];
-/* The static literal tree. Since the bit lengths are imposed, there is no
- * need for the L_CODES extra codes used during heap construction. However
- * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
- * below).
- */
-
-local ct_data static_dtree[D_CODES];
-/* The static distance tree. (Actually a trivial tree since all codes use
- * 5 bits.)
- */
-
-uch _dist_code[DIST_CODE_LEN];
-/* Distance codes. The first 256 values correspond to the distances
- * 3 .. 258, the last 256 values correspond to the top 8 bits of
- * the 15 bit distances.
- */
-
-uch _length_code[MAX_MATCH-MIN_MATCH+1];
-/* length code for each normalized match length (0 == MIN_MATCH) */
-
-local int base_length[LENGTH_CODES];
-/* First normalized length for each code (0 = MIN_MATCH) */
-
-local int base_dist[D_CODES];
-/* First normalized distance for each code (0 = distance of 1) */
-
-#else
-# include "../../../include/compress/zlib/trees.h"
-#endif /* GEN_TREES_H */
-
-struct static_tree_desc_s {
- const ct_data *static_tree; /* static tree or NULL */
- const intf *extra_bits; /* extra bits for each code or NULL */
- int extra_base; /* base index for extra_bits */
- int elems; /* max number of elements in the tree */
- int max_length; /* max bit length for the codes */
-};
-
-#ifdef NO_INIT_GLOBAL_POINTERS
-# define TCONST
-#else
-# define TCONST const
-#endif
-
-local TCONST static_tree_desc static_l_desc =
-{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
-
-local TCONST static_tree_desc static_d_desc =
-{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
-
-local TCONST static_tree_desc static_bl_desc =
-{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
-
-/* ===========================================================================
- * Output a short LSB first on the stream.
- * IN assertion: there is enough room in pendingBuf.
- */
-#define put_short(s, w) { \
- put_byte(s, (uch)((w) & 0xff)); \
- put_byte(s, (uch)((ush)(w) >> 8)); \
-}
-
-/* ===========================================================================
- * Reverse the first len bits of a code, using straightforward code (a faster
- * method would use a table)
- * IN assertion: 1 <= len <= 15
- */
-local unsigned bi_reverse(unsigned code, int len) {
- register unsigned res = 0;
- do {
- res |= code & 1;
- code >>= 1, res <<= 1;
- } while (--len > 0);
- return res >> 1;
-}
-
-/* ===========================================================================
- * Flush the bit buffer, keeping at most 7 bits in it.
- */
-local void bi_flush(deflate_state *s) {
- if (s->bi_valid == 16) {
- put_short(s, s->bi_buf);
- s->bi_buf = 0;
- s->bi_valid = 0;
- } else if (s->bi_valid >= 8) {
- put_byte(s, (Byte)s->bi_buf);
- s->bi_buf >>= 8;
- s->bi_valid -= 8;
- }
-}
-
-/* ===========================================================================
- * Flush the bit buffer and align the output on a byte boundary
- */
-local void bi_windup(deflate_state *s) {
- if (s->bi_valid > 8) {
- put_short(s, s->bi_buf);
- } else if (s->bi_valid > 0) {
- put_byte(s, (Byte)s->bi_buf);
- }
- s->bi_buf = 0;
- s->bi_valid = 0;
-#ifdef ZLIB_DEBUG
- s->bits_sent = (s->bits_sent + 7) & ~7;
-#endif
-}
-
-/* ===========================================================================
- * Generate the codes for a given tree and bit counts (which need not be
- * optimal).
- * IN assertion: the array bl_count contains the bit length statistics for
- * the given tree and the field len is set for all tree elements.
- * OUT assertion: the field code is set for all tree elements of non
- * zero code length.
- */
-local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) {
- ush next_code[MAX_BITS+1]; /* next code value for each bit length */
- unsigned code = 0; /* running code value */
- int bits; /* bit index */
- int n; /* code index */
-
- /* The distribution counts are first used to generate the code values
- * without bit reversal.
- */
- for (bits = 1; bits <= MAX_BITS; bits++) {
- code = (code + bl_count[bits - 1]) << 1;
- next_code[bits] = (ush)code;
- }
- /* Check that the bit counts in bl_count are consistent. The last code
- * must be all ones.
- */
- Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
- "inconsistent bit counts");
- Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
-
- for (n = 0; n <= max_code; n++) {
- int len = tree[n].Len;
- if (len == 0) continue;
- /* Now reverse the bits */
- tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
-
- Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
- n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1));
- }
-}
-
-#ifdef GEN_TREES_H
-local void gen_trees_header(void);
-#endif
-
-#ifndef ZLIB_DEBUG
-# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
- /* Send a code of the given tree. c and tree must not have side effects */
-
-#else /* !ZLIB_DEBUG */
-# define send_code(s, c, tree) \
- { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
- send_bits(s, tree[c].Code, tree[c].Len); }
-#endif
-
-/* ===========================================================================
- * Send a value on a given number of bits.
- * IN assertion: length <= 16 and value fits in length bits.
- */
-#ifdef ZLIB_DEBUG
-local void send_bits(deflate_state *s, int value, int length) {
- Tracevv((stderr," l %2d v %4x ", length, value));
- Assert(length > 0 && length <= 15, "invalid length");
- s->bits_sent += (ulg)length;
-
- /* If not enough room in bi_buf, use (valid) bits from bi_buf and
- * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid))
- * unused bits in value.
- */
- if (s->bi_valid > (int)Buf_size - length) {
- s->bi_buf |= (ush)value << s->bi_valid;
- put_short(s, s->bi_buf);
- s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
- s->bi_valid += length - Buf_size;
- } else {
- s->bi_buf |= (ush)value << s->bi_valid;
- s->bi_valid += length;
- }
-}
-#else /* !ZLIB_DEBUG */
-
-#define send_bits(s, value, length) \
-{ int len = length;\
- if (s->bi_valid > (int)Buf_size - len) {\
- int val = (int)value;\
- s->bi_buf |= (ush)val << s->bi_valid;\
- put_short(s, s->bi_buf);\
- s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
- s->bi_valid += len - Buf_size;\
- } else {\
- s->bi_buf |= (ush)(value) << s->bi_valid;\
- s->bi_valid += len;\
- }\
-}
-#endif /* ZLIB_DEBUG */
-
-
-/* the arguments must not have side effects */
-
-/* ===========================================================================
- * Initialize the various 'constant' tables.
- */
-local void tr_static_init(void) {
-#if defined(GEN_TREES_H) || !defined(STDC)
- static int static_init_done = 0;
- int n; /* iterates over tree elements */
- int bits; /* bit counter */
- int length; /* length value */
- int code; /* code value */
- int dist; /* distance index */
- ush bl_count[MAX_BITS+1];
- /* number of codes at each bit length for an optimal tree */
-
- if (static_init_done) return;
-
- /* For some embedded targets, global variables are not initialized: */
-#ifdef NO_INIT_GLOBAL_POINTERS
- static_l_desc.static_tree = static_ltree;
- static_l_desc.extra_bits = extra_lbits;
- static_d_desc.static_tree = static_dtree;
- static_d_desc.extra_bits = extra_dbits;
- static_bl_desc.extra_bits = extra_blbits;
-#endif
-
- /* Initialize the mapping length (0..255) -> length code (0..28) */
- length = 0;
- for (code = 0; code < LENGTH_CODES-1; code++) {
- base_length[code] = length;
- for (n = 0; n < (1 << extra_lbits[code]); n++) {
- _length_code[length++] = (uch)code;
- }
- }
- Assert (length == 256, "tr_static_init: length != 256");
- /* Note that the length 255 (match length 258) can be represented
- * in two different ways: code 284 + 5 bits or code 285, so we
- * overwrite length_code[255] to use the best encoding:
- */
- _length_code[length - 1] = (uch)code;
-
- /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
- dist = 0;
- for (code = 0 ; code < 16; code++) {
- base_dist[code] = dist;
- for (n = 0; n < (1 << extra_dbits[code]); n++) {
- _dist_code[dist++] = (uch)code;
- }
- }
- Assert (dist == 256, "tr_static_init: dist != 256");
- dist >>= 7; /* from now on, all distances are divided by 128 */
- for ( ; code < D_CODES; code++) {
- base_dist[code] = dist << 7;
- for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
- _dist_code[256 + dist++] = (uch)code;
- }
- }
- Assert (dist == 256, "tr_static_init: 256 + dist != 512");
-
- /* Construct the codes of the static literal tree */
- for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
- n = 0;
- while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
- while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
- while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
- while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
- /* Codes 286 and 287 do not exist, but we must include them in the
- * tree construction to get a canonical Huffman tree (longest code
- * all ones)
- */
- gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
-
- /* The static distance tree is trivial: */
- for (n = 0; n < D_CODES; n++) {
- static_dtree[n].Len = 5;
- static_dtree[n].Code = bi_reverse((unsigned)n, 5);
- }
- static_init_done = 1;
-
-# ifdef GEN_TREES_H
- gen_trees_header();
-# endif
-#endif /* defined(GEN_TREES_H) || !defined(STDC) */
-}
-
-/* ===========================================================================
- * Generate the file trees.h describing the static trees.
- */
-#ifdef GEN_TREES_H
-# ifndef ZLIB_DEBUG
-# include
-# endif
-
-# define SEPARATOR(i, last, width) \
- ((i) == (last)? "\n};\n\n" : \
- ((i) % (width) == (width) - 1 ? ",\n" : ", "))
-
-void gen_trees_header(void) {
- FILE *header = fopen("trees.h", "w");
- int i;
-
- Assert (header != NULL, "Can't open trees.h");
- fprintf(header,
- "/* header created automatically with -DGEN_TREES_H */\n\n");
-
- fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
- for (i = 0; i < L_CODES+2; i++) {
- fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
- static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
- }
-
- fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
- for (i = 0; i < D_CODES; i++) {
- fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
- static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
- }
-
- fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
- for (i = 0; i < DIST_CODE_LEN; i++) {
- fprintf(header, "%2u%s", _dist_code[i],
- SEPARATOR(i, DIST_CODE_LEN-1, 20));
- }
-
- fprintf(header,
- "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
- for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
- fprintf(header, "%2u%s", _length_code[i],
- SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
- }
-
- fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
- for (i = 0; i < LENGTH_CODES; i++) {
- fprintf(header, "%1u%s", base_length[i],
- SEPARATOR(i, LENGTH_CODES-1, 20));
- }
-
- fprintf(header, "local const int base_dist[D_CODES] = {\n");
- for (i = 0; i < D_CODES; i++) {
- fprintf(header, "%5u%s", base_dist[i],
- SEPARATOR(i, D_CODES-1, 10));
- }
-
- fclose(header);
-}
-#endif /* GEN_TREES_H */
-
-/* ===========================================================================
- * Initialize a new block.
- */
-local void init_block(deflate_state *s) {
- int n; /* iterates over tree elements */
-
- /* Initialize the trees. */
- for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
- for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
- for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
-
- s->dyn_ltree[END_BLOCK].Freq = 1;
- s->opt_len = s->static_len = 0L;
- s->sym_next = s->matches = 0;
-}
-
-/* ===========================================================================
- * Initialize the tree data structures for a new zlib stream.
- */
-void ZLIB_INTERNAL _tr_init(deflate_state *s) {
- tr_static_init();
-
- s->l_desc.dyn_tree = s->dyn_ltree;
- s->l_desc.stat_desc = &static_l_desc;
-
- s->d_desc.dyn_tree = s->dyn_dtree;
- s->d_desc.stat_desc = &static_d_desc;
-
- s->bl_desc.dyn_tree = s->bl_tree;
- s->bl_desc.stat_desc = &static_bl_desc;
-
- s->bi_buf = 0;
- s->bi_valid = 0;
-#ifdef ZLIB_DEBUG
- s->compressed_len = 0L;
- s->bits_sent = 0L;
-#endif
-
- /* Initialize the first block of the first file: */
- init_block(s);
-}
-
-#define SMALLEST 1
-/* Index within the heap array of least frequent node in the Huffman tree */
-
-
-/* ===========================================================================
- * Remove the smallest element from the heap and recreate the heap with
- * one less element. Updates heap and heap_len.
- */
-#define pqremove(s, tree, top) \
-{\
- top = s->heap[SMALLEST]; \
- s->heap[SMALLEST] = s->heap[s->heap_len--]; \
- pqdownheap(s, tree, SMALLEST); \
-}
-
-/* ===========================================================================
- * Compares to subtrees, using the tree depth as tie breaker when
- * the subtrees have equal frequency. This minimizes the worst case length.
- */
-#define smaller(tree, n, m, depth) \
- (tree[n].Freq < tree[m].Freq || \
- (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
-
-/* ===========================================================================
- * Restore the heap property by moving down the tree starting at node k,
- * exchanging a node with the smallest of its two sons if necessary, stopping
- * when the heap property is re-established (each father smaller than its
- * two sons).
- */
-local void pqdownheap(deflate_state *s, ct_data *tree, int k) {
- int v = s->heap[k];
- int j = k << 1; /* left son of k */
- while (j <= s->heap_len) {
- /* Set j to the smallest of the two sons: */
- if (j < s->heap_len &&
- smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) {
- j++;
- }
- /* Exit if v is smaller than both sons */
- if (smaller(tree, v, s->heap[j], s->depth)) break;
-
- /* Exchange v with the smallest son */
- s->heap[k] = s->heap[j]; k = j;
-
- /* And continue down the tree, setting j to the left son of k */
- j <<= 1;
- }
- s->heap[k] = v;
-}
-
-/* ===========================================================================
- * Compute the optimal bit lengths for a tree and update the total bit length
- * for the current block.
- * IN assertion: the fields freq and dad are set, heap[heap_max] and
- * above are the tree nodes sorted by increasing frequency.
- * OUT assertions: the field len is set to the optimal bit length, the
- * array bl_count contains the frequencies for each bit length.
- * The length opt_len is updated; static_len is also updated if stree is
- * not null.
- */
-local void gen_bitlen(deflate_state *s, tree_desc *desc) {
- ct_data *tree = desc->dyn_tree;
- int max_code = desc->max_code;
- const ct_data *stree = desc->stat_desc->static_tree;
- const intf *extra = desc->stat_desc->extra_bits;
- int base = desc->stat_desc->extra_base;
- int max_length = desc->stat_desc->max_length;
- int h; /* heap index */
- int n, m; /* iterate over the tree elements */
- int bits; /* bit length */
- int xbits; /* extra bits */
- ush f; /* frequency */
- int overflow = 0; /* number of elements with bit length too large */
-
- for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
-
- /* In a first pass, compute the optimal bit lengths (which may
- * overflow in the case of the bit length tree).
- */
- tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
-
- for (h = s->heap_max + 1; h < HEAP_SIZE; h++) {
- n = s->heap[h];
- bits = tree[tree[n].Dad].Len + 1;
- if (bits > max_length) bits = max_length, overflow++;
- tree[n].Len = (ush)bits;
- /* We overwrite tree[n].Dad which is no longer needed */
-
- if (n > max_code) continue; /* not a leaf node */
-
- s->bl_count[bits]++;
- xbits = 0;
- if (n >= base) xbits = extra[n - base];
- f = tree[n].Freq;
- s->opt_len += (ulg)f * (unsigned)(bits + xbits);
- if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
- }
- if (overflow == 0) return;
-
- Tracev((stderr,"\nbit length overflow\n"));
- /* This happens for example on obj2 and pic of the Calgary corpus */
-
- /* Find the first bit length which could increase: */
- do {
- bits = max_length - 1;
- while (s->bl_count[bits] == 0) bits--;
- s->bl_count[bits]--; /* move one leaf down the tree */
- s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */
- s->bl_count[max_length]--;
- /* The brother of the overflow item also moves one step up,
- * but this does not affect bl_count[max_length]
- */
- overflow -= 2;
- } while (overflow > 0);
-
- /* Now recompute all bit lengths, scanning in increasing frequency.
- * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
- * lengths instead of fixing only the wrong ones. This idea is taken
- * from 'ar' written by Haruhiko Okumura.)
- */
- for (bits = max_length; bits != 0; bits--) {
- n = s->bl_count[bits];
- while (n != 0) {
- m = s->heap[--h];
- if (m > max_code) continue;
- if ((unsigned) tree[m].Len != (unsigned) bits) {
- Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
- s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq;
- tree[m].Len = (ush)bits;
- }
- n--;
- }
- }
-}
-
-#ifdef DUMP_BL_TREE
-# include
-#endif
-
-/* ===========================================================================
- * Construct one Huffman tree and assigns the code bit strings and lengths.
- * Update the total bit length for the current block.
- * IN assertion: the field freq is set for all tree elements.
- * OUT assertions: the fields len and code are set to the optimal bit length
- * and corresponding code. The length opt_len is updated; static_len is
- * also updated if stree is not null. The field max_code is set.
- */
-local void build_tree(deflate_state *s, tree_desc *desc) {
- ct_data *tree = desc->dyn_tree;
- const ct_data *stree = desc->stat_desc->static_tree;
- int elems = desc->stat_desc->elems;
- int n, m; /* iterate over heap elements */
- int max_code = -1; /* largest code with non zero frequency */
- int node; /* new node being created */
-
- /* Construct the initial heap, with least frequent element in
- * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1].
- * heap[0] is not used.
- */
- s->heap_len = 0, s->heap_max = HEAP_SIZE;
-
- for (n = 0; n < elems; n++) {
- if (tree[n].Freq != 0) {
- s->heap[++(s->heap_len)] = max_code = n;
- s->depth[n] = 0;
- } else {
- tree[n].Len = 0;
- }
- }
-
- /* The pkzip format requires that at least one distance code exists,
- * and that at least one bit should be sent even if there is only one
- * possible code. So to avoid special checks later on we force at least
- * two codes of non zero frequency.
- */
- while (s->heap_len < 2) {
- node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
- tree[node].Freq = 1;
- s->depth[node] = 0;
- s->opt_len--; if (stree) s->static_len -= stree[node].Len;
- /* node is 0 or 1 so it does not have extra bits */
- }
- desc->max_code = max_code;
-
- /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree,
- * establish sub-heaps of increasing lengths:
- */
- for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
-
- /* Construct the Huffman tree by repeatedly combining the least two
- * frequent nodes.
- */
- node = elems; /* next internal node of the tree */
- do {
- pqremove(s, tree, n); /* n = node of least frequency */
- m = s->heap[SMALLEST]; /* m = node of next least frequency */
-
- s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
- s->heap[--(s->heap_max)] = m;
-
- /* Create a new node father of n and m */
- tree[node].Freq = tree[n].Freq + tree[m].Freq;
- s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
- s->depth[n] : s->depth[m]) + 1);
- tree[n].Dad = tree[m].Dad = (ush)node;
-#ifdef DUMP_BL_TREE
- if (tree == s->bl_tree) {
- fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
- node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
- }
-#endif
- /* and insert the new node in the heap */
- s->heap[SMALLEST] = node++;
- pqdownheap(s, tree, SMALLEST);
-
- } while (s->heap_len >= 2);
-
- s->heap[--(s->heap_max)] = s->heap[SMALLEST];
-
- /* At this point, the fields freq and dad are set. We can now
- * generate the bit lengths.
- */
- gen_bitlen(s, (tree_desc *)desc);
-
- /* The field len is now set, we can generate the bit codes */
- gen_codes ((ct_data *)tree, max_code, s->bl_count);
-}
-
-/* ===========================================================================
- * Scan a literal or distance tree to determine the frequencies of the codes
- * in the bit length tree.
- */
-local void scan_tree(deflate_state *s, ct_data *tree, int max_code) {
- int n; /* iterates over all tree elements */
- int prevlen = -1; /* last emitted length */
- int curlen; /* length of current code */
- int nextlen = tree[0].Len; /* length of next code */
- int count = 0; /* repeat count of the current code */
- int max_count = 7; /* max repeat count */
- int min_count = 4; /* min repeat count */
-
- if (nextlen == 0) max_count = 138, min_count = 3;
- tree[max_code + 1].Len = (ush)0xffff; /* guard */
-
- for (n = 0; n <= max_code; n++) {
- curlen = nextlen; nextlen = tree[n + 1].Len;
- if (++count < max_count && curlen == nextlen) {
- continue;
- } else if (count < min_count) {
- s->bl_tree[curlen].Freq += count;
- } else if (curlen != 0) {
- if (curlen != prevlen) s->bl_tree[curlen].Freq++;
- s->bl_tree[REP_3_6].Freq++;
- } else if (count <= 10) {
- s->bl_tree[REPZ_3_10].Freq++;
- } else {
- s->bl_tree[REPZ_11_138].Freq++;
- }
- count = 0; prevlen = curlen;
- if (nextlen == 0) {
- max_count = 138, min_count = 3;
- } else if (curlen == nextlen) {
- max_count = 6, min_count = 3;
- } else {
- max_count = 7, min_count = 4;
- }
- }
-}
-
-/* ===========================================================================
- * Send a literal or distance tree in compressed form, using the codes in
- * bl_tree.
- */
-local void send_tree(deflate_state *s, ct_data *tree, int max_code) {
- int n; /* iterates over all tree elements */
- int prevlen = -1; /* last emitted length */
- int curlen; /* length of current code */
- int nextlen = tree[0].Len; /* length of next code */
- int count = 0; /* repeat count of the current code */
- int max_count = 7; /* max repeat count */
- int min_count = 4; /* min repeat count */
-
- /* tree[max_code + 1].Len = -1; */ /* guard already set */
- if (nextlen == 0) max_count = 138, min_count = 3;
-
- for (n = 0; n <= max_code; n++) {
- curlen = nextlen; nextlen = tree[n + 1].Len;
- if (++count < max_count && curlen == nextlen) {
- continue;
- } else if (count < min_count) {
- do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
-
- } else if (curlen != 0) {
- if (curlen != prevlen) {
- send_code(s, curlen, s->bl_tree); count--;
- }
- Assert(count >= 3 && count <= 6, " 3_6?");
- send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2);
-
- } else if (count <= 10) {
- send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3);
-
- } else {
- send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7);
- }
- count = 0; prevlen = curlen;
- if (nextlen == 0) {
- max_count = 138, min_count = 3;
- } else if (curlen == nextlen) {
- max_count = 6, min_count = 3;
- } else {
- max_count = 7, min_count = 4;
- }
- }
-}
-
-/* ===========================================================================
- * Construct the Huffman tree for the bit lengths and return the index in
- * bl_order of the last bit length code to send.
- */
-local int build_bl_tree(deflate_state *s) {
- int max_blindex; /* index of last bit length code of non zero freq */
-
- /* Determine the bit length frequencies for literal and distance trees */
- scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
- scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
-
- /* Build the bit length tree: */
- build_tree(s, (tree_desc *)(&(s->bl_desc)));
- /* opt_len now includes the length of the tree representations, except the
- * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts.
- */
-
- /* Determine the number of bit length codes to send. The pkzip format
- * requires that at least 4 bit length codes be sent. (appnote.txt says
- * 3 but the actual value used is 4.)
- */
- for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
- if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
- }
- /* Update opt_len to include the bit length tree and counts */
- s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4;
- Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
- s->opt_len, s->static_len));
-
- return max_blindex;
-}
-
-/* ===========================================================================
- * Send the header for a block using dynamic Huffman trees: the counts, the
- * lengths of the bit length codes, the literal tree and the distance tree.
- * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
- */
-local void send_all_trees(deflate_state *s, int lcodes, int dcodes,
- int blcodes) {
- int rank; /* index in bl_order */
-
- Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
- Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
- "too many codes");
- Tracev((stderr, "\nbl counts: "));
- send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
- send_bits(s, dcodes - 1, 5);
- send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */
- for (rank = 0; rank < blcodes; rank++) {
- Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
- send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
- }
- Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
-
- send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */
- Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
-
- send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */
- Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
-}
-
-/* ===========================================================================
- * Send a stored block
- */
-void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
- ulg stored_len, int last) {
- send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */
- bi_windup(s); /* align on byte boundary */
- put_short(s, (ush)stored_len);
- put_short(s, (ush)~stored_len);
- if (stored_len)
- zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
- s->pending += stored_len;
-#ifdef ZLIB_DEBUG
- s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
- s->compressed_len += (stored_len + 4) << 3;
- s->bits_sent += 2*16;
- s->bits_sent += stored_len << 3;
-#endif
-}
-
-/* ===========================================================================
- * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
- */
-void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) {
- bi_flush(s);
-}
-
-/* ===========================================================================
- * Send one empty static block to give enough lookahead for inflate.
- * This takes 10 bits, of which 7 may remain in the bit buffer.
- */
-void ZLIB_INTERNAL _tr_align(deflate_state *s) {
- send_bits(s, STATIC_TREES<<1, 3);
- send_code(s, END_BLOCK, static_ltree);
-#ifdef ZLIB_DEBUG
- s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
-#endif
- bi_flush(s);
-}
-
-/* ===========================================================================
- * Send the block data compressed using the given Huffman trees
- */
-local void compress_block(deflate_state *s, const ct_data *ltree,
- const ct_data *dtree) {
- unsigned dist; /* distance of matched string */
- int lc; /* match length or unmatched char (if dist == 0) */
- unsigned sx = 0; /* running index in symbol buffers */
- unsigned code; /* the code to send */
- int extra; /* number of extra bits to send */
-
- if (s->sym_next != 0) do {
-#ifdef LIT_MEM
- dist = s->d_buf[sx];
- lc = s->l_buf[sx++];
-#else
- dist = s->sym_buf[sx++] & 0xff;
- dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
- lc = s->sym_buf[sx++];
-#endif
- if (dist == 0) {
- send_code(s, lc, ltree); /* send a literal byte */
- Tracecv(isgraph(lc), (stderr," '%c' ", lc));
- } else {
- /* Here, lc is the match length - MIN_MATCH */
- code = _length_code[lc];
- send_code(s, code + LITERALS + 1, ltree); /* send length code */
- extra = extra_lbits[code];
- if (extra != 0) {
- lc -= base_length[code];
- send_bits(s, lc, extra); /* send the extra length bits */
- }
- dist--; /* dist is now the match distance - 1 */
- code = d_code(dist);
- Assert (code < D_CODES, "bad d_code");
-
- send_code(s, code, dtree); /* send the distance code */
- extra = extra_dbits[code];
- if (extra != 0) {
- dist -= (unsigned)base_dist[code];
- send_bits(s, dist, extra); /* send the extra distance bits */
- }
- } /* literal or match pair ? */
-
- /* Check for no overlay of pending_buf on needed symbols */
-#ifdef LIT_MEM
- Assert(s->pending < (s->lit_bufsize << 1) + sx, "pendingBuf overflow");
-#else
- Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
-#endif
-
- } while (sx < s->sym_next);
-
- send_code(s, END_BLOCK, ltree);
-}
-
-/* ===========================================================================
- * Check if the data type is TEXT or BINARY, using the following algorithm:
- * - TEXT if the two conditions below are satisfied:
- * a) There are no non-portable control characters belonging to the
- * "block list" (0..6, 14..25, 28..31).
- * b) There is at least one printable character belonging to the
- * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
- * - BINARY otherwise.
- * - The following partially-portable control characters form a
- * "gray list" that is ignored in this detection algorithm:
- * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
- * IN assertion: the fields Freq of dyn_ltree are set.
- */
-local int detect_data_type(deflate_state *s) {
- /* block_mask is the bit mask of block-listed bytes
- * set bits 0..6, 14..25, and 28..31
- * 0xf3ffc07f = binary 11110011111111111100000001111111
- */
- unsigned long block_mask = 0xf3ffc07fUL;
- int n;
-
- /* Check for non-textual ("block-listed") bytes. */
- for (n = 0; n <= 31; n++, block_mask >>= 1)
- if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
- return Z_BINARY;
-
- /* Check for textual ("allow-listed") bytes. */
- if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
- || s->dyn_ltree[13].Freq != 0)
- return Z_TEXT;
- for (n = 32; n < LITERALS; n++)
- if (s->dyn_ltree[n].Freq != 0)
- return Z_TEXT;
-
- /* There are no "block-listed" or "allow-listed" bytes:
- * this stream either is empty or has tolerated ("gray-listed") bytes only.
- */
- return Z_BINARY;
-}
-
-/* ===========================================================================
- * Determine the best encoding for the current block: dynamic trees, static
- * trees or store, and write out the encoded block.
- */
-void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
- ulg stored_len, int last) {
- ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
- int max_blindex = 0; /* index of last bit length code of non zero freq */
-
- /* Build the Huffman trees unless a stored block is forced */
- if (s->level > 0) {
-
- /* Check if the file is binary or text */
- if (s->strm->data_type == Z_UNKNOWN)
- s->strm->data_type = detect_data_type(s);
-
- /* Construct the literal and distance trees */
- build_tree(s, (tree_desc *)(&(s->l_desc)));
- Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
- s->static_len));
-
- build_tree(s, (tree_desc *)(&(s->d_desc)));
- Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
- s->static_len));
- /* At this point, opt_len and static_len are the total bit lengths of
- * the compressed block data, excluding the tree representations.
- */
-
- /* Build the bit length tree for the above two trees, and get the index
- * in bl_order of the last bit length code to send.
- */
- max_blindex = build_bl_tree(s);
-
- /* Determine the best encoding. Compute the block lengths in bytes. */
- opt_lenb = (s->opt_len + 3 + 7) >> 3;
- static_lenb = (s->static_len + 3 + 7) >> 3;
-
- Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
- opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
- s->sym_next / 3));
-
-#ifndef FORCE_STATIC
- if (static_lenb <= opt_lenb || s->strategy == Z_FIXED)
-#endif
- opt_lenb = static_lenb;
-
- } else {
- Assert(buf != (char*)0, "lost buf");
- opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
- }
-
-#ifdef FORCE_STORED
- if (buf != (char*)0) { /* force stored block */
-#else
- if (stored_len + 4 <= opt_lenb && buf != (char*)0) {
- /* 4: two words for the lengths */
-#endif
- /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
- * Otherwise we can't have processed more than WSIZE input bytes since
- * the last block flush, because compression would have been
- * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
- * transform a block into a stored block.
- */
- _tr_stored_block(s, buf, stored_len, last);
-
- } else if (static_lenb == opt_lenb) {
- send_bits(s, (STATIC_TREES<<1) + last, 3);
- compress_block(s, (const ct_data *)static_ltree,
- (const ct_data *)static_dtree);
-#ifdef ZLIB_DEBUG
- s->compressed_len += 3 + s->static_len;
-#endif
- } else {
- send_bits(s, (DYN_TREES<<1) + last, 3);
- send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1,
- max_blindex + 1);
- compress_block(s, (const ct_data *)s->dyn_ltree,
- (const ct_data *)s->dyn_dtree);
-#ifdef ZLIB_DEBUG
- s->compressed_len += 3 + s->opt_len;
-#endif
- }
- Assert (s->compressed_len == s->bits_sent, "bad compressed size");
- /* The above check is made mod 2^32, for files larger than 512 MB
- * and uLong implemented on 32 bits.
- */
- init_block(s);
-
- if (last) {
- bi_windup(s);
-#ifdef ZLIB_DEBUG
- s->compressed_len += 7; /* align on byte boundary */
-#endif
- }
- Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3,
- s->compressed_len - 7*last));
-}
-
-/* ===========================================================================
- * Save the match info and tally the frequency counts. Return true if
- * the current block must be flushed.
- */
-int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
-#ifdef LIT_MEM
- s->d_buf[s->sym_next] = (ush)dist;
- s->l_buf[s->sym_next++] = (uch)lc;
-#else
- s->sym_buf[s->sym_next++] = (uch)dist;
- s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
- s->sym_buf[s->sym_next++] = (uch)lc;
-#endif
- if (dist == 0) {
- /* lc is the unmatched char */
- s->dyn_ltree[lc].Freq++;
- } else {
- s->matches++;
- /* Here, lc is the match length - MIN_MATCH */
- dist--; /* dist = match distance - 1 */
- Assert((ush)dist < (ush)MAX_DIST(s) &&
- (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
- (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
-
- s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++;
- s->dyn_dtree[d_code(dist)].Freq++;
- }
- return (s->sym_next == s->sym_end);
-}
diff --git a/kernel/src/compress/zlib/uncompr.c b/kernel/src/compress/zlib/uncompr.c
deleted file mode 100644
index 61d019b35..000000000
--- a/kernel/src/compress/zlib/uncompr.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* uncompr.c -- decompress a memory buffer
- * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#define ZLIB_INTERNAL
-#include "../../../include/compress/zlib/zlib.h"
-
-/* ===========================================================================
- Decompresses the source buffer into the destination buffer. *sourceLen is
- the byte length of the source buffer. Upon entry, *destLen is the total size
- of the destination buffer, which must be large enough to hold the entire
- uncompressed data. (The size of the uncompressed data must have been saved
- previously by the compressor and transmitted to the decompressor by some
- mechanism outside the scope of this compression library.) Upon exit,
- *destLen is the size of the decompressed data and *sourceLen is the number
- of source bytes consumed. Upon return, source + *sourceLen points to the
- first unused input byte.
-
- uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
- memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
- Z_DATA_ERROR if the input data was corrupted, including if the input data is
- an incomplete zlib stream.
-*/
-int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source,
- uLong *sourceLen) {
- z_stream stream;
- int err;
- const uInt max = (uInt)-1;
- uLong len, left;
- Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
-
- len = *sourceLen;
- if (*destLen) {
- left = *destLen;
- *destLen = 0;
- }
- else {
- left = 1;
- dest = buf;
- }
-
- stream.next_in = (z_const Bytef *)source;
- stream.avail_in = 0;
- stream.zalloc = (alloc_func)0;
- stream.zfree = (free_func)0;
- stream.opaque = (voidpf)0;
-
- err = inflateInit(&stream);
- if (err != Z_OK) return err;
-
- stream.next_out = dest;
- stream.avail_out = 0;
-
- do {
- if (stream.avail_out == 0) {
- stream.avail_out = left > (uLong)max ? max : (uInt)left;
- left -= stream.avail_out;
- }
- if (stream.avail_in == 0) {
- stream.avail_in = len > (uLong)max ? max : (uInt)len;
- len -= stream.avail_in;
- }
- err = inflate(&stream, Z_NO_FLUSH);
- } while (err == Z_OK);
-
- *sourceLen -= len + stream.avail_in;
- if (dest != buf)
- *destLen = stream.total_out;
- else if (stream.total_out && err == Z_BUF_ERROR)
- left = 1;
-
- inflateEnd(&stream);
- return err == Z_STREAM_END ? Z_OK :
- err == Z_NEED_DICT ? Z_DATA_ERROR :
- err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
- err;
-}
-
-int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
- uLong sourceLen) {
- return uncompress2(dest, destLen, source, &sourceLen);
-}
diff --git a/kernel/src/compress/zlib/zutil.c b/kernel/src/compress/zlib/zutil.c
deleted file mode 100644
index 740836653..000000000
--- a/kernel/src/compress/zlib/zutil.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-2017 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#include "../../../include/compress/zlib/zutil.h"
-#ifndef Z_SOLO
-# include "../../../include/compress/zlib/gzguts.h"
-#endif
-
-#include "sys/memory.h"
-
-z_const char * const z_errmsg[10] = {
- (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */
- (z_const char *)"stream end", /* Z_STREAM_END 1 */
- (z_const char *)"", /* Z_OK 0 */
- (z_const char *)"file error", /* Z_ERRNO (-1) */
- (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */
- (z_const char *)"data error", /* Z_DATA_ERROR (-3) */
- (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */
- (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */
- (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
- (z_const char *)""
-};
-
-
-const char * ZEXPORT zlibVersion(void) {
- return ZLIB_VERSION;
-}
-
-uLong ZEXPORT zlibCompileFlags(void) {
- uLong flags;
-
- flags = 0;
- switch ((int)(sizeof(uInt))) {
- case 2: break;
- case 4: flags += 1; break;
- case 8: flags += 2; break;
- default: flags += 3;
- }
- switch ((int)(sizeof(uLong))) {
- case 2: break;
- case 4: flags += 1 << 2; break;
- case 8: flags += 2 << 2; break;
- default: flags += 3 << 2;
- }
- switch ((int)(sizeof(voidpf))) {
- case 2: break;
- case 4: flags += 1 << 4; break;
- case 8: flags += 2 << 4; break;
- default: flags += 3 << 4;
- }
- switch ((int)(sizeof(z_off_t))) {
- case 2: break;
- case 4: flags += 1 << 6; break;
- case 8: flags += 2 << 6; break;
- default: flags += 3 << 6;
- }
-#ifdef ZLIB_DEBUG
- flags += 1 << 8;
-#endif
- /*
-#if defined(ASMV) || defined(ASMINF)
- flags += 1 << 9;
-#endif
- */
-#ifdef ZLIB_WINAPI
- flags += 1 << 10;
-#endif
-#ifdef BUILDFIXED
- flags += 1 << 12;
-#endif
-#ifdef DYNAMIC_CRC_TABLE
- flags += 1 << 13;
-#endif
-#ifdef NO_GZCOMPRESS
- flags += 1L << 16;
-#endif
-#ifdef NO_GZIP
- flags += 1L << 17;
-#endif
-#ifdef PKZIP_BUG_WORKAROUND
- flags += 1L << 20;
-#endif
-#ifdef FASTEST
- flags += 1L << 21;
-#endif
-#if defined(STDC) || defined(Z_HAVE_STDARG_H)
-# ifdef NO_vsnprintf
- flags += 1L << 25;
-# ifdef HAS_vsprintf_void
- flags += 1L << 26;
-# endif
-# else
-# ifdef HAS_vsnprintf_void
- flags += 1L << 26;
-# endif
-# endif
-#else
- flags += 1L << 24;
-# ifdef NO_snprintf
- flags += 1L << 25;
-# ifdef HAS_sprintf_void
- flags += 1L << 26;
-# endif
-# else
-# ifdef HAS_snprintf_void
- flags += 1L << 26;
-# endif
-# endif
-#endif
- return flags;
-}
-
-#ifdef ZLIB_DEBUG
-#include
-# ifndef verbose
-# define verbose 0
-# endif
-int ZLIB_INTERNAL z_verbose = verbose;
-
-void ZLIB_INTERNAL z_error(char *m) {
- fprintf(stderr, "%s\n", m);
- exit(1);
-}
-#endif
-
-/* exported to allow conversion of error code to string for compress() and
- * uncompress()
- */
-const char * ZEXPORT zError(int err) {
- return ERR_MSG(err);
-}
-
-#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
- /* The older Microsoft C Run-Time Library for Windows CE doesn't have
- * errno. We define it as a global variable to simplify porting.
- * Its value is always 0 and should not be used.
- */
- int errno = 0;
-#endif
-
-#ifndef HAVE_MEMCPY
-
-void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) {
- if (len == 0) return;
- do {
- *dest++ = *source++; /* ??? to be unrolled */
- } while (--len != 0);
-}
-
-int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) {
- uInt j;
-
- for (j = 0; j < len; j++) {
- if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
- }
- return 0;
-}
-
-void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) {
- if (len == 0) return;
- do {
- *dest++ = 0; /* ??? to be unrolled */
- } while (--len != 0);
-}
-#endif
-
-#ifndef Z_SOLO
-
-#ifdef SYS16BIT
-
-#ifdef __TURBOC__
-/* Turbo C in 16-bit mode */
-
-# define MY_ZCALLOC
-
-/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
- * and farmalloc(64K) returns a pointer with an offset of 8, so we
- * must fix the pointer. Warning: the pointer must be put back to its
- * original form in order to free it, use zcfree().
- */
-
-#define MAX_PTR 10
-/* 10*64K = 640K */
-
-local int next_ptr = 0;
-
-typedef struct ptr_table_s {
- voidpf org_ptr;
- voidpf new_ptr;
-} ptr_table;
-
-local ptr_table table[MAX_PTR];
-/* This table is used to remember the original form of pointers
- * to large buffers (64K). Such pointers are normalized with a zero offset.
- * Since MSDOS is not a preemptive multitasking OS, this table is not
- * protected from concurrent access. This hack doesn't work anyway on
- * a protected system like OS/2. Use Microsoft C instead.
- */
-
-voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
- voidpf buf;
- ulg bsize = (ulg)items*size;
-
- (void)opaque;
-
- /* If we allocate less than 65520 bytes, we assume that farmalloc
- * will return a usable pointer which doesn't have to be normalized.
- */
- if (bsize < 65520L) {
- buf = farmalloc(bsize);
- if (*(ush*)&buf != 0) return buf;
- } else {
- buf = farmalloc(bsize + 16L);
- }
- if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
- table[next_ptr].org_ptr = buf;
-
- /* Normalize the pointer to seg:0 */
- *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
- *(ush*)&buf = 0;
- table[next_ptr++].new_ptr = buf;
- return buf;
-}
-
-void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
- int n;
-
- (void)opaque;
-
- if (*(ush*)&ptr != 0) { /* object < 64K */
- farfree(ptr);
- return;
- }
- /* Find the original pointer */
- for (n = 0; n < next_ptr; n++) {
- if (ptr != table[n].new_ptr) continue;
-
- farfree(table[n].org_ptr);
- while (++n < next_ptr) {
- table[n-1] = table[n];
- }
- next_ptr--;
- return;
- }
- Assert(0, "zcfree: ptr not found");
-}
-
-#endif /* __TURBOC__ */
-
-
-#ifdef M_I86
-/* Microsoft C in 16-bit mode */
-
-# define MY_ZCALLOC
-
-#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
-# define _halloc halloc
-# define _hfree hfree
-#endif
-
-voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) {
- (void)opaque;
- return _halloc((long)items, size);
-}
-
-void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
- (void)opaque;
- _hfree(ptr);
-}
-
-#endif /* M_I86 */
-
-#endif /* SYS16BIT */
-
-
-#ifndef MY_ZCALLOC /* Any system without a special alloc function */
-
-#ifndef STDC
-extern voidp malloc(uInt size);
-extern voidp calloc(uInt items, uInt size);
-extern void free(voidpf ptr);
-#endif
-
-voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
- (void)opaque;
- return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
- (voidpf)calloc(items, size);
-}
-
-void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
- (void)opaque;
- free(ptr);
-}
-
-#endif /* MY_ZCALLOC */
-
-#endif /* !Z_SOLO */
diff --git a/kernel/src/debug/hexview.c b/kernel/src/debug/hexview.c
index 02a5a634c..ef5bcccc2 100644
--- a/kernel/src/debug/hexview.c
+++ b/kernel/src/debug/hexview.c
@@ -1,15 +1,24 @@
#include "common.h"
-// Prints a hexedecimal dump of memory.
-void hexview_advanced(char* buffer, size_t length, size_t width, bool relative, void (*printer_func)(const char *, ...)) {
- for(size_t i = 0; i < length; i += width) {
+/**
+ * @brief Печатает дамп памяти
+ * @param buffer Место в памяти откуда нужно печать дамп
+ * @param length Длина куска памяти
+ * @param width Сколько байт нужно показать в одной строке
+ * @param relative Показывает относительный адрес если true иначе показывает абсолютный
+ * @param printer_func Функция для печати (должна поддерживать форматирование)
+ */
+void hexview_advanced(void *buffer, size_t length, size_t width, bool relative, void (*printer_func)(const char *, ...)) {
+ char* cbuf = (char*)buffer;
+
+ for(size_t i = 0; i < length; i += width) {
if(relative)
printer_func("%08v: ", i);
else
- printer_func("%08v: ", buffer + i);
+ printer_func("%08v: ", cbuf + i);
for(int j = 0; j < (length - i < width ? length - i : width); j++) {
- printer_func("%02v ", ((char)*(buffer + i + j)) & 0xFF);
+ printer_func("%02v ", ((char)*(cbuf + i + j)) & 0xFF);
}
printer_func("\n");
diff --git a/kernel/src/debug/memmeter.c b/kernel/src/debug/memmeter.c
new file mode 100644
index 000000000..0909dd363
--- /dev/null
+++ b/kernel/src/debug/memmeter.c
@@ -0,0 +1,24 @@
+#include "common.h"
+#include "mem/vmm.h"
+#include "io/ports.h"
+
+void memmeter(void (*function)()) {
+ size_t mem_before = system_heap.used_memory;
+ size_t mem_before_cnt = system_heap.allocated_count;
+
+ function();
+
+ size_t mem_after = system_heap.used_memory;
+ size_t mem_after_cnt = system_heap.allocated_count;
+
+ int delta = (int)mem_after - (int)mem_before;
+
+ qemu_warn("Memory delta: %d bytes (%d objects)",
+ delta, mem_after_cnt - mem_before_cnt);
+
+ if(delta > 0) {
+ qemu_err("Memory leak!");
+ } else if(delta == 0) {
+ qemu_ok("No memory leak! :)");
+ }
+}
diff --git a/kernel/src/desktop/eki.c b/kernel/src/desktop/eki.c
new file mode 100644
index 000000000..eff32e8d5
--- /dev/null
+++ b/kernel/src/desktop/eki.c
@@ -0,0 +1,59 @@
+#include "desktop/render.h"
+#include "desktop/widget_button.h"
+#include "desktop/widget_image.h"
+#include "desktop/widget_label.h"
+#include "drv/disk/dpm.h"
+#include "io/ports.h"
+#include "../lib/libstring/include/string.h"
+
+extern DPM_Disk DPM_Disks[32];
+
+void eki_on_close(Window_t* window);
+
+void eki_start() {
+ vector_t* eki_strings = vector_new();
+
+ Window_t* eki_mainwindow = window_new("Eki");
+ eki_mainwindow->x = 100;
+ eki_mainwindow->y = 100;
+ eki_mainwindow->width = 200;
+ eki_mainwindow->height = 200;
+ eki_mainwindow->canvas_bgcolor = 0x333333;
+ eki_mainwindow->on_close = eki_on_close;
+ eki_mainwindow->data = eki_strings;
+
+ int yoffset = 0;
+
+ for (int i = 0; i < 32; i++) {
+ if (DPM_Disks[i].Ready) {
+ yoffset++;
+
+ string_t* tempstr = string_new();
+ string_append_char(tempstr, 'A' + i);
+
+ vector_push_back(eki_strings, (size_t) tempstr);
+
+ Widget_t* hello_button = new_widget_button(tempstr->data, 0x00ff00, 0x000000);
+ hello_button->x = 10;
+ hello_button->y = 10 + (yoffset * 20);
+ hello_button->width += 30;
+ hello_button->height += 15;
+
+ window_add_widget(eki_mainwindow, hello_button);
+ }
+ }
+
+ eki_mainwindow->state = DISPLAYING;
+}
+
+void eki_on_close(Window_t* window) {
+ qemu_log("EKI close!");
+
+ vector_t* that_vec = (vector_t*)window->data;
+
+ for(int i = 0; i < that_vec->size; i++) {
+ string_destroy((string_t*)vector_get(that_vec, i).element);
+ }
+
+ vector_destroy(that_vec);
+}
\ No newline at end of file
diff --git a/kernel/src/gui/parallel_desktop.c b/kernel/src/desktop/parallel_desktop.c
similarity index 51%
rename from kernel/src/gui/parallel_desktop.c
rename to kernel/src/desktop/parallel_desktop.c
index 1353524be..cb84d5d06 100644
--- a/kernel/src/gui/parallel_desktop.c
+++ b/kernel/src/desktop/parallel_desktop.c
@@ -1,9 +1,17 @@
-#include "gui/render.h"
-#include "gui/widget_image.h"
-#include "gui/widget_button.h"
-#include "gui/widget_label.h"
-#include "io/port_io.h"
+#include "desktop/render.h"
+#include "desktop/widget_button.h"
+#include "desktop/widget_label.h"
+#include "io/serial_port.h"
#include "lib/stdlib.h"
+#include "drv/cmos.h"
+#include "drv/input/keyboard.h"
+#include "io/ports.h"
+#include "mem/vmm.h"
+#include "lib/sprintf.h"
+#include "desktop/widget_image.h"
+#include "sys/scheduler.h"
+#include "desktop/widget_progress.h"
+#include "sys/timer.h"
extern Window_t* focused;
@@ -14,36 +22,82 @@ char membuf[16] = {0};
char label_for_memory[32] = {0};
char label_for_fps[8] = {0};
-void make_time() {
+void make_time_string(char* out) {
sayori_time_t time = get_time();
-
+
uint8_t h = time.hours;
uint8_t m = time.minutes;
uint8_t s = time.seconds;
- if(h < 10) {
- time_for_label[0] = '0';
- time_for_label[1] = ('0' + h);
- }else{
- time_for_label[0] = '0' + (h / 10);
- time_for_label[1] = '0' + (h % 10);
- }
+ sprintf(out, "%02d:%02d:%02d", h, m, s);
+}
- if(m < 10) {
- time_for_label[3] = '0';
- time_for_label[4] = ('0' + m);
- }else{
- time_for_label[3] = '0' + (m / 10);
- time_for_label[4] = '0' + (m % 10);
- }
+void shutdown_system_activity_real() {
+ Window_t* progwin = window_new("Shutting down...");
+
+ progwin->x = 20;
+ progwin->y = 20;
+
+ progwin->width = 500;
+ progwin->height = 160;
+
+ Widget_t* progress = new_widget_progress();
+
+ progress->x = 10;
+ progress->y = 10;
+
+ progress->width = 400;
+ progress->height = 30;
+
+ ((Widget_Progress_t*)progress->custom_widget_data)->current = 0;
+
+ window_add_widget(progwin, progress);
+
+ Widget_t* lab = new_widget_label("Getting ready to shutdown...", 10, 70, 0x00ffff);
+
+ window_add_widget(progwin, lab);
+
+ progwin->state = DISPLAYING;
+
+ size_t tst = timestamp();
- if(s < 10) {
- time_for_label[6] = '0';
- time_for_label[7] = ('0' + s);
- }else{
- time_for_label[6] = '0' + (s / 10);
- time_for_label[7] = '0' + (s % 10);
+ while(1) {
+// if(timestamp() - tst > 100) {
+// tst = timestamp();
+//
+// ((Widget_Progress_t*)progress->custom_widget_data)->current++;
+// }
+ if(timestamp() - tst > 11000) {
+ break;
+ } else if(timestamp() - tst > 9000) {
+ ((Widget_Progress_t *) progress->custom_widget_data)->current = 90;
+ ((Widget_Label_t*)lab->custom_widget_data)->label = "Destroying FS objects...";
+ } else if(timestamp() - tst > 5000) {
+ ((Widget_Progress_t*)progress->custom_widget_data)->current = 50;
+ ((Widget_Label_t*)lab->custom_widget_data)->label = "Synchronizing data to disks...";
+ } else if(timestamp() - tst > 3500) {
+ ((Widget_Progress_t*)progress->custom_widget_data)->current = 40;
+ ((Widget_Label_t*)lab->custom_widget_data)->label = "Flushing logs...";
+ } else if(timestamp() - tst > 2500) {
+ ((Widget_Progress_t*)progress->custom_widget_data)->current = 20;
+ ((Widget_Label_t*)lab->custom_widget_data)->label = "Notifying services...";
+ } else if(timestamp() - tst > 1000) {
+ ((Widget_Progress_t*)progress->custom_widget_data)->current = 10;
+ ((Widget_Label_t*)lab->custom_widget_data)->label = "Destroying FS objects...";
+ }
}
+
+ shutdown();
+}
+
+void shutdown_system_activity() {
+ thread_create(
+ get_current_proc(),
+ shutdown_system_activity_real,
+ 512,
+ true,
+ false
+ );
}
void parallel_desktop_start() {
@@ -54,8 +108,6 @@ void parallel_desktop_start() {
keyboardctl(KEYBOARD_ECHO, false);
log_window_manager_state();
-
- do_load_cursor_from_duke_image();
// ROOT WINDOW
@@ -70,20 +122,14 @@ void parallel_desktop_start() {
qemu_log("Root window! at %x", root_window);
- Widget_t* wallpaper = new_widget_image("/var/Jump.duke");
- qemu_log("Widget Image Info: X: %d; Y: %d W: %d; H: %d",
- wallpaper->x,
- wallpaper->y,
- wallpaper->width,
- wallpaper->height
- );
+ Widget_t* wallpaper = new_widget_image("R:\\Sayori\\bg.tga");
window_add_widget(root_window, wallpaper);
qemu_log("Wallpaper for it...");
// TASKBAR
- Window_t* taskbar = window_new("titlebar");
+ Window_t* taskbar = window_new("taskbar");
taskbar->x = 0;
taskbar->height = 30;
taskbar->y = getScreenHeight() - taskbar->height;
@@ -99,7 +145,7 @@ void parallel_desktop_start() {
qemu_log("Creating time label");
Widget_t* time_label = new_widget_label(time_for_label,
- taskbar->width - 8 * strlen(time_for_label) - 8,
+ taskbar->width - 8 * 8 - 8,
(taskbar->height - 16) / 2,
0x000000
);
@@ -149,6 +195,17 @@ void parallel_desktop_start() {
window_add_widget(window, hello_button);
+ Widget_t* sh_btn = new_widget_button("Shutdown system", 0xff0000, 0x000000);
+ sh_btn->x = 50;
+ sh_btn->y = 80;
+ sh_btn->width += 20;
+ sh_btn->height += 15;
+ sh_btn->on_click = shutdown_system_activity;
+
+ qemu_log("Button for it...");
+
+ window_add_widget(window, sh_btn);
+
root_window->state = DISPLAYING;
taskbar->state = DISPLAYING;
window->state = DISPLAYING;
@@ -160,20 +217,16 @@ void parallel_desktop_start() {
gui_restore();
break;
}
- make_time();
+
+ make_time_string(time_for_label);
gui_render();
- itoa(memory_get_used_kernel()/1024, membuf);
- strcpy(label_for_memory, membuf);
- strcat(label_for_memory, " kBytes used");
+ sprintf(label_for_memory, "%d kB used", system_heap.used_memory / 1024);
frames++;
if(get_time().seconds != seconds_old) {
- memset(membuf, 0, 16);
-
- itoa(frames, membuf);
- strcpy(label_for_fps, membuf);
- strcat(label_for_fps, " FPS");
+ sprintf(label_for_fps, "%d FPS", frames);
+
frames = 0;
seconds_old = get_time().seconds;
}
@@ -192,7 +245,8 @@ void parallel_desktop_start() {
qemu_log("Exit successfully!!!");
- print_allocated_map();
+ clean_tty_screen();
+
tty_printf("Memory allocation info written to COM1 (debug) port!!!");
log_window_manager_state();
diff --git a/kernel/src/gui/render.c b/kernel/src/desktop/render.c
similarity index 66%
rename from kernel/src/gui/render.c
rename to kernel/src/desktop/render.c
index f87f9e783..037a6712f 100644
--- a/kernel/src/gui/render.c
+++ b/kernel/src/desktop/render.c
@@ -1,12 +1,15 @@
-#include "gui/window.h"
#include "gui/basics.h"
-#include "gui/render.h"
#include "gui/pointutils.h"
+#include "desktop/window.h"
+#include "desktop/render.h"
+#include "drv/psf.h"
+#include "io/ports.h"
+#include
+#include "drv/input/mouse.h"
// getConfigFonts(2) - is height of current font
Window_t* active_window = 0; // Window that should be placed over all windows (selected window)
-Window_t** current_windows = 0;
bool dragging_mode = false;
bool click = false;
@@ -17,34 +20,12 @@ uint32_t dragy = 0;
void* cursor_data = 0;
size_t cursor_width = 0, cursor_height = 0;
-DukeHeader_t cursor_meta;
bool cursor_ok = false;
Window_t* focused = 0;
char* cursor_default_path = "/var/cursor_normal.duke";
-void do_load_cursor_from_duke_image() {
- qemu_log("DUKE2CURSOR: Loading cursor from %s", cursor_default_path);
-
- if(cursor_ok) return; // Do not reallocate memory second time.
-
- char error = duke_get_image_metadata(cursor_default_path, &cursor_meta);
- if(error) {
- qemu_log("DUKE2CURSOR: Failed to load: %s", cursor_default_path);
- return;
- }
-
- cursor_data = kmalloc(cursor_meta.data_length);
- if(!cursor_data) {
- qemu_log("DUKE2CURSOR: Failed to allocate %d bytes for DUKE image container!", cursor_meta.data_length);
- return;
- }
-
- duke_get_image_data(cursor_default_path, cursor_meta, cursor_data);
- cursor_ok = true;
-}
-
void gui_restore() {
if(cursor_ok) {
qemu_log("DUKE2CURSOR: Freeing cursor...");
@@ -59,37 +40,8 @@ void gui_restore() {
}
void gui_render_widgets(Window_t* window) {
- Widget_t** widgets = window->widgets;
-
- // qemu_log("Widget list: %x", widgets);
- // qemu_log("Widget count: %d", window->widget_count);
-
- /*
- for (size_t i = 0; i < window->widget_count; i++) {
- // Create copy of Widget and correct to 'stick' to window!
- Widget_t* wgt = widgets[i];
- // qemu_log("Widget original: %x", wgt);
-
- Widget_t* window_linked_wgt = kcalloc(1, sizeof(Widget_t)); // Fails with kcalloc!!!
- // qemu_log("Widget copy: %x", window_linked_wgt);
-
- memcpy(window_linked_wgt, wgt, sizeof(Widget_t));
- // qemu_log("Copied");
-
- window_linked_wgt->x += window->x;
- window_linked_wgt->y += window->y;
-
- // qemu_log("Rendering");
-
- window_linked_wgt->renderer(window_linked_wgt, window);
-
- kfree(window_linked_wgt);
- }
- */
-
- // /*
- for (size_t i = 0; i < window->widget_count; i++) {
- Widget_t* wgt = widgets[i];
+ for (size_t i = 0; i < window->widgets->size; i++) {
+ Widget_t* wgt = (Widget_t *) window->widgets->data[i];
wgt->x += window->x;
wgt->y += window->y;
@@ -99,7 +51,6 @@ void gui_render_widgets(Window_t* window) {
wgt->x -= window->x;
wgt->y -= window->y;
}
- // */
}
void gui_render_window(Window_t* window) {
@@ -137,9 +88,9 @@ void gui_render_window(Window_t* window) {
gui_render_widgets(window);
}
-Window_t* is_point_on_any_window_titlebar(ssize_t x, ssize_t y) {
+Window_t* is_point_on_any_window_titlebar(size_t x, size_t y) {
for (size_t i = 0; i < get_window_count(); i++) {
- struct Window* window = current_windows[i];
+ struct Window* window = WINDOW(i);
if(window->with_title_bar && point_in_rect(
x,
@@ -149,7 +100,7 @@ Window_t* is_point_on_any_window_titlebar(ssize_t x, ssize_t y) {
window->width,
WINDOW_TITLEBAR_HEIGHT
)) {
- return current_windows[i];
+ return WINDOW(i);
}
}
return 0;
@@ -161,13 +112,13 @@ Window_t* is_point_on_any_window(ssize_t x, ssize_t y) {
if(point_in_rect(
x,
y,
- current_windows[i]->x,
- current_windows[i]->y,
- current_windows[i]->width,
- current_windows[i]->height
+ WINDOW(i)->x,
+ WINDOW(i)->y,
+ WINDOW(i)->width,
+ WINDOW(i)->height
)) {
// qemu_log("It's: %d", current_windows[i]->id);
- return current_windows[i];
+ return WINDOW(i);
}
}
return 0;
@@ -175,7 +126,7 @@ Window_t* is_point_on_any_window(ssize_t x, ssize_t y) {
size_t get_window_index(Window_t* win) {
for(size_t i = 0, wnds = get_window_count(); i < wnds; i++){
- if(get_window_list()[i] == win) {
+ if(WINDOW(i) == win) {
return i;
}
}
@@ -200,7 +151,7 @@ void gui_handle_mouse() {
if(left_mouse) {
Window_t* tmp = is_point_on_any_window_titlebar(mouse_x, mouse_y);
- if((tmp != 0) && tmp->with_title_bar) {
+ if(tmp && tmp->with_title_bar) {
if(point_in_rect(
mouse_x,
mouse_y,
@@ -209,6 +160,9 @@ void gui_handle_mouse() {
WINDOW_TITLEBAR_HEIGHT + 2,
WINDOW_TITLEBAR_HEIGHT - 4
) && !dragging_mode) {
+ if(tmp->on_close)
+ tmp->on_close(tmp);
+
window_destroy(tmp);
return;
}else if(!dragging_mode){
@@ -222,8 +176,10 @@ void gui_handle_mouse() {
size_t mw = get_window_index(focused);
if(sw < mw) {
- get_window_list()[sw] = focused;
- get_window_list()[mw] = tmp;
+// WINDOW(sw) = focused;
+// WINDOW(mw) = tmp;
+
+ vector_swap(windows, sw, mw);
}
focused = tmp;
@@ -256,25 +212,20 @@ void gui_handle_mouse() {
click = false;
}
- if(cursor_ok) {
- duke_rawdraw(cursor_data, &cursor_meta, mouse_x, mouse_y);
- }else{
- draw_filled_rectangle(mouse_x, mouse_y, 8, 8, mouse_color);
- }
+ draw_filled_rectangle(mouse_x, mouse_y, 8, 8, mouse_color);
}
-void gui_render_windows(Window_t** current_windows) {
+void gui_render_windows(vector_t* current_windows) {
+
for(size_t i = 0, wnds = get_window_count(); i < wnds; i++){
- // qemu_log("Window %d: W: %d; H: %d", i, current_windows[i]->width, current_windows[i]->height);
- gui_render_window(current_windows[i]);
+// qemu_warn("Rendering %x", WINDOW(i));
+ gui_render_window(WINDOW(i));
}
}
// Return exit status
void gui_render() {
- current_windows = get_window_list();
-
- if(current_windows == 0) {
+ if(windows == 0) {
draw_filled_rectangle(0, 0, getScreenWidth(), getScreenHeight(), 0x666666);
draw_vga_str("No windows in the system.", 25, (getScreenWidth() - 25 * 8) / 2, (getScreenHeight() - 8) / 2, 0);
punch();
@@ -284,7 +235,7 @@ void gui_render() {
// qemu_log("Reached render step");
// qemu_log("Window count: %d", get_window_count());
- gui_render_windows(current_windows);
+ gui_render_windows(windows);
gui_handle_mouse();
punch();
diff --git a/kernel/src/gui/widget.c b/kernel/src/desktop/widget.c
similarity index 90%
rename from kernel/src/gui/widget.c
rename to kernel/src/desktop/widget.c
index d12577e15..8d4144a8f 100644
--- a/kernel/src/gui/widget.c
+++ b/kernel/src/desktop/widget.c
@@ -1,6 +1,7 @@
-#include
-#include "gui/widget.h"
-#include "io/port_io.h"
+#include "desktop/widget.h"
+#include "io/serial_port.h"
+#include "mem/vmm.h"
+#include "io/ports.h"
Widget_t* new_bare_widget(renderer_func_t renderer, destroyer_func_t destroyer, size_t x, size_t y, size_t width, size_t height) {
Widget_t* wgt = kcalloc(sizeof(Widget_t), 1);
@@ -20,6 +21,7 @@ void destroy_widget(Widget_t* widget) {
qemu_log("Destroying widget at %x: W: %d; H: %d", widget, widget->width, widget->height);
widget->destroyer(widget);
kfree(widget);
+ qemu_ok("Destroyed widget");
}
void widget_notify(struct Window* window, struct Widget* widget, WidgetNotifyCode_t code, void* data) {
diff --git a/kernel/src/gui/widget_button.c b/kernel/src/desktop/widget_button.c
similarity index 95%
rename from kernel/src/gui/widget_button.c
rename to kernel/src/desktop/widget_button.c
index 2441957ec..49cd91cf2 100644
--- a/kernel/src/gui/widget_button.c
+++ b/kernel/src/desktop/widget_button.c
@@ -1,8 +1,8 @@
#include
-#include "gui/widget.h"
-#include "gui/widget_button.h"
+#include "desktop/widget.h"
+#include "desktop/widget_button.h"
#include "gui/basics.h"
-#include "io/port_io.h"
+#include "io/serial_port.h"
void destroy_widget_button(Widget_t* widget);
diff --git a/kernel/src/desktop/widget_image.c b/kernel/src/desktop/widget_image.c
new file mode 100644
index 000000000..cfb926751
--- /dev/null
+++ b/kernel/src/desktop/widget_image.c
@@ -0,0 +1,73 @@
+#include
+#include "desktop/widget.h"
+#include "desktop/widget_image.h"
+#include "fmt/tga.h"
+#include "io/serial_port.h"
+#include "io/rgb_image.h"
+#include "sys/pixfmt.h"
+
+void destroy_widget_image(Widget_t* widget);
+
+void widget_image_renderer(struct Widget* this, struct Window* window) {
+ Widget_Image_t* this_data = (Widget_Image_t*)(this->custom_widget_data);
+
+ if(this_data->image_data == NULL)
+ return;
+
+ size_t real_width = this_data->meta.h;
+ size_t real_height = this_data->meta.w;
+
+ draw_rgb_image(this_data->image_data, real_width, real_height, 32, this->x, this->y);
+// drawRect(this->x, this->y, real_width, real_height, 0xff0000);
+}
+
+Widget_t* new_widget_image(const char *path) {
+ Widget_t* wgt = new_bare_widget(
+ &widget_image_renderer,
+ &destroy_widget_image,
+ 0, 0,
+ 0, 0
+ );
+
+ tga_header_t hdr;
+
+ bool ok = tga_extract_info(path, &hdr);
+
+ wgt->custom_widget_data = kcalloc(sizeof(Widget_Image_t), 1);
+ Widget_Image_t* wgt_data = (Widget_Image_t*)wgt->custom_widget_data;
+
+ if(!ok) {
+ wgt_data->loaded = false;
+
+ return wgt;
+ }
+
+ wgt_data->path = path;
+ wgt_data->display_mode = NORMAL;
+ wgt_data->meta = hdr;
+
+ wgt->width = hdr.w;
+ wgt->height = hdr.h;
+
+ void* buffer_image = kcalloc(hdr.w * hdr.h, 4);
+ wgt_data->image_data = buffer_image;
+
+ tga_extract_pixels(path, buffer_image);
+
+ pixfmt_conv(buffer_image, 32, hdr.h, hdr.w, SCREEN_BGR, SCREEN_RGB);
+
+// hexview_advanced(buffer_image, 512, 24, true, new_qemu_printf);
+
+ qemu_ok("Loaded successfully!");
+
+ return wgt;
+}
+
+void destroy_widget_image(Widget_t* widget) {
+ Widget_Image_t* wgt_data = (Widget_Image_t*)(widget->custom_widget_data);
+
+ kfree(wgt_data->image_data);
+ kfree(widget->custom_widget_data);
+
+ qemu_ok("Destroyed image widget");
+}
diff --git a/kernel/src/gui/widget_label.c b/kernel/src/desktop/widget_label.c
similarity index 71%
rename from kernel/src/gui/widget_label.c
rename to kernel/src/desktop/widget_label.c
index a9048a1d7..e13833017 100644
--- a/kernel/src/gui/widget_label.c
+++ b/kernel/src/desktop/widget_label.c
@@ -1,8 +1,10 @@
-#include
-#include "gui/widget.h"
-#include "gui/widget_label.h"
+#include "desktop/widget.h"
+#include "desktop/widget_label.h"
#include "gui/basics.h"
-#include "io/port_io.h"
+#include "lib/string.h"
+#include "drv/psf.h"
+#include "io/ports.h"
+#include "mem/vmm.h"
void widget_label_renderer(struct Widget* this, __attribute__((unused)) struct Window* container) {
Widget_Label_t* this_object = (Widget_Label_t*)(this->custom_widget_data);
@@ -10,11 +12,14 @@ void widget_label_renderer(struct Widget* this, __attribute__((unused)) struct W
// uint32_t color = getColorFont();
// setColorFont(this_object->color);
- draw_vga_str(this_object->label, strlen(this_object->label), this->x, this->y, this_object->color);
+ draw_vga_str(this_object->label,
+// this_object->length,
+ strlen(this_object->label),
+ this->x, this->y, this_object->color);
// setColorFont(color);
}
-Widget_t* new_widget_label(char* label, ssize_t x, ssize_t y, uint32_t color) {
+Widget_t* new_widget_label(const char *label, ssize_t x, ssize_t y, uint32_t color) {
Widget_t* wgt = new_bare_widget(
&widget_label_renderer,
&destroy_widget_label,
@@ -30,6 +35,7 @@ Widget_t* new_widget_label(char* label, ssize_t x, ssize_t y, uint32_t color) {
Widget_Label_t* wgt_data = (Widget_Label_t*)wgt->custom_widget_data;
wgt_data->label = label;
wgt_data->color = color;
+ wgt_data->length = strlen(label);
qemu_log("Okay?");
diff --git a/kernel/src/desktop/widget_progress.c b/kernel/src/desktop/widget_progress.c
new file mode 100644
index 000000000..2ea2b3804
--- /dev/null
+++ b/kernel/src/desktop/widget_progress.c
@@ -0,0 +1,42 @@
+#include "desktop/widget.h"
+#include "desktop/widget_progress.h"
+#include "gui/basics.h"
+#include "lib/string.h"
+#include "drv/psf.h"
+#include "io/ports.h"
+#include "mem/vmm.h"
+
+void widget_progress_renderer(struct Widget* this, __attribute__((unused)) struct Window* container) {
+ Widget_Progress_t* this_object = (Widget_Progress_t*)(this->custom_widget_data);
+
+ size_t cost = this->width / 100;
+
+ if(((Widget_Progress_t*)this->custom_widget_data)->current > 100) {
+ ((Widget_Progress_t*)this->custom_widget_data)->current = 100;
+ }
+
+ draw_rectangle(this->x, this->y, this->width, this->height, 0x000000);
+ draw_filled_rectangle(
+ this->x + 2,
+ this->y + 2,
+ (cost * ((Widget_Progress_t*)this->custom_widget_data)->current),
+ this->height - 4,
+ 0xffffff);
+}
+
+Widget_t* new_widget_progress() {
+ Widget_t* wgt = new_bare_widget(
+ &widget_progress_renderer,
+ &destroy_widget_progress,
+ 0, 0,
+ 1, 1
+ );
+
+ wgt->custom_widget_data = kcalloc(sizeof(Widget_Progress_t), 1);
+
+ return wgt;
+}
+
+void destroy_widget_progress(Widget_t* widget) {
+ kfree(widget->custom_widget_data);
+}
diff --git a/kernel/src/gui/window.c b/kernel/src/desktop/window.c
similarity index 57%
rename from kernel/src/gui/window.c
rename to kernel/src/desktop/window.c
index d28ec8ef5..12b4568d5 100644
--- a/kernel/src/gui/window.c
+++ b/kernel/src/desktop/window.c
@@ -1,13 +1,17 @@
-#include
-#include "gui/window.h"
-#include "gui/render.h"
+#include "desktop/window.h"
+#include "desktop/render.h"
+#include "io/ports.h"
+#include "mem/vmm.h"
+#include "../lib/libvector/include/vector.h"
size_t window_global_id = 0;
size_t window_count = 0;
-Window_t** windows = 0;
+
+vector_t* windows = 0;
Window_t* _window_new(char* title) {
Window_t* win = kcalloc(1, sizeof(Window_t));
+
win->id = window_global_id++;
win->width = 10;
win->height = 10;
@@ -19,13 +23,14 @@ Window_t* _window_new(char* title) {
win->minimizable = true;
win->with_title_bar = true;
win->canvas_bgcolor = WINDOW_CANVAS_COLOR;
- win->widget_count = 0;
- win->widgets = 0;
+ win->widgets = vector_new();
+
qemu_log("Bare window create ok");
+
return win;
}
-Window_t** get_window_list() {
+vector_t * get_window_list() {
return windows;
}
@@ -34,32 +39,19 @@ size_t get_window_count() {
}
void window_add_widget(Window_t* window, Widget_t* widget) {
- qemu_log("Widget count start: %d", window->widget_count);
-
- if(!window->widgets) {
- window->widgets = kcalloc(sizeof(Widget_t*), 1);
- }else{
- window->widgets = krealloc(window->widgets, sizeof(Widget_t*) * (window->widget_count + 1));
- }
+ qemu_log("Widget count start: %d", window->widgets->size);
- window->widgets[window->widget_count] = widget;
- window->widget_count++;
+ vector_push_back(window->widgets, (size_t) widget);
- qemu_log("Widget count end: %d", window->widget_count);
+ qemu_log("Widget count end: %d", window->widgets->size);
qemu_log("Added widget %x to window %x", widget, window);
}
void window_remove_widget(Window_t* window, Widget_t* widget) {
- for (size_t i = 0; i < window->widget_count; i++) {
- if(window->widgets[i] != 0) {
- if(window->widgets[i] == widget) {
- window->widget_count--;
-
- while(i < window->widget_count) {
- qemu_log("WIDGET ARRAY SHIFT: %x (POS: %d) = %x (POS: %d)", windows[i], i, windows[i+1], i+1);
- window->widgets[i] = window->widgets[i+1];
- i++;
- }
+ for (size_t i = 0; i < window->widgets->size; i++) {
+ if(window->widgets->data[i]) {
+ if((Widget_t*)window->widgets->data[i] == widget) {
+ vector_erase_nth(window->widgets, i);
}
}
}
@@ -68,56 +60,41 @@ void window_remove_widget(Window_t* window, Widget_t* widget) {
void _window_add_to_list(Window_t* window) {
if(!windows) {
qemu_log("First time creating windows array!!!");
- windows = kcalloc(sizeof(Window_t*), 1);
- }else{
- qemu_log("Expanding windows array to %d elements", window_count+1);
- windows = krealloc(windows, sizeof(Window_t*) * (window_count+1));
+ windows = vector_new();
}
- windows[window_count++] = window;
- // window_count++;
+ qemu_log("Expanding windows array to %d elements", window_count + 1);
+ vector_push_back(windows, (size_t) window);
+
+ window_count++;
}
void _window_remove_from_list(Window_t* window) {
qemu_log("Window count: %d", window_count);
qemu_log("Removing window with id: %d; Address: %x", window->id, window);
for (size_t i = 0; i < window_count; i++) {
- if(windows[i]) {
- if(windows[i]->id == window->id) {
+ if(WINDOW(i)) {
+ if(WINDOW(i)->id == window->id) {
qemu_log("Found that window at index: %d.", i);
- // TODO: Remove all widgets before freeing.
- qemu_log("Total widgets in window: %d", window->widget_count);
- for (size_t j = 0; j < window->widget_count; j++) {
+ qemu_log("Total widgets in window: %d", window->widgets->size);
+ for (size_t j = 0; j < window->widgets->size; j++) {
qemu_log("|- Removing widget: %x", window->widgets[j]);
- qemu_log("|--- Destroyer at: %x", window->widgets[j]->destroyer);
- //window->widgets[j]->destroyer(window->widgets[j]);
- destroy_widget(window->widgets[j]);
+ qemu_log("|--- Destroyer at: %x", ((Widget_t *)(window->widgets->data[j]))->destroyer);
+ destroy_widget((Widget_t *) window->widgets->data[j]);
}
- kfree(window->widgets);
-
- qemu_log("Shifting array");
+ vector_destroy(window->widgets);
window_count--;
qemu_log("Now, %d windows in the system", window_count);
- // while(windows[i+1] != 0) {
- while(i < window_count) {
- qemu_log("%x (POS: %d) = %x (POS: %d)", windows[i], i, windows[i+1], i+1);
- windows[i] = windows[i+1];
- i++;
- }
- // windows[i+1] = 0;
- if(window_count > 0) {
- qemu_log("Shrinking windows array to %d elements", window_count);
- windows = krealloc(windows, sizeof(Window_t*) * (window_count));
- }else{
+ vector_erase_nth(windows, i);
+
+ if(window_count == 0) {
qemu_log("ZEROING WINDOWS ARRAY");
- kfree(windows);
- windows = 0;
+ vector_destroy(windows);
}
qemu_log("Ok!!!");
- window_global_id--;
break;
}
}
@@ -134,14 +111,40 @@ Window_t* window_new(char* title) {
return instance;
}
+// Returns true if window in list false otherwise
+bool window_is_in_list(Window_t* win) {
+ for(size_t i = 0; i < windows->size; i++) {
+ if (WINDOW(i) == win) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void window_destroy(Window_t* win) {
- qemu_log("Reached window_destroy()");
+ qemu_log(" ========> Reached window_destroy()");
+ if(!windows) {
+ qemu_err("No array!");
+ return;
+ }
if(!win) {
qemu_log("Window address is 0, not destroying it");
return;
}
+
+ if(!window_is_in_list(win)) {
+ qemu_warn("Window not in window list so, please destroy it manually!");
+ return;
+ }
+
if(win->state != NOT_INITIALIZED) {
+ if(win->on_close)
+ win->on_close(win);
+
_window_remove_from_list(win); // Reallocate is here
+ } else {
+ qemu_warn("Window is not initialized, not destroying it");
}
qemu_log("Freeing all its data at: %x", win);
@@ -152,11 +155,13 @@ void window_destroy(Window_t* win) {
}
void destroy_all_windows() {
- qemu_log("DESTROYING ALL WINDOWS KNOWN TO WINDOW MANAGER!!!");
+ qemu_warn("DESTROYING ALL WINDOWS KNOWN TO WINDOW MANAGER!!!");
while(window_count > 0) {
qemu_log("%d windows remaining...", window_count);
- window_destroy(windows[window_count-1]);
+ window_destroy(WINDOW(window_count - 1));
}
+
+ windows = 0;
qemu_log("DESTROYED ALL WINDOWS!");
}
@@ -180,10 +185,10 @@ void window_send_signal(Window_t* window, WindowSignal_t signal, void* data) {
coords->y -= window->y;
qemu_log("Click on: X: %d; Y: %d", coords->x, coords->y);
- qemu_log("Widget count: %d", window->widget_count);
+ qemu_log("Widget count: %d", window->widgets->size);
- for (size_t i = 0; i < window->widget_count; i++) {
- Widget_t* wgt = window->widgets[i];
+ for (size_t i = 0; i < window->widgets->size; i++) {
+ Widget_t* wgt = (Widget_t *) window->widgets->data[i];
// qemu_log("Getting over widget: at %x", wgt);
// qemu_log("X: %d; Y: %d; W: %d; H: %d;", wgt->x, wgt->y, wgt->width, wgt->height);
@@ -214,14 +219,14 @@ void log_window_manager_state() {
qemu_log("===============[WINDOW MANAGER STATE]===================");
qemu_log("Window next global ID to be specified to next window: %d", window_global_id);
qemu_log("Window count: %d", window_count);
- qemu_log("Address of windows array: %d", windows);
+ qemu_log("Address of windows array: %x", windows);
for(size_t i = 0; i < window_count; i++) {
- qemu_log("Window #%d (%x): ID: %d", i, windows[i], windows[i]->id);
- if(windows[i] != 0) {
+ qemu_log("Window #%d (%x): ID: %d", i, windows[i], WINDOW(i)->id);
+ if(WINDOW(i) != 0) {
qemu_log("Widgets:");
- for (size_t j = 0; j < windows[i]->widget_count; j++) {
- qemu_log("|- Widget #%d: at %x", j, windows[i]->widgets[j]);
+ for (size_t j = 0; j < WINDOW(i)->widgets->size; j++) {
+ qemu_log("|- Widget #%d: at %x", j, WINDOW(i)->widgets[j]);
}
}
diff --git a/kernel/src/drv/ata_dma.c b/kernel/src/drv/ata_dma.c
deleted file mode 100644
index f20eabf62..000000000
--- a/kernel/src/drv/ata_dma.c
+++ /dev/null
@@ -1,127 +0,0 @@
-#include
-
-#define ATA_PCI_VEN 0x8086
-#define ATA_PCI_DEV 0x7010
-
-#define ATA_DMA_READ 0xC8
-#define ATA_DMA_WRITE 0xCA
-
-uint8_t ata_busnum;
-uint8_t ata_slot;
-uint8_t ata_func;
-
-uint16_t ata_dma_bar4;
-
-typedef struct prdt {
- uint32_t buffer_phys;
- uint16_t transfer_size;
- uint16_t mark_end;
-}__attribute__((packed)) prdt_t;
-
-void ata_dma_init() {
- pci_find_device(ATA_PCI_VEN, ATA_PCI_DEV, &ata_busnum, &ata_slot, &ata_func);
-
- uint16_t devnum = pci_get_device(ata_busnum, ata_slot, ata_func);
-
- qemu_log("ATA DMA ID: %d (%x)", devnum, devnum);
-
- if(devnum == PCI_VENDOR_NO_DEVICE) {
- qemu_log("ATA DMA not found!");
- return;
- }else{
- qemu_log("Detected ATA DMA");
- }
-
- qemu_log("Enabling Busmastering");
-
- uint16_t command_register = pci_read_confspc_word(ata_busnum, ata_slot, ata_func, 4);
- command_register |= 0x05;
- pci_write(ata_busnum, ata_slot, ata_func, 4, command_register);
-
- qemu_log("Enabled Busmastering!!!");
-
- ata_dma_bar4 = pci_read_confspc_word(ata_busnum, ata_slot, ata_func, 0x20);
-
- ata_dma_bar4--;
-
- qemu_log("ATA DMA: BAR4: %x (%d)", ata_dma_bar4, ata_dma_bar4);
-}
-
-prdt_t* ata_dma_allocate_prdt() {
- return kcalloc(1, sizeof(prdt_t));
-}
-
-void ata_dma_set_prdt_entry(prdt_t* prdt, uint16_t index, uint32_t address, uint16_t byte_count, bool is_last) {
- prdt[index].buffer_phys = address;
- prdt[index].transfer_size = byte_count;
- prdt[index].mark_end = is_last ? (0x8000) : (0x0000);
-}
-
-void ata_dma_test() {
- // SETUP PRDT
-
- prdt_t* prdt = kmalloc_common(sizeof(prdt_t), true);
- memset(prdt, 0, sizeof(prdt_t));
-
- size_t phys_prdt = virt2phys(get_kernel_dir(), prdt);
-
- qemu_log("PRDT: V%x => P%x", prdt, phys_prdt);
-
- // SETUP BUFFER
-
- size_t buf = kmalloc_common(PAGE_SIZE, true);
- memset(buf, 0, PAGE_SIZE);
-
- size_t phys_buf = virt2phys(get_kernel_dir(), buf);
-
- qemu_log("Buffer: V%x => P%x", buf, phys_buf);
-
- ata_dma_set_prdt_entry(prdt, 0, phys_buf, PAGE_SIZE, true);
-
- qemu_log("Address (physical): %x", prdt[0].buffer_phys);
- qemu_log("Size of transfer (bytes): %d", prdt[0].transfer_size);
- qemu_log("Last: %s", prdt[0].mark_end ? "yes" : "no");
-
- outl(ata_dma_bar4, 0);
-
- outl(ata_dma_bar4 + ATA_DMA_PRIMARY_PRDT, phys_prdt);
- // outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, (0xe0 | (0 & 0x0f000000) >> 24));
- ide_select_drive(ATA_PRIMARY, ATA_MASTER);
-
- outb(ATA_PRIMARY_IO + ATA_REG_SECCOUNT0, 1);
-
- outb(ATA_PRIMARY_IO + ATA_REG_LBA0, 0);
- outb(ATA_PRIMARY_IO + ATA_REG_LBA1, 0);
- outb(ATA_PRIMARY_IO + ATA_REG_LBA2, 0);
-
- outb(ATA_PRIMARY_IO + ATA_REG_COMMAND, ATA_CMD_READ_DMA);
-
- outl(ata_dma_bar4, 0x8 | 0x1);
-
- while (1) {
- int status = inb(ata_dma_bar4 + ATA_DMA_PRIMARY_STATUS);
- int dstatus = inb(ATA_PRIMARY_IO + ATA_REG_STATUS);
-
- qemu_log("Status: %x; Dstatus: %x", status, dstatus);
-
- if (!(status & 0x04)) {
- continue;
- }
-
- if (!(dstatus & 0x80)) {
- break;
- }
- }
-
- qemu_log("==============");
- qemu_log("Buffer: %s", buf);
-
- hexview_advanced(buf, 512, 16, true, new_qemu_printf);
-
- qemu_log("Ok?");
-
-
-
- kfree(buf);
- kfree(prdt);
-}
\ No newline at end of file
diff --git a/kernel/src/drv/audio/ac97.c b/kernel/src/drv/audio/ac97.c
index 49d082f77..4cc344e2c 100644
--- a/kernel/src/drv/audio/ac97.c
+++ b/kernel/src/drv/audio/ac97.c
@@ -1,64 +1,105 @@
// AC'97 driver by NDRAEY (Drew Pavlenko >_)
-// FIXME: Partially works in VirtualBox, fully in QEMU
-// FIXME: Per-frame lags! 180 ms!
+// FIXME: Not working in VirtualBox, only in QEMU
-#include
-#include
-#include
-#include
#include
+#include
+#include
+#include "io/ports.h"
+#include "drv/pci.h"
+#include "mem/pmm.h"
+#include "lib/stdio.h"
+#include "mem/vmm.h"
uint8_t ac97_busnum, ac97_slot, ac97_func;
bool ac97_initialized = false;
bool ac97_varibale_sample_rate = false;
+uint16_t native_audio_mixer = 0;
+uint16_t native_audio_bus_master = 0;
+
uint8_t ac97_bar0_type = 0;
uint8_t ac97_bar1_type = 0;
-size_t* physpages_ac97 = 0;
size_t currently_pages_count = 0;
uint32_t current_sample_rate = 44100;
+__attribute__((aligned(PAGE_SIZE))) AC97_BDL_t ac97_buffer[32];
+
+char* ac97_audio_buffer = 0;
+size_t ac97_audio_buffer_phys;
+
// Volume in dB, not % (max 64)
void ac97_set_master_volume(uint8_t left, uint8_t right, bool mute) {
- uint16_t value = (right & 63)
- | ((left & 63) << 8)
- | ((mute) << 15);
-
- outs(native_audio_mixer + NAM_SET_MASTER_VOLUME, value);
+ const uint16_t value = (right & 63) << 0
+ | (left & 63) << 8
+ | (uint8_t)mute << 15;
+ outw(native_audio_mixer + NAM_SET_MASTER_VOLUME, value);
}
// Volume in dB, not % (max 32)
void ac97_set_pcm_volume(uint8_t right, uint8_t left, bool mute) {
- uint16_t value = (right & 31)
- | ((left & 31) << 8)
- | ((mute) << 15);
-
- outs(native_audio_mixer + NAM_SET_PCM_VOLUME, value);
+ uint16_t value = (right & 31) << 0
+ | (left & 31) << 8
+ | (mute?1:0) << 15;
+ outw(native_audio_mixer + NAM_SET_PCM_VOLUME, value);
}
-void ac97_set_pcm_sample_rate(uint32_t sample_rate) {
+void ac97_set_pcm_sample_rate(uint16_t sample_rate) {
if(!ac97_varibale_sample_rate
- || (sample_rate > AC97_MAX_RATE
- || sample_rate < AC97_MIN_RATE)
- ) return;
+ || sample_rate > AC97_MAX_RATE
+ || sample_rate < AC97_MIN_RATE)
+ return;
- outs(native_audio_mixer + NAM_SAMPLE_RATE, sample_rate);
+ outw(native_audio_mixer + NAM_SAMPLE_RATE, sample_rate);
+// outs(native_audio_mixer + 0x2E, sample_rate);
+// outs(native_audio_mixer + 0x30, sample_rate);
}
+//void ac97_load_data(char* data, uint32_t length) {
+// size_t samples = 0xfffe;
+// size_t i;
+// size_t times = MIN(31, length/samples);
+//
+// for (i = 0; i < times; i++) {
+// ac97_buffer[i].memory_pos = data + (i * samples);
+// ac97_buffer[i].sample_count = samples;
+// }
+// ac97_buffer[i-1].flags = 1 << 14; // 14 bit - last entry of buffer, stop playing
+//}
+
void ac97_reset_channel() {
outb(native_audio_bus_master + 0x1b, inb(native_audio_bus_master + 0x1B) | 0x02);
}
+void ac97_clear_status_register() {
+ outb(native_audio_bus_master + 0x16, 0x1C);
+}
+
+void _ac97_update_bdl(uint32_t address) {
+ outl(native_audio_bus_master + NABM_PCM_OUT, address); // BDL Address register
+}
+
+void ac97_update_bdl() {
+ _ac97_update_bdl((uint32_t) ac97_buffer);
+}
+
+void ac97_update_lvi(uint8_t index) {
+ outb(native_audio_bus_master + NABM_PCM_OUT + 0x05, index);
+}
+
+void ac97_set_play_sound(bool play) {
+// outb(native_audio_bus_master + 0x1b, inb(native_audio_bus_master + 0x1B) | (uint8_t)play);
+ outb(native_audio_bus_master + 0x1b, (uint8_t)play);
+}
+
void ac97_init() {
// Find device
- pci_find_device(AC97_VENDOR, AC97_DEVICE,
- &ac97_busnum, &ac97_slot, &ac97_func);
+ pci_find_device(AC97_VENDOR, AC97_DEVICE, &ac97_busnum, &ac97_slot, &ac97_func);
- uint16_t devnum = pci_get_device(ac97_busnum, ac97_slot, ac97_func);
+ const uint16_t devnum = pci_get_device(ac97_busnum, ac97_slot, ac97_func);
qemu_log("AC'97 ID: %d (%x)", devnum, devnum);
@@ -88,37 +129,30 @@ void ac97_init() {
native_audio_mixer--;
native_audio_bus_master--;
+ // uint8_t hdrtype = pci_get_hdr_type(ac97_busnum, ac97_slot, ac97_func);
+ // native_audio_mixer = pci_get_bar(hdrtype, ac97_busnum, ac97_slot, ac97_func, 0, ac97_bar0_type); // BAR0
+ // native_audio_bus_master = pci_get_bar(hdrtype, ac97_busnum, ac97_slot, ac97_func, 1, ac97_bar1_type); // BAR1
+
qemu_log("NAM: %x; NABM: %x", native_audio_mixer, native_audio_bus_master);
- uint16_t extended_id = ins(native_audio_mixer + NAM_EXTENDED_ID);
+ const uint16_t extended_id = inw(native_audio_mixer + NAM_EXTENDED_ID);
- uint8_t rev = ((extended_id & (3 << 10)) >> 10) & 0b11;
- qemu_log("Codec revision: (%d) %s", rev,
- rev == 0 ? "r < 21" : (
- rev == 1 ? "r22" : (
- rev == 2 ? "r23"
- : "Not supported"
- )
- )
- );
+ const size_t rev = (extended_id >> 10) & 0b11;
+ const char* rev_strs[] = {"r < 21", "r22", "r23"};
+ qemu_log("Codec revision: (%d) %s", rev, rev_strs[rev]);
uint32_t gc = inl(native_audio_bus_master + NABM_GLOBAL_CONTROL);
qemu_log("Received global control: (%d) %x", gc, gc);
- gc |= 2; // Cold reset
-
- uint32_t word = pci_read_confspc_word(ac97_busnum, ac97_slot, ac97_func, 0x3C); // All 0xF PCI register
-
- qemu_log("AC'97's IRQ is: %d", word & 0xff);
-
+ gc |= 1 << 1; // Cold reset
outl(native_audio_bus_master + NABM_GLOBAL_CONTROL, gc);
- outs(native_audio_mixer + NAM_RESET, 1);
+ outw(native_audio_mixer + NAM_RESET, 1);
qemu_log("Cold reset");
// /*
// ac97_global_status_t status;
// ac97_global_status_t* statusptr = &status;
- uint32_t status = inl(native_audio_bus_master + NABM_GLOBAL_STATUS);
+ const uint32_t status = inl(native_audio_bus_master + NABM_GLOBAL_STATUS);
qemu_log("Status: %x", status);
// qemu_log("Status: %d (%x)\n", status, status);
@@ -128,49 +162,26 @@ void ac97_init() {
// */
- uint16_t extended_audio = ins(native_audio_mixer + NAM_EXTENDED_AUDIO);
+ uint16_t extended_audio = inw(native_audio_mixer + NAM_EXTENDED_AUDIO);
qemu_log("Status: %d", extended_audio);
- if((extended_id & 1) > 0) { // Check for variable sample rate
- qemu_log("AC'97 supports variable sample rate!!!");
+ if((extended_id & 1) != 0) { // Check for variable sample rate
+ qemu_log("AC'97 supports variable sample rate!!!\n");
extended_audio |= 1;
ac97_varibale_sample_rate = true;
}
- outs(native_audio_mixer + NAM_EXTENDED_AUDIO, extended_audio);
+ outw(native_audio_mixer + NAM_EXTENDED_AUDIO, extended_audio);
- // ac97_set_pcm_sample_rate(ac97_varibale_sample_rate ? 44100 : 48000);
- ac97_set_pcm_sample_rate(44100);
+ ac97_set_pcm_sample_rate(ac97_varibale_sample_rate ? 44100 : 48000);
ac97_set_master_volume(0, 0, false);
ac97_set_pcm_volume(0, 0, false);
- qemu_log("Updated capabilities");
+ qemu_log("Updated capabilities\n");
ac97_initialized = true;
- currently_pages_count = BUFFER_SIZE / PAGE_SIZE;
- physpages_ac97 = kcalloc(currently_pages_count, sizeof(size_t));
-
- for(size_t i = 0; i < currently_pages_count; i++) {
- physpages_ac97[i] = alloc_phys_pages(1);
-
- map_pages(
- get_kernel_dir(),
- physpages_ac97[i],
- physpages_ac97[i],
- 1,
- (PAGE_WRITEABLE | PAGE_PRESENT)
- );
-
- qemu_log("AC97: V: %x; P: %x", physpages_ac97[i], physpages_ac97[i]);
- }
-
- qemu_log("OK: Page count for 64 KB buffer is: %d", currently_pages_count);
- qemu_log(" Physical pages position: %x", physpages_ac97);
-
- qemu_log("sizeof(BDL_ENTRY) = %d", sizeof(AC97_BDL_t));
-
qemu_log("AC'97 initialized successfully!");
}
@@ -178,72 +189,85 @@ bool ac97_is_initialized() {
return ac97_initialized;
}
-size_t ac97_copy_user_memory_to_dma(char* data, size_t length) {
- if(length > BUFFER_SIZE)
- return currently_pages_count;
+size_t ac97_copy_user_memory_to_dma(const char* data, size_t length) {
+ currently_pages_count = length / PAGE_SIZE;
- for(size_t i = 0; i < currently_pages_count; i++) {
- memcpy(((char*)physpages_ac97[i]), data + (i * PAGE_SIZE), PAGE_SIZE);
- }
+ ac97_audio_buffer = kmalloc_common(length, PAGE_SIZE);
+ ac97_audio_buffer_phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t) ac97_audio_buffer);
+
+ memcpy(ac97_audio_buffer, data, length);
+
+ qemu_log("Made user buffer with %d pages on a board", currently_pages_count);
return currently_pages_count;
}
void ac97_destroy_user_buffer() {
- if(!physpages_ac97)
- return;
-
- for (register size_t i = 0; i < currently_pages_count; i++) {
- unmap_pages(get_kernel_dir(), physpages_ac97[i], 1);
- vmm_free_page(physpages_ac97[i]);
- }
+// if(!physpages_ac97)
+// return;
+//
+// for (size_t i = 0; i < currently_pages_count; i++) {
+// phys_free_single_page(physpages_ac97[i]);
+// }
- kfree(physpages_ac97);
+// memset(physpages_ac97, 0, sizeof(size_t) * currently_pages_count);
+// kfree(physpages_ac97);
+ kfree(ac97_audio_buffer);
currently_pages_count = 0;
- physpages_ac97 = 0;
+// physpages_ac97 = 0;
qemu_log("Destroyed buffer");
}
-void ac97_single_page_write(ssize_t page_num) {
- size_t pgs = MIN(page_num, 32);
-
- for (register size_t j = 0; j < pgs; j++) {
- ac97_bdl_buffer[j].memory_pos = (size_t)physpages_ac97[j];
- ac97_bdl_buffer[j].sample_count = PAGE_SIZE / 2;
+void ac97_single_page_write_wait(size_t page_num) {
+ size_t remaining_pages = currently_pages_count - page_num;
+ for (size_t j = 0; j < MIN(remaining_pages, 32); j++) {
+// ac97_buffer[j].memory_pos = physpages_ac97[(remaining_pages) + j];
+ ac97_buffer[j].memory_pos = (void *) (ac97_audio_buffer_phys + ((page_num + j) * PAGE_SIZE));
+ ac97_buffer[j].sample_count = PAGE_SIZE / 2;
}
- ac97_bdl_buffer[pgs].flags = 1 << 14;
+ ac97_buffer[remaining_pages >= 31 ? 31 : remaining_pages].flags = 1 << 14;
ac97_update_bdl();
- ac97_update_lvi(31);
+ ac97_update_lvi(remaining_pages >= 31 ? 31 : remaining_pages);
ac97_set_play_sound(true);
ac97_clear_status_register();
+
+ while(inb(native_audio_bus_master + 0x16) == 0) {}
+
+ memset(&ac97_buffer, 0, sizeof(AC97_BDL_t)*31);
}
-// FIXME: Needs optimizations
+void ac97_test() {
+ FILE* file = fopen("R:\\Sayori\\a.wav", "rb");
+ fseek(file, 0, SEEK_END);
-void ac97_single_page_write_wait(ssize_t page_num) {
- ac97_single_page_write(page_num);
+ const uint32_t filesize = ftell(file);
- qemu_log("Polling...");
-
- // uint16_t status = 0;
- //
- // while(status == 0) {
- // fast_ins(native_audio_bus_master + NABM_PCM_OUT + 0x06, status);
- // }
+ fseek(file, 0xae, SEEK_SET);
- // This also works, but without `sleep_ms` function it skips a lot of frames.
- while(ins(native_audio_bus_master + NABM_PCM_OUT + 0x08) != 0);
- sleep_ms(140);
+ char* data = kmalloc(filesize);
+ fread(file, filesize, 1, data);
+
+ size_t page_count = ac97_copy_user_memory_to_dma(data, filesize);
+
+ qemu_log("Allocated %d pages for user memory in DMA", page_count);
+
+ ac97_set_master_volume(2, 2, false);
+ ac97_set_pcm_volume(2, 2, false);
+
+ for(ssize_t i = 0; i < page_count; i += 32) {
+ ac97_single_page_write_wait(i);
+ }
- // How to fix that?
- /// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ qemu_log("Exiting");
+ ac97_reset_channel();
- qemu_log("Ok!");
+ kfree(data);
+ fclose(file);
- ac97_clear_bdl();
+ ac97_destroy_user_buffer();
}
diff --git a/kernel/src/drv/beeper.c b/kernel/src/drv/beeper.c
old mode 100755
new mode 100644
index 478f93ae6..b0b2266c2
--- a/kernel/src/drv/beeper.c
+++ b/kernel/src/drv/beeper.c
@@ -2,27 +2,28 @@
* @file drv/beeper.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru)
* @brief Драйвер пищалки
- * @version 0.3.3
+ * @version 0.3.4
* @date 2022-10-10
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-#include
#include
#include
+#include
+
uint32_t config = 0; ///< Корректировка
/**
- * @brief [Beeper] Вопроизвести звук
+ * @brief Вопроизвести звук (квадратной формы волны)
*
- * @param uint32_t nFrequence - Частота звука
+ * @param frequency - Частота звука
*/
-void beeperPlay(uint32_t nFrequence) {
+void beeperPlay(uint32_t frequency) {
uint32_t Div;
uint8_t tmp;
- Div = (getFrequency()*1000) + config;
- Div /= nFrequence;
+ Div = getFrequency() * 1000;
+ Div /= frequency;
outb(0x43, 0xb6);
outb(0x42, (uint8_t) (Div) );
@@ -41,212 +42,4 @@ void beeperPlay(uint32_t nFrequence) {
void beeperSilent() {
uint8_t tmp = inb(0x61) & 0xFC;
outb(0x61, tmp);
-}
-
-/**
- * @brief [Beeper] Настроить звук
- *
- * @param uint32_t val - Корректировка частоты
- */
-void beeperConfig(uint32_t val){
- config = val;
-}
-
-/**
- * @brief [Beeper] Инициализация
- */
-
-void beeperInit(int test){
- qemu_log("[Beeper] Init...");
- if(test != 1 & test != 2)
- {
- // beeperPlay(1000);
- }
- sleep_ms(50);
- beeperSilent();
- // FIXME: Beeper interrupts for a short time.
- if (test == 1){
-
- Note notes[150] = {
- {A4, 200},
- {A4, 200},
- {C5, 200},
- {A4, 200},
- {D5, 200},
- {A4, 200},
- {E5, 200},
- {D5, 200},
- {C5, 200},
- {C5, 200},
- {E5, 200},
- {C5, 200},
- {E5, 200},
- {C5, 200},
- {G5, 200},
- {C5, 200},
- {E5, 200},
- {C5, 200},
- {G4, 200},
- {G4, 200},
- {B4, 200},
- {G4, 200},
- {C5, 200},
- {G4, 200},
- {D5, 200},
- {C5, 200},
- {F4, 200},
- {F4, 200},
- {A4, 200},
- {F4, 200},
- {C5, 200},
- {F4, 200},
- {C5, 200},
- {B4, 200},
- {A4, 200},
- {A4, 200},
- {C5, 200},
- {A4, 200},
- {D5, 200},
- {A4, 200},
- {E5, 200},
- {D5, 200},
- {C5, 200},
- {C5, 200},
- {E5, 200},
- {D5, 200},
- {C5, 200},
- {C5, 200},
- {E5, 200},
- {C5, 200},
- {G5, 200},
- {C5, 200},
- {E5, 200},
- {C5, 200},
- {G4, 200},
- {G4, 200},
- {B4, 200},
- {G4, 200},
- {C5, 200},
- {G4, 200},
- {C5, 200},
- {G4, 200},
- {D5, 200},
- {C5, 200},
- {F4, 200},
- {F4, 200},
- {A4, 200},
- {F4, 200},
- {C5, 200},
- {F4, 200},
- {C5, 200},
- {B4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {G4, 200},
- {C5, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {G4, 200},
- {E4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {G4, 200},
- {C5, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {G4, 200},
- {C4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {G4, 200},
- {E4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {G4, 200},
- {C5, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- {A4, 200},
- };
- for(int i = 0; i < 122; i++) {
- if(notes[i].freq == 0) continue;
- beeperPlay(notes[i].freq);
- tty_printf("%d ", notes[i].freq);
- if (notes[i].duration == 0){
- beeperSilent();
- sleep_ms(100);
- continue;
- }
- sleep_ms((notes[i].duration)/3);
- beeperSilent();
- sleep_ms(100);
- }
- beeperSilent();
- }
- else if (test == 2)
- {
- Note notes[150] = {
- {A2, 50},
- {A3, 1000},
- {A4, 1000},
- {A2, 50},
- {A3, 1000},
- {A4, 1000},
- {C3, 50},
- {F3, 1000},
- {Fd4, 1000},
- {C3, 50},
- {F3, 1000},
- {Fd4, 1000},
- {A2, 50},
- {A3, 1000},
- {A4, 1000},
- {A2, 50},
- {A3, 1000},
- {A4, 1000},
- {C3, 50},
- {F3, 1000},
- {Fd4, 1000},
- {C3, 50},
- {F3, 1000},
- {Fd4, 1000},
- };
- for(int i = 0; i < 122; i++) {
- if(notes[i].freq == 0) continue;
- beeperPlay(notes[i].freq);
- tty_printf("%d ", notes[i].freq);
- if (notes[i].duration == 0){
- beeperSilent();
- sleep_ms(100);
- continue;
- }
- sleep_ms((notes[i].duration)/3);
- beeperSilent();
- sleep_ms(100);
- }
- beeperSilent();
- }
- qemu_log("Ok");
-}
+}
\ No newline at end of file
diff --git a/kernel/src/drv/cmos.c b/kernel/src/drv/cmos.c
old mode 100755
new mode 100644
index 0e24ef9cb..3cfede887
--- a/kernel/src/drv/cmos.c
+++ b/kernel/src/drv/cmos.c
@@ -2,13 +2,16 @@
* @file drv/cmos.c
* @brief Драйвер CMOS
* @author NDRAEY >_ (pikachu_andrey@vk.com)
- * @version 0.3.3
+ * @version 0.3.4
* @date 2022-11-01
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-
-#include
+#include "common.h"
+#include "io/ports.h"
+#include "drv/cmos.h"
+
+// FIXME: We need this?
#define CURRENT_YEAR 2022 // Change this each year!
int32_t century_register = 0x00; // Set by ACPI table parsing code if possible
@@ -37,6 +40,8 @@ enum {
/**
* @brief Проверяет CMOS на обновление
+ *
+ * @return Если значение не равно нулю, значит CMOS обновляется
*/
int32_t get_update_in_progress_flag() {
outb(cmos_address, 0x0A);
@@ -54,7 +59,6 @@ unsigned char get_RTC_register(int32_t reg) {
/**
* @brief Считывает время с CMOS
*/
-
void read_rtc() {
while (get_update_in_progress_flag()); // Make sure an update isn't in progress
@@ -127,6 +131,8 @@ void read_rtc() {
/**
* @brief Это високосный год?
+ *
+ * @param year Год в формате YYYY
*/
int isleap(int year) {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
diff --git a/kernel/src/drv/disk/ahci.c b/kernel/src/drv/disk/ahci.c
new file mode 100644
index 000000000..266cd9da6
--- /dev/null
+++ b/kernel/src/drv/disk/ahci.c
@@ -0,0 +1,642 @@
+#include "drv/disk/ahci.h"
+
+#include
+
+#include "drv/pci.h"
+#include "io/ports.h"
+#include "io/tty.h"
+#include "mem/pmm.h"
+#include "mem/vmm.h"
+#include "sys/isr.h"
+#include "drv/disk/ata.h"
+#include "debug/hexview.h"
+#include "drv/atapi.h"
+
+#define AHCI_CLASS 1
+#define AHCI_SUBCLASS 6
+
+struct ahci_port_descriptor ports[32] = {0};
+
+uint8_t ahci_busnum, ahci_slot, ahci_func;
+uint16_t ahci_vendor, ahci_devid;
+uint32_t ahci_irq;
+bool ahci_initialized = false;
+
+AHCI_HBA_MEM* abar;
+
+#undef qemu_log
+#undef qemu_err
+#undef qemu_warn
+#undef qemu_ok
+#define qemu_log(M, ...) tty_printf(M "\n", ##__VA_ARGS__)
+#define qemu_err(M, ...) tty_printf("[ERR] " M "\n", ##__VA_ARGS__)
+#define qemu_warn(M, ...) tty_printf("[WARN] " M "\n", ##__VA_ARGS__)
+#define qemu_ok(M, ...) tty_printf("[OK] " M "\n", ##__VA_ARGS__)
+
+#define AHCI_PORT(num) (abar->ports + (num))
+
+//#define qemu_log(M, ...) _tty_printf(M "\n", ##__VA_ARGS__)
+
+void ahci_irq_handler();
+
+void ahci_init() {
+ // Find controller
+
+ pci_find_device_by_class_and_subclass(AHCI_CLASS, AHCI_SUBCLASS, &ahci_vendor, &ahci_devid, &ahci_busnum, &ahci_slot, &ahci_func);
+
+ if(ahci_vendor == 0 || ahci_devid == 0) {
+ qemu_err("AHCI contoller not found!");
+ return;
+ }
+
+ qemu_ok("Found VEN: %x DEV: %x", ahci_vendor, ahci_devid);
+
+ // Enable Bus Mastering
+ uint16_t command_register = pci_read_confspc_word(ahci_busnum, ahci_slot, ahci_func, 4);
+
+ command_register |= 0x05;
+
+ pci_write(ahci_busnum, ahci_slot, ahci_func, 4, command_register);
+
+// qemu_ok("Enabled Bus Mastering");
+
+ // Get ABAR
+
+ abar = (AHCI_HBA_MEM*)pci_read32(ahci_busnum, ahci_slot, ahci_func, 0x24);
+
+ qemu_log("AHCI ABAR is: %x", abar);
+
+ // Map memory
+ map_pages(
+ get_kernel_page_directory(),
+ (physical_addr_t) abar,
+ (virtual_addr_t) abar,
+ PAGE_SIZE * 2,
+ PAGE_WRITEABLE | PAGE_CACHE_DISABLE
+ );
+
+ qemu_log("Version: %x", abar->version);
+
+ abar->global_host_control |= (1 << 31); // AHCI Enable
+
+ if(abar->host_capabilities_extended & 1) {
+ for(int i = 0; i < 5; i++) {
+ qemu_warn("PERFORMING BIOS HANDOFF!!!");
+ }
+
+ abar->handoff_control_and_status = abar->handoff_control_and_status | (1 << 1);
+
+ while(1) {
+ size_t status = abar->handoff_control_and_status;
+
+ if (~status & (1 << 0))
+ break;
+ }
+ } else {
+ qemu_ok("No BIOS Handoff");
+ }
+
+ // Reset
+ abar->global_host_control |= (1 << 0);
+
+ while(abar->global_host_control & (1 << 0));
+
+ qemu_ok("Controller reset ok");
+
+ // Interrupts
+ ahci_irq = pci_read_confspc_word(ahci_busnum, ahci_slot, ahci_func, 0x3C) & 0xFF; // All 0xF PCI register
+ qemu_log("AHCI IRQ: %x (%d)", ahci_irq, ahci_irq);
+
+ register_interrupt_handler(32 + ahci_irq, ahci_irq_handler);
+
+ // Init
+ abar->global_host_control |= (1 << 31) | (1 << 1); // AHCI Enable and AHCI Interrupts
+
+ qemu_ok("Enabled AHCI and INTERRUPTS");
+
+ size_t caps = abar->capability;
+ size_t slotCount = ((caps >> 8) & 0x1f) + 1;
+
+ qemu_log("Slot count: %d", slotCount);
+
+ // Scan bus
+
+ uint32_t implemented_ports = abar->port_implemented;
+
+ for(int i = 0; i < 32; i++) {
+ if (implemented_ports & (1 << i)) {
+ AHCI_HBA_PORT* port = AHCI_PORT(i);
+
+ if (!ahci_is_drive_attached(i)) {
+ continue;
+ }
+
+// qemu_log("%x", port->command_and_status);
+
+ // from nakst/essence
+
+ /*
+Ensure that the controller is not in the running state by reading and examining each
+implemented port’s PxCMD register. If PxCMD.ST, PxCMD.CR, PxCMD.FRE and
+PxCMD.FR are all cleared, the port is in an idle state. Otherwise, the port is not idle and
+should be placed in the idle state prior to manipulating HBA and port specific registers.
+System software places a port into the idle state by clearing PxCMD.ST and waiting for
+PxCMD.CR to return ‘0’ when read. Software should wait at least 500 milliseconds for
+this to occur. If PxCMD.FRE is set to ‘1’, software should clear it to ‘0’ and wait at least
+500 milliseconds for PxCMD.FR to return ‘0’ when read.
+ */
+
+// uint32_t norm = (1 << 0) | (1 << 4) | (1 << 15) | (1 << 14); // ST, FRE, CR and FR
+
+ port->command_and_status &= ~(1);
+
+ uint32_t st = port->command_and_status;
+
+ while(true) {
+ uint32_t cr = (port->command_and_status >> 15) & 1;
+
+ if(cr == 0) {
+ break;
+ }
+ }
+
+ uint32_t fre = (port->command_and_status >> 4) & 1;
+
+ if(fre == 1) {
+ port->command_and_status &= ~(1 << 4);
+ }
+
+ while(true) {
+ uint32_t fr = (port->command_and_status >> 14) & 1;
+
+ if(fr == 0) {
+ break;
+ }
+ }
+
+ ahci_rebase_memory_for(i);
+
+ port->command_and_status |= (1 << 4);
+
+ port->sata_error = (1 << i);
+
+ port->interrupt_enable = (1 << 5) | (1 << 0) | (1 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (1 << 26) | (1 << 24) | (1 << 23);
+
+ port->command_and_status |= 1;
+ /////////////
+
+// volatile size_t x = port->interrupt_status;
+// port->interrupt_status = x;
+//
+// port->sata_control |= (3 << 8);
+// port->command_and_status = (port->command_and_status & 0x0FFFFFFF) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 28);
+//
+// while((port->sata_status & 0x0f) != 3);
+//
+// x = port->sata_error;
+// port->sata_error = x;
+//
+// while(port->task_file_data & 0x88);
+//
+// port->command_and_status |= 1;
+//
+// port->interrupt_enable |= (1 << 5) | (1 << 0) | (1 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (1 << 26) | (1 << 24) | (1 << 23);
+
+ }
+ }
+
+ for(int i = 0; i < 32; i++) {
+ if(abar->port_implemented & (1 << i)) {
+ AHCI_HBA_PORT* port = abar->ports + i;
+
+ qemu_log("[%x: Port %d]", port, i);
+
+ if(!ahci_is_drive_attached(i)) {
+ qemu_log("\tNo drive attached to port!");
+ continue;
+ }
+
+ if(port->signature == AHCI_SIGNATURE_SATAPI) { // SATAPI
+ qemu_log("\tSATAPI drive");
+ ahci_identify(i);
+ } else if(port->signature == AHCI_SIGNATURE_SATA) { // SATA
+ qemu_log("\tSATA drive");
+ } else {
+ qemu_log("Other device: %x", port->signature);
+ }
+ }
+ }
+
+ ahci_initialized = true;
+}
+
+void ahci_rebase_memory_for(size_t port_num) {
+ if(port_num > 31)
+ return;
+
+ ahci_stop_cmd(port_num);
+
+ // Memory rebase
+ AHCI_HBA_PORT* port = AHCI_PORT(port_num);
+
+ void* virt = kmalloc_common(MEMORY_PER_AHCI_PORT, PAGE_SIZE);
+ memset(virt, 0, MEMORY_PER_AHCI_PORT);
+ size_t phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t) virt);
+
+ ports[port_num].command_list_addr_virt = virt;
+ ports[port_num].command_list_addr_phys = phys;
+
+ ports[port_num].fis_virt = AHCI_FIS(virt, 0);
+ ports[port_num].fis_phys = AHCI_FIS(phys, 0);
+
+// qemu_log("Virtual addresses: Command list %x, FIS %x", ports[port_num].command_list_addr_virt, ports[port_num].fis_virt);
+
+ port->command_list_base_address_low = phys;
+ port->command_list_base_address_high = 0;
+
+ port->fis_base_address_low = AHCI_FIS(phys, 0);
+ port->fis_base_address_high = 0;
+
+ AHCI_HBA_CMD_HEADER *cmdheader = (AHCI_HBA_CMD_HEADER*)virt;
+
+ for(int i = 0; i < 32; i++) {
+ cmdheader[i].prdtl = COMMAND_TABLE_PRDT_ENTRY_COUNT;
+
+ cmdheader[i].ctba = AHCI_COMMAND_TABLE_ENTRY(phys, 0, i);
+
+ cmdheader[i].ctbau = 0;
+ }
+
+// qemu_log("Port %d", port_num);
+// qemu_log("\t|- CMD LIST BASE: %x (%s)", port->command_list_base_address_low, IS_ALIGNED(port->command_list_base_address_low, 1024) ? "aligned" : "not aligned");
+// qemu_log("\t|- FIS BASE: %x (%s)", port->fis_base_address_low, IS_ALIGNED(port->fis_base_address_low, 256) ? "aligned" : "not aligned");
+// qemu_log("\t|- TABLE ENTRIES: %x - %x", cmdheader[0].ctba, cmdheader[31].ctba + 256);
+
+ ahci_start_cmd(port_num);
+
+ qemu_ok("Rebasing memory for: %d is OK.", port_num);
+}
+
+bool ahci_is_drive_attached(size_t port_num) {
+ if(port_num > 31){
+ return false;
+ }
+
+ uint32_t implemented_ports = abar->port_implemented;
+
+ if(implemented_ports & (1 << port_num)) {
+ AHCI_HBA_PORT* port = abar->ports + port_num;
+
+ uint32_t status = port->sata_status;
+
+ uint8_t ipm = (status >> 8) & 0xF;
+ uint8_t det = status & 0xF;
+
+ if(ipm == 1 && det == 3) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int ahci_free_cmd_slot(size_t port_num) {
+ if(port_num > 31)
+ return -1;
+
+ AHCI_HBA_PORT* port = AHCI_PORT(port_num);
+
+ uint32_t slots = port->sata_active | port->command_issue;
+
+ for(int i = 0; i < 32; i++) {
+ if((slots & (1 << i)) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+void ahci_start_cmd(size_t port_num) {
+ if(port_num > 31)
+ return;
+
+ AHCI_HBA_PORT* port = AHCI_PORT(port_num);
+
+ while (port->command_and_status & AHCI_HBA_CR);
+
+ port->command_and_status |= AHCI_HBA_FRE;
+ port->command_and_status |= AHCI_HBA_ST;
+}
+
+void ahci_stop_cmd(size_t port_num) {
+ if(port_num > 31)
+ return;
+
+ AHCI_HBA_PORT* port = AHCI_PORT(port_num);
+
+ port->command_and_status &= ~AHCI_HBA_ST;
+ port->command_and_status &= ~AHCI_HBA_FRE;
+
+ while(1) {
+ if (port->command_and_status & AHCI_HBA_FR)
+ continue;
+ if (port->command_and_status & AHCI_HBA_CR)
+ continue;
+ break;
+ }
+}
+
+void ahci_irq_handler() {
+ qemu_warn("AHCI interrupt!");
+
+ uint32_t status = abar->interrupt_status;
+
+ abar->interrupt_status = status;
+
+ for(int i = 0; i < 32; i++) {
+ if(status & (1 << i)) {
+ AHCI_HBA_PORT* port = AHCI_PORT(i);
+
+ uint32_t port_interrupt_status = port->interrupt_status;
+
+ port->interrupt_status = port_interrupt_status;
+
+ // if(port_interrupt_status == 0) {
+ // continue;
+ // }
+ }
+ }
+}
+
+void ahci_send_cmd(AHCI_HBA_PORT* port, size_t slot) {
+ int spin = 0;
+ while ((port->task_file_data & (ATA_SR_BSY | ATA_SR_DRQ)) && spin < 1000000) {
+ spin++;
+ }
+
+ if (spin == 1000000) {
+ qemu_err("Port is hung");
+ return;
+ }
+
+ qemu_warn("DRIVE IS READY");
+
+ port->command_issue |= 1 << slot;
+
+ qemu_warn("COMMAND IS ISSUED");
+
+ while (1) {
+ if (~port->command_issue & (1 << slot)) // Command is not running? Break
+ break;
+
+ if (port->interrupt_status & AHCI_HBA_TFES) { // Task file error? Tell about error and exit
+ qemu_err("Read disk error (Task file error); IS: %x", port->interrupt_status);
+
+ return;
+ }
+ }
+
+ qemu_warn("OK");
+}
+
+/**
+ * @brief Чтение `size` секторов с AHCI диска
+ * @param port_num - номер порта
+ * @param location - номер начального сектора
+ * @param sector_count - колчество секторов
+ * @param buffer - буфер куда сохранять данные
+ */
+void ahci_read_sectors(size_t port_num, size_t location, size_t sector_count, void* buffer) {
+ if(!ahci_initialized) {
+ qemu_err("AHCI not present!");
+ return;
+ }
+
+ qemu_warn("\033[7mAHCI READ STARTED\033[0m");
+
+ char* buffer_mem = kmalloc_common(sector_count * 512, PAGE_SIZE);
+ memset(buffer_mem, 0, sector_count * 512);
+
+ size_t buffer_phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t) buffer_mem);
+
+ AHCI_HBA_PORT* port = AHCI_PORT(port_num);
+
+ port->interrupt_status = (uint32_t)-1;
+
+ AHCI_HBA_CMD_HEADER* hdr = ports[port_num].command_list_addr_virt;
+
+ hdr->cfl = sizeof(AHCI_FIS_REG_DEVICE_TO_HOST) / sizeof(uint32_t); // Should be 5
+ hdr->a = 0; // Not ATAPI
+ hdr->w = 0; // Read
+ hdr->p = 0; // No prefetch
+
+ qemu_log("FIS IS %d DWORDs long", hdr->cfl);
+
+ HBA_CMD_TBL* table = (HBA_CMD_TBL*)AHCI_COMMAND_TABLE(ports[port_num].command_list_addr_virt, 0);
+
+ memset(table, 0, sizeof(HBA_CMD_TBL));
+
+ size_t bytes = sector_count * 512;
+
+ // FIXME: Simplify statements
+ int index = 0;
+ int i;
+ for(i = 0; i < bytes; i += (4 * MB) - 1) {
+ table->prdt_entry[index].dba = buffer_phys + i;
+ table->prdt_entry[index].dbau = 0;
+ table->prdt_entry[index].rsv0 = 0;
+ table->prdt_entry[index].dbc = MIN((4 * MB), (bytes - i) % (4 * MB)) - 1; // Size in bytes 4M max
+ table->prdt_entry[index].rsv1 = 0;
+ table->prdt_entry[index].i = 0;
+
+ qemu_log("PRDT[%d]: Address: %x; Size: %d bytes; Last: %d",
+ i,
+ table->prdt_entry[index].dba,
+ table->prdt_entry[index].dbc + 1,
+ table->prdt_entry[index].i);
+
+ index++;
+ }
+
+ table->prdt_entry[index - 1].i = 1;
+
+ hdr->prdtl = index;
+
+ AHCI_FIS_REG_HOST_TO_DEVICE *cmdfis = (AHCI_FIS_REG_HOST_TO_DEVICE*)&(table->cfis);
+
+ qemu_log("CMDFIS at: %x", cmdfis);
+
+ cmdfis->fis_type = FIS_TYPE_REG_HOST_TO_DEVICE;
+ cmdfis->c = 1; // Command
+ cmdfis->command = ATA_CMD_READ_DMA_EXT;
+
+ cmdfis->lba0 = location & 0xFF;
+ cmdfis->lba1 = (location >> 8) & 0xFF;
+ cmdfis->lba2 = (location >> 16) & 0xFF;
+ cmdfis->device = 1 << 6; // LBA mode
+
+ cmdfis->lba3 = (location >> 24) & 0xFF;
+ cmdfis->lba4 = (location >> 32) & 0xFF;
+ cmdfis->lba5 = (location >> 40) & 0xFF;
+
+ cmdfis->countl = sector_count & 0xff;
+ cmdfis->counth = (sector_count >> 8) & 0xff;
+
+ ahci_send_cmd(port, 0);
+
+ memcpy(buffer, buffer_mem, bytes);
+
+ kfree(buffer_mem);
+
+ qemu_warn("\033[7mOK?\033[0m");
+}
+
+/**
+ * @brief Запись `size` секторов с AHCI диска
+ * @param port_num - номер порта
+ * @param location - номер начального сектора
+ * @param sector_count - колчество секторов
+ * @param buffer - буфер куда сохранять данные
+ */
+void ahci_write_sectors(size_t port_num, size_t location, size_t sector_count, void* buffer) {
+ if(!ahci_initialized) {
+ qemu_err("AHCI not present!");
+ return;
+ }
+
+ qemu_warn("\033[7mAHCI WRITE STARTED\033[0m");
+
+ char* buffer_mem = kmalloc_common(sector_count * 512, PAGE_SIZE);
+ memset(buffer_mem, 0, sector_count * 512);
+ memcpy(buffer_mem, buffer, sector_count * 512);
+
+ size_t buffer_phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t) buffer_mem);
+
+ AHCI_HBA_PORT* port = AHCI_PORT(port_num);
+
+ port->interrupt_status = (uint32_t)-1;
+
+ AHCI_HBA_CMD_HEADER* hdr = ports[port_num].command_list_addr_virt;
+
+ hdr->cfl = sizeof(AHCI_FIS_REG_DEVICE_TO_HOST) / sizeof(uint32_t); // Should be 5
+ hdr->a = 0; // Not ATAPI
+ hdr->w = 1; // Write
+ hdr->p = 0; // No prefetch
+
+ qemu_log("FIS IS %d DWORDs long", hdr->cfl);
+
+ HBA_CMD_TBL* table = (HBA_CMD_TBL*)AHCI_COMMAND_TABLE(ports[port_num].command_list_addr_virt, 0);
+
+ memset(table, 0, sizeof(HBA_CMD_TBL));
+
+ size_t bytes = sector_count * 512;
+
+ // FIXME: Simplify statements
+ int index = 0;
+ int i;
+ for(i = 0; i < bytes; i += (4 * MB) - 1) {
+ table->prdt_entry[index].dba = buffer_phys + i;
+ table->prdt_entry[index].dbau = 0;
+ table->prdt_entry[index].rsv0 = 0;
+ table->prdt_entry[index].dbc = MIN((4 * MB), (bytes - i) % (4 * MB)) - 1; // Size in bytes 4M max
+ table->prdt_entry[index].rsv1 = 0;
+ table->prdt_entry[index].i = 0;
+
+ qemu_log("PRDT[%d]: Address: %x; Size: %d bytes; Last: %d",
+ i,
+ table->prdt_entry[index].dba,
+ table->prdt_entry[index].dbc + 1,
+ table->prdt_entry[index].i);
+
+ index++;
+ }
+
+ table->prdt_entry[index - 1].i = 1;
+
+ hdr->prdtl = index;
+
+ AHCI_FIS_REG_HOST_TO_DEVICE *cmdfis = (AHCI_FIS_REG_HOST_TO_DEVICE*)&(table->cfis);
+
+ qemu_log("CMDFIS at: %x", cmdfis);
+
+ cmdfis->fis_type = FIS_TYPE_REG_HOST_TO_DEVICE;
+ cmdfis->c = 1; // Command
+ cmdfis->command = ATA_CMD_WRITE_DMA_EXT;
+
+ size_t locsec = location / 512;
+
+ cmdfis->lba0 = locsec & 0xFF;
+ cmdfis->lba1 = (locsec >> 8) & 0xFF;
+ cmdfis->lba2 = (locsec >> 16) & 0xFF;
+ cmdfis->device = 1 << 6; // LBA mode
+
+ cmdfis->lba3 = (locsec >> 24) & 0xFF;
+ cmdfis->lba4 = (locsec >> 32) & 0xFF;
+ cmdfis->lba5 = (locsec >> 40) & 0xFF;
+
+ cmdfis->countl = sector_count & 0xff;
+ cmdfis->counth = (sector_count >> 8) & 0xff;
+
+ ahci_send_cmd(port, 0);
+
+ kfree(buffer_mem);
+
+ qemu_warn("\033[7mOK?\033[0m");
+}
+
+
+// Call SCSI START_STOP command to eject a disc
+void ahci_identify(size_t port_num) {
+ qemu_log("Trying to eject %d", port_num);
+
+ AHCI_HBA_PORT* port = AHCI_PORT(port_num);
+
+ port->interrupt_status = (uint32_t)-1;
+
+ int slot = 0;
+
+// qemu_log("Slot is: %d", slot);
+
+ AHCI_HBA_CMD_HEADER* hdr = ports[port_num].command_list_addr_virt;
+ hdr += slot;
+
+// qemu_log("CMDHEADER AT: %x", hdr);
+
+ hdr->cfl = sizeof(AHCI_FIS_REG_DEVICE_TO_HOST) / sizeof(uint32_t); // Should be 5
+ hdr->a = 1; // ATAPI
+ hdr->w = 0; // Read
+ hdr->p = 0; // No prefetch
+ hdr->prdtl = 1; // One entry only
+
+ void* memory = kmalloc_common(512, PAGE_SIZE);
+ size_t buffer_phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t) memory);
+
+ HBA_CMD_TBL* table = (HBA_CMD_TBL*)AHCI_COMMAND_TABLE(ports[port_num].command_list_addr_virt, 0);
+ memset(table, 0, sizeof(HBA_CMD_TBL));
+
+ qemu_log("Table at: %x", table);
+
+ uint8_t command[12] = {
+ ATAPI_CMD_START_STOP, // Command
+ 0, 0, 0, // Reserved
+ 1 << 1, // Eject disc
+ 0, 0, 0, 0, 0, 0, 0 // Reserved
+ };
+
+ memcpy(table->acmd, command, 12);
+
+ // Set only first PRDT for testing
+ table->prdt_entry[0].dba = buffer_phys;
+ table->prdt_entry[0].dbc = 0x1ff; // 512 bytes - 1
+ table->prdt_entry[0].i = 1;
+
+ AHCI_FIS_REG_HOST_TO_DEVICE *cmdfis = (AHCI_FIS_REG_HOST_TO_DEVICE*)&(table->cfis);
+
+ cmdfis->fis_type = FIS_TYPE_REG_HOST_TO_DEVICE;
+ cmdfis->c = 1; // Command
+ cmdfis->command = ATA_CMD_PACKET;
+
+ cmdfis->lba1 = 0;
+
+ ahci_send_cmd(port, slot);
+}
diff --git a/kernel/src/drv/disk/ata.c b/kernel/src/drv/disk/ata.c
index 2fc4a008d..2971a9180 100644
--- a/kernel/src/drv/disk/ata.c
+++ b/kernel/src/drv/disk/ata.c
@@ -1,11 +1,19 @@
-#include
+#include "drv/disk/ata.h"
#include
#include
-#include
+#include
+#include
+#include
#include
+#include "drv/disk/dpm.h"
+#include "sys/isr.h"
+#include "debug/hexview.h"
+#include "net/endianess.h"
#define DEFAULT_TIMEOUT (65535 * 2)
+const char possible_dpm_letters_for_ata[4] = "CDEF";
+
// PRIMARY MASTER
// PRIMARY SLAVE
// SECONDARY MASTER
@@ -18,39 +26,65 @@ extern uint16_t ata_dma_bar4;
void ide_select_drive(uint8_t bus, bool slave) {
if(bus == ATA_PRIMARY)
- outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, (0xA0 | (slave << 4)));
+ outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, (0xA0 | ((uint8_t)slave << 4)));
else
- outb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, (0xA0 | (slave << 4)));
+ outb(ATA_SECONDARY_IO + ATA_REG_HDDEVSEL, (0xA0 | ((uint8_t)slave << 4)));
}
void ide_primary_irq(__attribute__((unused)) registers_t regs) {
- qemu_log("=================== Got ATA interrupt. PRIMARY");
+// qemu_log("=================== Got ATA interrupt. PRIMARY");
uint8_t status = inb(ATA_PRIMARY_IO + ATA_REG_STATUS);
- qemu_log("Status: %d (%x)", status, status);
+// qemu_log("Status: %d (%x); Altstatus: %x", status, status, altstatus);
}
void ide_secondary_irq(__attribute__((unused)) registers_t regs) {
- qemu_log("=================== Got ATA interrupt. SECONDARY");
+// qemu_log("=================== Got ATA interrupt. SECONDARY");
size_t status = inb(ATA_SECONDARY_IO + ATA_REG_STATUS);
- qemu_log("Status: %d (%x)", status, status);
+// qemu_log("Status: %d (%x); Altstatus: %x", status, status, altstatus);
+}
+
+void ide_soft_reset(size_t io) {
+ outb(io + ATA_REG_CONTROL, 0x04);
+ ide_400ns_delay(io);
+ outb(io + ATA_REG_CONTROL, 0);
+}
+
+size_t dpm_ata_pio_read(size_t Disk, size_t Offset, size_t Size, void* Buffer){
+ /// Функции для чтения
+ DPM_Disk dpm = dpm_info(Disk + 65);
+ qemu_note("[ATA] [DPM] [DISK %d] [READ] Off: %d | Size: %d", dpm.Point, Offset, Size);
+ // TODO: @ndraey не забудь для своей функции сделать кол-во полученных байт
+ // FIXME: For those who want to see thid piece of code: I literally burned my eyes with this.
+ ata_pio_read((uint8_t)dpm.Point, Buffer, Offset, Size);
+ return Size;
}
+
+size_t dpm_ata_pio_write(size_t Disk, size_t Offset, size_t Size, void* Buffer){
+ /// Функции для записи
+ DPM_Disk dpm = dpm_info(Disk + 65);
+ qemu_note("[ATA] [DPM] [DISK %d] [WRITE] Off: %d | Size: %d", dpm.Point, Offset, Size);
+ // TODO: @ndraey не забудь для своей функции сделать кол-во записанных байт
+ // FIXME: For those who want to see thid piece of code: I literally burned my eyes with this.
+ ata_pio_write((uint8_t)dpm.Point, Buffer, Offset, Size);
+ return Size;
+}
+
+
uint8_t ide_identify(uint8_t bus, uint8_t drive) {
- uint16_t io;
+ uint16_t io = (bus == ATA_PRIMARY) ? ATA_PRIMARY_IO : ATA_SECONDARY_IO;
+
+ uint8_t drive_num = (bus << 1) | drive;
qemu_log("Identifying %s %s", PRIM_SEC(bus), MAST_SLV(drive));
-
+
+ ide_soft_reset(io);
ide_select_drive(bus, drive);
- if(bus == ATA_PRIMARY)
- io = ATA_PRIMARY_IO;
- else
- io = ATA_SECONDARY_IO;
-
outb(io + ATA_REG_SECCOUNT0, 0);
outb(io + ATA_REG_LBA0, 0);
outb(io + ATA_REG_LBA1, 0);
@@ -61,6 +95,8 @@ uint8_t ide_identify(uint8_t bus, uint8_t drive) {
uint8_t status = inb(io + ATA_REG_STATUS);
+ qemu_log("Status: %d; Err: %d", status, status & ATA_SR_ERR);
+
size_t timeout = DEFAULT_TIMEOUT;
if(status) {
@@ -71,8 +107,7 @@ uint8_t ide_identify(uint8_t bus, uint8_t drive) {
uint8_t lba_m = inb(io + ATA_REG_LBA1);
uint8_t lba_h = inb(io + ATA_REG_LBA2);
- qemu_log("%x %x %x %x", seccount, lba_l, lba_m, lba_h);
-
+ qemu_warn("%x %x %x %x", seccount, lba_l, lba_m, lba_h);
// ^----- If they contain 0x01, 0x01, 0x14, 0xEB then the device is a packet device,
// and `IDENTIFY PACKET DEVICE` (0xA1) should be used.
@@ -81,48 +116,92 @@ uint8_t ide_identify(uint8_t bus, uint8_t drive) {
qemu_log("ATA Packet Device!");
- drives[(bus << 1) | drive].online = true;
- drives[(bus << 1) | drive].is_packet = true;
+ drives[drive_num].online = true;
+ drives[drive_num].is_packet = true;
- // outb(io + ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
+ outb(io + ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
+
+ for(int i = 0; i < 256; i++) {
+ *(uint16_t *)(ide_buf + i) = inw(io + ATA_REG_DATA);
+ }
+
+ uint16_t* fwver = kcalloc(8, 1);
+ uint16_t* model_name = kcalloc(40, 1);
+ uint16_t* serial = kcalloc(20, 1);
+
+ memcpy(serial, ide_buf + 10, 20);
+ memcpy(fwver, ide_buf + 23, 8);
+ memcpy(model_name, ide_buf + 27, 40);
+
+ for(int i = 0; i < 10; i++) {
+ serial[i] = bit_flip_short(serial[i]);
+ }
+
+ for(int i = 0; i < 4; i++) {
+ fwver[i] = bit_flip_short(fwver[i]);
+ }
+
+ for(int i = 0; i < 20; i++) {
+ model_name[i] = bit_flip_short(model_name[i]);
+ }
+
+ // Zero-terminate the strings
+ ((uint8_t*)serial)[19] = 0;
+ ((uint8_t*)fwver)[7] = 0;
+ ((uint8_t*)model_name)[39] = 0;
- // for(int i = 0; i < 256; i++) {
- // *(uint16_t *)(ide_buf + i * 2) = ins(io + ATA_REG_DATA);
- // }
// Do my best for processing packet device.
- // 1. Get disc content size
+ drives[drive_num].capacity = atapi_read_size(bus, drive);
+ drives[drive_num].block_size = atapi_read_block_size(bus, drive);
- drives[(bus << 1) | drive].capacity = atapi_read_size(bus, drive);
- drives[(bus << 1) | drive].block_size = atapi_read_block_size(bus, drive);
+ drives[drive_num].fwversion = (char *) fwver;
+ drives[drive_num].model_name = (char *) model_name;
+ drives[drive_num].serial_number = (char *) serial;
- qemu_log("Size is: %d", drives[(bus << 1) | drive].capacity);
+ qemu_log("Size is: %d", drives[drive_num].capacity);
- return 0;
- } else if(lba_m == 0x3C && lba_h == 0xC3) {
- // https://wiki.osdev.org/SATA
+ memset(ide_buf, 0, 512);
- // Send a standard IDENTIFY command to the drive (0xEC).
- // The drive should respond with an error in the ERR bit of the Status Register,
- // and a pair of "signature bytes".
-
- // On the Primary ATA bus, you get the signature bytes by reading IO ports 0x1F4 and 0x1F5,
- // and you should see values of 0x3C and 0xC3.
+ qemu_note("DRIVE: %d", drive_num);
+
+ qemu_note("Serial: %s", serial);
+ qemu_note("Firmware version: %s", fwver);
+ qemu_note("Model name: %s", model_name);
+
+ ndpm_add_drive(&(drives[drive_num]), ata_ndpm_read, ata_ndpm_write);
- // NDRAEY: What about Secondary bus? 0x174 and 0x175?
+ // (drive_num) is an index (0, 1, 2, 3) of disk
+ int disk_inx = dpm_reg(
+ possible_dpm_letters_for_ata[drive_num],
+ "CD\\DVD drive",
+ "Unknown",
+ 1,
+ drives[drive_num].capacity * drives[drive_num].block_size,
+ drives[drive_num].capacity,
+ drives[drive_num].block_size,
+ 3, // Ставим 3ку, так как будем юзать функции для чтения и записи
+ "DISK1234567890",
+ (void*)drive_num // Оставим тут индекс диска
+ );
- qemu_log("FUCKING SATA!!!");
+ if (disk_inx < 0){
+ qemu_err("[ATA] [DPM] [ERROR] An error occurred during disk registration, error code: %d",disk_inx);
- drives[DRIVE(bus, drive)].is_sata = true;
+ } else {
+ qemu_ok("[ATA] [DPM] [Successful] [is_packet: %d] Your disk index: %d",drives[drive_num].is_packet, disk_inx);
+ dpm_fnc_write(disk_inx + 65, &dpm_ata_pio_read, &dpm_ata_pio_write);
+ }
return 0;
+ } else if(seccount == 0x7F && lba_l == 0x7F && lba_m == 0x7F && lba_h == 0x7F) {
+ qemu_err("Error possible (Virtualbox returns 0x7f 0x7f 0x7f 0x7f for non-existent drives)");
+ return 1;
}
/* Now, poll until BSY is clear. */
- while((inb(io + ATA_REG_STATUS) & ATA_SR_BSY) != 0){
- status = inb(io + ATA_REG_STATUS);
-
+ while((status & ATA_SR_BSY) != 0){
qemu_log("Got status %x", status);
if(status & ATA_SR_ERR) {
qemu_log("%s %s has ERR set. Disabled.", PRIM_SEC(bus), MAST_SLV(drive));
@@ -135,13 +214,13 @@ uint8_t ide_identify(uint8_t bus, uint8_t drive) {
} else {
timeout--;
}
+
+ status = inb(io + ATA_REG_STATUS);
}
timeout = DEFAULT_TIMEOUT;
while(!(status & ATA_SR_DRQ)) {
- status = inb(io + ATA_REG_STATUS);
-
qemu_log("Got status %x", status);
if(status & ATA_SR_ERR) {
qemu_log("%s %s has ERR set. Disabled.", PRIM_SEC(bus), MAST_SLV(drive));
@@ -151,19 +230,21 @@ uint8_t ide_identify(uint8_t bus, uint8_t drive) {
if(!timeout) {
qemu_log("ATA Timeout expired!");
return 1;
- } else {
- timeout--;
}
+
+ timeout--;
+
+ status = inb(io + ATA_REG_STATUS);
}
- drives[(bus << 1) | drive].online = true;
+ drives[drive_num].online = true;
qemu_log("%s %s is online.", PRIM_SEC(bus), MAST_SLV(drive));
for(int i = 0; i < 256; i++) {
- *(uint16_t *)(ide_buf + i * 2) = ins(io + ATA_REG_DATA);
+ *(uint16_t *)(ide_buf + i) = inw(io + ATA_REG_DATA);
}
-
+
uint16_t capacity_lba = ide_buf[ATA_IDENT_MAX_LBA];
uint16_t capacity_lba_ext = ide_buf[ATA_IDENT_MAX_LBA_EXT];
@@ -171,27 +252,81 @@ uint8_t ide_identify(uint8_t bus, uint8_t drive) {
uint16_t hds = ide_buf[ATA_IDENT_HEADS];
uint16_t scs = ide_buf[ATA_IDENT_SECTORS];
+ // Dump model and firmware version
+ drives[drive_num].fwversion = kcalloc(8, 1);
+ drives[drive_num].model_name = kcalloc(40, 1);
+ drives[drive_num].serial_number = kcalloc(20, 1);
+
+ uint16_t* fwver = (uint16_t *) drives[drive_num].fwversion;
+ uint16_t* model_name = (uint16_t *) drives[drive_num].model_name;
+ uint16_t* serial = (uint16_t *) drives[drive_num].serial_number;
+
+ memcpy(serial, ide_buf + 10, 20);
+ memcpy(fwver, ide_buf + 23, 8);
+ memcpy(model_name, ide_buf + 27, 40);
+
+ for(int i = 0; i < 10; i++) {
+ serial[i] = bit_flip_short(serial[i]);
+ }
+
+ for(int i = 0; i < 4; i++) {
+ fwver[i] = bit_flip_short(fwver[i]);
+ }
+
+ for(int i = 0; i < 20; i++) {
+ model_name[i] = bit_flip_short(model_name[i]);
+ }
+
+ // Zero-terminate the strings
+ ((uint8_t*)serial)[19] = 0;
+ ((uint8_t*)fwver)[7] = 0;
+ ((uint8_t*)model_name)[39] = 0;
+
size_t capacity = capacity_lba;
if(!capacity_lba) {
if(!capacity_lba_ext) {
// capacity = (cyl * hds * scs) + 128;
- drives[(bus << 1) | drive].is_chs_addressing = true;
+ drives[drive_num].is_chs_addressing = true;
- drives[(bus << 1) | drive].cylinders = cyl;
- drives[(bus << 1) | drive].heads = hds;
- drives[(bus << 1) | drive].sectors = scs;
+ drives[drive_num].cylinders = cyl;
+ drives[drive_num].heads = hds;
+ drives[drive_num].sectors = scs;
} else {
capacity = capacity_lba_ext;
}
}
- drives[(bus << 1) | drive].block_size = 512;
- drives[(bus << 1) | drive].capacity = capacity * 512;
+ drives[drive_num].drive = drive_num;
+ drives[drive_num].block_size = 512;
+ drives[drive_num].capacity = capacity;
+
+ // (drive_num) is an index (0, 1, 2, 3) of disk
+ int disk_inx = dpm_reg(
+ possible_dpm_letters_for_ata[drive_num],
+ "ATA IDE Disk",
+ "Unknown",
+ 1,
+ capacity * 512,
+ capacity,
+ drives[drive_num].block_size,
+ 3, // Ставим 3ку, так как будем юзать функции для чтения и записи
+ "DISK1234567890",
+ (void*)drive_num // Оставим тут индекс диска
+ );
+
+ if (disk_inx < 0){
+ qemu_err("[ATA] [DPM] [ERROR] An error occurred during disk registration, error code: %d",disk_inx);
+ } else {
+ qemu_ok("[ATA] [DPM] [Successful] [is_packet: %d] Your disk index: %d",drives[drive_num].is_packet, disk_inx);
+ dpm_fnc_write(disk_inx + 65, &dpm_ata_pio_read, &dpm_ata_pio_write);
+ }
+
+ ndpm_add_drive(drives + drive_num, ata_ndpm_read, ata_ndpm_write);
qemu_log("Identify finished");
}else{
- qemu_log("%s %s => No status. Drive may be disconnected!", PRIM_SEC(bus), MAST_SLV(drive));
+ qemu_err("%s %s => No status. Drive may be disconnected!", PRIM_SEC(bus), MAST_SLV(drive));
return 1;
}
@@ -239,28 +374,17 @@ void ide_poll(uint16_t io) {
while(1) {
status = inb(io + ATA_REG_STATUS);
- if(status & ATA_SR_ERR)
- qemu_log("ERR set, device failure!\n");
- // break;
+ if(status & ATA_SR_ERR) {
+ qemu_err("ERR set, device failure!\n");
+ break;
+ }
if(status & ATA_SR_DRQ)
break;
}
}
-static inline void ata_set_params(uint8_t drive, uint16_t* io, uint8_t* real_drive) {
- uint8_t _io = drive >> 1;
- uint8_t _drv = drive & 1;
-
- if(_io == ATA_PRIMARY)
- *io = ATA_PRIMARY_IO;
- else if(_io == ATA_SECONDARY)
- *io = ATA_SECONDARY_IO;
-
- *real_drive = _drv;
-}
-
-uint8_t ata_read_sector(uint8_t drive, uint8_t *buf, uint32_t lba) {
+uint8_t ata_pio_read_sector(uint8_t drive, uint8_t *buf, uint32_t lba) {
ON_NULLPTR(buf, {
qemu_log("Buffer is nullptr!");
return 0;
@@ -296,7 +420,7 @@ uint8_t ata_read_sector(uint8_t drive, uint8_t *buf, uint32_t lba) {
uint16_t* buf16 = (uint16_t*)buf;
for(int i = 0; i < 256; i++) {
- uint16_t data = ins(ata_data_reg);
+ uint16_t data = inw(ata_data_reg);
*(buf16 + i) = data;
}
@@ -305,7 +429,14 @@ uint8_t ata_read_sector(uint8_t drive, uint8_t *buf, uint32_t lba) {
return 1;
}
-uint8_t ata_write_raw_sector(uint8_t drive, const uint8_t *buf, uint32_t lba) {
+/**
+ * @brief Полностью перезаписывает сектор на диске
+ * @param drive Номер диска
+ * @param buf Юуффер с данными
+ * @param lba Номер сектора
+ * @return 0 - ошибка, 1 - ок
+ */
+uint8_t ata_pio_write_raw_sector(uint8_t drive, const uint8_t *buf, uint32_t lba) {
ON_NULLPTR(buf, {
qemu_log("Buffer is nullptr!");
return 0;
@@ -327,7 +458,7 @@ uint8_t ata_write_raw_sector(uint8_t drive, const uint8_t *buf, uint32_t lba) {
uint8_t slavebit = (drive == ATA_MASTER?0x00:0x01);
outb(io + ATA_REG_HDDEVSEL, (cmd | (slavebit << 4) | (uint8_t)((lba >> 24 & 0x0F))));
- outb(io + 1, 0x00);
+ outb(io + 1, 0x00);
outb(io + ATA_REG_SECCOUNT0, 1);
outb(io + ATA_REG_LBA0, (uint8_t)((lba)));
outb(io + ATA_REG_LBA1, (uint8_t)((lba) >> 8));
@@ -337,7 +468,7 @@ uint8_t ata_write_raw_sector(uint8_t drive, const uint8_t *buf, uint32_t lba) {
ide_poll(io);
for(int i = 0; i < 256; i++) {
- outs(io + ATA_REG_DATA, *(uint16_t*)(buf + i * 2));
+ outw(io + ATA_REG_DATA, *(uint16_t*)(buf + i * 2));
ide_400ns_delay(io);
}
@@ -347,18 +478,18 @@ uint8_t ata_write_raw_sector(uint8_t drive, const uint8_t *buf, uint32_t lba) {
}
// UNTESTED
-void ata_write_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, size_t sectors) {
+void ata_pio_write_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, size_t sectors) {
ON_NULLPTR(buf, {
qemu_log("Buffer is nullptr!");
return;
});
for(size_t i = 0; i < sectors; i++) {
- ata_write_raw_sector(drive, buf + (i * drives[drive].block_size), lba + i);
+ ata_pio_write_raw_sector(drive, buf + (i * drives[drive].block_size), lba + i);
}
}
-void ata_read_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, uint32_t numsects) {
+void ata_pio_read_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, uint32_t numsects) {
ON_NULLPTR(buf, {
qemu_log("Buffer is nullptr!");
return;
@@ -367,13 +498,13 @@ void ata_read_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, uint32_t numsec
uint8_t* rbuf = buf;
for(size_t i = 0; i < numsects; i++) {
- ata_read_sector(drive, rbuf, lba + i);
+ ata_pio_read_sector(drive, rbuf, lba + i);
rbuf += drives[drive].block_size;
}
}
// UNTESTED
-void ata_read(uint8_t drive, uint8_t* buf, uint32_t location, uint32_t length) {
+void ata_pio_read(uint8_t drive, uint8_t* buf, uint32_t location, uint32_t length) {
ON_NULLPTR(buf, {
qemu_log("Buffer is nullptr!");
return;
@@ -395,7 +526,7 @@ void ata_read(uint8_t drive, uint8_t* buf, uint32_t location, uint32_t length) {
uint8_t* real_buf = kmalloc(real_length);
if(!drives[drive].is_packet) {
- ata_read_sectors(drive, real_buf, start_sector, sector_count);
+ ata_pio_read_sectors(drive, real_buf, start_sector, sector_count);
} else {
atapi_read_sectors(drive, real_buf, start_sector, sector_count);
}
@@ -405,7 +536,7 @@ void ata_read(uint8_t drive, uint8_t* buf, uint32_t location, uint32_t length) {
kfree(real_buf);
}
-void ata_write(uint8_t drive, const uint8_t* buf, size_t location, size_t length) {
+void ata_pio_write(uint8_t drive, const uint8_t* buf, size_t location, size_t length) {
ON_NULLPTR(buf, {
qemu_log("Buffer is nullptr!");
return;
@@ -421,17 +552,32 @@ void ata_write(uint8_t drive, const uint8_t* buf, size_t location, size_t length
size_t sector_count = end_sector - start_sector + 1;
uint8_t* temp_buf = kmalloc(sector_count * drives[drive].block_size);
-
- ata_read_sectors(drive, temp_buf, start_sector, sector_count);
+
+ ata_pio_read_sectors(drive, temp_buf, start_sector, sector_count);
size_t start_offset = location % drives[drive].block_size;
memcpy(temp_buf + start_offset, buf, length);
-
- ata_write_sectors(drive, temp_buf, start_sector, sector_count);
+
+ ata_pio_write_sectors(drive, temp_buf, start_sector, sector_count);
kfree(temp_buf);
}
+void ata_ndpm_read(const ndpm_drive_t* drive, size_t location, int size, void* buffer) {
+ ata_drive_t* disk = drive->drive_specific_data;
+
+ qemu_note("Reading disk: %d", disk->drive);
+
+ ata_pio_read(disk->drive, buffer, location, size);
+}
+
+void ata_ndpm_write(const ndpm_drive_t* drive, size_t location, int size, void* buffer) {
+ ata_drive_t* disk = drive->drive_specific_data;
+
+ qemu_note("Writing disk: %d", disk->drive);
+
+ ata_pio_write(disk->drive, buffer, location, size);
+}
void ata_list() {
for (size_t i = 0; i < 4; i++) {
@@ -441,11 +587,16 @@ void ata_list() {
drives[i].online?"online ":"offline"
);
+ if(!drives[i].online) {
+ _tty_printf("\n");
+ continue;
+ }
+
if(!drives[i].is_chs_addressing) {
_tty_printf("(%d bytes | %d KB | %d MB)",
- drives[i].capacity,
- drives[i].capacity >> 10,
- drives[i].capacity >> 20);
+ (drives[i].capacity * drives[i].block_size),
+ (drives[i].capacity * drives[i].block_size) >> 10,
+ (drives[i].capacity * drives[i].block_size) >> 20);
} else {
_tty_printf("(C:H:S => %d:%d:%d)",
drives[i].cylinders,
@@ -459,6 +610,12 @@ void ata_list() {
if(drives[i].is_sata)
_tty_printf(" [SATA]");
+ qemu_note("Drive %d", i);
+ qemu_note("'%s' '%s' '%s'", drives[i].model_name, drives[i].fwversion, drives[i].serial_number);
+
+ _tty_printf("\n\t|-- Model: \"%s\"; Firmware version: \"%s\";", drives[i].model_name, drives[i].fwversion);
+ _tty_printf("\n\t|-- Serial number: \"%s\";", drives[i].serial_number);
+
_tty_printf("\n");
}
@@ -479,7 +636,7 @@ void ata_check_all() {
void ata_init() {
qemu_log("Checking for ATA drives");
- ide_buf = (uint16_t*)kmalloc(512);
+ ide_buf = (uint16_t*)kcalloc(512, 1);
register_interrupt_handler(32 + ATA_PRIMARY_IRQ, ide_primary_irq); // Fuck IRQs
register_interrupt_handler(32 + ATA_SECONDARY_IRQ, ide_secondary_irq);
diff --git a/kernel/src/drv/disk/ata_dma.c b/kernel/src/drv/disk/ata_dma.c
new file mode 100644
index 000000000..ef605c5d5
--- /dev/null
+++ b/kernel/src/drv/disk/ata_dma.c
@@ -0,0 +1,472 @@
+#include "common.h"
+#include "drv/disk/ata_dma.h"
+#include "drv/pci.h"
+#include "io/ports.h"
+#include "mem/vmm.h"
+#include "mem/pmm.h"
+#include "drv/disk/ata.h"
+#include "debug/hexview.h"
+
+#define ATA_PCI_VEN 0x8086
+#define ATA_PCI_DEV 0x7010
+
+#define ATA_DMA_READ 0xC8
+#define ATA_DMA_WRITE 0xCA
+
+uint8_t ata_busnum;
+uint8_t ata_slot;
+uint8_t ata_func;
+
+uint16_t ata_dma_bar4;
+
+prdt_t* ata_dma_prdt = 0;
+size_t ata_dma_phys_prdt = 0;
+size_t prdt_entry_count = 16;
+
+extern ata_drive_t drives[4];
+
+void ata_dma_init() {
+ pci_find_device(ATA_PCI_VEN, ATA_PCI_DEV, &ata_busnum, &ata_slot, &ata_func);
+
+ uint16_t devnum = pci_get_device(ata_busnum, ata_slot, ata_func);
+
+ qemu_log("ATA DMA ID: %d (%x)", devnum, devnum);
+
+ if(devnum == PCI_VENDOR_NO_DEVICE) {
+ qemu_log("ATA DMA not found!");
+ return;
+ }else{
+ qemu_log("Detected ATA DMA");
+ }
+
+ qemu_log("Enabling Busmastering");
+
+ uint16_t command_register = pci_read_confspc_word(ata_busnum, ata_slot, ata_func, 4);
+ command_register |= 0x05;
+ pci_write(ata_busnum, ata_slot, ata_func, 4, command_register);
+
+ qemu_log("Enabled Busmastering!!!");
+
+ ata_dma_bar4 = pci_read_confspc_word(ata_busnum, ata_slot, ata_func, 0x20);
+
+ if(ata_dma_bar4 & 0x01) {
+ ata_dma_bar4 &= 0xfffffffc;
+ }
+
+ qemu_log("ATA DMA: BAR4: %x (%d)", ata_dma_bar4, ata_dma_bar4);
+
+ qemu_log("PRDT: %d bytes", sizeof(prdt_t));
+
+ // SETUP PRDT
+ ata_dma_prdt = kmalloc_common(sizeof(prdt_t) * prdt_entry_count, PAGE_SIZE);
+ memset(ata_dma_prdt, 0, sizeof(prdt_t) * prdt_entry_count);
+
+ ata_dma_phys_prdt = virt2phys(get_kernel_page_directory(), (virtual_addr_t) ata_dma_prdt);
+
+ qemu_log("PRDT ON: V%x; P%x", ata_dma_prdt, ata_dma_phys_prdt);
+}
+
+void ata_dma_clear_prdt() {
+ memset(ata_dma_prdt, 0, sizeof(prdt_t) * prdt_entry_count);
+}
+
+void ata_dma_set_prdt_entry(prdt_t* prdt, uint16_t index, uint32_t address, uint16_t byte_count, bool is_last) {
+ prdt[index].buffer_phys = address;
+ prdt[index].transfer_size = byte_count;
+ prdt[index].mark_end = is_last ? ATA_DMA_MARK_END : 0;
+}
+
+void dump_prdt(prdt_t* prdt) {
+ int i = 0;
+ size_t bytes = 0;
+ qemu_warn("Dumping PRDT:");
+ do {
+ size_t size;
+
+ if(prdt[i].transfer_size == 0)
+ size = 65536;
+ else
+ size = prdt[i].transfer_size;
+
+ qemu_log("[%d:%d] [Address: %x] -> %d", i, prdt[i].mark_end, prdt[i].buffer_phys, size);
+
+ bytes += size;
+ i++;
+ } while(prdt[i - 1].mark_end != ATA_DMA_MARK_END);
+
+ qemu_ok("Entries: %d; Bytes to process: %d", i, bytes);
+}
+
+status_t ata_dma_read_sector(uint8_t drive, uint8_t *buf, uint32_t lba) {
+ ON_NULLPTR(buf, {
+ qemu_err("Buffer is nullptr!");
+ return E_INVALID_BUFFER;
+ });
+
+ if (!drives[drive].online) {
+ qemu_err("Attempted read from drive that does not exist.");
+ return E_DEVICE_NOT_ONLINE;
+ }
+
+ // Clear our prdt
+ ata_dma_clear_prdt();
+
+ // Allocate a temporary buffer
+ void* temp_buf = kmalloc_common(PAGE_SIZE, PAGE_SIZE);
+ memset(temp_buf, 0, PAGE_SIZE);
+
+ // Make a physical address from a virtual to tell DMA where is our temp buffer
+ size_t phys_buf = virt2phys(get_kernel_page_directory(), (virtual_addr_t) temp_buf);
+
+ // Set only one PRDT entry to read only 512 bytes
+ ata_dma_set_prdt_entry(ata_dma_prdt, 0, phys_buf, 512, true);
+
+ // Only 28-bit LBA supported!
+ lba &= 0x00FFFFFF;
+
+ uint16_t io = 0;
+
+ // Set our port address and drive number
+ ata_set_params(drive, &io, &drive);
+
+ // Set our addresses according to IO
+ size_t status_offset = io == ATA_PRIMARY_IO ? ATA_DMA_PRIMARY_STATUS : ATA_DMA_SECONDARY_STATUS;
+ size_t prdt_offset = io == ATA_PRIMARY_IO ? ATA_DMA_PRIMARY_PRDT : ATA_DMA_SECONDARY_PRDT;
+ size_t cmd_offset = io == ATA_PRIMARY_IO ? ATA_DMA_PRIMARY_CMD : ATA_DMA_SECONDARY_CMD;
+
+ outb(ata_dma_bar4 + cmd_offset, 8);
+ outb(ata_dma_bar4 + status_offset, 6);
+
+ // Send our PRDT address
+ outl(ata_dma_bar4 + prdt_offset, ata_dma_phys_prdt);
+
+ // Select drive
+ outb(io + ATA_REG_HDDEVSEL, drive == ATA_MASTER ? 0xE0 : 0xF0);
+ outb(io + 1, 0x00);
+
+ // Write LBA
+ outb(io + ATA_REG_LBA0, (uint8_t)((lba) & 0xFF));
+ outb(io + ATA_REG_LBA1, (uint8_t)((lba >> 8) & 0xFF));
+ outb(io + ATA_REG_LBA2, (uint8_t)((lba >> 16) & 0xFF));
+
+ // Send command to read DMA!
+ outb(io + ATA_REG_COMMAND, ATA_CMD_READ_DMA);
+
+ // Start DMA transfer!
+ outb(ata_dma_bar4 + cmd_offset, 9);
+
+ while (1) {
+ int status = inb(ata_dma_bar4 + status_offset);
+ int dstatus = inb(io + ATA_REG_STATUS);
+
+// qemu_log("Status: %x; Dstatus: %x; ERR: %d", status, dstatus, status & (1 << 1));
+
+ if (!(status & 0x04)) continue;
+ if (!(dstatus & 0x80)) break;
+ }
+
+ outb(ata_dma_bar4 + cmd_offset, 0);
+
+ memcpy(buf, temp_buf, 512);
+
+ kfree(temp_buf);
+
+ return OK;
+}
+
+// Internal function: do not use in production!
+// WARNING: buffer is MUST be PAGE_SIZE aligned!
+// WARNING: if numsects = 0 there's 256 sectors
+status_t ata_dma_read_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, uint8_t numsects) {
+ ON_NULLPTR(buf, {
+ qemu_err("Buffer is nullptr!");
+ return E_INVALID_BUFFER;
+ });
+
+ if (!drives[drive].online) {
+ qemu_err("Attempted read from drive that does not exist.");
+ return E_DEVICE_NOT_ONLINE;
+ }
+
+
+ // Clear our prdt
+ ata_dma_clear_prdt();
+
+ // Make a physical address from a virtual to tell DMA where is our temp buffer
+ size_t phys_buf = virt2phys(get_kernel_page_directory(), (virtual_addr_t)buf);
+// qemu_log("Read: buffer at %x (P%x); LBA: %d; %d sectors", buf, phys_buf, lba, numsects);
+
+ // Fill the PRDT
+ int i = 0;
+ size_t byte_count;
+
+ if(numsects == 0)
+ byte_count = 256 * 512;
+ else
+ byte_count = numsects * 512;
+
+// qemu_warn("Filling with: %d bytes", byte_count);
+
+ while(byte_count >= 65536) {
+ byte_count -= 65536;
+
+ ata_dma_set_prdt_entry(ata_dma_prdt, i, phys_buf + (i * 65536), 0, false);
+
+ i++;
+ }
+// qemu_warn("Remaining bytes: %d", byte_count);
+
+ if(byte_count != 0) {
+// qemu_ok("Zero!");
+ ata_dma_set_prdt_entry(ata_dma_prdt, i, phys_buf + (i * 65536), byte_count, true);
+ } else {
+// qemu_ok("Not zero!");
+ ata_dma_prdt[i - 1].mark_end = ATA_DMA_MARK_END;
+ }
+
+// dump_prdt(ata_dma_prdt);
+
+ // Only 28-bit LBA supported!
+ lba &= 0x00FFFFFF;
+
+ uint16_t io = 0;
+
+ // Set our port address and drive number
+ ata_set_params(drive, &io, &drive);
+
+ // Set our addresses according to IO
+ size_t status_offset = io == ATA_PRIMARY_IO ? ATA_DMA_PRIMARY_STATUS : ATA_DMA_SECONDARY_STATUS;
+ size_t prdt_offset = io == ATA_PRIMARY_IO ? ATA_DMA_PRIMARY_PRDT : ATA_DMA_SECONDARY_PRDT;
+ size_t cmd_offset = io == ATA_PRIMARY_IO ? ATA_DMA_PRIMARY_CMD : ATA_DMA_SECONDARY_CMD;
+
+ outb(ata_dma_bar4 + cmd_offset, 8);
+ outb(ata_dma_bar4 + status_offset, 6);
+
+ // Send our PRDT address
+ outl(ata_dma_bar4 + prdt_offset, ata_dma_phys_prdt);
+
+ // Select drive
+ outb(io + ATA_REG_HDDEVSEL, drive == ATA_MASTER ? 0xE0 : 0xF0);
+ outb(io + 1, 0x00);
+
+ // Write LBA
+ outb(io + ATA_REG_SECCOUNT0, numsects); // 0x00 is 128KB
+ outb(io + ATA_REG_LBA0, lba & 0xFF);
+ outb(io + ATA_REG_LBA1, (lba >> 8) & 0xFF);
+ outb(io + ATA_REG_LBA2, (lba >> 16) & 0xFF);
+
+ // Send command to read DMA!
+ outb(io + ATA_REG_COMMAND, ATA_CMD_READ_DMA);
+
+ // TODO: WAIT DRQ HERE
+
+ // Start DMA transfer!
+ outb(ata_dma_bar4 + cmd_offset, 9);
+
+ while (1) {
+ int status = inb(ata_dma_bar4 + status_offset);
+ int dstatus = inb(io + ATA_REG_STATUS);
+
+// qemu_log("Status: %x; Dstatus: %x; ERR: %d", status, dstatus, status & (1 << 1));
+
+ if (!(status & 0x04)) continue;
+ if (!(dstatus & 0x80)) break;
+ }
+
+ outb(ata_dma_bar4 + cmd_offset, 0);
+
+// int status = inb(ata_dma_bar4 + status_offset);
+// int dstatus = inb(io + ATA_REG_STATUS);
+//
+// qemu_log("FINAL: Status: %x; Dstatus: %x; ERR: %d", status, dstatus, status & (1 << 1));
+
+ return OK;
+}
+
+// Internal function: do not use in production!
+// WARNING: buffer is MUST be PAGE_SIZE aligned!
+// WARNING: if numsects = 0 there's 256 sectors
+status_t ata_dma_write_sectors(uint8_t drive, uint8_t *buf, uint32_t lba, uint8_t numsects) {
+ ON_NULLPTR(buf, {
+ qemu_err("Buffer is nullptr!");
+ return E_INVALID_BUFFER;
+ });
+
+ if (!drives[drive].online) {
+ qemu_err("Attempted read from drive that does not exist.");
+ return E_DEVICE_NOT_ONLINE;
+ }
+
+ // Clear our prdt
+ ata_dma_clear_prdt();
+
+ // Make a physical address from a virtual to tell DMA where is our temp buffer
+ size_t phys_buf = virt2phys(get_kernel_page_directory(), (virtual_addr_t)buf);
+// qemu_log("Read: buffer at %x (P%x); LBA: %d; %d sectors", buf, phys_buf, lba, numsects);
+
+ // Fill the PRDT
+ int i = 0;
+ size_t byte_count;
+
+ if(numsects == 0)
+ byte_count = 256 * 512;
+ else
+ byte_count = numsects * 512;
+
+// qemu_warn("Filling with: %d bytes", byte_count);
+
+ while(byte_count >= 65536) {
+ byte_count -= 65536;
+
+ ata_dma_set_prdt_entry(ata_dma_prdt, i, phys_buf + (i * 65536), 0, false);
+
+ i++;
+ }
+// qemu_warn("Remaining bytes: %d", byte_count);
+
+ if(byte_count != 0) {
+// qemu_ok("Zero!");
+ ata_dma_set_prdt_entry(ata_dma_prdt, i, phys_buf + (i * 65536), byte_count, true);
+ } else {
+// qemu_ok("Not zero!");
+ ata_dma_prdt[i - 1].mark_end = ATA_DMA_MARK_END;
+ }
+
+// dump_prdt(ata_dma_prdt);
+
+ // Only 28-bit LBA supported!
+ lba &= 0x00FFFFFF;
+
+ uint16_t io = 0;
+
+ // Set our port address and drive number
+ ata_set_params(drive, &io, &drive);
+
+ // Set our addresses according to IO
+ size_t status_offset = io == ATA_PRIMARY_IO ? ATA_DMA_PRIMARY_STATUS : ATA_DMA_SECONDARY_STATUS;
+ size_t prdt_offset = io == ATA_PRIMARY_IO ? ATA_DMA_PRIMARY_PRDT : ATA_DMA_SECONDARY_PRDT;
+ size_t cmd_offset = io == ATA_PRIMARY_IO ? ATA_DMA_PRIMARY_CMD : ATA_DMA_SECONDARY_CMD;
+
+ outb(ata_dma_bar4 + cmd_offset, 0);
+ outb(ata_dma_bar4 + status_offset, 6);
+
+ // Send our PRDT address
+ outl(ata_dma_bar4 + prdt_offset, ata_dma_phys_prdt);
+
+ // Select drive
+ outb(io + ATA_REG_HDDEVSEL, drive == ATA_MASTER ? 0xE0 : 0xF0);
+ outb(io + 1, 0x00);
+
+ // Write LBA
+ outb(io + ATA_REG_SECCOUNT0, numsects); // 0x00 is 128KB
+ outb(io + ATA_REG_LBA0, lba & 0xFF);
+ outb(io + ATA_REG_LBA1, (lba >> 8) & 0xFF);
+ outb(io + ATA_REG_LBA2, (lba >> 16) & 0xFF);
+
+ // Send command to write DMA!
+ outb(io + ATA_REG_COMMAND, ATA_CMD_WRITE_DMA);
+
+ // TODO: WAIT DRQ HERE
+
+ // Start DMA transfer!
+ outb(ata_dma_bar4 + cmd_offset, 1);
+
+ while (1) {
+ int status = inb(ata_dma_bar4 + status_offset);
+ int dstatus = inb(io + ATA_REG_STATUS);
+
+ qemu_log("Status: %x; Dstatus: %x; ERR: %d", status, dstatus, status & (1 << 1));
+
+ if (!(status & 0x04)) continue;
+ if (!(dstatus & 0x80)) break;
+ }
+
+ outb(ata_dma_bar4 + cmd_offset, 0);
+
+ return OK;
+}
+
+status_t ata_dma_read(uint8_t drive, char *buf, uint32_t location, uint32_t length) {
+ ON_NULLPTR(buf, {
+ qemu_err("Buffer is nullptr!");
+ return E_INVALID_BUFFER;
+ });
+
+ if(!drives[drive].online) {
+ qemu_log("Attempted read from drive that does not exist.");
+ return E_DEVICE_NOT_ONLINE;
+ }
+
+ size_t start_sector = location / drives[drive].block_size;
+ size_t end_sector = (location + length - 1) / drives[drive].block_size;
+ size_t sector_count = end_sector - start_sector + 1;
+
+ size_t real_length = sector_count * drives[drive].block_size;
+
+ // TODO: Optimize to read without kmalloc
+ uint8_t* real_buf = kmalloc_common(real_length, PAGE_SIZE);
+
+ if(!drives[drive].is_packet) {
+ // Okay, ATA can only read 256 sectors (128 KB of memory) at one request, so subdivide our data to clusters to manage.
+ int i = 0;
+ size_t cluster_count = sector_count / 256;
+ size_t remaining_count = sector_count % 256;
+
+ for(; i < cluster_count; i++) {
+ ata_dma_read_sectors(drive, real_buf + (i * (65536 * 2)), start_sector + (i * 256), 0);
+ }
+
+ if(remaining_count != 0)
+ ata_dma_read_sectors(drive, real_buf + (i * (65536 * 2)), start_sector + (i * 256), remaining_count);
+ }
+
+ memcpy(buf, real_buf + (location % drives[drive].block_size), length);
+
+ kfree(real_buf);
+
+ return OK;
+}
+
+status_t ata_dma_write(uint8_t drive, const char *buf, uint32_t location, uint32_t length) {
+ ON_NULLPTR(buf, {
+ qemu_err("Buffer is nullptr!");
+ return E_INVALID_BUFFER;
+ });
+
+ if(!drives[drive].online) {
+ qemu_log("Attempted read from drive that does not exist.");
+ return E_DEVICE_NOT_ONLINE;
+ }
+
+ size_t start_sector = location / drives[drive].block_size;
+ size_t end_sector = (location + length - 1) / drives[drive].block_size;
+ size_t sector_count = end_sector - start_sector + 1;
+
+ size_t real_length = sector_count * drives[drive].block_size;
+
+ // TODO: Optimize to read without kmalloc
+ uint8_t* real_buf = kmalloc_common(real_length, PAGE_SIZE);
+
+ ata_dma_read_sectors(drive, real_buf, start_sector, sector_count);
+
+ size_t start_offset = location % drives[drive].block_size;
+ memcpy(real_buf + start_offset, buf, length);
+
+ if(!drives[drive].is_packet) {
+ // Okay, ATA can only operate with 256 sectors (128 KB of memory) at one request, so subdivide our data to clusters to manage.
+ int i = 0;
+ size_t cluster_count = sector_count / 256;
+ size_t remaining_count = sector_count % 256;
+
+ for(; i < cluster_count; i++) {
+ ata_dma_write_sectors(drive, real_buf + (i * (65536 * 2)), start_sector + (i * 256), 0);
+ }
+
+ if(remaining_count != 0)
+ ata_dma_write_sectors(drive, real_buf + (i * (65536 * 2)), start_sector + (i * 256), remaining_count);
+ }
+
+ kfree(real_buf);
+
+ return OK;
+}
diff --git a/kernel/src/drv/disk/atapi.c b/kernel/src/drv/disk/atapi.c
index 346cae229..0d66e1d1c 100644
--- a/kernel/src/drv/disk/atapi.c
+++ b/kernel/src/drv/disk/atapi.c
@@ -1,11 +1,25 @@
+/**
+ * @brief Драйвер ATAPI PIO
+ * @author NDRAEY >_
+ * @date 2023-07-21
+ * @version 0.3.4
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+ */
+
// Super-duper original ATAPI driver by NDRAEY (c) 2023
// for SayoriOS
#include "drv/atapi.h"
+#include "net/endianess.h"
#include "debug/hexview.h"
// FIXME: Add REQUEST_SENSE command to handle errors.
+/**
+ * @brief Ждёт пока освободится порт ATA
+ * @param bus Шина (PRIMARY или SECONDARY)
+ * @return true - если есть ошибка, false - всё ок
+ */
bool ata_scsi_status_wait(uint8_t bus) {
while (1) {
uint8_t status = inb(ATA_PORT(bus) + ATA_REG_COMMAND);
@@ -22,6 +36,14 @@ bool ata_scsi_status_wait(uint8_t bus) {
return false;
}
+/**
+ * @brief Отправляет SCSI команду на ATA дисковод
+ * @param bus Шина (PRIMARY или SECONDARY)
+ * @param slave Является ли устройство SLAVE
+ * @param lba_mid_hi Метаданные
+ * @param command Команда размером 12 байт
+ * @return
+ */
bool ata_scsi_send(uint16_t bus, bool slave, uint16_t lba_mid_hi, uint8_t command[12]) {
qemu_log("ATAPI SCSI send [%s %s], LBA (MID AND HI): %d",
PRIM_SEC(bus), MAST_SLV(slave), lba_mid_hi);
@@ -51,7 +73,11 @@ bool ata_scsi_send(uint16_t bus, bool slave, uint16_t lba_mid_hi, uint8_t comman
return false;
}
-// Read size of transfer
+/**
+ * @brief Считывает размер передачи данных
+ * @param bus Шина (PRIMARY или SECONDARY)
+ * @return Размер передачи в байтах
+ */
size_t ata_scsi_receive_size_of_transfer(uint16_t bus) {
bool error = ata_scsi_status_wait(bus);
@@ -64,11 +90,22 @@ size_t ata_scsi_receive_size_of_transfer(uint16_t bus) {
| inb(ATA_PORT(bus) + ATA_REG_LBA1);
}
+/**
+ * @brief Считывает данные с ATA дисковода
+ * @param bus Шина (PRIMARY или SECONDARY)
+ * @param size Размер в байтах
+ * @param buffer Буффер для хранения данных
+ */
void ata_scsi_read_result(uint16_t bus, size_t size, uint16_t* buffer) {
insw(ATA_PORT(bus) + ATA_REG_DATA, (uint16_t*)((uint8_t *)buffer), size);
}
-/// 0 if error
+/**
+ * @brief Считывает размер диска
+ * @param bus Шина (PRIMARY или SECONDARY)
+ * @param slave Является ли устройство SLAVE
+ * @return Размер диска в секторах
+ */
size_t atapi_read_size(uint16_t bus, bool slave) {
qemu_log("SIZE REQUEST ON (ints): %d %d", bus, slave);
qemu_log("SIZE REQUEST ON: %s %s", PRIM_SEC(bus), MAST_SLV(slave));
@@ -87,7 +124,7 @@ size_t atapi_read_size(uint16_t bus, bool slave) {
if(!transf_size)
return 0;
- uint16_t* data = (uint16_t*)kcalloc(transf_size, 1);
+ uint16_t* data = kcalloc(transf_size, 1);
ata_scsi_read_result(bus, transf_size, data);
@@ -103,9 +140,15 @@ size_t atapi_read_size(uint16_t bus, bool slave) {
kfree(data);
- return (maxlba + 1) * blocksize;
+ return maxlba;
}
+/**
+ * @brief Считывает размер блока
+ * @param bus Номер привода в системе
+ * @param slave Является ли устрйоство SLAVE
+ * @return Размер блока в байтах
+ */
size_t atapi_read_block_size(uint16_t bus, bool slave) {
uint8_t command[12] = {
ATAPI_READ_CAPACITY,
@@ -129,6 +172,14 @@ size_t atapi_read_block_size(uint16_t bus, bool slave) {
return blocksize;
}
+/**
+ * @brief Читает сектора с диска
+ * @param drive Номер привода в системе
+ * @param buf Буффер
+ * @param lba Номер сектора на диске
+ * @param sector_count Количество секторов которые необходимо прочитать
+ * @return true - если есть ошибка, false - если нет
+ */
bool atapi_read_sectors(uint16_t drive, uint8_t *buf, uint32_t lba, size_t sector_count) {
uint8_t bus = (drive >> 1) & 1;
bool slave = (bool)((drive >> 0) & 1);
@@ -164,7 +215,7 @@ bool atapi_read_sectors(uint16_t drive, uint8_t *buf, uint32_t lba, size_t secto
}
for (uint32_t i = 0; i < sector_count; i++) {
- bool error = ata_scsi_status_wait(bus);
+ error = ata_scsi_status_wait(bus);
if(error)
return true;
@@ -177,6 +228,12 @@ bool atapi_read_sectors(uint16_t drive, uint8_t *buf, uint32_t lba, size_t secto
return false;
}
+/**
+ * @brief Извлекает диск из привода
+ * @param bus Шина (PRIMARY или SECONDARY)
+ * @param slave Является ли диск SLAVE
+ * @return true если есть ошибка, false - если нет
+ */
bool atapi_eject(uint8_t bus, bool slave) {
// Byte 4:
// Bit 0: Start
@@ -212,7 +269,13 @@ bool atapi_eject(uint8_t bus, bool slave) {
return error;
}
-// Used for error handling
+/**
+ * @brief Считывает и возвращает ошибку (если таковая имеется)
+ * @param bus Шина (PRIMARY или SECONDARY)
+ * @param slave Является ли дисковод SLAVE
+ * @param out Буффер размером 18 байт
+ * @return Структура с кодом ошибки
+ */
atapi_error_code atapi_request_sense(uint8_t bus, bool slave, uint8_t out[18]) {
uint8_t command[12] = {
ATAPI_CMD_RQ_SENSE, 0, 0, 0,
@@ -233,6 +296,12 @@ atapi_error_code atapi_request_sense(uint8_t bus, bool slave, uint8_t out[18]) {
return (atapi_error_code){(out[0] >> 7) & 1, out[2] & 0b00001111, out[12], out[13]};
}
+/**
+ * @brief Проверяет дисковод на наличие диска внутри
+ * @param bus Шина (PRIMARY или SECONDARY)
+ * @param slave Является ли дисковод SLAVE
+ * @return true если диск вствлен, false если нет
+ */
bool atapi_check_media_presence(uint8_t bus, bool slave) {
uint8_t command[12] = {
ATAPI_CMD_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -245,7 +314,7 @@ bool atapi_check_media_presence(uint8_t bus, bool slave) {
return false;
}
- char errorcode[18];
+ uint8_t errorcode[18];
atapi_error_code error_code = atapi_request_sense(1, 0, errorcode);
diff --git a/kernel/src/drv/disk/dpm.c b/kernel/src/drv/disk/dpm.c
new file mode 100644
index 000000000..a8f127481
--- /dev/null
+++ b/kernel/src/drv/disk/dpm.c
@@ -0,0 +1,260 @@
+/**
+ * @file drv/disk/dpm.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru)
+ * @brief Disk Partition Manager - Менеджер разметки дисков
+ * @version 0.3.4
+ * @date 2023-10-16
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+
+#include
+#include
+#include "mem/vmm.h"
+bool dpm_debug = false;
+
+DPM_Disk DPM_Disks[32] = {0};
+
+int dpm_searchFreeIndex(int Index){
+ Index = (Index < 0 || Index > 25 ? 0 : Index);
+
+ for (int i = Index; i < 32; i++){
+ if (DPM_Disks[i].Ready == 1)
+ continue;
+
+ return i;
+ }
+
+ for (int i = 4; i < 32; i++){
+ if (DPM_Disks[i].Ready == 1)
+ continue;
+
+ return i;
+ }
+
+ return -1;
+}
+
+void dpm_fnc_write(char Letter, dpm_disk_rw_cmd Read, dpm_disk_rw_cmd Write){
+ int Index = Letter - 65;
+
+ Index = (Index > 32 ? Index - 32 : Index);
+ Index = (Index < 0 || Index > 25 ? 0 : Index);
+
+
+ if (DPM_Disks[Index].Ready == 0 || DPM_Disks[Index].Status == 0)
+ return;
+
+ DPM_Disks[Index].Read = Read;
+ DPM_Disks[Index].Write = Write;
+}
+
+void* dpm_metadata_read(char Letter){
+ int Index = Letter - 65;
+
+ Index = (Index > 32 ? Index - 32 : Index);
+ Index = (Index < 0 || Index > 25 ? 0 : Index);
+
+ if (DPM_Disks[Index].Ready == 0 || DPM_Disks[Index].Status == 0)
+ return 0;
+
+ return DPM_Disks[Index].Reserved;
+}
+
+void dpm_metadata_write(char Letter, uint32_t Addr){
+ int Index = Letter - 65;
+
+ Index = (Index > 32 ? Index - 32 : Index);
+ Index = (Index < 0 || Index > 25 ? 0 : Index);
+
+ DPM_Disks[Index].Reserved = (void*)Addr;
+}
+
+/**
+ * @brief [DPM] Считывание данных с диска
+ *
+ * @param Letter - Буква для считывания
+ * @param Offset - Отступ для считывания
+ * @param Size - Кол-во байт данных для считывания
+ * @param Buffer - Буфер куда будет идти запись
+ *
+ * @return Кол-во прочитанных байт
+ */
+size_t dpm_read(char Letter, size_t Offset, size_t Size, void *Buffer){
+ int Index = Letter - 65;
+
+ Index = (Index > 32 ? Index - 32 : Index);
+ Index = (Index < 0 || Index > 25 ? 0 : Index);
+
+ if (DPM_Disks[Index].Ready == 0 || DPM_Disks[Index].Status == 0)
+ return DPM_ERROR_NOT_READY;
+
+ if (DPM_Disks[Index].AddrMode == 2){
+ // Диск является частью ОЗУ, поэтому мы просто копируем данные оттуда
+ if (dpm_debug)qemu_log("[DPM] [2] An attempt to read data in 'Disk %c' from position %x to the number of %d bytes.", Index+65, DPM_Disks[Index].Point+Offset, Size);
+ memcpy(Buffer, (void *) (DPM_Disks[Index].Point + Offset), Size);
+
+ return Size;
+ } else if (DPM_Disks[Index].AddrMode == 3){
+ // Режим 3, предполагает что вы указали функцию для чтения и записи с диска
+ if (dpm_debug)qemu_log("[DPM] [3] An attempt to read data in 'Disk %c' from position %x to the number of %d bytes.", Index+65, DPM_Disks[Index].Point+Offset, Size);
+ if (DPM_Disks[Index].Read == 0){
+ qemu_err("[DPM] [3] Function 404");
+ return 0;
+ }
+
+ return DPM_Disks[Index].Read(Index,Offset,Size,Buffer);
+ } else {
+ if (dpm_debug)qemu_log("[DPM] This functionality has not been implemented yet.");
+ }
+
+ return DPM_ERROR_NO_READ;
+}
+
+/**
+ * @brief [DPM] Запись данных на диск
+ *
+ * @param Letter - Буква
+ * @param size_t Offset - Отступ
+ * @param size_t Size - Кол-во байт данных для записи
+ * @param Buffer - Буфер откуда будет идти запись
+ *
+ * @return size_t - Кол-во записанных байт
+ */
+size_t dpm_write(char Letter, size_t Offset, size_t Size, char* Buffer){
+ int Index = Letter - 65;
+
+ Index = (Index > 32 ? Index - 32 : Index);
+ Index = (Index < 0 || Index > 25 ? 0 : Index);
+
+ if (DPM_Disks[Index].Ready == 0 || DPM_Disks[Index].Status == 0)
+ return DPM_ERROR_NOT_READY;
+
+ if (DPM_Disks[Index].AddrMode == 2){
+ // Диск является частью ОЗУ, поэтому мы просто копируем данные туда
+ // Опастна! Если не знать, что делать!
+ if (dpm_debug)qemu_log("[DPM] [2] An attempt to write data in 'Disk %c' from position %x to the number of %d bytes.", Index+65, DPM_Disks[Index].Point+Offset, Size);
+ memcpy((void *) (DPM_Disks[Index].Point + Offset), Buffer, Size);
+
+ return Size;
+ } else if (DPM_Disks[Index].AddrMode == 3){
+ // Режим 3, предполагает что вы указали функцию для чтения и записи с диска
+ if (dpm_debug)qemu_log("[DPM] [3] An attempt to write data in 'Disk %c' from position %x to the number of %d bytes.", Index+65, DPM_Disks[Index].Point+Offset, Size);
+ if (DPM_Disks[Index].Write == 0){
+ qemu_err("[DPM] [3] Function 404");
+ return 0;
+ }
+ return DPM_Disks[Index].Write(Index,Offset,Size,Buffer);
+ } else {
+ if (dpm_debug)qemu_log("[DPM] This functionality has not been implemented yet.");
+ }
+
+ return DPM_ERROR_NO_READ;
+}
+
+int dpm_unmount(char Letter, bool FreeReserved){
+ int Index = Letter - 65;
+
+ Index = (Index > 32 ? Index - 32 : Index);
+ Index = (Index < 0 || Index > 25 ? 0 : Index);
+
+ if (DPM_Disks[Index].Ready == 0) return 0;
+
+ DPM_Disks[Index].Ready = 0;
+
+ //memcpy(DPM_Disks[Index].Name, NULL, sizeof(NULL));
+ //memcpy(DPM_Disks[Index].Serial, NULL, sizeof(NULL));
+ //memcpy(DPM_Disks[Index].FileSystem, NULL, sizeof(NULL));
+ DPM_Disks[Index].Status = 0;
+ DPM_Disks[Index].Size = 0;
+ DPM_Disks[Index].Sectors = 0;
+ DPM_Disks[Index].SectorSize = 0;
+ DPM_Disks[Index].AddrMode = 0;
+ DPM_Disks[Index].Point = 0;
+
+ if (FreeReserved && DPM_Disks[Index].Reserved != 0) {
+ kfree(DPM_Disks[Index].Reserved);
+ }
+ return 1;
+}
+
+/**
+ * @brief [DPM] Регистрация дискового раздела
+ *
+ * @param Letter - Буква для регистрации
+ *
+ * @return int - Результат регистрации
+ */
+int dpm_reg(char Letter, char* Name, char* FS, int Status, size_t Size, size_t Sectors, size_t SectorSize, int AddrMode, char* Serial, void *Point){
+ int Index = Letter - 65;
+
+ Index = (Index > 32 ? Index - 32 : Index);
+ Index = (Index < 0 || Index > 25 ? 0 : Index);
+
+ if (DPM_Disks[Index].Ready == 1){
+ qemu_warn("[DPM] Warning! This letter is already occupied, and an attempt will be made to search for a free letter.");
+ Index = dpm_searchFreeIndex(Index);
+ if (Index == DPM_ERROR_NO_MOUNT){
+ qemu_warn("[DPM] Sorry, but the disk could not be registered because there is no free letter. Delete the extra devices and try again.");
+ return DPM_ERROR_NO_MOUNT;
+ }
+ qemu_log("[DPM] The drive was assigned the letter '%c'",Index+65);
+ }
+
+ DPM_Disks[Index].Ready = 1;
+
+ memcpy(DPM_Disks[Index].Name,Name,strlen(Name));
+ memcpy(DPM_Disks[Index].Serial,Serial,strlen(Serial));
+ memcpy(DPM_Disks[Index].FileSystem,FS,strlen(FS));
+ DPM_Disks[Index].Status = Status;
+ DPM_Disks[Index].Size = Size;
+ DPM_Disks[Index].Sectors = Sectors;
+ DPM_Disks[Index].SectorSize = SectorSize;
+ DPM_Disks[Index].AddrMode = AddrMode;
+ DPM_Disks[Index].Point = Point;
+
+ qemu_log("[DPM] Disk '%c' is registered!",Index+65);
+ qemu_log(" |-- Name: %s",DPM_Disks[Index].Name);
+ qemu_log(" |-- Serial: %s",DPM_Disks[Index].Serial);
+ qemu_log(" |-- FileSystem: %s",DPM_Disks[Index].FileSystem);
+ qemu_log(" |-- Status: %d",DPM_Disks[Index].Status);
+ qemu_log(" |-- Size: %d",DPM_Disks[Index].Size);
+ qemu_log(" |-- Sectors: %d",DPM_Disks[Index].Sectors);
+ qemu_log(" |-- SectorSize: %d",DPM_Disks[Index].SectorSize);
+ qemu_log(" |-- AddrMode: %d",DPM_Disks[Index].AddrMode);
+ qemu_log(" |-- Point: %x",DPM_Disks[Index].Point);
+
+ return Index;
+}
+
+void dpm_FileSystemUpdate(char Letter, char* FileSystem){
+ Letter -= 65;
+
+ size_t index = (Letter > 32 ? Letter - 32 : Letter);
+ index = (Letter < 0 || Letter > 25 ? 0 : Letter);
+
+ size_t c = strlen(FileSystem);
+ memset(DPM_Disks[index].FileSystem, 0, 64); /// Зачищаем данные
+ memcpy(DPM_Disks[index].FileSystem, FileSystem, (c > 64 || c == 0?64:c)); /// Пишем данные
+}
+
+
+void dpm_LabelUpdate(char Letter, char* Label){
+ Letter -= 65;
+
+ size_t index = (Letter > 32 ? Letter - 32 : Letter);
+ index = (Letter < 0 || Letter > 25 ? 0 : Letter);
+
+ size_t c = strlen(Label);
+ memset(DPM_Disks[index].Name, 0, 128); /// Зачищаем данные
+ memcpy(DPM_Disks[index].Name, Label, (c > 128 || c == 0?128:c));/// Пишем данные
+}
+
+DPM_Disk dpm_info(char Letter){
+ Letter -= 65;
+
+ size_t index = (Letter > 32 ? Letter - 32 : Letter);
+ index = (Letter < 0 || Letter > 25 ? 0 : Letter);
+
+ return DPM_Disks[index];
+}
+
diff --git a/kernel/src/drv/disk/floppy.c b/kernel/src/drv/disk/floppy.c
index 1b8245769..3baf1c122 100644
--- a/kernel/src/drv/disk/floppy.c
+++ b/kernel/src/drv/disk/floppy.c
@@ -2,20 +2,25 @@
* @file drv/disk/floppy.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru)
* @brief Драйвер Floppy
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-07-25
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-#include
+
#include
#include
+#include "sys/timer.h"
+#include "mem/vmm.h"
+#include "drv/disk/dpm.h"
+#include "io/tty.h"
+#include "sys/isr.h"
bool _FloppyDebug = false;
floppy_t floppy_data[2] = {0};
// standard IRQ number for floppy controllers
-static const int floppy_irq = 6;
+//static const int floppy_irq = 6;
static const char * drive_types[8] = {
"none",
"360kB 5.25\"",
@@ -28,7 +33,7 @@ static const char * drive_types[8] = {
"unknown type"
};
static const char FLOPPY_DMABUFA[floppy_dmalen] __attribute__((aligned(0x8000))); ///< Буфер дискеты 1
-static const char FLOPPY_DMABUFB[floppy_dmalen] __attribute__((aligned(0x8000))); ///< Буфер дискеты 2
+//static const char FLOPPY_DMABUFB[floppy_dmalen] __attribute__((aligned(0x8000))); ///< Буфер дискеты 2
bool interrupted = false;
floppy_t Floppy(int device){
@@ -194,13 +199,16 @@ int _FloppyReset(int device){
_FloppyCMD(device, 0x02); /* load time = 16ms, no-DMA = 0 */
// it could fail...
- if(_FloppyCalibrate(device) != 0) return _FloppyError(device,FLOPPY_ERROR_RESET);
+ if(_FloppyCalibrate(device) != 0)
+ return _FloppyError(device,FLOPPY_ERROR_RESET);
+ else
+ return 0;
}
int _FloppySeek(int device, unsigned cyli, int head){
- unsigned i, st0, cyl = -1;
+ int i, st0, cyl = -1;
_FloppyMotor(device, 1);
for(i = 0; i < 10; i++) {
if (_FloppyDebug) qemu_log(" [FD%c] Attempt Seek %d | Cyli: %c | Head: %d",(device?'B':'A'),i,cyli,head);
@@ -326,17 +334,18 @@ int _FloppyCache(int device,FloppyMode mode,unsigned int addr,unsigned int* offs
/**
* @brief [Floppy] Чтение данных на устройство
*
- * @param dst - Данные, куда выполнить запись
- * @param addr - Адрес,откуда читать (0 - в начало)
+ * @param dst - Данные, откуда выполнить чтение
+ * @param addr - Адрес, откуда читать (0 - в начало)
* @param size - Сколько считать данных
*
* @return int Количество записанных байт
*/
-int _FloppyRead(int device,char* dst,uint32_t addr,uint32_t size){
+size_t _FloppyRead(int device,char* dst,uint32_t addr,uint32_t size){
if (Floppy(device).Status != 1) return _FloppyError(FDA,FLOPPY_ERROR_NOREADY);
//qemu_log("[FD%c] Read | Addr: %d | Size: %d",(device==FDB?'B':'A'),addr,size);
floppy_data[device].LastErr = 0;
- uint32_t offset,ws,ds = 0;
+ uint32_t offset=0, ws=0;
+ size_t ds = 0;
int ret;
while (size > ds){
ret = _FloppyCache(device,FLOPPY_READ,addr+ds,&offset,&ws);
@@ -348,10 +357,12 @@ int _FloppyRead(int device,char* dst,uint32_t addr,uint32_t size){
return ds;
}
-int _FloppyWrite(int device,const char* dst,uint32_t addr,uint32_t size){
+size_t _FloppyWrite(int device,const char* dst,uint32_t addr,uint32_t size){
if (Floppy(device).Status != 1) return _FloppyError(FDA,FLOPPY_ERROR_NOREADY);
//qemu_log("[FD%c] Write | Addr: %d | Size: %d",(device==FDB?'B':'A'),addr,size);
- uint32_t offset,ws,ds = 0;
+
+ uint32_t offset=0, ws=0;
+ size_t ds = 0;
int ret;
while (size > ds){
ret = _FloppyCache(device,FLOPPY_READ,addr+ds, &offset, &ws);
@@ -365,6 +376,19 @@ int _FloppyWrite(int device,const char* dst,uint32_t addr,uint32_t size){
return ds;
}
+void _FloppyServiceA(){
+ outb(0x70, 0x10);
+ unsigned drives = inb(0x71);
+ int DiskA = drives >> 4;
+ if (DiskA != floppy_data[FDA].Type){
+ // Выполняем обслуживание Диска А, так как диск извлечен.
+ floppy_data[FDA].Type = DiskA;
+ floppy_data[FDA].Status = (floppy_data[FDA].Type == 4?1:0);
+ dpm_unmount('A', false);
+ dpm_reg('A',"Disk A","Unknown",floppy_data[FDA].Status,0,0,0,3,"FLOP-PYDA",0);
+ }
+}
+
/**
* @brief Автоматическое обновление данных о FD
*/
@@ -394,12 +418,14 @@ void _FloppyCheck(){
} else {
floppy_data[FDB].Status = 1;
}
+
+
// Обновление имени устройства
char fda_fs[6],fdb_fs[6] = {0};
char fda_label[12],fdb_label[12] = {0};
char fs_fat12[6] = {'F','A','T','1','2',0};
- char fs_smfs10[8] = {'S','M','F','S','1','.','0',0};
+// char fs_smfs10[8] = {'S','M','F','S','1','.','0',0};
int read = -1;
if (Floppy(FDA).Status == 1){
//qemu_log("[FD%c] U",(device==FDB?'B':'A'));
@@ -411,15 +437,14 @@ void _FloppyCheck(){
floppy_data[FDA].LastErr = 0;
}
read = Floppy(FDA).Read(FDA,fda_fs,54,8);
- if (Floppy(FDA).LastErr == 0 & strcmp(fs_fat12, fda_fs) == 0){
+ if (Floppy(FDA).LastErr == 0 && strcmp(fs_fat12, fda_fs) == 0){
if (_FloppyDebug) qemu_log("[FDA] File System: FAT12");
Floppy(FDA).Read(FDA, fda_label, 43, 11);
fda_label[11] = 0;
memcpy((void*) floppy_data[FDA].Name, fda_label, 12);
memcpy((void*) floppy_data[FDA].FileSystem, fda_fs, 6);
if (_FloppyDebug) qemu_log("[FDA] Label: %s",floppy_data[FDA].Name);
- kfree(fda_label);
- kfree(fda_fs);
+
}
}
if (Floppy(FDB).Status == 1){
@@ -436,12 +461,48 @@ void _FloppyCheck(){
memcpy((void*) floppy_data[FDB].Name, fdb_label, 12);
if (_FloppyDebug) qemu_log("[FDB] Label: %s",floppy_data[FDB].Name);
memcpy((void*) floppy_data[FDB].FileSystem, fdb_fs, 6);
- kfree(fdb_label);
- kfree(fdb_fs);
+
}
}
- kfree(fs_fat12);
+ //kfree(fs_fat12);
+
+}
+
+size_t _FloppyDPMWriteA(size_t Disk, size_t Offset, size_t Size, void* Buffer){
+ qemu_log("[DPM] Floppy A Write! Offset: %d | Size: %d",Offset, Size);
+ if (Floppy(0).Status != 1) return 0;
+ //qemu_log("[FD%c] Write | Addr: %d | Size: %d",(device==FDB?'B':'A'),addr,size);
+ uint32_t _offset = 0, ws = 0;
+ size_t ds = 0;
+ int ret;
+ while (Size > ds){
+ ret = _FloppyCache(0,FLOPPY_READ, Offset+ds, &_offset, &ws);
+ if (ret < 0) return ret;
+ if (ws > Size - ds) ws = Size - ds;
+ memcpy((void*) &FLOPPY_DMABUFA[_offset], Buffer+ds, ws);
+ ret = _FloppyCache(0,FLOPPY_WRITE, Offset+ds, nullptr, nullptr);
+ if (ret < 0) return ret;
+ ds += ws;
+ }
+ return ds;
+}
+
+size_t _FloppyDPMReadA(size_t Disk, size_t Offset, size_t Size, void* Buffer){
+ qemu_log("[DPM] Floppy A Read! Offset: %d | Size: %d",Offset, Size);
+ if (Floppy(0).Status != 1) return 0;
+ floppy_data[0].LastErr = 0;
+ uint32_t _offset=0, ws=0;
+ size_t ds = 0;
+ int ret;
+ while (Size > ds){
+ ret = _FloppyCache(0, FLOPPY_READ, Offset+ds, &_offset, &ws);
+ if (ret < 0) return ret;
+ if (ws > Size - ds) ws = Size - ds;
+ memcpy(Buffer + ds, (void*) &FLOPPY_DMABUFA[_offset], ws);
+ ds += ws;
+ }
+ return ds;
}
void _FloppyPrint(){
@@ -496,10 +557,29 @@ void initFloppy() {
_FloppyReset(FDB);
register_interrupt_handler(32+6,&irqFloppy);
+ dpm_reg('A',"Disk A","Unknown",1,0,0,0,3,"FLOP-PYDA",0);
+ dpm_metadata_write('A', (uint32_t) &floppy_data[FDA]);
+ dpm_fnc_write('A',_FloppyDPMReadA,_FloppyDPMWriteA);
+
+ _FloppyServiceA();
+
+
+ dpm_reg('B',"Disk B","Unknown",0,0,0,0,3,"FLOP-PYDB",0);
+ dpm_metadata_write('B', (uint32_t) &floppy_data[FDB]);
+
_FloppyCheck();
_FloppyPrint();
+
+// fs_tarfs_detect('A');
+// fs_tarfs_detect('R');
+//
+// char* fs_fat12 = kmalloc(32);
+// size_t read = dpm_read('A', 0x1F, 12, fs_fat12);
+//
+// qemu_log("[DPM] [A] Ready: %d | '%s'",read,fs_fat12);
+
// base - 0x03f0
- //int data = 0;
+ //int data = 0;ЮПСРВЯАФ1234567890-=
//char text[32] = {0};
//int read = Floppy(0).Read(0,text,0xD0,32);
//qemu_log("FD0:TEST = (%d) '%s'",read,text);
diff --git a/kernel/src/drv/disk/initrd.c b/kernel/src/drv/disk/initrd.c
new file mode 100644
index 000000000..c9e768d67
--- /dev/null
+++ b/kernel/src/drv/disk/initrd.c
@@ -0,0 +1,71 @@
+/**
+ * @file drv/disk/initrd.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru)
+ * @brief Файл виртуального диска, основаного на основе TarFS
+ * @version 0.3.4
+ * @date 2023-08-03
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+
+#include
+#include
+#include
+#include "drv/disk/dpm.h"
+#include "mem/vmm.h"
+
+#define INITRD_RW_SIZE (2*1024*1024) ///< Размер виртуального диска 2mb
+
+int initrd_tarfs(uint32_t start,uint32_t end){
+ qemu_log("[TarFS] Init...\n * Start: %x\n * End: %x\n * Size: %d",start,end,end-start);
+
+ size_t initrd_size = end - start;
+ if (start > end)
+ return 0;
+
+ void* initrd_data = (void*)start;
+
+ qemu_warn("Initrd occupies %d pages", ALIGN(initrd_size, 4096) / 4096);
+
+ TarFS_ROOT* l_initrd = fs_tarfs_init((uint32_t) initrd_data, initrd_size, 1);
+
+ if (l_initrd->Ready == 0)
+ return 0;
+
+// qemu_log("dpm_metadata_read:%x ",dpm_metadata_read('R'));
+//
+ dpm_reg('R', "RamDisk", "TARFS", 2, initrd_size, 0, 0, 2, "TAR0-FSV1", initrd_data);
+ dpm_metadata_write('R', (uint32_t) l_initrd);
+
+ qemu_log("[INITRD] Create virtual read-write disk...");
+ void* disk_t = kmalloc(INITRD_RW_SIZE+1);
+ if (disk_t == NULL){
+ qemu_log("[INITRD] Fatal create virtual disk");
+ return 0;
+ }
+ qemu_log("[INITRD] Temp disk is (%d bytes) created to %x", INITRD_RW_SIZE, disk_t);
+
+
+ dpm_reg('T',"TempDisk","SMFS",2,INITRD_RW_SIZE,0,0,2,"TEMP-DISK",disk_t);
+ //dpm_metadata_write('R',l_initrd);
+
+ //fs_smfs_format('T');
+
+// qemu_log("dpm_metadata_read:%x ",dpm_metadata_read('R'));
+// qemu_log("l_initrd:%x ",l_initrd);
+//
+// FSM_FILE file = fsm_info(fsm_getIDbyName("TARFS"),'R',"main.c");
+////
+// qemu_log("[FF Test] Name: %s",file.Name);
+// qemu_log("[FF Test] Size: %d",file.Size);
+// qemu_log("[FF Test] Type: %d",file.Type);
+// qemu_log("[FF Test] Mode: %d",file.Mode);
+//
+//
+// char* b_mainc = kmalloc(file.Size);
+// size_t r_mainc = fsm_read(fsm_getIDbyName("TARFS"),'R',"main.c",10,5,b_mainc);
+// qemu_log("[TEST] [TarFS] Content:\n%s\n",b_mainc);
+//
+// qemu_log("TARFS:%d|%d",fsm_getIDbyName("TARFS"),fsm_getIDbyName("TarFS"));
+ return 1;
+}
+
diff --git a/kernel/src/drv/disk/mbr.c b/kernel/src/drv/disk/mbr.c
index d84290356..4a34cc7d8 100644
--- a/kernel/src/drv/disk/mbr.c
+++ b/kernel/src/drv/disk/mbr.c
@@ -2,13 +2,14 @@
* @file drv/disk/mbr.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru)
* @brief MBR Info
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-08-03
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-#include
-#include
+#include "common.h"
+#include "io/tty.h"
+#include
typedef struct {
uint8_t Attr; ///< Атрибуты диска (7 = активный)
diff --git a/kernel/src/drv/disk/ndpm.c b/kernel/src/drv/disk/ndpm.c
new file mode 100644
index 000000000..ee1ceab4d
--- /dev/null
+++ b/kernel/src/drv/disk/ndpm.c
@@ -0,0 +1,48 @@
+//
+// Created by ndraey on 23.12.23.
+//
+
+#include
+#include
+#include
+
+ndpm_drive_t ndpm_drives[255] = {0};
+int ndpm_drive_count = 0;
+
+void ndpm_init() {
+
+}
+
+void ndpm_add_drive(void* specific_data, ndpm_read_fn_t reader, ndpm_write_fn_t writer) {
+ for(int i = 0; i < 255; i++) {
+ if(ndpm_drives[i].drive_specific_data == 0) {
+ ndpm_drives[i].drive_specific_data = specific_data;
+ ndpm_drives[i].read_fn = reader;
+ ndpm_drives[i].write_fn = writer;
+
+ ndpm_drive_count++;
+
+ return;
+ }
+ }
+
+ qemu_ok("Add drive ok");
+}
+
+ndpm_drive_t* ndpm_get_drive(int index) {
+ if(index >= 255 || ndpm_drives[index].drive_specific_data == 0) {
+ return 0;
+ }
+
+ return ndpm_drives + index;
+}
+
+void ndpm_list() {
+ _tty_printf("Drive count: %d", ndpm_drive_count);
+
+ /*for(int i = 0; i < 255; i++) {
+ if(ndpm_drives[i].drive_specific_data != 0) {
+
+ }
+ }*/
+}
\ No newline at end of file
diff --git a/kernel/src/drv/fpu.c b/kernel/src/drv/fpu.c
index 46b494a26..d90faa471 100644
--- a/kernel/src/drv/fpu.c
+++ b/kernel/src/drv/fpu.c
@@ -2,7 +2,7 @@
* @file fpu.c
* @author NDRAEY >_ (pikachu_andrey@vk.com)
* @brief FPU
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-12-19
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
@@ -11,16 +11,19 @@
bool fpu_initialized = false;
+/// Возвращает статус FPU
bool fpu_isInitialized() {
return fpu_initialized;
}
+/// Для инициализации FPU
void fpu_fldcw(const uint16_t cw) {
__asm__ volatile("fldcw %0" : : "m"(cw));
}
+/// Инициализация FPU
void fpu_init() {
- uint32_t cr4 = 0;
+ size_t cr4 = 0;
__asm__ volatile ("mov %%cr4, %0":"=r"(cr4));
cr4 |= 0x200;
diff --git a/kernel/src/drv/input/keyboard.c b/kernel/src/drv/input/keyboard.c
old mode 100755
new mode 100644
index 6ee5ce3a5..4853baa80
--- a/kernel/src/drv/input/keyboard.c
+++ b/kernel/src/drv/input/keyboard.c
@@ -2,15 +2,21 @@
* @file drv/input/keyboard.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru), NDRAEY >_ (pikachu_andrey@vk.com)
* @brief Драйвер клавиатуры
- * @version 0.3.3
+ * @version 0.3.4
* @date 2022-11-01
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
extern void tty_backspace();
-#include
+#include
#include
#include
+#include "drv/input/keyboard.h"
+#include "sys/sync.h"
+#include "sys/timer.h"
+#include "io/tty.h"
+#include "drv/psf.h"
+#include "sys/isr.h"
#define KEY_BUFFER_SIZE 16
#define KBD_IS_READDATA (1 << 0)
@@ -28,8 +34,7 @@ extern void tty_backspace();
bool SHIFT = false, ///< Включен ли SHIFT
RU = false, ///< Печатаем русскими?
enabled = true; ///< Включен ли вывод?
-int lastKey = 0, ///< Последний индекс клавишы
- timePresed = 0; ///< Время последнего нажатия
+int lastKey = 0; ///< Последний индекс клавишы
char kbdbuf[256] = {0}; ///< Буфер клавиатуры
uint8_t kbdstatus = 0; ///< Статус клавиатуры
bool echo = true; ///< Включен ли вывод?
@@ -42,10 +47,10 @@ uint32_t chartyped = 0;
/**
* @brief Выводит правильный символ, в зависимости от языка и шифта
*
- * @param char* en_s - Символ маленький англиский
- * @param char* en_b - Символ большой англиский
- * @param char* ru_s - Символ маленький русский
- * @param char* ru_b - Символ большой русский
+ * @param en_s - Символ маленький англиский
+ * @param en_b - Символ большой англиский
+ * @param ru_s - Символ маленький русский
+ * @param ru_b - Символ большой русский
*
* @return char* - Символ в зависимости от раскладки и языка
*/
@@ -66,8 +71,9 @@ void changeStageKeyboard(bool s){
/**
* @brief Выводит символ, в зависимости от кода полученного с клавиатуры
*
- * @param int key - Код клавиатуры
- *
+ * @param key - Код клавиатуры
+ * @param mode - Какой-то режим
+ *
* @return char* - Или символ или код
*/
char* getCharKeyboard(int key, bool mode){
@@ -245,9 +251,7 @@ void* getCharKeyboardWait(bool ints) {
char* getStringBufferKeyboard(){
memset(kbdbuf, 0, 256);
while(1){
-
- int kblen;
- if ((kblen = strlen(kbdbuf)) > 254){
+ if (strlen(kbdbuf) > 254){
qemu_log("Buffer FULL! Max 255!!");
break;
}
@@ -280,34 +284,57 @@ void kbd_add_char(char *buf, char* key) {
}
if(lastKey == 0x0E) { // BACKSPACE
- // qemu_log("BACKSPACE!");
-
- if(chartyped > 0) {
+ if(chartyped > 0) {
tty_backspace();
chartyped--;
- // qemu_log("Deleted character: %c", buf[chartyped]);
buf[chartyped] = 0;
}
}
- }else if(kmode==2){
+ } else if(kmode == 2) {
curbuf = key;
}
}
void gets(char *buffer) { // TODO: Backspace
- // qemu_log("KMODE is: %d, curbuf at: %x", kmode, (int)((void*)curbuf));
-
- kmode = 1;
- curbuf = buffer;
+ // qemu_log("KMODE is: %d, curbuf at: %x", kmode, (int)((void*)curbuf));
- while(kmode==1) {
- if (lastKey == 0x9C) { // Enter key pressed
+ kmode = 1;
+ curbuf = buffer;
+
+ while(kmode == 1) {
+ if (lastKey == 0x9C) { // Enter key pressed
curbuf = 0;
- lastKey = 0;
+ lastKey = 0;
kmode = 0;
- chartyped = 0;
+ chartyped = 0;
}
- }
+ }
+}
+
+// Limited version of gets.
+// Returns 0 if okay, returns 1 if you typed more than `length` keys.
+int gets_max(char *buffer, int length) { // TODO: Backspace
+ kmode = 1;
+ curbuf = buffer;
+
+ while(kmode == 1) {
+ if(chartyped >= length) {
+ curbuf = 0;
+ lastKey = 0;
+ kmode = 0;
+ chartyped = 0;
+ return 1;
+ }
+
+ if (lastKey == 0x9C) { // Enter key pressed
+ curbuf = 0;
+ lastKey = 0;
+ kmode = 0;
+ chartyped = 0;
+ }
+ }
+
+ return 0;
}
/**
@@ -372,7 +399,6 @@ void keyboardHandler(registers_t regs){
}
*/
- timePresed = getTicks()+100;
return;
}
}
@@ -406,7 +432,6 @@ void keyboardInit() {
outb(KBD_STATE_REG, 0xA7); // 2
// Flush The Output Buffer
- // FIXME: It works on QEMU, but on real hardware it hangs until you press any key.
draw_vga_str("Warning: Now, SayoriOS will perform PS/2 buffer flushing. Process is very fast,", 79, 0, 16, 0xffffff);
draw_vga_str(" but on real hardware you can encounter system hanging.", 63, 0, 32, 0xffffff);
@@ -414,22 +439,11 @@ void keyboardInit() {
draw_vga_str(" And even better, help us on https://github.com/pimnik98/SayoriOS", 73, 0, 64 + 16, 0xffffff);
punch();
-
- // inb(KBD_DATA_PORT);
-
- size_t spin = 1000;
-
- while(spin--) {
- uint8_t bit = (inb(KBD_STATE_REG));
-
- qemu_log("Status reg is: %x", bit);
-
- if((bit & 1) == 1)
- inb(KBD_DATA_PORT);
- else
- break;
- };
+ while(inb(KBD_STATE_REG) & 1) {
+ inb(KBD_DATA_PORT);
+ }
+
uint8_t byte = ps2_read_configuration_byte();
if((byte >> 5) & 1) {
diff --git a/kernel/src/drv/input/mouse.c b/kernel/src/drv/input/mouse.c
index b6e4d1e50..05d96f0c4 100644
--- a/kernel/src/drv/input/mouse.c
+++ b/kernel/src/drv/input/mouse.c
@@ -2,21 +2,26 @@
* @file drv/input/mouse.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru), Рустем Гимадутдинов (https://github.com/rgimad/EOS)
* @brief Драйвер мыши
- * @version 0.3.3
+ * @version 0.3.4
* @date 2022-12-11
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-#include
#include
#include
#include
+#include "io/screen.h"
+#include "sys/isr.h"
uint8_t mouse_ready = 0; ///< Готова ли мышь к работе
int32_t mouse_x = 0; ///< Позиция мыши по X
int32_t mouse_y = 0; ///< Позиция мыши по Y
+
+int32_t mouse_ox = 0; ///< Позиция мыши по X (старое значение)
+int32_t mouse_oy = 0; ///< Позиция мыши по Y (старое значение)
+
uint32_t mouse_b1 = 0; ///< Левая кнопка мыши
uint32_t mouse_b2 = 0; ///< Правая кнопка мыши
uint32_t mouse_b3 = 0; ///< Средняя кнопка мыши
@@ -25,15 +30,6 @@ uint32_t mouse_b5 = 0; ///< ???
int mouse_wheel = 0; ///< После каждого чтения меняем на 0
-MouseDrawState_t mouse_state = CURSOR_LOADING;
-
-DANDescriptor_t* mouse_normal = 0;
-char* mouse_normal_frame = 0;
-DANDescriptor_t* mouse_loading = 0;
-char* mouse_loading_frame = 0;
-
-size_t mouse_animation_frame = 0;
-
/**
* @brief Структура данных пакета от мыши
*/
@@ -72,10 +68,6 @@ bool isMouseInit(){
return mouse_ready==1?true:false;
}
-void mouse_set_state(MouseDrawState_t state) {
- mouse_state = state;
-}
-
/**
* @brief Парсинг пакета мыши
*
@@ -100,8 +92,11 @@ void mouse_parse_packet(const char *buf, uint8_t has_wheel, uint8_t has_5_button
ps2m_buffer.button_r = mouse_b2;
ps2m_buffer.button_m = mouse_b3;
- if (mouse_b1 || mouse_b2 || mouse_b3){
+
+ if (mouse_b1 || mouse_b2 || mouse_b3 || (mouse_x != mouse_ox) || (mouse_y != mouse_oy)){
CallTrigger(0x0003,(void*)mouse_b1,(void*)mouse_b2,(void*)mouse_b3,(void*)mouse_x,(void*)mouse_y);
+ mouse_ox = mouse_x;
+ mouse_oy = mouse_y;
}
//qemu_log("MPP: B1: %d | B2: %d | B3: %d | X:%d | Y:%d",mouse_b1,mouse_b2,mouse_b3,mouse_x,mouse_y);
@@ -114,50 +109,6 @@ void mouse_parse_packet(const char *buf, uint8_t has_wheel, uint8_t has_5_button
}
}
-/**
- * @brief Рисует мышь
- *
- * @warning Не нужно вызывать самостоятельно, только для обработчика мыши!
- */
-void mouse_draw() {
- if(mouse_state == CURSOR_HIDDEN)
- return;
-
- if(mouse_state == CURSOR_NORMAL) {
- if(!mouse_normal)
- return;
-
- read_frame_dan(mouse_normal, mouse_animation_frame, mouse_normal_frame);
-
- // duke_rawdraw(mouse_normal_frame, &(struct DukeImageMeta) {
- // {'D', 'U', 'K', 'E'},
- // mouse_normal->header.width,
- // mouse_normal->header.height,
- // mouse_normal->framesize,
- // mouse_normal->header.alpha
- // }, mouse_x, mouse_y);
-
- mouse_animation_frame = (mouse_animation_frame + 1) % mouse_normal->header.frame_count;
- } else if(mouse_state == CURSOR_LOADING) {
- if(!mouse_loading)
- return;
-
- read_frame_dan(mouse_loading, mouse_animation_frame, mouse_loading_frame);
-
- // duke_rawdraw(mouse_loading_frame, &(struct DukeImageMeta) {
- // {'D', 'U', 'K', 'E'},
- // mouse_loading->header.width,
- // mouse_loading->header.height,
- // mouse_loading->framesize,
- // mouse_loading->header.alpha
- // }, mouse_x, mouse_y);
-
- mouse_animation_frame = (mouse_animation_frame + 1) % mouse_loading->header.frame_count;
- }
-
- punch();
-}
-
/**
* @brief Обработчик мыши
*
@@ -190,7 +141,7 @@ void mouse_handler(__attribute__((unused)) struct registers r) {
/**
* @brief Ожидание ответа мыши
*
- * @param uint8_t a_type - Тип отправляемых данных
+ * @param a_type - Тип отправляемых данных
*
* @warning Не нужно вызывать самостоятельно, только для обработчика мыши!
*/
@@ -246,15 +197,6 @@ uint8_t mouse_read() {
* @warning Не нужно вызывать самостоятельно, только для обработчика мыши!
*/
void mouse_install() {
- mouse_normal = alloc_dan("/Sayori/Cursor/normal.dan", false);
- mouse_loading = alloc_dan("/Sayori/Cursor/loading.dan", false);
-
- if(mouse_normal)
- mouse_normal_frame = (char*)kcalloc(1, mouse_normal->framesize);
-
- if(mouse_loading)
- mouse_loading_frame = (char*)kcalloc(1, mouse_normal->framesize);
-
uint8_t _status; //unsigned char
// Включить вспомогательное устройство мыши
diff --git a/kernel/src/drv/pci.c b/kernel/src/drv/pci.c
index baeda4448..c28096de1 100644
--- a/kernel/src/drv/pci.c
+++ b/kernel/src/drv/pci.c
@@ -1,29 +1,29 @@
/**
* @defgroup pci Драйвер PCI (Peripheral Component Interconnect)
* @file drv/pci.c
- * @author Пиминов Никита (nikita.piminoff@yandex.ru), Арен Елчинян (SynapseOS)
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru), Арен Елчинян (SynapseOS), NDRAEY >_ (pikachu_andrey@vk.com)
* @brief Драйвер PCI (Peripheral Component Interconnect)
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-01-14
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-#include
+
#include
#include
#include
-
+#include "io/tty.h"
/**
* @brief [PCI] Чтение 16-битных полей из пространства механизма конфигураций 1
*
- * @param uint8_t bus Шина
- * @param uint8_t slot Слот
- * @param uint8_t function Функция
- * @param uint8_t offset Отступ
+ * @param bus Шина
+ * @param slot Слот
+ * @param function Функция
+ * @param offset Отступ
*
* @warning Когда доступ к конфигурации пытается выбрать несуществующее устройство, хост-мост завершает доступ без ошибок, удаляя все данные при записи и возвращая все данные при чтении.
*
- * @return uint16_t
+ * @return Значение поля
*/
uint16_t pci_read_confspc_word(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset) {
uint32_t addr;
@@ -36,9 +36,17 @@ uint16_t pci_read_confspc_word(uint8_t bus, uint8_t slot, uint8_t function, uint
outl(PCI_ADDRESS_PORT, addr);
- return (uint16_t)((inl(PCI_DATA_PORT) >> ((offset & 2) * 8)) & 0xffff); //this too... I'm too lazy to write them
+ return inl(PCI_DATA_PORT) >> ((offset & 2) * 8);
}
+/**
+ * @brief Чтение данных из шины PCI
+ * @param bus Шина
+ * @param slot Слот
+ * @param function Функция
+ * @param offset Отступ
+ * @return Значение поля
+ */
uint32_t pci_read32(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset) {
uint32_t addr;
uint32_t bus32 = bus;
@@ -47,7 +55,7 @@ uint32_t pci_read32(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset)
addr = (uint32_t)((bus32 << 16) | (slot32 << 11) |
(func32 << 8) | (offset & 0xfc) | ((uint32_t)0x80000000)); //yes, this line is copied from osdev
outl(PCI_ADDRESS_PORT, addr);
- return ((inl(PCI_DATA_PORT) >> ((offset & 2) * 8)) & 0xffff); //this too... I'm too lazy to write them
+ return ((inl(PCI_DATA_PORT) >> ((offset & 2) * 8)) & 0xffffffff); //this too... I'm too lazy to write them
}
@@ -194,13 +202,13 @@ static struct {
/**
* @brief [PCI] Получение основной категории устройства
*
- * @param uint8_t bus Шина
- * @param uint8_t slot Слот
- * @param uint8_t function Функция
+ * @param bus Шина
+ * @param slo Слот
+ * @param function Функция
*
- * @return uint8_t Категория устройства
+ * @return Категория устройства
*/
-uint8_t pci_get_class(uint8_t bus, uint8_t slot, uint8_t function) {
+inline uint8_t pci_get_class(uint8_t bus, uint8_t slot, uint8_t function) {
/* Сдвигаем, чтобы оставить только нужные данные в переменной */
return (uint8_t) (pci_read_confspc_word(bus, slot, function, 10) >> 8);
}
@@ -208,12 +216,12 @@ uint8_t pci_get_class(uint8_t bus, uint8_t slot, uint8_t function) {
/**
* @brief [PCI] Получение под-категории устройства
*
- * @param uint8_t bus Шина
- * @param uint8_t slot Слот
- * @param uint8_t function Функция
+ * @param bus Шина
+ * @param slot Слот
+ * @param function Функция
* @return uint8_t Подкатегория устройства
*/
-uint8_t pci_get_subclass(uint8_t bus, uint8_t slot, uint8_t function) {
+inline uint8_t pci_get_subclass(uint8_t bus, uint8_t slot, uint8_t function) {
/* Сдвигаем, чтобы оставить только нужные данные в переменной */
return (uint8_t) pci_read_confspc_word(bus, slot, function, 10);
}
@@ -221,12 +229,12 @@ uint8_t pci_get_subclass(uint8_t bus, uint8_t slot, uint8_t function) {
/**
* @brief [PCI] Получение HDR-тип устройства
*
- * @param uint8_t bus Шина
- * @param uint8_t slot Слот
- * @param uint8_t function Функция
+ * @param bus Шина
+ * @param slot Слот
+ * @param function Функция
* @return uint8_t HDR-тип
*/
-uint8_t pci_get_hdr_type(uint8_t bus, uint8_t slot, uint8_t function) {
+inline uint8_t pci_get_hdr_type(uint8_t bus, uint8_t slot, uint8_t function) {
/* Сдвигаем, чтобы оставить только нужные данные в переменной */
return (uint8_t) pci_read_confspc_word(bus, slot, function, 7);
}
@@ -234,12 +242,12 @@ uint8_t pci_get_hdr_type(uint8_t bus, uint8_t slot, uint8_t function) {
/**
* @brief [PCI] Получение ID-поставщика
*
- * @param uint8_t bus Шина
- * @param uint8_t slot Слот
- * @param uint8_t function Функция
- * @return uint16_t ID-поставщика
+ * @param bus Шина
+ * @param slot Слот
+ * @param function Функция
+ * @return ID-поставщика
*/
-uint16_t pci_get_vendor(uint8_t bus, uint8_t slot, uint8_t function) {
+inline uint16_t pci_get_vendor(uint8_t bus, uint8_t slot, uint8_t function) {
/* Сдвигаем, чтобы оставить только нужные данные в переменной */
return pci_read_confspc_word(bus, slot, function, 0);
}
@@ -247,12 +255,12 @@ uint16_t pci_get_vendor(uint8_t bus, uint8_t slot, uint8_t function) {
/**
* @brief [PCI] Получение ID-Устройства
*
- * @param uint8_t bus Шина
- * @param uint8_t slot Слот
- * @param uint8_t function Функция
- * @return uint8_t ID-Устройства
+ * @param bus Шина
+ * @param slot Слот
+ * @param function Функция
+ * @return ID-Устройства
*/
-uint16_t pci_get_device(uint8_t bus, uint8_t slot, uint8_t function) {
+inline uint16_t pci_get_device(uint8_t bus, uint8_t slot, uint8_t function) {
/* Сдвигаем, чтобы оставить только нужные данные в переменной */
return pci_read_confspc_word(bus, slot, function, 2);
}
@@ -260,9 +268,9 @@ uint16_t pci_get_device(uint8_t bus, uint8_t slot, uint8_t function) {
/**
* @brief [PCI] Получение классификации устройства
*
- * @param uint8_t class Группа А
- * @param uint8_t subclass Группа Б
- * @return const char * Возращает классификацию устройства
+ * @param klass Группа А
+ * @param subclass Группа Б
+ * @return Возращает классификацию устройства
*/
const char *pci_get_device_type(uint8_t klass, uint8_t subclass) {
for (int i=0; pci_device_type_strings[i].name != nullptr; i++)
@@ -275,7 +283,7 @@ const char *pci_get_device_type(uint8_t klass, uint8_t subclass) {
/**
* @brief [PCI] Получение названия поставщика
*
- * @param uint16_t vendor Поставщик
+ * @param vendor Поставщик
* @return const char * Возращает имя поставщика
*/
const char *pci_get_vendor_name(uint16_t vendor) {
@@ -290,12 +298,12 @@ const char *pci_get_vendor_name(uint16_t vendor) {
/**
* @brief [PCI] ???
*
- * @param uint8_t hdrtype ???
- * @param uint8_t bus Шина
- * @param uint8_t slot Слот
- * @param uint8_t function Функция
- * @param uint8_t bar_number Номер BAR от 0 до 5
- * @param uint8_t *bar_type ???
+ * @param hdrtype ???
+ * @param bus Шина
+ * @param slot Слот
+ * @param func Функция
+ * @param bar_number Номер BAR от 0 до 5
+ * @param bar_type Тип BAR
*
* @todo Необходимо добавить 64-бит реализацию
*
@@ -339,11 +347,11 @@ void pci_write(uint8_t bus, uint8_t slot, uint8_t func, uint32_t offset, uint32_
/**
* @brief [PCI] Поиск устройства по ID-поставшика и устройства
*
- * @param uint16_t vendor ID-Поставщика
- * @param uint16_t device ID-Устройства
- * @param uint8_t *bus_ret
- * @param uint8_t *slot_ret
- * @param uint8_t *func_ret
+ * @param vendor ID-Поставщика
+ * @param device ID-Устройства
+ * @param bus_ret
+ * @param slot_ret
+ * @param func_ret
*/
void pci_find_device(uint16_t vendor, uint16_t device, uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret) {
// qemu_log("Checking device: %x:%x\n", vendor, device);
@@ -362,9 +370,43 @@ void pci_find_device(uint16_t vendor, uint16_t device, uint8_t *bus_ret, uint8_t
}
}
- *bus_ret = *slot_ret = *func_ret = 0xFF;
+ *bus_ret = *slot_ret = *func_ret = 0xFF;
+}
+
+void pci_find_device_by_class_and_subclass(uint16_t class, uint16_t subclass, uint16_t *vendor_ret, uint16_t *deviceid_ret,
+ uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret) {
+ uint8_t func = 0;
+
+ for (uint32_t bus = 0; bus < 256; bus++) {
+ for (uint32_t slot = 0; slot < 32; slot++) {
+
+ if (pci_get_class(bus, slot, func) == class
+ && pci_get_subclass(bus, slot, func) == subclass) {
+ *vendor_ret = pci_get_vendor(bus, slot, func);
+ *deviceid_ret = pci_get_device(bus, slot, func);
+ *bus_ret = bus;
+ *slot_ret = slot;
+ *func_ret = func;
+ return;
+ }
+
+ if((pci_get_hdr_type(bus, slot, 0) & 0x80) == 0) {
+ for (func = 1; func < 8; func++) {
+ if (pci_get_class(bus, slot, func) == class
+ && pci_get_subclass(bus, slot, func) == subclass) {
+ *vendor_ret = pci_get_vendor(bus, slot, func);
+ *deviceid_ret = pci_get_device(bus, slot, func);
+ *bus_ret = bus;
+ *slot_ret = slot;
+ *func_ret = func;
+ return;
+ }
+ }
+ }
+ }
+ }
-// qemu_log("Not found");
+ *bus_ret = *slot_ret = *func_ret = 0xFF;
}
/**
@@ -379,30 +421,28 @@ void pci_print_list() {
tty_printf("PCI список устройств:\n");
for (uint32_t bus = 0; bus < 256; bus++) {
- for (uint32_t slot = 0; slot < 32; slot++) {
+ for (uint8_t slot = 0; slot < 32; slot++) {
uint32_t func = 0;
- clid = pci_get_class(bus, slot, func);
- sclid = pci_get_subclass(bus, slot, func);
vendor = pci_get_vendor(bus, slot, func);
- hdrtype = pci_get_hdr_type(bus, slot, func);
- device = pci_get_device(bus, slot, func);
- if (clid != 0xFF && vendor != 0xFFFF) {
- qemu_log("%u:%u.%u %s: %s (%x), девайс: %x", bus, slot, func, pci_get_device_type(clid, sclid), pci_get_vendor_name(vendor),vendor, device);
- _tty_printf("\t%u:%u.%u %s: %s (%x), девайс: %x\n", bus, slot, func, pci_get_device_type(clid, sclid), pci_get_vendor_name(vendor),vendor, device);
- }
+ if (vendor != 0xFFFF) {
+ clid = pci_get_class(bus, slot, func);
+ sclid = pci_get_subclass(bus, slot, func);
+ hdrtype = pci_get_hdr_type(bus, slot, func);
+ device = pci_get_device(bus, slot, func);
+ _tty_printf("\t%d:%d:%d:%d.%d %s: %s (%x), девайс: %x\n", clid, sclid, bus, slot, func, pci_get_device_type(clid, sclid), pci_get_vendor_name(vendor),vendor, device);
+ }
if ((hdrtype & 0x80) == 0) {
for (func = 1; func < 8; func++) {
- clid = pci_get_class(bus, slot, func);
- sclid = pci_get_subclass(bus, slot, func);
vendor = pci_get_vendor(bus, slot, func);
- device = pci_get_device(bus, slot, func);
- if (clid != 0xFF && vendor != 0xFFFF) {
- qemu_log("%u:%u.%u %s: %s (%x), девайс: %x", bus, slot, func, pci_get_device_type(clid, sclid), pci_get_vendor_name(vendor),vendor, device);
- _tty_printf("\t%u:%u.%u %s: %s (%x), девайс: %x\n", bus, slot, func, pci_get_device_type(clid, sclid), pci_get_vendor_name(vendor),vendor, device);
+ if (vendor != 0xFFFF) {
+ clid = pci_get_class(bus, slot, func);
+ sclid = pci_get_subclass(bus, slot, func);
+ device = pci_get_device(bus, slot, func);
+ _tty_printf("\t%d:%d:%d:%d.%d %s: %s (%x), девайс: %x\n", clid, sclid, bus, slot, func, pci_get_device_type(clid, sclid), pci_get_vendor_name(vendor),vendor, device);
}
}
}
diff --git a/kernel/src/drv/psf.c b/kernel/src/drv/psf.c
index 196c45d0d..120eea8a1 100644
--- a/kernel/src/drv/psf.c
+++ b/kernel/src/drv/psf.c
@@ -2,14 +2,17 @@
* @file drv/psf.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru), Арен Елчинян (SynapseOS)
* @brief Поддержка шрифтов PSF
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-01-13
* @copyright Copyright SayoriOS Team (c) 2023
*/
-#include
+
#include
#include
#include
+#include "mem/vmm.h"
+#include "io/serial_port.h"
+#include "io/screen.h"
uint32_t psf_font_version = 0;
@@ -134,6 +137,9 @@ void draw_vga_ch(uint16_t c, uint16_t c2, size_t pos_x, size_t pos_y, size_t col
uint8_t *glyph = psf1_get_glyph(psf1_rupatch(c, c2));
+ if(!glyph)
+ return;
+
// size_t ph = _h; //psf1_get_h();
// size_t pw = _w; //psf1_get_w();
for (size_t y = 0; y < _h; y++){
@@ -157,7 +163,7 @@ void draw_vga_str(const char* text, size_t len, int x, int y, uint32_t color){
size_t scrwidth = getScreenWidth();
for(int i = 0; i < len; i++){
- if (x + 8 <= scrwidth){
+ if (x + _w <= scrwidth){
if (isUTF(text[i])){
draw_vga_ch(text[i], text[i+1], x, y, color);
i++;
@@ -166,7 +172,7 @@ void draw_vga_str(const char* text, size_t len, int x, int y, uint32_t color){
return;
draw_vga_ch(text[i], 0, x, y, color);
}
- x += 8;
+ x += _w;
} else {
break;
}
diff --git a/kernel/src/drv/rtl8139.c b/kernel/src/drv/rtl8139.c
index bd4b9b4af..2d6c9bc86 100644
--- a/kernel/src/drv/rtl8139.c
+++ b/kernel/src/drv/rtl8139.c
@@ -1,11 +1,28 @@
-#include
-#include
+/**
+ * @brief Драйвер сетевой карты RTL8139
+ * @author NDRAEY >_
+ * @version 0.3.4
+ * @date 2022-04-12
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
+#include "lib/string.h"
+#include "mem/vmm.h"
+#include "mem/pmm.h"
uint8_t rtl8139_busnum, rtl8139_slot, rtl8139_func;
uint32_t rtl8139_io_base, rtl8139_mem_base, rtl8139_bar_type;
-size_t rtl8139_phys_buffer;
+size_t rtl8139_phys_buffer = 0;
+char* rtl8139_virt_buffer = (char*)0;
uint8_t rtl8139_irq;
uint8_t rtl8139_mac[6];
@@ -15,6 +32,12 @@ uint8_t TSD_array[4] = {0x10, 0x14, 0x18, 0x1C};
size_t rtl8139_current_tx_index = 0;
+void* rtl8139_transfer_buffer;
+size_t rtl8139_transfer_buffer_phys;
+
+void rtl8139_send_packet(void* data, size_t length);
+void rtl8139_receive_packet();
+
#define NETCARD_NAME ("RTL8139")
void rtl8139_netcard_get_mac(uint8_t mac[6]) {
@@ -25,8 +48,9 @@ void rtl8139_netcard_get_mac(uint8_t mac[6]) {
netcard_entry_t rtl8139_netcard = {
NETCARD_NAME,
+ {0, 0, 0, 0},
rtl8139_netcard_get_mac,
- rtl8139_send_packet
+ rtl8139_send_packet,
};
void rtl8139_init() {
@@ -68,17 +92,13 @@ void rtl8139_init() {
rtl8139_wake_up();
rtl8139_sw_reset();
- rtl8139_phys_buffer = alloc_phys_pages(RTL8139_BUFFER_PAGE_COUNT);
+ rtl8139_virt_buffer = kmalloc_common(RTL8139_BUFFER_PAGE_COUNT, PAGE_SIZE);
+ rtl8139_phys_buffer = virt2phys(get_kernel_page_directory(), (virtual_addr_t) rtl8139_virt_buffer);
- map_pages(
- get_kernel_dir(),
- rtl8139_phys_buffer,
- rtl8139_phys_buffer,
- RTL8139_BUFFER_PAGE_COUNT,
- (PAGE_WRITEABLE | PAGE_PRESENT)
- );
+ rtl8139_transfer_buffer = kmalloc_common(65535, PAGE_SIZE);
+ rtl8139_transfer_buffer_phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t)rtl8139_transfer_buffer);
- rtl8139_init_buffer();
+ rtl8139_init_buffer();
qemu_log("RTL8139 Physical buffer at: %x", rtl8139_phys_buffer);
@@ -90,12 +110,12 @@ void rtl8139_init() {
rtl8139_read_mac();
// If okay, add network card to list.
- netcard_add(rtl8139_netcard);
+ netcard_add(&rtl8139_netcard);
}
void rtl8139_read_mac() {
uint32_t mac_part1 = inl(rtl8139_io_base + MAC0_5);
- uint16_t mac_part2 = ins(rtl8139_io_base + MAC0_5 + 4);
+ uint16_t mac_part2 = inw(rtl8139_io_base + MAC0_5 + 4);
rtl8139_mac[0] = (mac_part1 >> 0) & 0xFF;
rtl8139_mac[1] = mac_part1 >> 8;
@@ -140,7 +160,7 @@ void rtl8139_init_buffer() {
void rtl8139_handler(registers_t regs) {
qemu_log("Received RTL8139 interrupt!");
- uint16_t status = ins(rtl8139_io_base + 0x3e);
+ uint16_t status = inw(rtl8139_io_base + 0x3e);
if(status & TOK) {
qemu_log("Packet sent");
@@ -148,66 +168,77 @@ void rtl8139_handler(registers_t regs) {
if (status & ROK) {
qemu_log("Packet received!\n");
+
+ // TODO: Push packet to stack then, when needed, work with packets on the stack
+ rtl8139_receive_packet();
}
- outs(rtl8139_io_base + 0x3E, 0x05);
+ outw(rtl8139_io_base + 0x3E, 0x05);
}
-void rtl8139_send_packet(void* data, size_t length) {
- // First, copy the data to a physically contiguous chunk of memory
+void rtl8139_send_packet(void *data, size_t length) {
+ // First, copy the data to a physically contiguous chunk of memory
- void* transfer_data = kmalloc_a(ALIGN(length, 4096));
- size_t phys_addr = virt2phys(get_kernel_dir(), (virtual_addr_t)transfer_data);
- memcpy(transfer_data, data, length);
+ memset(rtl8139_transfer_buffer, 0, 65535);
- qemu_log("Send packet: Virtual memory at %x", transfer_data);
- qemu_log("Send packet: Physical memory at %x", phys_addr);
+ memcpy(rtl8139_transfer_buffer, data, length);
- // Second, fill in physical address of data, and length
+ qemu_log("Send packet: Virtual memory at %x", rtl8139_transfer_buffer);
+ qemu_log("Send packet: Physical memory at %x", rtl8139_transfer_buffer_phys);
- qemu_log("Before: %d", rtl8139_current_tx_index);
-
- outl(rtl8139_io_base + TSAD_array[rtl8139_current_tx_index], (uint32_t)phys_addr);
- outl(rtl8139_io_base + TSD_array[rtl8139_current_tx_index++], length);
-
- qemu_log("After: %d", rtl8139_current_tx_index);
+ // Second, fill in physical address of data, and length
+
+ qemu_log("Before: %d", rtl8139_current_tx_index);
+
+ outl(rtl8139_io_base + TSAD_array[rtl8139_current_tx_index], (uint32_t)rtl8139_transfer_buffer_phys);
+ outl(rtl8139_io_base + TSD_array[rtl8139_current_tx_index++], length);
+
+ qemu_log("After: %d", rtl8139_current_tx_index);
- if(rtl8139_current_tx_index == 4)
- rtl8139_current_tx_index = 0;
+ if(rtl8139_current_tx_index > 3)
+ rtl8139_current_tx_index = 0;
}
size_t rtl8139_current_packet_ptr = 0;
void rtl8139_receive_packet() {
- uint16_t* packet = (uint16_t*)(rtl8139_phys_buffer + rtl8139_current_packet_ptr);
+ uint16_t* packet = (uint16_t*)(rtl8139_virt_buffer + rtl8139_current_packet_ptr);
+
+ EthernetPacked* e_pack = (EthernetPacked*)packet;
+
+ qemu_log("[Net] [RTL8139] Получен пакет!");
+ qemu_log(" |-- Заголовок данных: %x",e_pack->Header);
+ qemu_log(" |-- Длина данных: %d",e_pack->Size);
+ qemu_log(" |-- Источник: %x:%x:%x:%x:%x:%x",e_pack->MAC_SOURCE[0] ,e_pack->MAC_SOURCE[1],e_pack->MAC_SOURCE[2], e_pack->MAC_SOURCE[3] ,e_pack->MAC_SOURCE[4] ,e_pack->MAC_SOURCE[5]);
+ qemu_log(" |-- Кому: %x:%x:%x:%x:%x:%x", e_pack->MAC_DEVICE[0], e_pack->MAC_DEVICE[1], e_pack->MAC_DEVICE[2], e_pack->MAC_DEVICE[3], e_pack->MAC_DEVICE[4], e_pack->MAC_DEVICE[5]);
+ qemu_log(" |-- Тип данных: %x", bit_flip_short(e_pack->Type));
+
// Skip packet header, get packet length
- uint16_t packet_header = packet[0];
- uint16_t packet_length = packet[1];
+ //^ Может быть и верно, но теряется сама логика пакета, из-за этого я не мог понять некоторые моменты
+ // NDRAEY: Это сырая реализция!!!1
- uint16_t* packet_data = packet + 2;
+ uint16_t packet_header = e_pack->Header;
+ uint16_t packet_length = e_pack->Size;
- qemu_log("Packet!!!");
- qemu_log("Packet header: %x", packet_header);
- qemu_log("Packet length: %d", packet_length);
+ uint16_t* packet_data = packet + 2;
- qemu_log("Packet data: ");
+ qemu_log("[Net] [RTL8139] Данные с пакета:\n");
- for(int i = 0; i < packet_length / sizeof(uint16_t); i++) {
- qemu_printf("%x", packet_data[i]);
- }
+// hexview_advanced((char *) packet_data, packet_length, 10, true, new_qemu_printf);
- qemu_printf("\n");
+ if(packet_header == HARDWARE_TYPE_ETHERNET)
+ ethernet_handle_packet(&rtl8139_netcard, (ethernet_frame_t *)packet_data, packet_length);
rtl8139_current_packet_ptr = (rtl8139_current_packet_ptr + packet_length + 7) & RX_READ_POINTER_MASK;
if(rtl8139_current_packet_ptr > 8192)
rtl8139_current_packet_ptr -= 8192;
- outs(rtl8139_io_base + CAPR, rtl8139_current_packet_ptr - 0x10);
+ outw(rtl8139_io_base + CAPR, rtl8139_current_packet_ptr - 0x10);
}
void rtl8139_init_interrupts() {
- outs(rtl8139_io_base + IMR, 0x0005);
+ outw(rtl8139_io_base + IMR, 0x0005);
// https://wiki.osdev.org/PCI
//
@@ -225,4 +256,4 @@ void rtl8139_init_interrupts() {
register_interrupt_handler(32 + rtl8139_irq, rtl8139_handler);
qemu_log("Initialized RTl8139 interrupts!");
-}
\ No newline at end of file
+}
diff --git a/kernel/src/drv/vfs_new.c b/kernel/src/drv/vfs_new.c
deleted file mode 100755
index 396859d97..000000000
--- a/kernel/src/drv/vfs_new.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/**
- * @file drv/vfs_new.c
- * @author Пиминов Никита (nikita.piminoff@yandex.ru), NDRAEY >_ (pikachu_andrey@vk.com)
- * @brief Драйвер виртуальной файловой системы
- * @version 0.3.3
- * @date 2022-11-01
- * @copyright Copyright SayoriOS Team (c) 2022-2023
- */
-#include
-#include
-#include
-#include
-
-fs_node_t *fs_root; ///< Точка монтирования виртуального корня
-fs_node_t *vfs_mount[128]; ///< Точки монтирования
-size_t countMount = 0; ///< Кол-во смонтированных устройств
-
-/**
- * @brief [VFS] Получить реальный путь на устройстве
- *
- * @param int node - Адрес монтирования
- * @param char* path - Путь к файлу (виртуальный)
- */
-void vfs_getPath(int node, const char* path, char* buf){
- // strcpy(buf, path);
- substr(buf, path, strlen(vfs_mount[node]->name), strlen(path));
-
- // qemu_log("Before: %s; After: %s; Path in node: %s", path, buf, vfs_mount[node]->name);
-}
-
-/**
- * @brief [VFS] Получить адрес монтирования у файла
- *
- * @param char* path - Путь к файлу (виртуальный)
- *
- * @warning РАБОТАЕТ НЕМНОГО КОСТЫЛЬНО! ПЕРЕДЕЛАТЬ!!!!!
- *
- * @todo АХТУНГ
- *
- * @return int - Индекс, или отрицательное значение если точка монтирования не найдена
- */
-int vfs_foundMount(const char* path){
- for (int i=countMount-1; i >= 0; i--){
- if (strlen(vfs_mount[i]->name) > strlen(path)){
- /// Нет смысла чекать, ибо длина монтирования, длинее имени пути.
- continue;
- }
- for(size_t a = 0; a < strlen(vfs_mount[i]->name);a++){
- if ((int) vfs_mount[i]->name[a] != (int) path[a]){
- break;
- }
- if(strlen(vfs_mount[i]->name)-1 == a){
- /// О, кажись совпало.
- return i;
- }
- }
- }
- // qemu_log("IM HERE BLYAT");
- return 0;
-}
-
-/**
- * @brief [VFS] Монтирование устройства
- *
- * @param int location - Адрес монтирования
- * @param int type - Тип файловой системы
- */
-fs_node_t *NatSuki_initrd(uint32_t location);
-bool isInitNatSuki();
-void vfs_reg(size_t location, size_t end, size_t type){
- if (type == VFS_TYPE_MOUNT_SEFS){
- //qemu_log("[VFS] [REG] [%d] Sayori Easy File System | Location: %x",countMount,location);
- // vfs_mount[countMount] = (fs_node_t*) kmalloc(sizeof(fs_node_t*));
- vfs_mount[countMount++] = (fs_node_t*) sefs_initrd(location, end);
- // countMount++;
- } else if (type == VFS_TYPE_MOUNT_NATSUKI){
- qemu_log("[VFS] [REG] NatSuki %x | Location: %x", type, location);
- // vfs_mount[countMount] = (fs_node_t*) kmalloc(sizeof(fs_node_t*));
- vfs_mount[countMount] = (fs_node_t*)NatSuki_initrd(location);
- if (isInitNatSuki()){
- countMount++;
- }
- } else {
- qemu_log("[VFS] [REG] Unknown | Location: %x",location);
- }
-}
-
-/**
- * @brief [VFS] Запись в файл
- *
- * @param int node - Адрес монтирования
- * @param int elem - Индекс файла
- * @param size_t offset - С какой позиции читать файл
- * @param size_t size - Длина читаемого файла
- * @param void* buf - Что пишем
- *
- */
-int vfs_write(int node, int elem, size_t offset, size_t size, const void *buf){
- if (vfs_mount[node]->write != 0){
- uint32_t ret = vfs_mount[node]->write(elem,offset,size,buf);
- return ret;
- } else {
- return -1;
- }
-}
-
-/**
- * @brief [VFS] Получить индекс файла, который находиться на устройстве
- *
- * @param char* filename - Путь к файлу (виртуальный)
- *
- * @return int - Индекс файла, или отрицательное значение при ошибке
- */
-int vfs_findFile(const char* filename){
- //qemu_log("[VFS] [FindFile] File: `%s`",filename);
- int node = vfs_foundMount(filename);
- if (vfs_mount[node]->findFile) {
- char* path = (char*)kmalloc(sizeof(char)*strlen(filename));
- vfs_getPath(node, filename, path);
- uint32_t elem = vfs_mount[node]->findFile(path);
-
- kfree(path);
- //qemu_log("\n[VFS] Node: %d | Elem:%d \n",node,elem);
- return elem;
- }
- return -1;
-}
-
-/**
- * @brief [VFS] Проверить существует ли файл
- *
- * @param char* filename - Путь к файлу (виртуальный)
- *
- * @return bool - true если файл найден
- */
-bool vfs_exists(const char* filename){
- if (vfs_findFile(filename) != -1){
- return true;
- }
- return false;
-
- // NDRAEY says:
- // return vfs_findFile(filename) != -1;
-}
-
-/**
- * @brief [VFS] Чтение файла
- *
- * @param int node - Адрес монтирования
- * @param int elem - Индекс файла
- * @param size_t offset - С какой позиции читать файл
- * @param size_t size - Длина читаемого файла
- * @param void* buf - Буфер
- *
- * @return uint32_t - Размер файла или отрицательное значение при ошибке
- */
-int vfs_read(int node, int elem, size_t offset, size_t size, void *buf){
- //qemu_log("[VFS] [Read] Node:%d | Elem: %d | Off: %d | Size: %d", node, elem, offset, size);
- if (vfs_mount[node]->read != 0){
- uint32_t ret = vfs_mount[node]->read(elem, offset, size, buf);
- // qemu_log("Buf now: %s", buf);
- return ret;
- }
- //qemu_log("[VFS] [Read] Error!!!");
- return -1;
-}
-
-/**
- * @brief [VFS] Полное чтение файла
- *
- * @param int node - Адрес монтирования
- * @param int elem - Индекс файла
- *
- * @return char* - Содержимое файла
- */
-char* vfs_readChar(int node,int elem){
- //qemu_log("[VFS] [readChar] Node:%d | Elem: %d",node,elem);
- if (vfs_mount[node]->readChar != 0){
- char* buffer = vfs_mount[node]->readChar(elem);
- return buffer;
- }
- return 0;
-}
-
-/**
- * @brief [VFS] Поиск папки
- *
- * @param char* filename - Путь к папке (виртуальный)
- *
- * @return uint32_t - Индекс папки, или отрицательное значение при ошибке
- */
-uint32_t vfs_findDir(char* path){
- qemu_log("`%s`",path);
-
- int node = vfs_foundMount(path);
-
- if (vfs_mount[node]->findDir != 0){
- char* c_path = (char*)kmalloc(sizeof(char)*(strlen(path)+1));
-
- vfs_getPath(node, path, c_path);
-
- qemu_log("Got path: %s", c_path);
-
- uint32_t elem = vfs_mount[node]->findDir(c_path);
-
- kfree(c_path);
- return elem;
- }
-
- return -1;
-}
-
-/**
- * @brief [VFS] Получить длину файла (поиск по виртуальному пути)
- *
- * @param char* filename - Путь к файлу (виртуальный)
- *
- * @return size_t - Размер файла или отрицательное значение при ошибке
- */
-ssize_t vfs_getLengthFilePath(const char* filename){
- int node = vfs_foundMount(filename);
- if (vfs_mount[node]->findFile != 0 && vfs_mount[node]->getLengthFile != 0){
- char* path = (char*)kmalloc(sizeof(char)*strlen(filename));
- vfs_getPath(node, filename, path);
- uint32_t elem = vfs_mount[node]->findFile(path);
- size_t size = vfs_mount[node]->getLengthFile(elem);
-
- kfree(path);
- //qemu_log("\n\n\t * [VFS] [gLFP] Node: %d | Elem: %d | Size: %d",node,elem,size);
- return size;
- }
- return -2;
-}
-
-/**
- * @brief [VFS] Получить размер файла (поиск по индексу)
- *
- * @param int node - Адрес монтирования
- * @param int elem - Индекс файла
- *
- * @return size_t - Размер файла или отрицательное значение при ошибке
- */
-size_t vfs_getLengthFile(int node,int elem){
- if (vfs_mount[node]->getLengthFile != 0){
- return vfs_mount[node]->getLengthFile(elem);
- }
- return -1;
-}
-
-/**
- * @brief [VFS] Получить отступ в файловой системе у файла
- *
- * @param int node - Адрес монтирования
- * @param int elem - Индекс файла
- *
- * @return int - Позиция файла или отрицательное значение при ошибке
- */
-int vfs_getOffsetFile(int node,int elem){
- if (vfs_mount[node]->getOffsetFile != 0){
- return vfs_mount[node]->getOffsetFile(elem);
- }
- return -1;
-}
-
-/**
- * @brief [VFS] Получить размер устройства
- *
- * @param int node - Адрес монтирования
- *
- * @return size_t - Размер диска
- */
-size_t vfs_getDiskSize(int node){
- return vfs_mount[node]->diskSize(node);
-}
-
-/**
- * @brief [VFS] Получить свободное место устройства
- *
- * @param int node - Адрес монтирования
- *
- * @return size_t - Размер свободного пространства диска
- */
-size_t vfs_getDiskSpace(int node){
- return vfs_mount[node]->diskSpace(node);
-
-}
-
-/**
- * @brief [VFS] Получить занятое место устройства
- *
- * @param int node - Адрес монтирования
- *
- * @return size_t - Размер занятого пространства диска
- */
-size_t vfs_getDiskUsed(int node){
- return vfs_mount[node]->diskUsed(node);
-}
-
-/**
- * @brief [VFS] Получить название устройства
- *
- * @param int node - Адрес монтирования
- *
- * @return char* - Название устройства
- */
-char* vfs_getName(int node){
- return vfs_mount[node]->getDevName(node);
-}
-
-/**
- * @brief [VFS] Получить количество файлов в папке
- *
- * @param char* path - Путь к файлу (виртуальный)
- *
- * @return size_t - Количество файлов
- */
-size_t vfs_getCountElemDir(char* path){
- int node = vfs_foundMount(path);
- if (vfs_mount[node]->getCountElemFolder != 0) {
- char* c_path = (char*)kmalloc(sizeof(char)*strlen(path));
- vfs_getPath(node, path, c_path);
-
- uint32_t folder_elems = vfs_mount[node]->getCountElemFolder(c_path);
-
- kfree(c_path);
- return folder_elems;
- }
- return 0;
-}
-
-/**
- * @brief [VFS] Поиск папки
- *
- * @param char* filename - Путь к папке (виртуальный)
- *
- * @return int - Индекс папки, или отрицательное значение при ошибке
- */
-struct dirent* vfs_getListFolder(char* path){
- int node = vfs_foundMount(path);
- struct dirent* elem = 0;
-
- if (vfs_mount[node]->getListElem != 0) {
- char* c_path = (char*)kmalloc(sizeof(char)*strlen(path) + 1);
-
- vfs_getPath(node, path, c_path);
- elem = vfs_mount[node]->getListElem(c_path);
-
- kfree(c_path);
- return elem;
- }
-
- return elem;
-}
-
-/**
- * @brief [VFS] Создание файла
- *
- * @warning Еше не реализовано
- */
-void vfs_createFile(){
-}
-
-/**
- * @brief [VFS] Создание папки
- *
- * @warning Еше не реализовано
- */
-void vfs_createDir(){
-}
-
-/**
- * @brief [VFS] Вывод содержимого списка файла и папок
- *
- * @warning Еше не реализовано
- */
-void vfs_list(){
- vfs_mount[0]->list("");
-}
-
-/**
- * @brief [VFS] Удаление файла
- *
- * @warning Еше не реализовано
- */
-void vfs_deleteFile(){
-}
-
-
-/**
- * @brief [VFS] Получить тип устройства
- *
- * @warning Еше не реализовано
- */
-void vfs_getType(){
-}
-
-/**
- * @brief [VFS] Получить точку монтирования устройства
- *
- * @warning Еше не реализовано
- */
-void vfs_getMountPoint(){
-}
-
-void vfs_unlistFolder(const char* path, struct dirent* ptr) {
- int node = vfs_foundMount(path);
- if (vfs_mount[node]->unlistElem){
- vfs_mount[node]->unlistElem(ptr);
- }
-}
-
-size_t vfs_byteToKByte(size_t bytes){
- return (bytes == 0?0:bytes/1024);
-}
diff --git a/kernel/src/drv/video/vbe.c b/kernel/src/drv/video/vbe.c
index ca43b2b14..10c5b960f 100644
--- a/kernel/src/drv/video/vbe.c
+++ b/kernel/src/drv/video/vbe.c
@@ -2,7 +2,7 @@
* @file drv/video/vbe.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru)
* @brief Драйвер VBE
- * @version 0.3.3
+ * @version 0.3.4
* @date 2022-11-01
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
diff --git a/kernel/src/extra/cli.c b/kernel/src/extra/cli.c
new file mode 100644
index 000000000..7a378fbfb
--- /dev/null
+++ b/kernel/src/extra/cli.c
@@ -0,0 +1,491 @@
+/**
+ * @file extra/cli.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru), NDRAEY >_ (pikachu_andrey@vk.com)
+ * @brief [CLI] Sayori Command Line (SCL -> Shell)
+ * @version 0.3.4
+ * @date 2022-10-20
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+ */
+
+#include
+#include
+#include "elf/elf.h"
+#include "io/tty.h"
+#include "mem/vmm.h"
+#include "io/status_loggers.h"
+#include "mem/pmm.h"
+#include "lib/split.h"
+#include "version.h"
+#include "drv/input/keyboard.h"
+#include "lib/php/explode.h"
+#include "fs/nvfs.h"
+#include "lib/list.h"
+#include "sys/scheduler.h"
+#include "sys/timer.h"
+#include "drv/disk/dpm.h"
+#include
+#include
+#include "sys/pixfmt.h"
+#include "io/rgb_image.h"
+#include
+
+size_t T_CLI_KYB = 0; ///< Индекс триггера
+int G_CLI_CURINXA = 0;
+int G_CLI_CURINXB = 0;
+int G_CLI_H_KYB = 1;
+int G_CLI_CURINXD = 17; ///< Текущий диск
+char G_CLI_PATH[1024] = "R:\\Sayori\\";
+
+typedef struct {
+ char* name;
+ char* alias;
+ uint32_t (*funcv)(uint32_t, char**);
+ char* helpstring;
+} CLI_CMD_ELEM;
+
+CLI_CMD_ELEM G_CLI_CMD[];
+
+// void F_CLI_KYB(void* data1,void* data2,void* data3,void* data4,void* data5){
+// if (G_CLI_H_KYB == 0) return;
+// qemu_log("[F_CLI_KYB] Key:%d | Pressed: %x",(int) data1, (int) data2);
+// }
+
+uint32_t CLI_CMD_GBA(uint32_t c, char* v[]){
+ if (c == 0 || (c == 1 && (strcmpn(v[1],"/?")))){
+ _tty_printf("Эмулятор GameBoy.\n");
+ _tty_printf("Пример:\"GBA R:\\game.gb\".\n");
+ _tty_printf("\n");
+ return 1;
+ }
+ // gb game.gb
+ tty_printf("%d\n", c);
+
+ for(int i = 0; i < c; i++) {
+ tty_printf("#%d = %s\n", i, v[i]);
+ }
+
+ gb_main(c, v);
+
+ return 1;
+}
+
+
+uint32_t CLI_CMD_CLS(uint32_t c, char* v[]){
+ clean_tty_screen();
+ return 1;
+}
+
+uint32_t CLI_CMD_SYSINFO(uint32_t c, char* v[]){
+ clean_tty_screen();
+
+ setPosY(256);
+
+ tty_printf("SayoriOS by SayoriOS Team (pimnik98 and NDRAEY)\n\n");
+
+ tty_printf("Системная информация:\n");
+ tty_printf("\tOS: SayoriOS v%d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
+ tty_printf("\tДата сборки: %s\n", __TIMESTAMP__);
+ tty_printf("\tАрхитектура: %s\n", ARCH_TYPE);
+ tty_printf("\tПроцессор: %s\n", getNameBrand());
+ tty_printf("\tОЗУ: %d kb\n", getInstalledRam()/1024);
+ tty_printf("\tВидеоадаптер: %s\n","Basic video adapter (Unknown)");
+ tty_printf("\tДисплей: %s (%dx%d)\n", "(\?\?\?)", getScreenWidth(), getScreenHeight());
+ tty_printf("\tТики: %d\n", getTicks());
+ tty_printf("\tЧастота таймера: %d Гц\n", getFrequency());
+ tty_printf("\tВремя с момента запуска: %f секунд\n", getUptime());
+ return 1;
+}
+
+
+uint32_t CLI_CMD_DISKPART(uint32_t c, char* v[]){
+ _tty_printf("Список примонтированных дисков:\n");
+// fsm_dpm_update(-1);
+ for(int i = 0; i < 26; i++){
+ DPM_Disk dpm = dpm_info(i + 65);
+ if (dpm.Ready != 1) continue;
+ _tty_printf(" [%c] %s | %s\n", i + 65, dpm.FileSystem, dpm.Name);
+ }
+
+ _tty_printf("\n");
+ //clean_tty_screen();
+ return 1;
+}
+
+
+uint32_t CLI_CMD_CAT(uint32_t c, char* v[]){
+ if (c == 0 || (c == 1 && (strcmpn(v[1],"/?")))){
+ _tty_printf("Данная программа выводит содержимое файла.\n");
+ _tty_printf("Пример:\"CAT R:\\Sayori\\motd\".\n");
+ _tty_printf("\n");
+ return 1;
+ }
+ FILE* cat_file = fopen(v[1], "r");
+ if (!cat_file){
+ tty_setcolor(COLOR_ERROR);
+ tty_printf("[CMD] [CAT] Не удалось найти файл `%s`. Проверьте правильность введенного вами пути.\n",v[1]);
+ return 2;
+ }
+
+ size_t filesize = fsize(cat_file);
+
+ uint8_t* buffer = kcalloc(1,filesize);
+
+ fread(cat_file, 1, filesize, buffer);
+
+ tty_printf("%s", buffer);
+
+ fclose(cat_file);
+
+ kfree(buffer);
+ return 1;
+}
+
+uint32_t CLI_CMD_JSE(uint32_t c, char* v[]){
+ if (c == 0 || (c == 1 && (strcmpn(v[1],"/?")))){
+ _tty_printf("JavaScript Engine.\n");
+ _tty_printf("Пример:\"JSE R:\\jse\\console.js\".\n");
+ _tty_printf("\n");
+ return 1;
+ }
+
+ int res = elk_file(v[1]);
+
+ if (!res) {
+ tty_setcolor(COLOR_ERROR);
+ tty_printf(" [JSE] Произошла ошибка при выполнении скрипта. Подробности отправлены в консоль.");
+ }
+ return 1;
+}
+
+uint32_t CLI_CMD_SET(uint32_t c, char* v[]){
+ if (c == 1 && (strcmpn(v[1],"/?"))){
+ _tty_printf("Для получения данных переменной введите \"SET ПЕРЕМЕННАЯ\".\n");
+ _tty_printf("Для установки переменной введите \"SET ПЕРЕМЕННАЯ=ЗНАЧЕНИЕ\".\n");
+ _tty_printf("Для удаления переменной введите \"SET ПЕРЕМЕННАЯ=\".\n\n");
+
+ _tty_printf("\n");
+ return 1;
+ }
+ if (c == 0){
+ VARIABLE* s = variable_list("");
+ for(size_t i = 0; i<512; i++) {
+ if (s[i].Ready != 1) break;
+ _tty_printf("%s=%s\n", s[i].Key, s[i].Value);
+ }
+ kfree(s);
+ } else {
+ uint32_t pc = str_cdsp2(v[1], '=');
+ char** out = explode(v[1], '=');
+
+ if (pc != 1){
+ /// Поиск переменной
+ qemu_log("[Режим поиска] %s",v[1]);
+ VARIABLE* s = variable_list(v[1]);
+ for(size_t i = 0; i<512; i++) {
+ if (s[i].Ready != 1) break;
+ _tty_printf("%s=%s\n", s[i].Key, s[i].Value);
+ }
+ kfree(s);
+ } else if (out[1] == NULL || strlen(out[1]) == 0) {
+ qemu_log("[Режим удаления] %s",out[0]);
+ variable_write(out[0],"");
+ } else if (out[1] != NULL) {
+ qemu_log("[Режим изменения] %s",out[0]);
+ variable_write(out[0],out[1]);
+ }
+
+// Почему-то не работает, а должно
+// for (int d = 0; d <= out;d++){
+// kfree(out[d]);
+// }
+ kfree(out);
+ }
+ punch();
+
+ return 0;
+}
+
+uint32_t CLI_CMD_DIR(uint32_t c, char* v[]) {
+ const char* path = (c <= 1 ? G_CLI_PATH : v[1]);
+
+ FSM_DIR* Dir = nvfs_dir(path);
+ if (Dir->Ready != 1){
+ tty_printf("Ошибка %d! При чтении папки: %s\n",Dir->Ready, path);
+ kfree(Dir);
+ return 1;
+ } else {
+ tty_printf("Содержимое папки папки: %s\n\n", path);
+ size_t Sizes = 0;
+ for (int i = 0; i < Dir->Count; i++){
+ char* btime = fsm_timePrintable(Dir->Files[i].LastTime);
+ tty_printf("%s\t%s\t\t%s\n",
+ btime,
+ (Dir->Files[i].Type == 5?"<ПАПКА>":"<ФАЙЛ> "),
+ Dir->Files[i].Name
+ );
+ Sizes += Dir->Files[i].Size;
+ kfree(btime);
+ }
+ tty_printf("\nФайлов: %d | Папок: %d | Всего: %d\n", Dir->CountFiles, Dir->CountDir, Dir->Count);
+ tty_printf("Размер папки: %d мб. | %d кб. | %d б.\n", (Sizes != 0?(Sizes/1024/1024):0), (Sizes != 0?(Sizes/1024):0), Sizes);
+ }
+ /// Сначала чистим массив внутри массива
+ kfree(Dir->Files);
+ /// А потом только основной массив
+ kfree(Dir);
+ return 1;
+}
+
+uint32_t CLI_CMD_RUN(uint32_t c, char* v[]) {
+ if (c == 0){
+ //tty_setcolor(COLOR_ERROR);
+ tty_printf("Файл не указан.\n");
+ return 1;
+ }
+
+ const char* path = v[0];
+
+ FILE* elf_exec = fopen(path, "r");
+
+ if(!elf_exec) {
+ fclose(elf_exec);
+ tty_error("\"%s\" не является внутренней или внешней\n командой, исполняемой программой или пакетным файлом.\n", path);
+ return 2;
+ }
+
+ if(!is_elf_file(elf_exec)) {
+ fclose(elf_exec);
+ tty_printf("\"%s\" не является программой или данный тип файла не поддерживается.\n", path);
+ return 2;
+ }
+
+ fclose(elf_exec);
+
+ run_elf_file(path, c, v);
+
+ return 0;
+}
+
+uint32_t CLI_CMD_ECHO(uint32_t c, char* v[]){
+ if (c == 1 && (strcmpn(v[1],"/?"))){
+ _tty_printf("Данная команда выводит сообщение на экран, а также переменные.\n");
+ _tty_printf("\n");
+ return 1;
+ }
+ for (int i = 1; i <= c;i++){
+ /// Сначало переформируем все в переменные в текст
+ size_t len_v = strlen(v[i]);
+ size_t len_e = len_v-1;
+ if (v[i][0] == '%' && v[i][len_e] == '%'){
+ char* tmp_ve = kmalloc(len_v);
+ substr(tmp_ve,v[i],1,len_e-1);
+ char* tmp_dv = variable_read(tmp_ve);
+ kfree(tmp_ve);
+ if (tmp_dv != NULL) {
+ _tty_printf("%s",tmp_dv);
+ continue;
+ }
+ }
+ //if (str_contains(v[i],""))
+ if (strcmpn(v[i],"%DATE%") || strcmpn(v[i],"%date%")){
+ _tty_printf("2023-01-01");
+ } else if (strcmpn(v[i],"%CD%") || strcmpn(v[i],"%cd%") || strcmpn(v[i],"%path%") || strcmpn(v[i],"%PATH%")){
+ _tty_printf("%s",G_CLI_PATH);
+ } else if (strcmpn(v[i],"%RANDOM%") || strcmpn(v[i],"%random%")){
+ /// Магии не будет - я хз как у нас тут работает рандом
+ _tty_printf("%d",1);
+ } else if (strcmpn(v[i],"%TIME%") || strcmpn(v[i],"%time%")){
+ _tty_printf("%s","12:34");
+ } else {
+ _tty_printf("%s ", v[i]);
+ }
+ }
+ _tty_printf("\n");
+ return 1;
+}
+
+uint32_t CLI_CMD_HELP(__attribute__((unused)) uint32_t c, __attribute__((unused)) char* v[]){
+ _tty_printf("Для получения дополнительной информации, наберите \"команда /?\", если справка по команде есть, она будет отображена.\n\n");
+ size_t hlp_padding = 11;
+ for(size_t i = 0; G_CLI_CMD[i].name != nullptr; i++) {
+ _tty_printf("%s", G_CLI_CMD[i].name);
+ for(size_t j = 0; j < hlp_padding - strlen(G_CLI_CMD[i].name); j++) {
+ _tty_printf(" ");
+ }
+ _tty_printf(" | %s\n", G_CLI_CMD[i].helpstring);
+ }
+
+ punch();
+
+ return 1;
+}
+
+// Pimnik98, don't being thirsty
+
+uint32_t gfxbench(uint32_t argc, char* args[]);
+uint32_t miniplay(uint32_t argc, char* args[]);
+uint32_t CLI_CMD_NET(uint32_t c, char **v);
+uint32_t parallel_desktop_start(uint32_t argc, char* args[]);
+uint32_t mala_draw(uint32_t argc, char* argv[]);
+uint32_t pci_print_list(uint32_t argc, char* argv[]);
+//uint32_t pavi_view(uint32_t argc, char* argv[]);
+uint32_t rust_command(uint32_t argc, char* argv[]);
+uint32_t CLI_MEMINFO(uint32_t argc, char* argv[]) {
+ tty_printf("Физическая:\n");
+ tty_printf(" Используется: %d байт (%d MB)\n", used_phys_memory_size, used_phys_memory_size / MB);
+ tty_printf(" Свободно: %d байт (%d MB)\n", phys_memory_size - used_phys_memory_size, (phys_memory_size - used_phys_memory_size) / MB);
+ tty_printf("Виртуальная:\n");
+ tty_printf(" %d записей\n", system_heap.allocated_count);
+ tty_printf(" Используется: %d байт (%d MB)\n", system_heap.used_memory, system_heap.used_memory / MB);
+
+ return 0;
+}
+
+uint32_t proc_list(uint32_t argc, char* argv[]) {
+ extern list_t process_list;
+ extern list_t thread_list;
+
+ tty_printf("%d процессов\n", process_list.count);
+
+ list_item_t* item = process_list.first;
+ for(int i = 0; i < process_list.count; i++) {
+
+ process_t* proc = (process_t*)item;
+
+ tty_printf(" Процесс: %d [%s]\n", proc->pid, proc->name);
+
+ item = item->next;
+ }
+
+ tty_printf("%d потоков\n", thread_list.count);
+
+ list_item_t* item_thread = thread_list.first;
+ for(int j = 0; j < thread_list.count; j++) {
+ thread_t* thread = (thread_t*)item_thread;
+
+ tty_printf(" Поток: %d [Стек: (%x, %x, %d)]\n", thread->id, thread->stack_top, thread->stack, thread->stack_size);
+
+ item_thread = item_thread->next;
+ }
+
+
+ return 0;
+}
+
+uint32_t ndpm_list(uint32_t, char**);
+uint32_t minesweeper(uint32_t, char**);
+uint32_t shell_diskctl(uint32_t, char**);
+uint32_t calendar(uint32_t, char**);
+
+CLI_CMD_ELEM G_CLI_CMD[] = {
+
+ {"CLS", "cls", CLI_CMD_CLS, "Очистка экрана"},
+ {"CAT", "cat", CLI_CMD_CAT, "Выводит содержимое файла на экран"},
+ {"ECHO", "echo", CLI_CMD_ECHO, "Выводит сообщение на экран."},
+ {"DIR", "dir", CLI_CMD_DIR, "Выводит список файлов и папок."},
+ {"GBA", "gba", CLI_CMD_GBA, "GameBoy Emulator"},
+ {"HELP", "help", CLI_CMD_HELP, "Выводит справочную информацию о командах SayoriOS (CLI)."},
+ {"SET", "set", CLI_CMD_SET, "Показывает, указывает и удаляет переменные среды SayoriOS"},
+ {"NET", "net", CLI_CMD_NET, "Net info"},
+ {"GFXBENCH", "gfxbench", gfxbench, "Тестирование скорости фреймбуфера"},
+ {"MEMINFO", "meminfo", CLI_MEMINFO, "Информация об оперативной памяти"},
+ {"MINIPLAY", "miniplay", miniplay, "WAV-проиграватель"},
+ {"DESKTOP", "desktop", parallel_desktop_start, "Рабочий стол"},
+ {"MALA", "mala", mala_draw, "Нарисовать рисунок"},
+// {"PAVI", "pavi", pavi_view, "Программа для просмотра изображений"},
+ {"PCI", "pci", pci_print_list, "Список PCI устройств"},
+ // {"RS", "rs", rust_command, "Rust command"},
+ {"PROC", "proc", proc_list, "Список процессов"},
+ {"SYSINFO", "sysinfo", CLI_CMD_SYSINFO, "Информация о системе"},
+ {"JSE", "jse", CLI_CMD_JSE, "JavaScript Engine"},
+ {"NDPM", "ndpm", ndpm_list, "Список дисков NDPM"},
+ {"MINESWEEPER", "minesweeper", minesweeper, "Сапёр"},
+ {"DISKPART", "diskpart", CLI_CMD_DISKPART, "Список дисков Disk Partition Manager"},
+ {"DISKCTL", "diskctl", shell_diskctl, "Управление ATA-дисками"},
+ {"CALENDAR", "calendar", calendar, "Календарь"},
+ {nullptr, nullptr, nullptr}
+};
+
+void cli_handler(const char* ncmd){
+ set_cursor_enabled(0);
+
+ uint32_t argc = str_cdsp(ncmd," ") + 1;
+ char* argv[128] = {0};
+
+ str_split(ncmd, argv, " ");
+
+ for(size_t i = 0; i < argc; i++){
+ qemu_log("[CLI] '%s' => argc: %d => argv: %s", ncmd, i, argv[i]);
+ }
+
+ bool found = false;
+
+ for(size_t i = 0; G_CLI_CMD[i].name != nullptr; i++) {
+ if(strcmpn(G_CLI_CMD[i].name, argv[0]) || strcmpn(G_CLI_CMD[i].alias, argv[0])) {
+ G_CLI_CMD[i].funcv(argc, argv);
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ CLI_CMD_RUN(argc + 1, argv);
+ }
+
+ set_cursor_enabled(1);
+}
+
+void cli(){
+ qemu_log("[CLI] Started...");
+ tty_set_bgcolor(0xFF000000);
+ tty_setcolor(0xFFFFFF);
+
+ variable_write("HOSTNAME", "SAYORISOUL");
+ variable_write("SYSTEMROOT", "R:\\Sayori\\");
+ variable_write("TEMP", "T:\\");
+ variable_write("USERNAME", "OEM");
+
+// T_CLI_KYB = RegTrigger(0x0001, &F_CLI_KYB);
+
+// clean_tty_screen();
+ _tty_printf("SayoriOS [Версия: v%d.%d.%d]\n",VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
+ _tty_printf("(c) SayoriOS Team, 2023.\nДля дополнительной информации наберите \"help\".\n\n");
+
+ punch();
+
+ char* input_buffer = kcalloc(1, 256);
+ while(1) {
+ size_t memory_cur = system_heap.used_memory;
+ size_t memory_cnt_cur = system_heap.allocated_count;
+
+ tty_setcolor(0xFFFFFF);
+ tty_printf("%s>", G_CLI_PATH);
+ memset(input_buffer, 0, 256);
+
+ int result = gets_max(input_buffer, 255);
+
+ if(result == 1) {
+ tty_alert("\nMaximum 255 characters!\n");
+ continue;
+ }
+
+ size_t current_time = timestamp();
+ qemu_log("cmd: %s", input_buffer);
+
+ cli_handler(input_buffer);
+ tty_printf("\n");
+
+ ssize_t delta = (int)system_heap.used_memory - (int)memory_cur;
+ ssize_t delta_blocks = (int)system_heap.allocated_count - (int)memory_cnt_cur;
+ qemu_warn("Used memory before: %d (%d blocks)", memory_cur, memory_cnt_cur);
+ qemu_warn("Used memory now: %d (%d blocks)", system_heap.used_memory, system_heap.allocated_count);
+ qemu_warn("Memory used: %d (%d blocks)", delta, delta_blocks);
+
+ if(delta > 0) {
+ qemu_err("Memory leak!");
+ }
+
+ qemu_note("Time elapsed: %d milliseconds", timestamp() - current_time);
+ }
+
+ kfree(input_buffer);
+}
diff --git a/kernel/src/extra/texplorer.c b/kernel/src/extra/texplorer.c
index 55b96db54..f418bad5d 100644
--- a/kernel/src/extra/texplorer.c
+++ b/kernel/src/extra/texplorer.c
@@ -10,7 +10,6 @@
*/
#include
#include
-#include
#include
#include
#include
@@ -31,8 +30,7 @@
#define TE_COLOR_PGB_BODY 0x12
#define TE_COLOR_PGB_TEXT 0x13
-
-DukeHeader_t* TE_Icons[32];
+//DukeHeader_t* TE_Icons[32];
int TE_getColor(int item){
if (item == TE_COLOR_BODY) return 0xFFFFFF;
@@ -55,7 +53,7 @@ int TE_getColor(int item){
void TE_DrawTime(){
setPosY(getScreenHeight() - 20);
- sayori_time_t time = get_time();
+// sayori_time_t time = get_time();
setPosX(getScreenWidth() - 68);
tty_puts_color("22:22:22",TE_getColor(TE_COLOR_START_TEXT),TE_getColor(TE_COLOR_START_BODY));
@@ -118,68 +116,44 @@ void TE_DrawMessageBox(char* title, char* msg, int mode, int x, int y, int close
}
void TE_IconsLoader(){
- char* app = "/Sayori/Icons/app.duke";
- char* config = "/Sayori/Icons/config.duke";
- char* file = "/Sayori/Icons/file.duke";
- char* folder = "/Sayori/Icons/folder.duke";
- char* hdd = "/Sayori/Icons/hdd.duke";
- char* img = "/Sayori/Icons/img.duke";
- char* off = "/Sayori/Icons/off.duke";
- char* start = "/Sayori/Icons/start.duke";
- char* videocard = "/Sayori/Icons/videocard.duke";
-
- FILE* fp_app = fopen(app, "r");
-
- if(!fp_app) {
- qemu_log("[TE] [ICONS] FATAL ERROR LOADER!!! File: %s | Code: %x\n", app,0);
- kfree(TE_Icons[0]);
- return;
- }
-
- fread(fp_app, 1, sizeof(DukeHeader_t), TE_Icons[0]);
- fclose(fp_app);
-
- bool error = duke_draw_from_file(app, 0, 0);
-
- if(error) {
- qemu_log("[TE] [DBG] Во время рендера картинки произошла ошибка.\n");
- }
-
-
-
- //TE_Icons[1];
+ // If you want to place icons here, use TGA.
}
void TE_DesktopBG(){
- DukeHeader_t* imdata = kmalloc(sizeof(DukeHeader_t));
- char* rpath = "/Sayori/Wallpaper/wallpaper.png.duke";
+ // TODO: If you want to support TExplorer further, replace duke with TGA!
+// DukeHeader_t* imdata = kmalloc(sizeof(DukeHeader_t));
+// char* rpath = "/Sayori/Wallpaper/wallpaper.png.duke";
///< Вот СХУЯЛИ баня загорелась? ПРИЧЕМ ТУТ ЖД, если считывание с вирт диска???????????
// Да всё Никита, успокойся, я пофиксил.
///< Спасибо
- FILE* fp = fopen(rpath, "r");
- if(!fp) {
- qemu_log("[TE] [DBG] Произошла ошибка при открытии файла %s\n", rpath);
- kfree(imdata);
- return;
- }
-
- fread(fp, 1, sizeof(DukeHeader_t), imdata);
- fclose(fp);
-
- uint32_t w = getScreenWidth() - imdata->width;
- uint32_t h = getScreenHeight() - imdata->height;
-
- bool error = duke_draw_from_file(rpath, w / 2, h / 2);
-
- if(error) {
- qemu_log("[TE] [DBG] Во время рендера картинки произошла ошибка.\n");
- }
-
- kfree(rpath);
- kfree(imdata);
-
+ // TODO: If you want to support TExplorer further, replace duke with TGA!
+// FILE* fp = fopen(rpath, "r");
+
+// if(!fp) {
+// qemu_log("[TE] [DBG] Произошла ошибка при открытии файла %s\n", rpath);
+// kfree(imdata);
+// return;
+// }
+
+// fread(fp, 1, sizeof(DukeHeader_t), imdata);
+// fclose(fp);
+//
+// uint32_t w = getScreenWidth() - imdata->width;
+// uint32_t h = getScreenHeight() - imdata->height;
+//
+
+ // TODO: If you want to support TExplorer further, replace duke with TGA!
+// bool error = duke_draw_from_file(rpath, w / 2, h / 2);
+
+// if(error) {
+// qemu_log("[TE] [DBG] Во время рендера картинки произошла ошибка.\n");
+// }
+//
+// kfree(rpath);
+// kfree(imdata);
+//
TE_IconsLoader();
punch();
}
diff --git a/kernel/src/extra/tshell.c b/kernel/src/extra/tshell.c
index 759123c21..9e43c6a13 100644
--- a/kernel/src/extra/tshell.c
+++ b/kernel/src/extra/tshell.c
@@ -23,7 +23,7 @@ uint32_t bakMenu = -1;
void headBar(){
drawLine(2,TUI_BASE_COLOR_HEAD);
- char* OSNAME = " SayoriOS v0.3.3 (Dev)";
+ char* OSNAME = " SayoriOS v0.3.4 (Dev)";
setPosX(0);
setPosY(16*1);
tty_puts_color(OSNAME,getColorsTUI(false), TUI_BASE_COLOR_HEAD);
@@ -148,7 +148,7 @@ void menu1(bool items){
if (items){
setCurrentItemTUI(0);
cleanItems();
- addItem("OS: SayoriOS v0.3.3 (Dev)",true,"","");
+ addItem("OS: SayoriOS v0.3.4 (Dev)",true,"","");
addItem("CPU: CX",true,"","");
addItem("RAM: ASD kb",true,"","");
addItem("Display: %s",true,"",""); // 2
diff --git a/kernel/src/fmt/tga.c b/kernel/src/fmt/tga.c
index 29830d092..52f3f56b4 100644
--- a/kernel/src/fmt/tga.c
+++ b/kernel/src/fmt/tga.c
@@ -2,17 +2,17 @@
* @file fmt/tga.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru)
* @brief [Images] Targa - Формат, который также используется многими игровыми движками (например, Quake)
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-07-28
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-
-
-#include
-#include
+#include "lib/stdio.h"
+#include "mem/vmm.h"
+#include "io/screen.h"
+#include "io/tty.h"
#include
-
+#include
int tga_paint(char* path) {
ON_NULLPTR(path, {
@@ -26,7 +26,8 @@ int tga_paint(char* path) {
qemu_log("[CMD] [TGA] [PAINT] Не удалось найти файл `%s`. Проверьте правильность введенного вами пути.\n",path);
return -1;
}
- rgba_color* rgba = kmalloc(sizeof(rgba_color));
+
+// rgba_color* rgba = kmalloc(sizeof(rgba_color));
size_t zxfsize = fsize(file);
char* ptr = kmalloc(zxfsize);
@@ -126,7 +127,7 @@ int tga_paint(char* path) {
y = i = 0;
- size_t pixel = 0;
+// size_t pixel = 0;
size_t current_processing = 0;
size_t cur_x = 0;
@@ -203,6 +204,8 @@ int tga_paint(char* path) {
qemu_log("[TGA] DONE %d-1",ptr[2]);
punch();
qemu_log("[TGA] DONE %d-2",ptr[2]);
+
+ return 0;
}
int tga_info(char* path){
diff --git a/kernel/src/fmt/tga_extract.c b/kernel/src/fmt/tga_extract.c
index ea785f4d4..a560d6584 100644
--- a/kernel/src/fmt/tga_extract.c
+++ b/kernel/src/fmt/tga_extract.c
@@ -3,8 +3,8 @@
#include "common.h"
#include "lib/stdio.h"
#include "fmt/tga.h"
-#include "sys/memory.h"
#include "io/ports.h"
+#include "mem/vmm.h"
bool tga_extract_info(const char* path, tga_header_t* out_meta){
FILE* file = fopen(path, "rb");
@@ -25,108 +25,108 @@ int tga_extract_pixels(const char* path, uint32_t* pixel_buf) {
FILE* file = fopen(path, "rb");
if(!file){
- return -1;
- }
+ return -1;
+ }
+
+ fseek(file, 0, SEEK_END);
- fseek(file, 0, SEEK_END);
+ size_t filesize = ftell(file);
- size_t filesize = ftell(file);
+ fseek(file, 0, SEEK_SET);
- fseek(file, 0, SEEK_SET);
+ uint8_t* file_data = kcalloc(filesize, 1);
- uint8_t* file_data = kcalloc(filesize, 1);
-
- fread(file, filesize, 1, file_data);
+ fread(file, filesize, 1, file_data);
tga_header_t* targa_header = (tga_header_t*)file_data;
-
+
char* data = (char*)file_data + sizeof(tga_header_t);
- // IDK how to understand this code.
+ // IDK how to understand this code.
int i = 0,
- j = 0,
- k = 0,
- x = 0,
- y = 0,
- w = targa_header->w,
- h = targa_header->h,
- o = (file_data[11] << 8) + file_data[10];
+ j = 0,
+ k = 0,
+ x = 0,
+ y = 0,
+ w = targa_header->w,
+ h = targa_header->h,
+ o = (file_data[11] << 8) + file_data[10];
int m = (targa_header->colormap ? (file_data[7]>>3) * file_data[5] : 0) + 18;
-
+
if(w < 1 || h < 1) {
return -2;
}
-
+
if (targa_header->image_type != 1
&& targa_header->image_type != 2
&& targa_header->image_type != 9
&& targa_header->image_type != 10)
- {
+ {
return -3;
}
switch(targa_header->image_type) {
case TGA_MODE_UC_CMI: {
- if(file_data[6] != 0
- || file_data[4] != 0
- || file_data[3] != 0
- || (file_data[7]!=24 && file_data[7]!=32)) {
+ if(file_data[6] != 0
+ || file_data[4] != 0
+ || file_data[3] != 0
+ || (file_data[7]!=24 && file_data[7]!=32)) {
return -4;
}
-
- for(y = i = 0; y>3) + 18;
-
+
+ for(y = i = 0; y>3) + 18;
+
int g = file_data[j];
int a = file_data[j+1];
int b = file_data[j+2];
int r = (file_data[7]==32?file_data[j+3]:0xff);
- pixel_buf[
- y * targa_header->w + x
- ] = (a << 24)
- | (b << 16)
- | (g << 8 )
- | (r << 0 );
- }
- }
- break;
- }
+ pixel_buf[
+ y * targa_header->w + x
+ ] = (a << 24)
+ | (b << 16)
+ | (g << 8 )
+ | (r << 0 );
+ }
+ }
+ break;
+ }
case TGA_MODE_UC_RGB:{
- if(file_data[5]!=0 || file_data[6]!=0 || file_data[1]!=0 || (file_data[16]!=24 && file_data[16]!=32)) {
+ if(file_data[5]!=0 || file_data[6]!=0 || file_data[1]!=0 || (file_data[16]!=24 && file_data[16]!=32)) {
return -4;
}
-
- for(y = i = 0; y < h; y++) {
- j = (!o ? h - y - 1 : y) * w * (targa_header->bpp >> 3);
- for(x = 0; x < w; x++) {
+
+ for(y = i = 0; y < h; y++) {
+ j = (!o ? h - y - 1 : y) * w * (targa_header->bpp >> 3);
+ for(x = 0; x < w; x++) {
int g = file_data[j];
int a = file_data[j+1];
int b = file_data[j+2];
int r = (targa_header->bpp == 32 ? file_data[j+3] : 0xff);
-
- pixel_buf[
- y * targa_header->w + x
- ] = (a << 24)
- | (b << 16)
- | (g << 8 )
- | (r << 0 );
-
- j += targa_header->bpp >> 3;
- }
- }
- break;
+
+ pixel_buf[
+ y * targa_header->w + x
+ ] = (a << 24)
+ | (b << 16)
+ | (g << 8 )
+ | (r << 0 );
+
+ j += targa_header->bpp >> 3;
+ }
+ }
+ break;
}
case TGA_MODE_RL_RGB: {
if(file_data[5]!=0 || file_data[6]!=0 || file_data[1]!=0 || (file_data[16]!=24 && file_data[16]!=32)) {
return -4;
}
- y = i = 0;
+ y = i = 0;
size_t current_processing = 0;
@@ -136,7 +136,7 @@ int tga_extract_pixels(const char* path, uint32_t* pixel_buf) {
while(cur_y < targa_header->h) {
uint8_t rep_count_raw = data[current_processing++];
uint8_t repetition_count = (rep_count_raw & 0b01111111) + 1;
-
+
// If packet is raw, repetition count will indicate pixel count.
bool is_raw = ((rep_count_raw & 0b10000000) >> 7); // Extract highest bit
@@ -144,7 +144,7 @@ int tga_extract_pixels(const char* path, uint32_t* pixel_buf) {
g = 0,
b = 0,
a = 0;
-
+
if(is_raw) {
r = data[current_processing++] & 0xff;
g = data[current_processing++] & 0xff;
@@ -165,12 +165,12 @@ int tga_extract_pixels(const char* path, uint32_t* pixel_buf) {
// b, g, r, a
// });
- pixel_buf[
- cur_y * targa_header->w + cur_x
- ] = (a << 24)
- | (b << 16)
- | (g << 8 )
- | (r << 0 );
+ pixel_buf[
+ cur_y * targa_header->w + cur_x
+ ] = (a << 24)
+ | (b << 16)
+ | (g << 8 )
+ | (r << 0 );
cur_x++;
}
@@ -194,12 +194,12 @@ int tga_extract_pixels(const char* path, uint32_t* pixel_buf) {
// b, g, r, a
// });
- pixel_buf[
- cur_y * targa_header->w + cur_x
- ] = (a << 24)
- | (b << 16)
- | (g << 8 )
- | (r << 0 );
+ pixel_buf[
+ cur_y * targa_header->w + cur_x
+ ] = (a << 24)
+ | (b << 16)
+ | (g << 8 )
+ | (r << 0 );
cur_x++;
}
@@ -207,7 +207,200 @@ int tga_extract_pixels(const char* path, uint32_t* pixel_buf) {
}
}
- break;
+ break;
+ }
+ default: {
+ qemu_err("Error: Mode not implemented: %d\n", targa_header->image_type);
+ break;
+ }
+ }
+
+ kfree(file_data);
+ fclose(file);
+
+ return 0;
+}
+
+// Pixel buffer needs to be 32-bit ARGB buffer
+int tga_extract_pixels_from_data(const char* raw_data, uint32_t* pixel_buf) {
+ ON_NULLPTR(raw_data, {
+ return 0;
+ });
+
+ tga_header_t* targa_header = (tga_header_t*)raw_data;
+
+ qemu_warn("W: %d", targa_header->w);
+ qemu_warn("H: %d", targa_header->h);
+ qemu_warn("BPP: %d", targa_header->bpp);
+
+ char* data = (char*)raw_data + sizeof(tga_header_t);
+
+ // IDK how to understand this code.
+
+ int i = 0,
+ j = 0,
+ k = 0,
+ x = 0,
+ y = 0,
+ w = targa_header->w,
+ h = targa_header->h,
+ o = (raw_data[11] << 8) + raw_data[10];
+
+ int m = (targa_header->colormap ? (raw_data[7]>>3) * raw_data[5] : 0) + 18;
+
+ if(w < 1 || h < 1) {
+ return -2;
+ }
+
+ if (targa_header->image_type != 1
+ && targa_header->image_type != 2
+ && targa_header->image_type != 9
+ && targa_header->image_type != 10)
+ {
+ return -3;
+ }
+
+ switch(targa_header->image_type) {
+ case TGA_MODE_UC_CMI: {
+ if(raw_data[6] != 0
+ || raw_data[4] != 0
+ || raw_data[3] != 0
+ || (raw_data[7]!=24 && raw_data[7]!=32)) {
+ return -4;
+ }
+
+ for(y = i = 0; y>3) + 18;
+
+ int g = raw_data[j];
+ int a = raw_data[j+1];
+ int b = raw_data[j+2];
+ int r = (raw_data[7]==32?raw_data[j+3]:0xff);
+
+ pixel_buf[
+ y * targa_header->w + x
+ ] = (a << 24)
+ | (b << 16)
+ | (g << 8 )
+ | (r << 0 );
+ }
+ }
+ break;
+ }
+ case TGA_MODE_UC_RGB:{
+ if(raw_data[5]!=0 || raw_data[6]!=0 || raw_data[1]!=0 || (raw_data[16]!=24 && raw_data[16]!=32)) {
+ return -4;
+ }
+
+ for(y = i = 0; y < h; y++) {
+ j = (!o ? h - y - 1 : y) * w * (targa_header->bpp >> 3);
+ for(x = 0; x < w; x++) {
+ int g = raw_data[j];
+ int a = raw_data[j+1];
+ int b = raw_data[j+2];
+ int r = (targa_header->bpp == 32 ? raw_data[j+3] : 0xff);
+
+ pixel_buf[
+ y * targa_header->w + x
+ ] = (a << 24)
+ | (b << 16)
+ | (g << 8 )
+ | (r << 0 );
+
+ j += targa_header->bpp >> 3;
+ }
+ }
+ break;
+ }
+ case TGA_MODE_RL_RGB: {
+ if(raw_data[5]!=0 || raw_data[6]!=0 || raw_data[1]!=0 || (raw_data[16]!=24 && raw_data[16]!=32)) {
+ return -4;
+ }
+
+ y = i = 0;
+
+ size_t current_processing = 0;
+
+ size_t cur_x = 0;
+ size_t cur_y = 0;
+
+ while(cur_y < targa_header->h) {
+ uint8_t rep_count_raw = data[current_processing++];
+ uint8_t repetition_count = (rep_count_raw & 0b01111111) + 1;
+
+ // If packet is raw, repetition count will indicate pixel count.
+ bool is_raw = ((rep_count_raw & 0b10000000) >> 7); // Extract highest bit
+
+ uint8_t r = 0,
+ g = 0,
+ b = 0,
+ a = 0;
+
+ if(is_raw) {
+ r = data[current_processing++] & 0xff;
+ g = data[current_processing++] & 0xff;
+ b = data[current_processing++] & 0xff;
+
+ if(targa_header->bpp == 32)
+ a = data[current_processing++] & 0xff;
+ else
+ a = 0xFF;
+
+ while(repetition_count--) {
+ if(cur_x >= targa_header->w) {
+ cur_x = 0;
+ cur_y++;
+ }
+
+ // setPixelAlpha(cur_x, cur_y, (rgba_color) {
+ // b, g, r, a
+ // });
+
+ pixel_buf[
+ cur_y * targa_header->w + cur_x
+ ] = (a << 24)
+ | (b << 16)
+ | (g << 8 )
+ | (r << 0 );
+
+ cur_x++;
+ }
+ } else {
+ while(repetition_count--) {
+ r = data[current_processing++] & 0xff;
+ g = data[current_processing++] & 0xff;
+ b = data[current_processing++] & 0xff;
+
+ if(targa_header->bpp == 32)
+ a = data[current_processing++];
+ else
+ a = 0xFF;
+
+ if(cur_x >= targa_header->w) {
+ cur_x = 0;
+ cur_y++;
+ }
+
+ // setPixelAlpha(cur_x, cur_y, (rgba_color) {
+ // b, g, r, a
+ // });
+
+ pixel_buf[
+ cur_y * targa_header->w + cur_x
+ ] = (a << 24)
+ | (b << 16)
+ | (g << 8 )
+ | (r << 0 );
+
+ cur_x++;
+ }
+
+ }
+ }
+
+ break;
}
default: {
qemu_log("Error: Mode not implemented: %d\n", targa_header->image_type);
@@ -215,5 +408,5 @@ int tga_extract_pixels(const char* path, uint32_t* pixel_buf) {
}
}
- return 0;
-}
\ No newline at end of file
+ return 0;
+}
diff --git a/kernel/src/fs/NatSuki.c b/kernel/src/fs/NatSuki.c
index ec200ee7d..6a3388ea2 100644
--- a/kernel/src/fs/NatSuki.c
+++ b/kernel/src/fs/NatSuki.c
@@ -2,14 +2,20 @@
* @file fs/NatSuki.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru), NDRAEY >_ (pikachu_andrey@vk.com)
* @brief [VFS] [Драйвер] NatSuki - Виртуальная файловая система
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-01-27
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-#include
+#include
#include
-fs_node_t *nat_root; ///< Ссылка на виртуальную фс
+#include "drv/vfs_new.h"
+#include "io/serial_port.h"
+#include "mem/vmm.h"
+#include "lib/split.h"
+#include "io/tty.h"
+
+fs_node_t *nat_root = 0; ///< Ссылка на виртуальную фс
bool __milla_b_init = false; ///< Milla готова к работе?
char* __milla_null = "null"; ///< Ответ, если Milla не готовa
char* __milla_buffer = 0; ///< Буфер
@@ -40,7 +46,9 @@ int __milla_getCode(){
* @brief [Milla] Отправка пакета
*/
void __milla_sendcmd(char* msg){
- if (!__milla_b_init){return;}
+ if (!__milla_b_init)
+ return;
+
__com_formatString(PORT_COM2,"%s |$MC#|",msg);
}
@@ -156,7 +164,7 @@ int __milla_cleanState(){
}
}
-char* __milla_getFile(char* path) {
+char* __milla_getFile(const char *path) {
if (!__milla_b_init){return __milla_null;}
__com_formatString(PORT_COM2,"READ %s |$MC#|",path);
int answer = atoi(__milla_getcmd());
@@ -173,9 +181,16 @@ char* __milla_getFile(char* path) {
size_t inx = 0;
char* buf = (char*)kmalloc(sizeof(char*) * answer);
memset(buf,0,answer);
+ bool st1 = false;
for(;;) {
if (inx >= answer)break;
- tmp = serial_readchar(PORT_COM2);
+ tmp = serial_readchar_timeout(PORT_COM2,10000,false);
+ if (tmp == 0xFFFFFFFF && !st1){
+ //qemu_log("SKIP 0xFFFFFFFF");
+ continue;
+ }
+ if (tmp != 0xFFFFFFFF && !st1) st1 = true;
+
buf[inx] = tmp;
inx++;
}
@@ -281,9 +296,17 @@ char* __milla_getList(char* path){
size_t inx = 0;
char* buf = (char*)kmalloc(sizeof(char*) * answer);
memset(buf,0,answer);
+ bool st1 = false;
for(;;) {
if (inx >= answer)break;
- tmp = serial_readchar(PORT_COM2);
+
+ tmp = serial_readchar_timeout(PORT_COM2,10000,false);
+ if (tmp == 0xFFFFFFFF && !st1){
+ //qemu_log("SKIP 0xFFFFFFFF");
+ continue;
+ }
+ if (tmp != 0xFFFFFFFF && !st1) st1 = true;
+
buf[inx] = tmp;
inx++;
}
@@ -354,7 +377,7 @@ void __milla_destroy(){
/**
* @brief [SEFS] Полное чтение файла
*
- * @param int node - Индекс файла
+ * @param node - Индекс файла
*
* @return char* - Содержимое файла
*/
@@ -366,10 +389,10 @@ char* nat_readChar(uint32_t node){
/**
* @brief [SEFS] Чтение файла
*
- * @param int node - Индекс файла
- * @param int offset - С какой позиции читать файл
- * @param int size - Длина читаемого файла
- * @param void* buf - Буфер
+ * @param node - Индекс файла
+ * @param offset - С какой позиции читать файл
+ * @param size - Длина читаемого файла
+ * @param buf - Буфер
*
* @return uint32_t - Размер файла или отрицательное значение при ошибке
*/
@@ -386,10 +409,10 @@ uint32_t nat_read(uint32_t node, size_t offset, size_t size, void *buffer){
/**
* @brief [SEFS] запись в файл
*
- * @param int node - Индекс файла
- * @param int offset - С какой позиции писать файл
- * @param int size - Сколько пишем
- * @param void* buf - Буфер
+ * @param node - Индекс файла
+ * @param offset - С какой позиции писать файл
+ * @param size - Сколько пишем
+ * @param buf - Буфер
*
* @return uint32_t - Размер записаных байтов или отрицательное значение при ошибке
*/
@@ -402,7 +425,7 @@ uint32_t nat_write(uint32_t node, size_t offset, size_t size, void *buffer){
/**
* @brief [SEFS] Получить размер файла (поиск по индексу)
*
- * @param int node - Индекс файла
+ * @param node - Индекс файла
*
* @return size_t - Размер файла или 0
*/
@@ -416,7 +439,7 @@ size_t nat_getLengthFile(int node){
/**
* @brief [SEFS] Получить отступ в файловой системе у файла
*
- * @param int node - Индекс файла
+ * @param node - Индекс файла
*
* @return int - Позиция файла или отрицательное значение при ошибке
*/
@@ -428,7 +451,7 @@ size_t nat_getOffsetFile(int node){
/**
* @brief [SEFS] Поиск файла на устройстве
*
- * @param char* filename - Путь к файлу (виртуальный)
+ * @param filename - Путь к файлу (виртуальный)
*
* @return int - Индекс файла, или отрицательное значение при ошибке
*/
@@ -441,7 +464,7 @@ int32_t nat_findFile(char* filename){
/**
* @brief [SEFS] Поиск папки на устройстве
*
- * @param char* filename - Путь к папке (виртуальный)
+ * @param filename - Путь к папке (виртуальный)
*
* @return int - Индекс папки, или отрицательное значение при ошибке
*/
@@ -513,7 +536,7 @@ struct dirent* nat_list(char* path){
/**
* @brief [SEFS] Количество используемого места устройства
*
- * @param int node - Нода
+ * @param node - Нода
*
* @return uint64_t - Количество используемого места устройства
*/
@@ -525,7 +548,7 @@ size_t nat_diskUsed(int node){
/**
* @brief [SEFS] Количество свободного места устройства
*
- * @param int node - Нода
+ * @param node - Нода
*
* @return uint64_t - Количество свободного места устройства
*/
@@ -537,7 +560,7 @@ size_t nat_diskSpace(int node){
/**
* @brief [SEFS] Количество всего места устройства
*
- * @param int node - Нода
+ * @param node - Нода
*
* @return uint64_t - Количество всего места устройства
*/
@@ -549,7 +572,7 @@ size_t nat_diskSize(int node){
/**
* @brief [SEFS] Получение имени устройства
*
- * @param int node - Нода
+ * @param node - Нода
*
* @return char* - Имя устройства
*/
@@ -570,7 +593,7 @@ bool isInitNatSuki(){
/**
* @brief [SEFS] Инициализация Sayori Easy File System
*
- * @param uint32_t location - Точка монтирования
+ * @param location - Точка монтирования
*
* @return fs_node_t - Структура с файлами
*/
@@ -596,22 +619,22 @@ fs_node_t *NatSuki_initrd(uint32_t location){
nat_root->flags = FS_DIRECTORY;
nat_root->open = 0;
nat_root->close = 0;
- nat_root->findFile = &nat_findFile;
- nat_root->findDir = &nat_findDir;
+ nat_root->findFile = (findFile_type_t) &nat_findFile;
+ nat_root->findDir = (findFile_type_t) &nat_findDir;
nat_root->getLengthFile = &nat_getLengthFile;
nat_root->getOffsetFile = &nat_getOffsetFile;
- nat_root->list = &nat_list;
+ nat_root->list = (list_type_t) &nat_list;
nat_root->ptr = 0;
nat_root->impl = 0;
nat_root->readChar = &nat_readChar;
nat_root->read = &nat_read;
- nat_root->write = &nat_write;
+ nat_root->write = (write_type_t) &nat_write;
nat_root->diskUsed = &nat_diskUsed;
nat_root->diskSpace = &nat_diskSpace;
nat_root->diskSize = &nat_diskSize;
nat_root->getDevName = &nat_getDevName;
nat_root->getCountElemFolder = &nat_countElemFolder;
- nat_root->getListElem = &nat_list;
+ nat_root->getListElem = (dirlist_type_t) &nat_list;
nat_root->unlistElem = &nat_dirfree;
return nat_root;
diff --git a/kernel/src/fs/fat12.c b/kernel/src/fs/fat12.c
index 5aea26b49..c5eff2465 100644
--- a/kernel/src/fs/fat12.c
+++ b/kernel/src/fs/fat12.c
@@ -2,7 +2,7 @@
* @file drv/fs/fat12.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru)
* @brief Файловая система FAT12
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-07-28
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
diff --git a/kernel/src/fs/fat32.c b/kernel/src/fs/fat32.c
new file mode 100644
index 000000000..6ab77e5d2
--- /dev/null
+++ b/kernel/src/fs/fat32.c
@@ -0,0 +1,301 @@
+/**
+ * @file drv/fs/fat32.c
+ * @author Павленко Андрей (pikachu.andrey@vk.com)
+ * @brief Файловая система FAT32
+ * @version 0.3.4
+ * @date 2023-12-26
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+
+#include
+#include
+#include
+#include
+
+#include "drv/disk/dpm.h"
+#include "mem/vmm.h"
+#include "lib/utf_conversion.h"
+
+size_t fs_fat32_read(char Disk, const char* Path, size_t Offset, size_t Size,void* Buffer){
+ return 0;
+}
+
+size_t fs_fat32_write(char Disk, const char* Path,size_t Offset,size_t Size,void* Buffer){
+ return 0;
+}
+
+FSM_FILE fs_fat32_info(char Disk, const char* Path) {
+ return (FSM_FILE){};
+}
+
+FSM_DIR* fs_fat32_dir(char Disk,const char* Path){
+ fat_description_t* desc = dpm_metadata_read(Disk);
+
+ FSM_DIR *Dir = kcalloc(sizeof(FSM_DIR), 1);
+ FSM_FILE *Files = kcalloc(sizeof(FSM_FILE), 1);
+
+ // TODO: Actually provide an information about disk
+
+ Dir->Ready = 1;
+ Dir->Count = 0;
+ Dir->CountFiles = 0;
+ Dir->CountDir = 0;
+ Dir->CountOther = 0;
+ Dir->Files = Files;
+
+ return Dir;
+}
+
+int fs_fat32_create(char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+int fs_fat32_delete(char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+void fs_fat32_label(char Disk, char* Label){
+ fat_description_t* desc = dpm_metadata_read(Disk);
+
+ memcpy(Label, desc->info.volume_label, 11);
+}
+
+vector_t* fs_fat32_get_clusters(char Disk, size_t cluster_number) {
+ fat_description_t* desc = dpm_metadata_read(Disk);
+
+ vector_t* container = vector_new();
+
+ uint32_t cur_cluster = cluster_number;
+
+ do {
+ uint32_t old_cluster = cur_cluster;
+
+ dpm_read(Disk, desc->fat_offset + (cur_cluster * 4), 4, &cur_cluster);
+
+ vector_push_back(container, old_cluster);
+ } while(!(cur_cluster == 0x0fffffff || cur_cluster == 0x0ffffff8));
+
+ return container;
+}
+
+// Make sure buffer size is cluster-size aligned :)
+void fs_fat32_read_clusters_to_memory(char Disk, size_t cluster_number, void* buffer) {
+ fat_description_t* desc = dpm_metadata_read(Disk);
+
+ vector_t* cluster_list = fs_fat32_get_clusters(Disk, cluster_number);
+
+ for(int i = 0; i < cluster_list->size; i++) {
+ size_t current_cluster = vector_get(cluster_list, i).element;
+
+ size_t addr = ((desc->info.reserved_sectors + (desc->info.fat_size_in_sectors * 2)) \
+ + ((current_cluster - 2) * desc->info.sectors_per_cluster)) * desc->info.bytes_per_sector;
+
+ dpm_read(Disk, addr, desc->cluster_size, (void*)(((size_t)buffer) + (i * desc->cluster_size)));
+ }
+
+ vector_destroy(cluster_list);
+}
+
+size_t fs_fat32_get_cluster_count(char Disk, size_t cluster_number) {
+ vector_t* clusters = fs_fat32_get_clusters(Disk, cluster_number);
+
+ size_t cluster_count = clusters->size;
+
+ vector_destroy(clusters);
+
+ return cluster_count;
+}
+
+size_t fs_fat32_read_lfn(char* data, char* out) {
+ size_t encoded_characters = 0;
+
+ uint16_t* chunk = kcalloc(sizeof(uint16_t), 13);
+ LFN_t lfn = {0};
+
+ memset(out, 0, 256);
+
+ while(true) {
+ memcpy(&lfn, data, sizeof lfn);
+
+ data += sizeof lfn;
+
+ uint8_t lfn_num = lfn.attr_number & ~LFN_LAST_ENTRY;
+
+ if(lfn.reserved != 0 || lfn_num > 20 || lfn.attribute != 0x0F) {
+ // It's normal
+ // qemu_err("Invalid LFN!");
+ return 0;
+ }
+
+ memcpy(chunk, lfn.first_name_chunk, 10);
+ memcpy(chunk + 5, lfn.second_name_chunk, 12);
+ memcpy(chunk + 11, lfn.third_name_chunk, 4);
+
+ uint16_t* prepared_chunk = kcalloc(sizeof(uint16_t), 13);
+
+ for(int i = 0; i < 13; i++) {
+ if(chunk[i] == 0xffff) {
+ break;
+ } else {
+ prepared_chunk[i] = chunk[i];
+ encoded_characters += 2;
+ }
+ }
+
+// char* x = new char[encoded_characters];
+ char* x = kcalloc(1, encoded_characters);
+
+ utf16_to_utf8((short*)prepared_chunk,
+ (int)encoded_characters / 2,
+ x);
+
+// qemu_note("[%d] PIECE: %.13s", encoded_characters, x);
+
+ memmove(out + 13, out, strlen(x));
+ memcpy(out, x, 13);
+
+ kfree(prepared_chunk);
+ kfree(x);
+
+ memset(chunk, 0, 26);
+
+ if(lfn_num == 1) // Is last?
+ break;
+ }
+
+ kfree(chunk);
+
+ return encoded_characters;
+}
+
+fat_file_info_t fs_fat32_get_file_info(char* data) {
+ fat_file_info_t info = {0};
+
+ size_t ecc = fs_fat32_read_lfn(data, info.filename);
+
+ size_t byte_count = ecc / 2;
+
+ size_t div = byte_count / 13, rem = byte_count % 13;
+
+ if(rem > 0) div++;
+
+ // Skip LFN and get into the file info section
+ data += sizeof(LFN_t) * div;
+
+ memcpy(&info.advanced_info, data, sizeof info.advanced_info);
+
+ if(strlen(info.filename) == 0) {
+ for(int i = 0; i < 11; i++) {
+// if(info.advanced_info.short_file_name[i] == ' ')
+// break;
+
+ info.filename[i] = info.advanced_info.short_file_name[i];
+ }
+
+// qemu_note("TODO: Read SFN and make it filename!");
+// while(1);
+ info.is_lfn = false;
+ } else {
+ info.is_lfn = true;
+ }
+
+ info.starting_cluster = (info.advanced_info.first_cluster_high << 16) | info.advanced_info.first_cluster_low;
+ info.size = info.advanced_info.file_size_in_bytes;
+
+ return info;
+}
+
+void fs_fat32_scan_directory(char Disk, size_t directory_cluster) {
+ fat_description_t* desc = dpm_metadata_read(Disk);
+
+ size_t cluster_count = fs_fat32_get_cluster_count(Disk, directory_cluster);
+ char* cluster_data = kcalloc(1, desc->cluster_size * cluster_count);
+
+ fs_fat32_read_clusters_to_memory(Disk, directory_cluster, cluster_data);
+
+ size_t offset = 0;
+
+ // TODO: Actually scan directory
+ while(1) {
+ fat_file_info_t file = fs_fat32_get_file_info(cluster_data + offset);
+
+ if(file.advanced_info.short_file_name[0] == 0)
+ break;
+
+ size_t len = strlen(file.filename);
+ size_t skip_lfns_count = (len / 13);
+ size_t skip_lfns_remiander = (len % 13);
+
+ if(skip_lfns_remiander > 0)
+ skip_lfns_count++;
+
+ if(file.is_lfn)
+ offset += sizeof(LFN_t) * skip_lfns_count;
+
+ offset += sizeof(fat_object_info_t);
+
+ qemu_note("%s %d", file.filename, file.size);
+ }
+
+// while(1);
+
+ kfree(cluster_data);
+}
+
+int fs_fat32_detect(char Disk) {
+// If we initialize fat32 again, bug will appear (could not read root directory)
+// if(dpm_metadata_read(Disk)) {
+// qemu_err("WHAT?");
+// while(1);
+// }
+
+ fat_description_t* fat_system = kcalloc(1, sizeof(fat_description_t));
+
+ dpm_read(Disk, 0, sizeof(fat_info_t), &fat_system->info);
+
+ qemu_warn("Trying FAT32...");
+
+ bool is_fat_bootcode = (unsigned char)fat_system->info.bootcode[0] == 0xEB
+ && (unsigned char)fat_system->info.bootcode[1] == 0x58
+ && (unsigned char)fat_system->info.bootcode[2] == 0x90;
+
+ bool is_fat_fsname = memcmp(fat_system->info.fs_type, "FAT32", 0) == 0;
+
+ if(is_fat_bootcode && is_fat_fsname) {
+ qemu_note("FAT filesystem found!");
+ qemu_note("Disk label: %.11s", fat_system->info.volume_label);
+
+ // Calculate needed values
+ fat_system->cluster_size = fat_system->info.bytes_per_sector * fat_system->info.sectors_per_cluster;
+ fat_system->fat_offset = fat_system->info.reserved_sectors * fat_system->info.bytes_per_sector;
+ fat_system->fat_size = fat_system->info.fat_size_in_sectors * fat_system->info.bytes_per_sector;
+ fat_system->reserved_fat_offset = (fat_system->info.reserved_sectors + fat_system->info.fat_size_in_sectors) * fat_system->info.bytes_per_sector;
+ fat_system->root_directory_offset = ((fat_system->info.reserved_sectors + (fat_system->info.fat_size_in_sectors * 2)) + ((fat_system->info.root_directory_offset_in_clusters - 2) * fat_system->info.sectors_per_cluster)) * fat_system->info.bytes_per_sector;
+
+ qemu_note("Cluster size: %d", fat_system->cluster_size);
+ qemu_note("FAT offset: %d", fat_system->fat_offset);
+ qemu_note("FAT size: %d", fat_system->fat_size);
+ qemu_note("Reserved FAT offset: %d", fat_system->reserved_fat_offset);
+ qemu_note("Root directory offset: %d", fat_system->root_directory_offset);
+
+ // Assign FAT32 filesystem in-place
+ dpm_metadata_write(Disk, (uint32_t) fat_system);
+
+ vector_t* root_directory = fs_fat32_get_clusters(Disk, 2);
+
+ qemu_note("[%d] Root occupies folllwing clusters:", root_directory->size);
+ for(int i = 0; i < root_directory->size; i++) {
+ qemu_note("Cluster: %d", vector_get(root_directory, i).element);
+ }
+
+ vector_destroy(root_directory);
+
+ qemu_warn("SCANNING ROOT DIRECTORY");
+ fs_fat32_scan_directory(Disk, 2);
+ qemu_warn("END SCANNING ROOT DIRECTORY");
+
+ return 1;
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/kernel/src/fs/fsm.c b/kernel/src/fs/fsm.c
new file mode 100644
index 000000000..e470d47f1
--- /dev/null
+++ b/kernel/src/fs/fsm.c
@@ -0,0 +1,246 @@
+/**
+ * @file drv/fs/fsm.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru)
+ * @brief File System Manager (Менеджер файловых систем)
+ * @version 0.3.4
+ * @date 2023-10-16
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+
+#include
+#include
+#include
+#include "lib/php/str_contains.h"
+#include "lib/php/explode.h"
+#include "lib/sprintf.h"
+#include "mem/vmm.h"
+
+#include "drv/disk/dpm.h"
+
+FSM G_FSM[255] = {0};
+int C_FSM = 0;
+bool fsm_debug = false;
+
+void fsm_convertUnix(uint32_t unix_time, FSM_TIME* time) {
+ if (fsm_debug) qemu_log("[FSM] Convert unix: %d",unix_time);
+ uint32_t seconds_per_day = 24 * 60 * 60;
+ uint32_t days = unix_time / seconds_per_day;
+
+ uint32_t years = 1970;
+ uint32_t month, day;
+ while (1) {
+ uint32_t days_in_year = (years % 4 == 0 && (years % 100 != 0 || years % 400 == 0)) ? 366 : 365;
+ if (days < days_in_year) {
+ break;
+ }
+ days -= days_in_year;
+ years++;
+ }
+
+ int8_t month_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ if (years % 4 == 0 && (years % 100 != 0 || years % 400 == 0)) {
+ month_days[1] = 29;
+ }
+
+ uint32_t year_day = days;
+ for (month = 0; month < 12; month++) {
+ if (year_day < month_days[month]) {
+ break;
+ }
+ year_day -= month_days[month];
+ }
+ day = year_day + 1;
+
+ // Вычисляем компоненты времени
+ uint32_t seconds = unix_time % seconds_per_day;
+ uint32_t hour = seconds / 3600;
+ uint32_t minute = (seconds % 3600) / 60;
+ uint32_t second = seconds % 60;
+ //qemu_log("%d.%d.%d %d:%d:%d",years, month, day, hour, minute, second);
+
+ time->year = years;
+ time->month = month;
+ time->day = day;
+ time->hour = hour;
+ time->minute = minute;
+ time->second = second;
+ //memcpy();
+ //qemu_log("%d.%d.%d %d:%d:%d", time->year, time->month, time->day, time->hour, time->minute, time->second);
+}
+
+char* fsm_timePrintable(FSM_TIME time){
+ char* btime = 0;
+
+ asprintf(&btime, "%04d.%02d.%02d %02d:%02d:%02d",
+ time.year,
+ time.month,
+ time.day,
+ time.hour,
+ time.minute,
+ time.second);
+
+ return btime;
+}
+
+int fsm_isPathToFile(const char* Path,const char* Name){
+ char* zpath = pathinfo(Name, PATHINFO_DIRNAME); ///< Получаем родительскую папку элемента
+ char* bpath = pathinfo(Name, PATHINFO_BASENAME); ///< Получаем имя файла (или пустоту если папка)
+ bool isCheck1 = strcmpn(zpath,Path); ///< Проверяем совпадение путей
+ bool isCheck2 = strlen(bpath) == 0; ///< Проверяем, что путе нет ничего лишнего (будет 0, если просто папка)
+ bool isCheck3 = str_contains(Name, Path); ///< Проверяем наличие, вхождения путя
+ size_t c1 = str_cdsp2(Path,'\\');
+ size_t c2 = str_cdsp2(Name,'\\');
+ size_t c3 = str_cdsp2(Path,'/');
+ size_t c4 = str_cdsp2(Name,'/');
+
+ bool isCheck4 = ((c2 - c1) == 1) && (c4 == c3);
+ bool isCheck5 = ((c4 - c3) == 1) && (c2 == c1);
+/*
+ qemu_log("[%d] [%d] [%d] [%d] [%d] %s", isCheck1, isCheck2, isCheck3, isCheck4, isCheck5, Name);
+ qemu_log(" |--- %d == %d",c1,c2);
+ qemu_log(" |--- %d == %d",c3,c4);*/
+ bool isPassed = ((isCheck1 && !isCheck2 && isCheck3) || (!isCheck1 && isCheck2 && isCheck3 && (isCheck4 || isCheck5)));
+
+ // pimnik98, ставь kfree если есть kmalloc!!!!!!!!!!!!!!!!!!!!!!1111
+ kfree(zpath);
+ kfree(bpath);
+
+ return isPassed;
+}
+
+int fsm_getIDbyName(const char* Name){
+ for (int i = 0; i < C_FSM; i++){
+ if (!strcmpn(G_FSM[i].Name,Name)) continue;
+ return i;
+ }
+ return -1;
+}
+
+void fsm_dump(FSM_FILE file){
+ qemu_log(" |--- Ready : %d",file.Ready);
+ qemu_log(" |--- Name : %s",file.Name);
+ qemu_log(" |--- Path : %s",file.Path);
+ qemu_log(" |--- Mode : %d",file.Mode);
+ qemu_log(" |--- Size : %d",file.Size);
+ qemu_log(" |--- Type : %d",file.Type);
+ qemu_log(" |--- Date : %d",file.LastTime.year);
+}
+
+size_t fsm_read(int FIndex, char DIndex, const char* Name, size_t Offset, size_t Count, void* Buffer){
+ if (fsm_debug) qemu_log("[FSM] [READ] F:%d | D:%d | N:%d | O:%d | C:%d",FIndex,DIndex,Name,Offset,Count);
+ if (G_FSM[FIndex].Ready == 0) return 0;
+ if (fsm_debug) qemu_log("[FSM] [READ] GO TO DRIVER");
+ return G_FSM[FIndex].Read(DIndex,Name,Offset, Count, Buffer);
+}
+
+
+int fsm_create(int FIndex, char DIndex, const char* Name, int Mode){
+ if (G_FSM[FIndex].Ready == 0) return 0;
+ return G_FSM[FIndex].Create(DIndex,Name,Mode);
+}
+
+
+int fsm_delete(int FIndex, const char DIndex, const char* Name, int Mode){
+ if (G_FSM[FIndex].Ready == 0)
+ return 0;
+
+ return G_FSM[FIndex].Delete(DIndex,Name,Mode);
+}
+
+size_t fsm_write(int FIndex, const char DIndex, const char* Name, size_t Offset, size_t Count, void* Buffer){
+ if (G_FSM[FIndex].Ready == 0)
+ return 0;
+
+ return G_FSM[FIndex].Write(DIndex,Name,Offset, Count, Buffer);
+}
+
+FSM_FILE fsm_info(int FIndex,const char DIndex, const char* Name){
+ if (fsm_debug) qemu_log("[FSM] [INFO] F:%d | D:%d | N:%s",FIndex,DIndex,Name);
+ if (G_FSM[FIndex].Ready == 0){
+ if (fsm_debug) qemu_log("[FSM] [INFO] READY == 0");
+ return (FSM_FILE){};
+ }
+ if (fsm_debug) qemu_log("[FSM] [INFO] GO TO GFSM");
+ return G_FSM[FIndex].Info(DIndex,Name);
+}
+
+FSM_DIR* fsm_dir(int FIndex,const char DIndex, const char* Name){
+ if (fsm_debug) qemu_log("[FSM] [DIR] F:%d | D:%d | N:%s",FIndex,DIndex,Name);
+
+ if (G_FSM[FIndex].Ready == 0){
+ if (fsm_debug) qemu_log("[FSM] [INFO] READY == 0");
+ FSM_DIR* dir = kmalloc(sizeof(FSM_DIR));
+ return dir;
+ }
+
+ return G_FSM[FIndex].Dir(DIndex, Name);
+}
+
+void fsm_reg(const char* Name,int Splash,fsm_cmd_read_t Read, fsm_cmd_write_t Write, fsm_cmd_info_t Info, fsm_cmd_create_t Create, fsm_cmd_delete_t Delete, fsm_cmd_dir_t Dir, fsm_cmd_label_t Label, fsm_cmd_detect_t Detect){
+ G_FSM[C_FSM].Ready = 1;
+ G_FSM[C_FSM].Splash = Splash;
+ G_FSM[C_FSM].Read = Read;
+ G_FSM[C_FSM].Write = Write;
+ G_FSM[C_FSM].Info = Info;
+ G_FSM[C_FSM].Create = Create;
+ G_FSM[C_FSM].Delete = Delete;
+ G_FSM[C_FSM].Dir = Dir;
+ G_FSM[C_FSM].Label = Label;
+ G_FSM[C_FSM].Detect = Detect;
+ memcpy(G_FSM[C_FSM].Name,Name,strlen(Name));
+ qemu_log("[FSM] Registration of the '%s' file system driver is complete.",Name);
+ C_FSM++;
+}
+
+int fsm_getMode(int FIndex){
+ if (G_FSM[FIndex].Ready == 0) return 0;
+
+ return G_FSM[FIndex].Splash;
+}
+
+
+void fsm_dpm_update(char Letter){
+ char BLANK[128] = {'U','n','k','n','o','w','n',0};
+ if (Letter == -1){
+ // Global update
+ for(int i = 0; i < 26; i++){
+ int DISKID = i + 65;
+ dpm_LabelUpdate(DISKID, BLANK);
+ dpm_FileSystemUpdate(DISKID, BLANK);
+ DPM_Disk dpm = dpm_info(DISKID);
+ if (dpm.Ready != 1) continue;
+ for(int f = 0; f < C_FSM; f++){
+ qemu_note("[FSM] [DPM] >>> Disk %c | Test %s", DISKID, G_FSM[f].Name);
+ int detect = G_FSM[f].Detect(DISKID);
+ if (detect != 1) continue;
+ char* lab_test = kcalloc(1,129);
+ G_FSM[f].Label(DISKID,lab_test);
+ dpm_LabelUpdate(DISKID, lab_test);
+ dpm_FileSystemUpdate(DISKID, G_FSM[f].Name);
+ qemu_note(" | Label: %s", lab_test);
+ kfree(lab_test);
+ break;
+ }
+ }
+ } else {
+ // Personal update
+ int DISKID = Letter;
+ dpm_LabelUpdate(DISKID, BLANK);
+ dpm_FileSystemUpdate(DISKID, BLANK);
+ for(int f = 0; f < C_FSM; f++){
+ qemu_note("[FSM] [DPM] >>> Disk %c | Test %s", DISKID, G_FSM[f].Name);
+ int detect = G_FSM[f].Detect(DISKID);
+
+ if (detect != 1)
+ continue;
+
+ char* lab_test = kcalloc(1,129);
+ G_FSM[f].Label(DISKID, lab_test);
+ dpm_LabelUpdate(DISKID, lab_test);
+ dpm_FileSystemUpdate(DISKID, G_FSM[f].Name);
+ qemu_note("[FSM] [DPM] ^^^ Disk %c | Label: %s", DISKID, lab_test);
+ kfree(lab_test);
+ break;
+ }
+ }
+}
diff --git a/kernel/src/fs/iso9660.c b/kernel/src/fs/iso9660.c
new file mode 100644
index 000000000..354d953e3
--- /dev/null
+++ b/kernel/src/fs/iso9660.c
@@ -0,0 +1,123 @@
+/**
+ * @file drv/fs/iso9660.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru)
+ * @brief Файловая система ISO 9660
+ * @version 0.3.4
+ * @date 2023-12-23
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+
+#include
+#include "portability.h"
+#include
+#include <../src/lib/elk/ext/jse_function.h>
+
+void __out_limit(char* pr, char* str, size_t count){
+ char* buf = kcalloc(1, count+1);
+ memcpy(buf,str, count);
+ printf("%s: '%s'\n",pr, buf);
+ kfree(buf);
+}
+
+
+size_t fs_iso9660_read(const char Disk,const char* Path, size_t Offset, size_t Size,void* Buffer){
+ return 0;
+}
+
+size_t fs_iso9660_write(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer){
+ return 0;
+}
+
+FSM_FILE fs_iso9660_info(const char Disk,const char* Path){
+ return (FSM_FILE){};
+}
+
+FSM_DIR* fs_iso9660_dir(const char Disk,const char* Path){
+ return 0;
+}
+
+int fs_iso9660_create(const char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+int fs_iso9660_delete(const char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+void fs_iso9660_label(const char Disk, char* Label){
+ char* l = kcalloc(1, 33);
+ int buf_read = dpm_read(Disk, 0x8028, 32, l);
+ if (buf_read != 32){
+ memcpy(Label,"Unsupported disk",strlen("Unsupported disk"));
+ } else {
+ l[33] = 0;
+ jse_trim(l);
+ memcpy(Label,l,strlen(l));
+ }
+ kfree(l);
+}
+
+int fs_iso9660_detect(const char Disk){
+ ISO9660_PVD* pvd = kcalloc(1, sizeof(ISO9660_PVD));
+ int buf_read = dpm_read(Disk, 0x8000, sizeof(ISO9660_PVD), pvd);
+ if (
+ pvd->Version != 0x1 ||
+ pvd->ID[0] != 0x43 ||
+ pvd->ID[1] != 0x44 ||
+ pvd->ID[2] != 0x30 ||
+ pvd->ID[3] != 0x30 ||
+ pvd->ID[4] != 0x31 ||
+ pvd->FileStructureVersion != 0x1
+ ){
+ qemu_err("[ISO9660] %c | No passed test!",Disk);
+
+ kfree(pvd);
+ return 0;
+ }
+
+ qemu_warn("--------------------------------");
+ qemu_warn("| Label Disk %c | READ: %d", Disk, buf_read);
+ qemu_warn("| Zero | %x | %d ", pvd->Zero, pvd->Zero);
+ __out_limit("ID", pvd->ID, 5);
+ qemu_warn("| Version | %x | %d ", pvd->Version, pvd->Version);
+ __out_limit("SystemName", pvd->SystemName, 32);
+ __out_limit("Label", pvd->Label, 32);
+ qemu_warn("| VolumeSpaceSize | %x | %d ", pvd->VolumeSpaceSize, pvd->VolumeSpaceSize);
+ qemu_warn("| VolumeSetSize | %x | %d ", pvd->VolumeSetSize, pvd->VolumeSetSize);
+ qemu_warn("| VolumeSequenceNumber | %x | %d ", pvd->VolumeSequenceNumber, pvd->VolumeSequenceNumber);
+ qemu_warn("| LogicalBlockSize | %x | %d ", pvd->LogicalBlockSize, pvd->LogicalBlockSize);
+ qemu_warn("| PathTableSize | %x | %d ", pvd->PathTableSize, pvd->PathTableSize);
+ qemu_warn("| LocOfType_L_PathTable | %x | %d ", pvd->LocOfType_L_PathTable, pvd->LocOfType_L_PathTable);
+ qemu_warn("| LocOfOpti_L_PathTable | %x | %d ", pvd->LocOfOpti_L_PathTable, pvd->LocOfOpti_L_PathTable);
+ qemu_warn("| LocOfType_M_PathTable | %x | %d ", pvd->LocOfType_M_PathTable, pvd->LocOfType_M_PathTable);
+ qemu_warn("| LocOfOpti_M_PathTable | %x | %d ", pvd->LocOfOpti_M_PathTable, pvd->LocOfOpti_M_PathTable);
+
+ __out_limit("DirectoryEntry", pvd->DirectoryEntry, 34);
+ __out_limit("VolumeSetID", pvd->VolumeSetID, 128);
+ __out_limit("PublisherID", pvd->PublisherID, 128);
+ __out_limit("DataPreparerID", pvd->DataPreparerID, 128);
+ __out_limit("ApplicationID", pvd->ApplicationID, 128);
+ __out_limit("CopyrightFileID", pvd->CopyrightFileID, 37);
+ __out_limit("AbstractFileID", pvd->AbstractFileID, 37);
+ __out_limit("BibliographicFileID", pvd->BibliographicFileID, 37);
+ __out_limit("VolumeCreationDate", pvd->VolumeCreationDate, 37);
+ __out_limit("VolumeModificationDate", pvd->VolumeModificationDate, 17);
+ __out_limit("VolumeExpirationDate", pvd->VolumeExpirationDate, 17);
+ __out_limit("VolumeEffectiveDate", pvd->VolumeEffectiveDate, 17);
+
+ qemu_warn("| FSVersion | %x | %d ", pvd->FileStructureVersion, pvd->FileStructureVersion);
+ qemu_warn("--------------------------------");
+
+
+
+
+// ISO9660_Entity* entity = kcalloc(1, sizeof(ISO9660_Entity));
+// buf_read = dpm_read(Disk, 0x809C - 3, sizeof(ISO9660_Entity), entity);
+//
+// int lba = (entity->LBA[0] & 0xFF) | ((entity->LBA[0] & 0xFF00) >> 8) | ((entity->LBA[0] & 0xFF0000) >> 16) | ((entity->LBA[0] & 0xFF000000) >> 24);
+// qemu_warn("LBA: %d | %x",lba,lba);
+
+ kfree(pvd);
+ //kfree(entity);
+ return (1);
+}
\ No newline at end of file
diff --git a/kernel/src/fs/lucario/fs.c b/kernel/src/fs/lucario/fs.c
deleted file mode 100644
index 694666d3e..000000000
--- a/kernel/src/fs/lucario/fs.c
+++ /dev/null
@@ -1,146 +0,0 @@
-#include
-#include
-
-LucarioDescriptor_t* lucario_fs_build_descriptor() {
- return kcalloc(1, sizeof(LucarioDescriptor_t));
-}
-
-bool lucario_fs_init(LucarioDescriptor_t* descr, uint8_t ata_drive) {
- ata_drive_t* ata_drives = ata_get_drives();
-
- if(!ata_drives[ata_drive].online) {
- qemu_log("Drive %x not online", ata_drive);
- return false;
- }
-
- descr->ata_drive = ata_drive;
- descr->disk_capacity = ata_drives[ata_drive].capacity;
-
- ata_read(ata_drive, (uint8_t*)&(descr->header), 0, 512); // Read header
-
- if(memcmp(descr->header.magic, LUCARIOFS_MAGIC, 7)) {
- qemu_log("Invalid magic for drive %x!", ata_drive);
- return false;
- }
-
- qemu_log("Initialized successfully for drive: %x", ata_drive);
-
- qemu_log("Info:");
- qemu_log("\t Magic: %s", descr->header.magic);
- qemu_log("\t Version: %d.%d.%d",
- descr->header.version_major,
- descr->header.version_minor,
- descr->header.version_patch);
-
- descr->max_entries = descr->disk_capacity / LUCARIO_DIVISOR;
-
- qemu_log("\t Max possible entries in this disk: %d", descr->max_entries);
-
- descr->ok = true;
-
- return true;
-}
-
-void lucario_fs_destroy_descriptor(LucarioDescriptor_t* descr) {
- kfree(descr);
-}
-
-void lucario_fs_read_file_entry(LucarioDescriptor_t* descr, size_t index, LucarioFileEntry_t* out) {
- if(index > descr->max_entries)
- return;
-
- ata_read(
- descr->ata_drive,
- (uint8_t*)out,
- 512 + (sizeof(LucarioFileEntry_t) * index),
- sizeof(LucarioFileEntry_t)
- );
-}
-
-void lucario_fs_get_file_entry(LucarioDescriptor_t* descr, char name[], size_t folder_id, LucarioFileEntry_t* out) {
- for(size_t i = 0; i < descr->max_entries; i++) {
- lucario_fs_read_file_entry(descr, i, out);
-
- if(strcmp(out->name, name) == 0 && out->folder_id == folder_id) {
- return;
- }
- }
-
- out->type = E_NONE;
-}
-
-bool lucario_fs_file_exists(LucarioDescriptor_t* descr, char name[], size_t folder_id) {
- for(size_t i = 0; i < descr->max_entries; i++) {
- LucarioFileEntry_t* entry = kcalloc(1, sizeof *entry);
-
- lucario_fs_read_file_entry(descr, i, entry);
-
- if(strcmp(entry->name, name) == 0 && entry->folder_id == folder_id) {
- kfree(entry);
- return true;
- }
-
- kfree(entry);
- }
-
- return false;
-}
-
-size_t lucario_fs_file_size(LucarioDescriptor_t* descr, char name[], size_t folder_id) {
- size_t size = 0;
-
- LucarioFileEntry_t* entry = kcalloc(1, sizeof *entry);
-
- lucario_fs_get_file_entry(descr, name, folder_id, entry);
-
- if(entry->type == E_FILE) {
- size = entry->file_size;
- }
-
- kfree(entry);
-
- return size;
-}
-
-// Offset in sectors!!!
-void lucario_fs_read_sectors_to(LucarioDescriptor_t* descr, size_t sector_list_addr, size_t sector_list_size, size_t offset, char* out) {
- uint32_t cursector;
-
- for (size_t i = 0; i < sector_list_size; i++) {
- ata_read(descr->ata_drive, (uint8_t*)&cursector, sector_list_addr + (i * sizeof(uint32_t)), sizeof(uint32_t));
-
- // qemu_log("Sector number at addr %x: %d", sector_list_addr + (i * sizeof(uint32_t)), cursector);
-
- ata_read_sector(descr->ata_drive, (uint8_t*)(out + (i * 512)), cursector);
- }
-}
-
-// Offset in bytes!!!
-bool lucario_fs_read_file(LucarioDescriptor_t* descr, char name[], size_t folder_id, size_t offset, size_t length, char* out) {
- LucarioFileEntry_t* entry = kcalloc(1, sizeof *entry);
-
- lucario_fs_get_file_entry(descr, name, folder_id, entry);
-
- if(!entry->type) {
- kfree(entry);
-
- return false;
- }
-
- char* temp = kcalloc(1, ALIGN(entry->file_size, 512));
-
- lucario_fs_read_sectors_to(
- descr,
- entry->sector_list_lba * 512,
- entry->sector_list_size,
- ALIGN(offset, 512) / 512,
- temp
- );
- qemu_log("Temp buffer becames: %s", temp);
-
- memcpy(out, temp + offset, length);
-
- kfree(temp);
-
- return true;
-}
diff --git a/kernel/src/fs/milla.c b/kernel/src/fs/milla.c
deleted file mode 100644
index 4d37c9e0e..000000000
--- a/kernel/src/fs/milla.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- *
- * @file fs/milla.c
- * @author Пиминов Никита (nikita.piminoff@yandex.ru), NDRAEY >_ (pikachu_andrey@vk.com)
- * @brief Проект Милла
- * @version 0.3.3
- * @date 2023-01-23
- * @copyright Copyright SayoriOS Team (c) 2022-2023
- */
-#include
-#include
-
diff --git a/kernel/src/fs/natfs.c b/kernel/src/fs/natfs.c
new file mode 100644
index 000000000..2be49465b
--- /dev/null
+++ b/kernel/src/fs/natfs.c
@@ -0,0 +1,171 @@
+/**
+ * @file drv/fs/tarfs.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru)
+ * @brief Файловая система NatFS - NatSuki File System
+ * @version 0.3.6
+ * @date 2023-12-08
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+
+#include
+#include
+#include
+#include
+
+#include
+
+size_t fs_natfs_read(const char Disk,const char* Path, size_t Offset, size_t Size,void* Buffer){
+ char* buf = __milla_getFile(Path);
+ qemu_log("NatSuki:\n\t Path: %s\n\tSize: %d | %d\n\tContent: %s", Path, Size, strlen(buf), buf);
+
+ memcpy(Buffer, buf, Size);
+ //substr(Buffer, (void*)__milla_getFile(Path), Offset, Size);
+ kfree(buf);
+ return Size;
+}
+
+size_t fs_natfs_write(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer){
+ return 0;
+}
+
+FSM_FILE fs_natfs_info(const char Disk,const char* Path){
+ FSM_FILE file = {};
+ file.Size = __milla_getSizeFile(Path);
+ if (__milla_isFile(__milla_findID(Path,"file")) != 1){
+ qemu_warn("[NatFS] File no found???");
+ return file;
+ }
+ file.Ready = 1;
+ //fsm_convertUnix(atoi(_m_s[3]), &file.LastTime);
+
+ char* zpath = pathinfo(Path, PATHINFO_DIRNAME);
+ char* zname = pathinfo(Path, PATHINFO_BASENAME);
+
+ file.Mode = 'r';
+ //file.Type = ((strcmpn(_m_s[0], "file")?0:5));
+ file.Type = 0;
+ file.Ready = 1;
+
+ memcpy(file.Path, Path, strlen(Path));
+ memcpy(file.Name, zname, strlen(zname));
+ return file;
+}
+
+FSM_DIR* fs_natfs_dir(const char Disk,const char* Path){
+ size_t inxDir = __milla_findID(Path,"DIR");
+ if (inxDir < 0){
+ qemu_warn("[NatSuki] When searching for a folder, the error %d was returned, perhaps the folder was not found or the device is not ready to work.", inxDir);
+ return 0;
+ }
+
+ qemu_log("[NatSuki] Get path: %s",Path);
+ FSM_DIR *Dir = kcalloc(sizeof(FSM_DIR), 1);
+ size_t CA = 0, CF = 0, CD = 0, CO = 0;
+
+ char* listt = __milla_getList(Path);
+ char* _m_d[256] = {0};
+ char* _m_s[256] = {0};
+ uint32_t _m_d2 = 0;
+
+ uint32_t _m_d1 = str_cdsp(listt,"\n");
+
+ str_split(listt,_m_d,"\n");
+
+ //tty_printf("Найдено файлов и папок: %d\n",_m_d1-1);
+
+
+ FSM_FILE *Files = kcalloc(sizeof(FSM_FILE), _m_d1);
+ //struct dirent* testFS = kcalloc(_m_d1, sizeof(struct dirent));
+ if (_m_d1 == 0){
+ Dir->Ready = 1;
+ Dir->Count = CA;
+ Dir->CountFiles = CF;
+ Dir->CountDir = CD;
+ Dir->CountOther = CO;
+ Dir->Files = Files;
+
+ return Dir;
+ }
+ for(size_t ind = 0; ind < _m_d1; ind++){
+ _m_d2 = str_cdsp(_m_d[ind],"::");
+ if (_m_d2 < 1) continue;
+ memset(_m_s,0,256);
+ str_split(_m_d[ind],_m_s,"::");
+
+ fsm_convertUnix(atoi(_m_s[3]), &Files[CA].LastTime);
+
+// Files[CA].Mode = 'rw'; // INVALID!
+ Files[CA].Mode = 'r';
+ Files[CA].Size = (atoi(_m_s[4]));
+ Files[CA].Type = ((strcmpn(_m_s[0], "file")?0:5));
+ Files[CA].Ready = 1;
+
+ memcpy(Files[CA].Path, Path, strlen(Path));
+ memcpy(Files[CA].Name, _m_s[1], strlen(_m_s[1]));
+
+
+ if (Files[CA].Type == 0) {
+ /// Это файл
+ CF++;
+ } else if (Files[CA].Type == 5){
+ /// Это папка
+ CD++;
+ } else {
+ /// Рандомный элемент
+ CO++;
+ }
+ CA++;
+
+ //testFS[inxFile].type = ((strcmpn(_m_s[0], "file")?FS_FILE:FS_DIRECTORY));
+ //testFS[inxFile].ino = inxFile;
+ //testFS[inxFile].next = inxFile+1;
+ //testFS[inxFile].length = (atoi(_m_s[4]));
+ //strcpy(testFS[inxFile].name, _m_s[1]);
+ qemu_log("[Milla] [%s] %s (%d b.) Date: %s Owner: %s",_m_s[0],_m_s[1],(atoi(_m_s[4])),_m_s[3],_m_s[5]);
+ }
+ kfree(listt);
+
+ Dir->Ready = 1;
+ Dir->Count = CA;
+ Dir->CountFiles = CF;
+ Dir->CountDir = CD;
+ Dir->CountOther = CO;
+ Dir->Files = Files;
+
+ return Dir;
+}
+
+int fs_natfs_create(const char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+int fs_natfs_delete(const char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+void fs_natfs_label(const char Disk, char* Label){
+ memcpy(Label,"NatFS",strlen("NatFS"));
+}
+
+int fs_natfs_detect(const char Disk){
+ return (0);
+}
+
+char* __milla_getDiskInfo_Name();
+int __milla_getDiskInfo_All();
+
+int fs_natfs_init(){
+ int _m = __milla_init();
+ if (_m != 0){
+ qemu_warn("[NatFS] An error occurred during initialization, the server returned a response: %d",_m);
+ return 0;
+ }
+ int dsize = __milla_getDiskInfo_All();
+ char* dname = __milla_getDiskInfo_Name();
+ int dpm = dpm_reg('N', dname, "NatFS", 2, dsize, 0, 0, 3, "NAT0-SUKI", (void *) _m);
+ if (dpm != 1){
+ qemu_warn("[NatFS] An error occurred while initializing the disk in the operating system! DPM returned the code: %d", dpm);
+ return 0;
+ }
+ return 1;
+}
diff --git a/kernel/src/fs/nullfs.c b/kernel/src/fs/nullfs.c
new file mode 100644
index 000000000..ff2cca990
--- /dev/null
+++ b/kernel/src/fs/nullfs.c
@@ -0,0 +1,44 @@
+/**
+ * @file drv/fs/tarfs.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru)
+ * @brief Файловая система NullFS
+ * @version 0.3.4
+ * @date 2023-10-14
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+
+#include
+#include
+
+
+size_t fs_nullfs_read(const char Disk,const char* Path, size_t Offset, size_t Size,void* Buffer){
+ return 0;
+}
+
+size_t fs_nullfs_write(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer){
+ return 0;
+}
+
+FSM_FILE fs_nullfs_info(const char Disk,const char* Path){
+
+}
+
+FSM_DIR* fs_nullfs_dir(const char Disk,const char* Path){
+
+}
+
+int fs_nullfs_create(const char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+int fs_nullfs_delete(const char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+void fs_nullfs_label(const char Disk, char* Label){
+ memcpy(Label,"NullFS",strlen("NullFS"));
+}
+
+int fs_nullfs_detect(const char Disk){
+ return (0);
+}
\ No newline at end of file
diff --git a/kernel/src/fs/nvfs.c b/kernel/src/fs/nvfs.c
new file mode 100644
index 000000000..48a84fd1c
--- /dev/null
+++ b/kernel/src/fs/nvfs.c
@@ -0,0 +1,140 @@
+/**
+ * @file drv/fs/nvfs.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru)
+ * @brief New Virtual File System - Новая виртуальная файловая система
+ * @version 0.3.4
+ * @date 2023-10-14
+ * @warning Некит, напиши документацию
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+
+#include
+#include
+#include
+
+#include "../lib/libstring/include/string.h"
+#include "mem/vmm.h"
+#include "lib/php/explode.h"
+#include "fs/fsm.h"
+#include "lib/php/str_replace.h"
+
+bool nvfs_debug = false;
+
+
+
+NVFS_DECINFO nvfs_decode(const char* Name){
+ NVFS_DECINFO info = {};
+ info.Ready = 0;
+ info.DriverFS = -1;
+ uint32_t pc = str_cdsp2(Name, ':');
+
+ string_t* strname = string_from_charptr(Name);
+ vector_t* out = string_split(strname, ":");
+
+ if (pc != 1)
+ goto end;
+
+ info.Disk = ADDR2STRING(out->data[0])->data[0];
+
+ substr(info.Path, ADDR2STRING(out->data[1])->data, 1 , ADDR2STRING(out->data[1])->length - 1);
+
+ DPM_Disk disk = dpm_info(info.Disk);
+
+ if (disk.Ready != 1)
+ goto end;
+
+ info.Online = 1;
+ memcpy(info.FileSystem, disk.FileSystem, sizeof(disk.FileSystem));
+
+ info.DriverFS = fsm_getIDbyName(info.FileSystem);
+
+ if (info.DriverFS == -1)
+ goto end;
+
+ int fgm = fsm_getMode(info.DriverFS);
+
+ if (fgm == 0){
+ char_replace(0x2F,0x5C,info.Path);
+ } else {
+ char_replace(0x5C,0x2F,info.Path);
+ }
+
+ info.Ready = 1;
+
+ end:
+
+ string_split_free(out);
+ string_destroy(strname);
+
+ return info;
+}
+
+size_t nvfs_read(const char* Name, size_t Offset, size_t Count, void* Buffer){
+ const NVFS_DECINFO vinfo = nvfs_decode(Name);
+ if (vinfo.Ready == 0) return 0;
+ return fsm_read(vinfo.DriverFS, vinfo.Disk, vinfo.Path, Offset, Count, Buffer);
+}
+
+int nvfs_create(const char* Name, int Mode){
+ const NVFS_DECINFO vinfo = nvfs_decode(Name);
+ if (vinfo.Ready == 0) return 0;
+ return fsm_create(vinfo.DriverFS, vinfo.Disk, vinfo.Path, Mode);
+}
+
+int nvfs_delete(const char* Name, int Mode){
+ const NVFS_DECINFO vinfo = nvfs_decode(Name);
+ if (vinfo.Ready == 0)
+ return 0;
+ return fsm_delete(vinfo.DriverFS, vinfo.Disk, vinfo.Path, Mode);
+}
+
+size_t nvfs_write(const char* Name, size_t Offset, size_t Count, const void *Buffer){
+ const NVFS_DECINFO vinfo = nvfs_decode(Name);
+ if (vinfo.Ready == 0)
+ return 0;
+ return fsm_write(vinfo.DriverFS, vinfo.Disk, vinfo.Path, Offset, Count, Buffer);
+}
+
+FSM_FILE nvfs_info(const char* Name){
+ NVFS_DECINFO vinfo = nvfs_decode(Name); // no memleak
+ if (nvfs_debug) qemu_log("NVFS INFO:\nReady: %d\nDisk: [%d] %c\nPath: [%d] %s\nDisk Online: %d\nDisk file system: [%d] %s\nLoaded in file system driver: %d",vinfo.Ready,vinfo.Disk,vinfo.Disk,strlen(vinfo.Path),vinfo.Path,vinfo.Online,strlen(vinfo.FileSystem),vinfo.FileSystem,vinfo.DriverFS);
+
+ if (vinfo.Ready != 1){
+ return (FSM_FILE){};
+ }
+
+ FSM_FILE file = fsm_info(vinfo.DriverFS, vinfo.Disk, vinfo.Path);
+
+ return file;
+}
+
+FSM_DIR* nvfs_dir(const char* Name){
+ NVFS_DECINFO vinfo = nvfs_decode(Name);
+
+ if (vinfo.Ready != 1) {
+ FSM_DIR* dir = kcalloc(sizeof(FSM_DIR), 1);
+ return dir;
+ }
+
+ FSM_DIR* dir = fsm_dir(vinfo.DriverFS, vinfo.Disk, vinfo.Path);
+ return dir;
+}
+
+/*
+
+void vnfs_test(){
+
+ FSM_FILE file = nvfs_info("R:\\help next you\\main.c");
+ //qemu_log("Ready: %d",file.Ready);
+ fsm_dump(file);
+
+ char* bf1 = kmalloc(file.Size);
+ int rf1 = nvfs_read("R:\\help next you\\main.c",10,5,bf1);
+
+ qemu_log("Read %d / %d |\n%s\n",rf1,file.Size,bf1);
+
+ FSM_FILE file2 = nvfs_info("b:\\pizdec\\вот это драйвер\\ахуеть.exe");
+
+ fsm_dump(file2);
+ while(1){}
+}*/
diff --git a/kernel/src/fs/sefs.c b/kernel/src/fs/sefs.c
deleted file mode 100755
index d29c03775..000000000
--- a/kernel/src/fs/sefs.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/**
- * @file fs/sefs.c
- * @author Пиминов Никита (nikita.piminoff@yandex.ru), NDRAEY >_ (pikachu_andrey@vk.com)
- * @brief Файловая система SEFS (Sayori Easy File System)
- * @version 0.3.3
- * @date 2022-11-01
- * @copyright Copyright SayoriOS Team (c) 2022-2023
- */
-#include
-#include
-#include
-#include
-
-sefs_header_t *sefs_header; ///< ...
-sefs_file_header_t *file_headers; ///< ...
-fs_node_t *sefs_root; ///< ...
-fs_node_t *sefs_dev; ///< ...
-fs_node_t *root_nodes; ///< ...
-int nroot_nodes; ///< Количество файлов.
-struct dirent dirent; ///< ...
-size_t dirName[2048]; ///< Ссылка на названия папок по индексу
-size_t diskUsed = 0; ///< Количество используемого пространства
-size_t diskSize = 0; ///< Общие кол-во дисков
-size_t dirCount = 0; ///< Количество папок
-
-/**
- * @brief [SEFS] Полное чтение файла
- *
- * @param int node - Индекс файла
- *
- * @warning IT's MEMORY LEAKY!!!
- * @return char* - Содержимое файла
- */
-char* sefs_readChar(uint32_t node){
- sefs_file_header_t header = file_headers[node];
- //qemu_log("[SEFS] [readChar] Elem: %d",node);
- char* buf = (char*)kmalloc(header.length);
- memcpy(buf, (void*)header.offset, header.length);
- return buf;
-}
-
-/**
- * @brief [SEFS] Чтение файла
- *
- * @param int node - Индекс файла
- * @param int offset - С какой позиции читать файл
- * @param int size - Длина читаемого файла
- * @param void* buf - Буфер
- *
- * @return uint32_t - Размер файла или отрицательное значение при ошибке
- */
-uint32_t sefs_read(uint32_t node, size_t offset, size_t size, void *buffer){
- sefs_file_header_t header = file_headers[node];
- //qemu_log("[SEFS] [Read] Elem: %d | Off: %d | Size: %d", node, offset, size);
-
- // Did you mean: offset+size > header.length
- if (header.length < size) {
- size = header.length;
- }
-
- qemu_log("SEFS -> Read from: %x to (%x) (size %d)", header.offset + offset, header.offset + offset + size, size);
-
- memcpy(buffer, (char*)(header.offset+offset), size);
-
- // qemu_log("SEFS early buffer now: %s", (char*)(header.offset + offset));
- // qemu_log("SEFS buffer now: %s", buffer);
- return size;
-}
-
-/**
- * @brief [SEFS] запись в файл
- *
- * @param int node - Индекс файла
- * @param int offset - С какой позиции писать файл
- * @param int size - Сколько пишем
- * @param void* buf - Буфер
- *
- * @return uint32_t - Размер записаных байтов или отрицательное значение при ошибке
- */
-uint32_t sefs_write(uint32_t node, size_t offset, size_t size, void *buffer){
- sefs_file_header_t header = file_headers[node];
- //qemu_log("[SEFS] [Write] Elem: %d | Off: %d | Size: %d",node,offset,size);
- if (offset > size){
- return -2;
- }
- void* newfile = kmalloc((size + offset > header.length)?(size + offset):header.length);
- int w_tmp1 = 0; ///< Сколько скопировано с начала
- // int w_tmp2 = 0; ///< Сколько вставлено с буфера
- int w_tmp3 = 0; ///< Сколько вставлено с остатка
- // Сохраняем первую часть данных
- if (offset > 0){
- void* tmp1 = kmalloc(offset);
- w_tmp1 = sefs_read(node,0,offset,tmp1);
- memcpy(newfile, tmp1, offset);
- }
- // Сохраняем буфер
- strcat((char*)newfile, (const char*)buffer);
- // если остались остатки, то копируем
- if ((size + offset < header.length)){
- w_tmp3 = header.length - (size + offset); // Откуда копируем
- void* tmp3 = kmalloc(offset);
- w_tmp3 = sefs_read(node,0,w_tmp3,tmp3);
- strcat((char*)newfile, (const char*)tmp3);
- }
- return w_tmp1+size+w_tmp3;
-}
-
-/**
- * @brief [SEFS] Получить размер файла (поиск по индексу)
- *
- * @param int node - Индекс файла
- *
- * @return size_t - Размер файла или 0
- */
-size_t sefs_getLengthFile(int node){
- //qemu_log("[SEFS] [gLF] Node: %d | Size: %d",node,root_nodes[node].length);
-
- return root_nodes[node].length;
-}
-
-/**
- * @brief [SEFS] Получить отступ в файловой системе у файла
- *
- * @param int node - Индекс файла
- *
- * @return int - Позиция файла или отрицательное значение при ошибке
- */
-size_t sefs_getOffsetFile(int node){
- return file_headers[node].offset;
-}
-
-/**
- * @brief [SEFS] Поиск файла на устройстве
- *
- * @param char* filename - Путь к файлу (виртуальный)
- *
- * @return int - Индекс файла, или отрицательное значение при ошибке
- */
-int32_t sefs_findFile(const char* filename){
- char* file = (char*)kmalloc(sizeof(char)*256);
- char* sl = "/";
- strcpy(file, sl);
- strcat(file,filename);
-
- //qemu_log("[SeFS] `%s` | `%s`",filename,file);
- for (size_t i = 0; i < sefs_header->nfiles; i++){
- if (strcmpn(root_nodes[i].path,file)){
- kfree(file);
- return i;
- }
- }
- kfree(file);
- return -1;
-}
-
-/**
- * @brief [SEFS] Поиск папки на устройстве
- *
- * @param char* filename - Путь к папке (виртуальный)
- *
- * @return int - Индекс папки, или отрицательное значение при ошибке
- */
-int32_t sefs_findDir(const char* path){
- char* file = (char*)kmalloc(sizeof(char)*256);
- char* sl = "/";
-
- strcpy(file, sl);
- strcat(file, path);
-
- qemu_log("[SeFS] `%s` | `%s`", path, file);
-
- for (size_t i = 0, a = 0; i < sefs_header->nfiles; i++){
- if (root_nodes[i].flags != FS_DIRECTORY) continue;
- if (strcmpn(root_nodes[i].name, file)){
- kfree(file);
- return a;
- }
- a++;
- }
- kfree(file);
- return -1;
-}
-
-/**
- * @brief [SEFS] Считает количество элементов в папке
- */
-size_t sefs_countElemFolder(char* path){
- ssize_t inxDir = sefs_findDir(path);
- if (inxDir < 0) {
- return 0;
- }
- size_t count = 0;
- for (size_t i = 0; i < sefs_header->nfiles; i++){
- if (root_nodes[i].root != inxDir){
- continue;
- }
- count++;
- }
- return count;
-}
-
-/**
- * @brief [SEFS] Выводит список файлов
- */
-struct dirent* sefs_list(const char* path){
- size_t inxDir = sefs_findDir(path);
- if (inxDir < 0){
- return 0;
- }
-
- struct dirent* testFS = (struct dirent*)kcalloc(sefs_header->nfiles, sizeof(struct dirent));
-
- qemu_log("[Index Dir] %d",inxDir);
- size_t inxFile = 0;
- for (size_t i = 0; i < sefs_header->nfiles; i++){
- if (root_nodes[i].root != inxDir){
- continue;
- }
- testFS[inxFile].type = root_nodes[i].flags;
- testFS[inxFile].ino = i;
- testFS[inxFile].next = i+1;
- testFS[inxFile].length = root_nodes[i].length;
- strcpy(testFS[inxFile].name, root_nodes[i].name);
- inxFile++;
-
- qemu_log("[SEFS] [Init] I:%d",i);
- qemu_log("\t * Name:%s",root_nodes[i].name);
- qemu_log("\t * mask:%d",root_nodes[i].mask);
- qemu_log("\t * length:%d",root_nodes[i].length);
- qemu_log("\t * flags:%x",root_nodes[i].flags);
- qemu_log("\t * inode:%d",root_nodes[i].inode);
- qemu_log("\t * offset:%d",file_headers[i].offset);
- qemu_log("\t * root:%d",root_nodes[i].root);
- }
- testFS[inxFile].next = 0;
- return testFS;
-}
-
-/**
- * @brief [SEFS] Количество используемого места устройства
- *
- * @param int node - Нода
- *
- * @return size_t - Количество используемого места устройства
- */
-size_t sefs_diskUsed(int node){
- return diskUsed;
-}
-
-/**
- * @brief [SEFS] Количество свободного места устройства
- *
- * @param int node - Нода
- *
- * @return size_t - Количество свободного места устройства
- */
-size_t sefs_diskSpace(int node){
- return 0;
-}
-
-/**
- * @brief [SEFS] Количество всего места устройства
- *
- * @param int node - Нода
- *
- * @return size_t - Количество всего места устройства
- */
-size_t sefs_diskSize(int node){
- return diskSize;
-}
-
-/**
- * @brief [SEFS] Получение имени устройства
- *
- * @param int node - Нода
- *
- * @return char* - Имя устройства
- */
-char* sefs_getDevName(int node){
- return sefs_root->devName;
-}
-
-void sefs_dirfree(struct dirent* ptr) {
- // qemu_log("SEFS freeing dirent pointer: %x", ptr);
- if(ptr) {
- kfree(ptr);
- ptr = 0;
- }
-}
-
-/**
- * @brief [SEFS] Инициализация Sayori Easy File System
- *
- * @param uint32_t location - Точка монтирования
- *
- * @return fs_node_t - Структура с файлами
- */
-fs_node_t *sefs_initrd(uint32_t location, uint32_t end) {
- qemu_log("[SEFS] [Init] loc: %x", location);
- qemu_log("[SEFS] Disk size is: %d bytes.", end - location);
-
- qemu_log("SEFS INIT SCOPE =====================================");
-
- // TODO: FIXME: XXX: NEED TO MAP PAGES FOR SEFS LOCATION!
-
- size_t page_count = (end - location) / PAGE_SIZE;
-
- page_count += 1;
-
- // size_t* pages = kcalloc(page_count, sizeof(size_t));
-
- // for(int i = 0; i < page_count; i++) {
- // pages[i] = alloc_phys_pages(1);
- // }
-
- for(int i = 0; i < page_count; i++) {
- map_pages(
- get_kernel_dir(),
- location + (i * PAGE_SIZE), // Find secure place to map pages
- location + (i * PAGE_SIZE),
- 1,
- PAGE_WRITEABLE | PAGE_PRESENT
- );
- }
-
- // qemu_log("Ok");
-
- // while(1);
-
- // Инициализирует указатели main и заголовке файлов и заполняет корневой директорий.
- sefs_header = (sefs_header_t *)location;
- file_headers = (sefs_file_header_t *)(location + sizeof(sefs_header_t));
- sefs_root = (fs_node_t*)kcalloc(1, sizeof(fs_node_t));
-
- strcpy(sefs_root->name, "/");
- strcpy(sefs_root->devName, "SayoriDisk RDv2");
-
- sefs_root->mask = sefs_root->uid = sefs_root->gid = sefs_root->inode = sefs_root->length = 0;
- sefs_root->flags = FS_DIRECTORY;
- sefs_root->open = 0;
- sefs_root->close = 0;
- sefs_root->findFile = &sefs_findFile;
- sefs_root->findDir = &sefs_findDir;
- sefs_root->getLengthFile = &sefs_getLengthFile;
- sefs_root->getOffsetFile = &sefs_getOffsetFile;
- sefs_root->list = &sefs_list;
- sefs_root->ptr = 0;
- sefs_root->impl = 0;
- sefs_root->readChar = &sefs_readChar;
- sefs_root->read = &sefs_read;
- sefs_root->write = &sefs_write;
- sefs_root->diskUsed = &sefs_diskUsed;
- sefs_root->diskSpace = &sefs_diskSpace;
- sefs_root->diskSize = &sefs_diskSize;
- sefs_root->getDevName = &sefs_getDevName;
- sefs_root->getCountElemFolder = &sefs_countElemFolder;
- sefs_root->getListElem = &sefs_list;
- sefs_root->unlistElem = &sefs_dirfree;
-
- root_nodes = (fs_node_t*)kcalloc(sefs_header->nfiles, sizeof(fs_node_t));
- nroot_nodes = sefs_header->nfiles;
- // Для каждого файла...
- for (int i = 0; i < nroot_nodes; i++){
- // Отредактируем заголовок файла — в настоящее время в нем указывается смещение файла
- // относительно ramdisk. Мы хотим, чтобы оно указывалось относительно начала
- // памяти.
- root_nodes[i].root = file_headers[i].parentDir;
- file_headers[i].offset += location;
-
- // Создаем нод нового файла.
- strcpy(root_nodes[i].name, file_headers[i].name);
- root_nodes[i].mask = root_nodes[i].uid = root_nodes[i].gid = 0;
- root_nodes[i].length = (size_t) file_headers[i].length;
- root_nodes[i].inode = i;
- root_nodes[i].flags = (!file_headers[i].types?FS_FILE:FS_DIRECTORY);
-
- if (root_nodes[i].flags == FS_FILE){
- diskUsed += root_nodes[i].length;
- diskSize += root_nodes[i].length;
- }
-
- if (root_nodes[i].flags == FS_DIRECTORY){
- dirCount++;
- }
- }
-
- for (int i = 0; i < sefs_header->nfiles; i++){
- if (root_nodes[i].flags != FS_FILE)
- continue;
-
- strcpy(root_nodes[i].path, root_nodes[(sefs_header->nfiles - dirCount) + root_nodes[i].root].name);
- strcat(root_nodes[i].path,root_nodes[i].name);
-
- int fpath_len = strlen(root_nodes[i].path);
- root_nodes[i].path[fpath_len+1] = '\0';
- }
-
- return sefs_root;
-}
-
diff --git a/kernel/src/fs/smfs.c b/kernel/src/fs/smfs.c
index aa4411ce1..6886783ba 100644
--- a/kernel/src/fs/smfs.c
+++ b/kernel/src/fs/smfs.c
@@ -1,378 +1,76 @@
/**
- * @file fs/fat12.c
+ * @file drv/fs/smfs.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru)
- * @brief Файловая система SMFS (Sayori Medium File System)
- * @version 0.3.3
- * @date 2023-07-28
+ * @brief Файловая система SMFS
+ * @version 0.3.4
+ * @date 2023-10-14
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
#include
#include
-
+#include
#include
+#include
-#define FLOPPY_SIZE 1474559 ///< Размер Floppy
-SMFS_BOOT_SECTOR boot[16] = {0};
-SMFS_Elements elements[8196] = {0};
-SMFS_PACKAGE pkg[8196] = {0};
-SMFS_PACKAGE _smfs_getInfoPackAge(int Address){
- SMFS_PACKAGE* pack = kmalloc(sizeof(SMFS_PACKAGE));
-
- if (pack == -1){
- qemu_log("KMALLOC ERROR!");
- pack[0].Status = SMFS_PACKAGE_UNKNOWN;
- return pack[0];
- }
-
- int read = _FloppyRead(0, &pack[0], Address, sizeof(SMFS_PACKAGE));
-
- return pack[0];
+size_t fs_smfs_read(const char Disk,const char* Path, size_t Offset, size_t Size,void* Buffer){
+ return 0;
}
-SMFS_Elements _smfs_getInfoElem(unsigned int Index){
- SMFS_Elements* elem = kmalloc(sizeof(SMFS_Elements));
-
- if (!elem){
- qemu_log("KMALLOC ERROR!");
- elem[0].Attr = SMFS_TYPE_UNKNOWN;
- return elem[0];
- }
-
- int read = _FloppyRead(0,&elem[0],sizeof(SMFS_BOOT_SECTOR)+(sizeof(SMFS_Elements)*Index),sizeof(SMFS_Elements));
-
- return elem[0];
+size_t fs_smfs_write(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer){
+ return 0;
}
-uint32_t _smfs_foundFile(char* path){
- char ser[2] = {0x5C,0};
-
- char_replace(0x2F,0x5C,path); //< Превращает все (0x2F)/ в (0x5C)\\
-
- strtolower(path); //! Нет поддержки русских букв!
+FSM_FILE fs_smfs_info(const char Disk,const char* Path){
- char tname[32] = {0};
- qemu_log("[smfs] found file: %s",path);
-
- uint32_t dir_c = str_cdsp(path,ser);
- char* out[128] = {0};
-
- str_split(path,out,ser);
-
- qemu_log("[smfs] found: %d",dir_c);
- uint32_t dir = 0;
- for(int i = 0; i < dir_c; i++){
- for (int a = 0; a < boot[1].MaximumElems; a++){
- SMFS_Elements elem = _smfs_getInfoElem(a);
-
- if (elem.Attr == SMFS_TYPE_UNKNOWN) continue; ///< Пропускаем, тк битый файл
- if (elem.Attr == SMFS_TYPE_DELETE) continue; ///< Пропускаем, тк удален файл
- if (elem.Dir != dir) continue; ///< Пропускаем, тк не рут папка
-
- memcpy(tname,elem.Name,32);
- strtolower(tname); //! Нет поддержки русских букв!
- if (strcmp(tname,out[0]) == 0 && i+1 == dir_c){
- qemu_log("OUT");
- return i;
- } else if (strcmp(tname,out[0]) == 0) {
- qemu_log("Next door: %d",a);
- dir = a;
- continue;
- } else {
- /// ????
- }
-
-
- qemu_log("[%i] [%s == %s] => %d",i,tname,out[0],strcmp(tname,out[0]));
-
- __com_formatString(0x3f8," |--- Index | %x\n",elem.Index);
- __com_formatString(0x3f8," |--- Attr | %x\n",elem.Attr);
- __com_formatString(0x3f8," |--- Size | %x\n",elem.Size);
- __com_formatString(0x3f8," |--- TimeCreateHIS | %x\n",elem.TimeCreateHIS);
- __com_formatString(0x3f8," |--- TimeCreateDate | %x\n",elem.TimeCreateDate);
- __com_formatString(0x3f8," |--- TimeAccess | %x\n",elem.TimeAccess);
- __com_formatString(0x3f8," |--- Point | %x\n",elem.Point);
- __com_formatString(0x3f8," |--- Dir | %x\n",elem.Dir);
- __com_formatString(0x3f8," |--- Name | %s\n",elem.Name);
- __com_formatString(0x3f8," |--- Size | %d\n",elem.Size);
- }
-
- qemu_log("[smfs] [%d] %s ",i,out[i]);
- }
- return -1;
-}
-
-void _smfs_PackageFix(char* src, int count){
- for (int i = count; i < 9;i++){
- src[i] = 0;
- }
-}
-
-
-uint32_t _smfs_ReadFile(uint32_t Index, char* dst){
- SMFS_Elements elem = _smfs_getInfoElem(Index);
- if (elem.Attr == SMFS_TYPE_UNKNOWN){
- qemu_log("ReadFile Error");
- return -1;
- }
- if (elem.Attr == SMFS_TYPE_DELETE){
- qemu_log("ReadFile Deleted!");
- return -2;
- }
- SMFS_PACKAGE pack = _smfs_getInfoPackAge(elem.Point);
- if (pack.Status == SMFS_PACKAGE_UNKNOWN){
- return -3;
- }
- int seek = 0;
- while(1){
- for (int i=0;i < pack.Length; i++){
- dst[seek] = pack.Data[i];
- seek++;
- }
- if (pack.Next == -1) break;
- pack = _smfs_getInfoPackAge(pack.Next);
- }
- return seek;
}
-int _smfs_WritePackage(uint32_t Addr, SMFS_PACKAGE pack) {
- int read = 0;
- read = _FloppyWrite(0,&pack,Addr,sizeof(SMFS_Elements));
- qemu_log("[SMFS] Send to package to %x",Addr);
- __com_formatString(0x3f8," |--- Addr | %x\n",Addr);
- __com_formatString(0x3f8," |--- Write | %d\n",read);
- __com_formatString(0x3f8," |--- Data | %s\n",pack.Data);
- __com_formatString(0x3f8," |--- Status | %d\n",pack.Status);
- __com_formatString(0x3f8," |--- Length | %d\n",pack.Length);
- __com_formatString(0x3f8," |--- Next | %x\n\n",pack.Next);
- return read;
-}
-
-int _smfs_DeletePackage(uint32_t Addr){
- if (Addr == 0) return 0;
- SMFS_PACKAGE Free = _smfs_getInfoPackAge(Addr);
- if (Free.Status == SMFS_PACKAGE_FREE) return 1;
- memset(Free.Data, 0, 9);
- Free.Length = 0;
- Free.Next = -1;
- Free.Status = SMFS_PACKAGE_FREE;
-
- return _smfs_WritePackage(Addr,Free);
+FSM_DIR* fs_smfs_dir(const char Disk,const char* Path){
}
-uint32_t _smfs_DeleteFile(uint32_t Index){
- SMFS_Elements elem = _smfs_getInfoElem(Index);
- if (elem.Attr == SMFS_TYPE_UNKNOWN){
- qemu_log("File Error");
- return -1;
- }
- if (elem.Attr == SMFS_TYPE_DELETE){
- qemu_log("Already Deleted!");
- return -2;
- }
- if (elem.Point != 0){
- /// Зачищаем блоки, только если точка монтирования указана
- SMFS_PACKAGE pack = _smfs_getInfoPackAge(elem.Point);
- if (pack.Status == SMFS_PACKAGE_UNKNOWN){
- return -3;
- }
- int countPack = (elem.Size == 0?1:(elem.Size/8)+1);
- uint32_t *pkg_addr = kmalloc(sizeof(uint32_t)*(countPack+1));
- int seek = 1;
- pkg_addr[0] = elem.Point;
- while(1){
- if (pack.Next == -1) break;
-
- pkg_addr[seek] = pack.Next;
- pack = _smfs_getInfoPackAge(pack.Next);
- seek++;
- if (pack.Status == SMFS_PACKAGE_UNKNOWN){
- qemu_log("CRITICAL GET ERROR");
- return -4;
- }
- }
-
- for (int i = 0; i < countPack; i++) {
- qemu_log("Delete %x",pkg_addr[i]);
- _smfs_DeletePackage(pkg_addr[i]);
- }
- }
- char eName[32] = {0};
- elements[0].Attr = SMFS_TYPE_DELETE;
- elements[0].Size = 0;
- elements[0].TimeCreateHIS = 0;
- elements[0].TimeCreateDate = 0;
- elements[0].TimeAccess = 0;
- elements[0].Dir = 0;
- elements[0].Point = 0;
- memcpy((void*) elements[0].Name, eName, 32);
- int read = _FloppyWrite(0,&elements[0],sizeof(SMFS_BOOT_SECTOR)+(sizeof(SMFS_Elements)*Index),sizeof(SMFS_Elements));
- if (read != sizeof(SMFS_Elements)){
- return -5;
- }
- qemu_log("Deleted file complete! %d",read);
- return 1;
+int fs_smfs_create(const char Disk,const char* Path,int Mode){
+ return 0;
}
-uint32_t _smfs_FreePackAge(int skip) {
- int adr = 0;
-
- for (int i = 0; i < boot[1].MaxPackage; i++){
- adr = (sizeof(SMFS_BOOT_SECTOR) + (sizeof(SMFS_Elements) * boot[1].MaximumElems) + (i * sizeof(SMFS_PACKAGE)));
-
- SMFS_PACKAGE pack = _smfs_getInfoPackAge(adr);
-
- qemu_log("[%d] Test PackAge");
-
- __com_formatString(0x3f8," |--- Addr | %x\n",adr);
- __com_formatString(0x3f8," |--- Data | %s\n",pack.Data);
- __com_formatString(0x3f8," |--- Status | %d\n",pack.Status);
- __com_formatString(0x3f8," |--- Length | %d\n",pack.Length);
- __com_formatString(0x3f8," |--- Next | %x\n\n",pack.Next);
-
- if (pack.Status == SMFS_PACKAGE_FREE && skip !=0){
- skip--;
- continue;
- }
-
- if (pack.Status == SMFS_PACKAGE_FREE) return adr;
- }
-
- return -1;
+int fs_smfs_delete(const char Disk,const char* Path,int Mode){
+ return 0;
}
-int _smfs_WriteFile(char* path, char* src){
- // Тут мы типа должны найти файл и обратиться по позиции указанном в Pointer
-
- int found = _smfs_foundFile(path);
- if (found == -1){
- return -1;
- }
- int src_size = strlen(src);
- int src_seek = 0;
- int currentAddr = 0;
- int read = 0;
- char src_buf[8] = {0};
- int countPack = (src_size == 0?1:(src_size/8)+1);
-
- qemu_log("[WriteFile]\n * src_size: %d\n * countPack : %d\n * src: %s\n",src_size,countPack,src);
-
- SMFS_PACKAGE *pkg_free = kmalloc(sizeof(SMFS_PACKAGE));
- uint32_t *pkg_addr = kmalloc(sizeof(uint32_t)*(countPack+1));
- // Выделяем память для структур и записи
- if (pkg_free == -1 || pkg_addr == -1){
- qemu_log("KMALLOC ERROR");
- return -1;
- }
-
- for (int i = 0; i < countPack; i++) {
- pkg_addr[i] = _smfs_FreePackAge(i);
-
- if (pkg_addr[i] == -1) {
- qemu_log("NO FREE PACKAGE!!!");
- return -1;
- }
-
- qemu_log("Found %x FREE PACKAGE!", pkg_addr[i]);
- }
-
- for (int a = 0; a <= src_size; a++){
- if (src_seek == 8){
- // Buffer
- _smfs_PackageFix(src_buf,src_seek);
-
- qemu_log("Buffer: %s",src_buf);
-
- memcpy((void*) pkg_free[0].Data, src_buf, 9);
-
- pkg_free[0].Length = 8;
- pkg_free[0].Next = pkg_addr[currentAddr+1];
- pkg_free[0].Status = SMFS_PACKAGE_READY;
-
- _smfs_WritePackage(pkg_addr[currentAddr], pkg_free[0]);
-
- currentAddr++;
- src_seek = 0;
- a--;
- //src_buf = {0};
- } else if (a == (src_size)){
- _smfs_PackageFix(src_buf,src_seek);
-
- qemu_log("EOL | Buffer: %s",src_buf);
- memcpy((void*) pkg_free[0].Data, src_buf, 8);
-
- pkg_free[0].Length = src_seek;
- pkg_free[0].Next = -1;
- pkg_free[0].Status = SMFS_PACKAGE_READY;
-
- _smfs_WritePackage(pkg_addr[currentAddr],pkg_free[0]);
-
- break;
- } else {
- src_buf[src_seek] = src[a];
- src_seek++;
- }
- //pkg_free[0].Status = SMFS_PACKAGE_READY;
- //pkg_free[0].Status = SMFS_PACKAGE_READY;
- }
-
- qemu_log("Write complete!");
- qemu_log("[+] Package to write:\n");
-
- for (int i = 0; i < countPack; i++){
- __com_formatString(0x3f8," |--- Addr | %x\n",pkg_addr[i]);
- }
- return src_size;
-
- //uint32_t fpa = _smfs_FreePackAge();
+void fs_smfs_label(const char Disk, char* Label){
+ memcpy(Label,"SMFS",strlen("SMFS"));
}
-int _smfs_createFile(uint32_t dir,const char* name,int type){
- uint32_t Index = -1;
- SMFS_Elements elem;
- for (int a = 0; a < boot[1].MaximumElems; a++){
- SMFS_Elements elem = _smfs_getInfoElem(a);
- if (elem.Attr == SMFS_TYPE_UNKNOWN) continue;
- if (elem.Attr == SMFS_TYPE_DELETE){
- Index = a;
- }
- }
- if (Index == -1){
+int fs_smfs_format(const char Disk){
+
+ DPM_Disk IDisk = dpm_info(Disk);
+ size_t MaxFiles = (((IDisk.Size) - (sizeof(SMFS_BOOT_SECTOR))) / 2048); /// 1024 ф.
+ if (MaxFiles <= 0){
+ qemu_log("FATAL FORMAT!");
return 0;
}
- elem.Attr = type;
- elem.Size = 0;
- elem.TimeCreateHIS = 0;
- elem.TimeCreateDate = 0;
- elem.TimeAccess = 0;
- elem.Dir = dir;
- elem.Point = 0;
- memcpy((void*) elem.Name, name, 32);
- int read = _FloppyWrite(0, &elem, sizeof(SMFS_BOOT_SECTOR) + (sizeof(SMFS_Elements) * Index), sizeof(SMFS_Elements));
- qemu_log("[SMFS] FDA WRITE:%d | Index: %d\n", read, Index);
- return 1;
-}
-
-void _smfs_format(int MaxFiles){
- int read = 0,seek = 0;
- int sizeFiles = ((sizeof(SMFS_Elements))*MaxFiles);
- int freeSpa = (FLOPPY_SIZE-(sizeFiles)-(sizeof(SMFS_BOOT_SECTOR)));
- int allPkg = (freeSpa/(sizeof(SMFS_PACKAGE)));
+ qemu_log("FORMAT IS STARTING...");
+
+ size_t read = 0,seek = 0;
+ int sizeFiles = ((sizeof(SMFS_Elements)) * MaxFiles); ////< 74 * 1024 =
+ int freeSpa = ((IDisk.Size) - (sizeFiles) - (sizeof(SMFS_BOOT_SECTOR)));
+ int allPkg = (freeSpa / (sizeof(SMFS_PACKAGE)));
qemu_log("[SMFS] Formatting FDA STARTED!");
- qemu_log("[SMFS] FLOPPY_SIZE = %d",FLOPPY_SIZE);
- qemu_log("[SMFS] BOOT_SIZE = %d",(sizeof(SMFS_BOOT_SECTOR)));
- qemu_log("[SMFS] Max Elems = %d | %d",MaxFiles,sizeFiles);
- qemu_log("[SMFS] FREE SPA = %d",freeSpa);
- qemu_log("[SMFS] Max Package = %d",allPkg);
+ qemu_log("[SMFS] DISK_SIZE = %d", (IDisk.Size)); ///< 2097152
+ qemu_log("[SMFS] BOOT_SIZE = %d", (sizeof(SMFS_BOOT_SECTOR))); ///< 39
+ qemu_log("[SMFS] Max Elems = %d | %d", MaxFiles, sizeFiles); ///< 1024 | 75776
+ qemu_log("[SMFS] FREE SPA = %d", freeSpa); ///< (2021337)
+ qemu_log("[SMFS] Max Package = %d", allPkg); ///< 2021337 / 15 = мин. 134756 | макс. 1078048 байт
qemu_log("[SMFS] We overwrite on our own BOOT SECTOR");
char oem[8] = {'S','A','Y','O','R','I','O','S'};
char label[11] = {'S','M','F','S',' ',' ',' ',' ',' ',' ',0};
- char fsid[8] = {'S','M','F','S','1','.','0',' '};
+ char fsid[8] = {'S','M','F','S','1','.','0',0};
+ SMFS_BOOT_SECTOR *boot = kmalloc(sizeof(SMFS_BOOT_SECTOR));
+
boot[0].magic1 = 0x7246;
boot[0].magic2 = 0xCAFE;
boot[0].MaximumElems = MaxFiles;
@@ -381,19 +79,23 @@ void _smfs_format(int MaxFiles){
memcpy((void*) boot[0].oem_name, oem, 8);
memcpy((void*) boot[0].volume_label, label, 11);
memcpy((void*) boot[0].fsid, fsid, 8);
-
- read = _FloppyWrite(0,&boot[0],0,sizeof(SMFS_BOOT_SECTOR));
+
+ read = dpm_write(Disk, seek, sizeof(SMFS_BOOT_SECTOR), &boot[0]);
+
+ //read = _FloppyWrite(0,&boot[0],0,sizeof(SMFS_BOOT_SECTOR));
qemu_log("[SMFS] FDA WRITE:%d\n",read);
if (read == -1){
qemu_log("[SMFS] FATAL FORMAT!");
- return;
+ return 0;
}
seek = sizeof(SMFS_BOOT_SECTOR);
qemu_log("[SMFS] Create markup structures for files and folders");
+ SMFS_Elements *elements = kmalloc(sizeof(SMFS_Elements));
+
char eName[32] = {0};
elements[0].Attr = SMFS_TYPE_DELETE;
elements[0].Size = 0;
@@ -406,125 +108,48 @@ void _smfs_format(int MaxFiles){
memcpy((void*) elements[0].Name, eName, 32);
for (int i = 0; i < MaxFiles; i++) {
- TE_DrawMessageBox("Разметка макета", "Это длительный процесс...", 2, getScreenWidth() / 4, 100, 0, i, MaxFiles);
elements[0].Index = i;
- read = _FloppyWrite(0,&elements[0],seek,sizeof(SMFS_Elements));
- qemu_log("[SMFS] FDA WRITE:%d | I: %d | In: %x\n",read,i,seek);
- seek += sizeof(SMFS_Elements);
- punch();
+ read = dpm_write(Disk, seek, sizeof(SMFS_Elements), &elements[0]);
+ //read = _FloppyWrite(0,&elements[0],seek,sizeof(SMFS_Elements));
+ qemu_log("[SMFS] DISK WRITE:%d | I: %d | In: %x\n",read,i,seek);
+ seek += sizeof(SMFS_Elements);
}
qemu_log("[SMFS] Now we write packages");
+ SMFS_PACKAGE *pkg = kmalloc(sizeof(SMFS_PACKAGE));
char eData[8] = {0};
memcpy((void*) pkg[0].Data, eData, 8);
pkg[0].Length = 0;
pkg[0].Next = -1;
pkg[0].Status = SMFS_PACKAGE_FREE;
-
-
- //char* outmark = kmalloc(sizeof(SMFS_PACKAGE)*allPkg);
-
- //int32_t* outmark = memoryMulti(pkg[0],5,allPkg);
-
- //memmove(outmark, pkg[0], allPkg);
- //read = _FloppyWrite(0,outmark,seek,5*allPkg);
- //qemu_log("[PRINT] \n%s\n",outmark);
- //qemu_log("[SMFS] FDA WRITE:%d | Count: %d | In: %x\n",read,sizeof(SMFS_PACKAGE)*allPkg,seek);
for (int i = 0; i < allPkg; i++){
- TE_DrawMessageBox("Разметка пакета", "Последний этап", 2, getScreenWidth() / 4, 400, 0, i, allPkg);
- read = _FloppyWrite(0,&pkg[0],seek,sizeof(SMFS_PACKAGE));
- qemu_log("[SMFS] FDA WRITE:%d | I: %d | In: %x\n",read,i,seek);
- seek += sizeof(SMFS_PACKAGE);
- punch();
- }
-
-
-}
+
+ read = dpm_write(Disk, seek, sizeof(SMFS_PACKAGE), &pkg[0]);
-void _smfs_write(void* data,size_t size){
- qemu_log("WRITE!");
- for (int i = 0; i < size; i++){
- __com_formatString(0x3f8,"[%d] %d | %c\n",i,((int*)data)[i],((char*)data)[i]);
+ //read = _FloppyWrite(0,&pkg[0],seek,sizeof(SMFS_PACKAGE));
+ qemu_log("[SMFS] DISK WRITE:%d | I: %d | In: %x\n",read,i,seek);
+ seek += sizeof(SMFS_PACKAGE);
}
+ return 1;
}
-void bKbMb(int bytes){
- qemu_log("[SMFS] %d b | %d Kb | %d Mb",bytes,bytes/1024,(bytes/1024)/1024);
-}
-
-void _smfs_printFF(){
- int read = 0;
- qemu_log("[Print Files & Folder]");
- qemu_log("[SMFS] Emelent size: %d",sizeof(SMFS_Elements));
- qemu_log("[SMFS] MaximumElems: %d",boot[1].MaximumElems);
- for (int i = 0; i < boot[1].MaximumElems; i++){
- read = _FloppyRead(0,&elements[1],sizeof(SMFS_BOOT_SECTOR)+(sizeof(SMFS_Elements)*i),sizeof(SMFS_Elements));
- qemu_log("[%d] READ: %d | Pos: %d",i,read,sizeof(SMFS_BOOT_SECTOR)+(sizeof(SMFS_Elements)*i));
- __com_formatString(0x3f8," |--- Index | %x\n",elements[1].Index);
- __com_formatString(0x3f8," |--- Attr | %x\n",elements[1].Attr);
- __com_formatString(0x3f8," |--- Size | %x\n",elements[1].Size);
- __com_formatString(0x3f8," |--- TimeCreateHIS | %x\n",elements[1].TimeCreateHIS);
- __com_formatString(0x3f8," |--- TimeCreateDate | %x\n",elements[1].TimeCreateDate);
- __com_formatString(0x3f8," |--- TimeAccess | %x\n",elements[1].TimeAccess);
- __com_formatString(0x3f8," |--- Point | %x\n",elements[1].Point);
- __com_formatString(0x3f8," |--- Dir | %x\n",elements[1].Dir);
- __com_formatString(0x3f8," |--- Name | %s\n",elements[1].Name);
- __com_formatString(0x3f8,"\n",elements[1].Size);
- }
- //elements[0];
-}
+int fs_smfs_detect(const char Disk){
+ SMFS_BOOT_SECTOR* BOOT = kmalloc(sizeof(SMFS_BOOT_SECTOR)+1);
+ dpm_read(Disk, 0, sizeof(SMFS_BOOT_SECTOR), BOOT);
-void _smfs_init(){
- qemu_log("[SMFS] Init...");
- qemu_log("%d | %x",0x167FFF,0x167FFF);
- qemu_log("[SMFS] В пизду");return;
- qemu_log("[SMFS] Boot Sector size: %d",sizeof(SMFS_BOOT_SECTOR));
- qemu_log("[SMFS] Package size: %d",sizeof(SMFS_PACKAGE));
- qemu_log("[SMFS] Emelent size: %d",sizeof(SMFS_Elements));
- qemu_log("[SMFS] Emelents group size: %d",sizeof(SMFS_Elements)*256);
- qemu_log("[SMFS] Free Space: %d",FLOPPY_SIZE-(sizeof(SMFS_Elements)*256)-sizeof(SMFS_BOOT_SECTOR));
- bKbMb(FLOPPY_SIZE-(sizeof(SMFS_Elements)*256)-sizeof(SMFS_BOOT_SECTOR));
- qemu_log("[SMFS] Count package: %d",(FLOPPY_SIZE-(sizeof(SMFS_Elements)*256)-sizeof(SMFS_BOOT_SECTOR))/sizeof(SMFS_PACKAGE));
- bKbMb((FLOPPY_SIZE-(sizeof(SMFS_Elements)*256)-sizeof(SMFS_BOOT_SECTOR))/sizeof(SMFS_PACKAGE));
-
- //_smfs_format(256); return;
- int read = 0;
- read = _FloppyRead(0,&boot[1],0,39);
- qemu_log("[SMFS] Read:%d",read);
- //_smfs_write(boot,sizeof(SMFS_BOOT_SECTOR));
- //read = _FloppyWrite(0,boot,0,sizeof(SMFS_BOOT_SECTOR));
- //qemu_log("[SMFS] WRITE:%d\n%s",read);
qemu_log("[SMFS] Check BootSector:");
- __com_formatString(0x3f8," |--- magic1 | %x\n",boot[1].magic1);
- __com_formatString(0x3f8," |--- magic2 | %x\n",boot[1].magic2);
- __com_formatString(0x3f8," |--- MaximumElems | %d\n",boot[1].MaximumElems);
- __com_formatString(0x3f8," |--- MaxPackage | %d\n",boot[1].MaxPackage);
- __com_formatString(0x3f8," |--- OEM | %s\n",boot[1].oem_name);
- __com_formatString(0x3f8," |--- Label | %s\n",boot[1].volume_label);
- __com_formatString(0x3f8," |--- FSID | %s\n",boot[1].fsid);
- // FloppySize - 1509949
- qemu_log("[SMFS] %d b | %d Kb | %d Mb",FLOPPY_SIZE,FLOPPY_SIZE/1024,(FLOPPY_SIZE/1024)/1024);
- int fadr = _smfs_foundFile("\\TeST.TxT");
- if (fadr == -1){
- qemu_log("Test.txt No found");
- } else {
- SMFS_Elements elem = _smfs_getInfoElem(fadr);
- if (elem.Attr == SMFS_TYPE_UNKNOWN){
- qemu_log("SMFS_TYPE_ERROR");
- } else {
- char* data = kmalloc(elem.Size);
- int asd = _smfs_ReadFile(elem.Index,data);
- qemu_log("READ: %d | \n%s",asd,data);
- }
- }
- //qemu_log("Delete file? %d",_smfs_DeleteFile(0),_smfs_DeleteFile(1),_smfs_DeleteFile(2));
- //_smfs_foundFile("\\SUKA\\BLAT/Poshe.txt");
- //_smfs_foundFile("/SayoriDev/SDK/Chip/ПиздЕц.elf");
- //_smfs_WriteFile(0,"Is im here blyat! Da skolko mozno tvorit' ety dick!");
- //_smfs_FreePackAge(16);
- //_smfs_printFF();
-}
+ qemu_log(" |--- magic1 | %x\n",BOOT->magic1);
+ qemu_log(" |--- magic2 | %x\n",BOOT->magic2);
+ qemu_log(" |--- MaximumElems | %d\n",BOOT->MaximumElems);
+ qemu_log(" |--- MaxPackage | %d\n",BOOT->MaxPackage);
+ qemu_log(" |--- OEM | %s\n",BOOT->oem_name);
+ qemu_log(" |--- Label | %s\n",BOOT->volume_label);
+ qemu_log(" |--- FSID | %s\n",BOOT->fsid);
+
+ kfree(BOOT);
+ return (0);
+}
\ No newline at end of file
diff --git a/kernel/src/fs/tarfs.c b/kernel/src/fs/tarfs.c
new file mode 100644
index 000000000..a4e2986ab
--- /dev/null
+++ b/kernel/src/fs/tarfs.c
@@ -0,0 +1,279 @@
+/**
+ * @file drv/fs/tarfs.c
+ * @author Пиминов Никита (nikita.piminoff@yandex.ru)
+ * @brief Файловая система TarFS
+ * @version 0.3.4
+ * @date 2023-10-14
+ * @copyright Copyright SayoriOS Team (c) 2022-2023
+*/
+
+
+#include
+#include
+#include
+#include
+#include
+#include "lib/string.h"
+#include "mem/vmm.h"
+
+bool tarfs_debug = false;
+
+
+
+int oct2bin(char *str, int size) {
+ int n = 0;
+ char *c = str;
+ while (size-- > 0) {
+ n *= 8;
+ n += *c - '0';
+ c++;
+ }
+ return n;
+}
+
+size_t fs_tarfs_read(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer){
+ if (tarfs_debug) qemu_log("[FSM] [TARFS] [READ] D:%d | N: %s | O:%d | S:%d",Disk,Path,Offset,Size);
+ TarFS_ROOT* initrd = (TarFS_ROOT*) dpm_metadata_read(Disk);
+ for (int i = 1;i < initrd->Count;i++){
+ if (!strcmpn(initrd->Files[i].Name,Path))
+ continue;
+
+ return dpm_read(Disk,initrd->Files[i].Addr+Offset, Size, Buffer);
+ }
+ if (tarfs_debug) qemu_log("[FSM] [TARFS] [READ] NO FOUND!!");
+ return 0;
+}
+
+size_t fs_tarfs_write(const char Disk,const char* Path,size_t Offset,size_t Size,void* Buffer){
+ return 0;
+}
+
+int fs_tarfs_create(const char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+int fs_tarfs_delete(const char Disk,const char* Path,int Mode){
+ return 0;
+}
+
+FSM_FILE fs_tarfs_info(const char Disk,const char* Path){
+ if (tarfs_debug) qemu_log("[FSM] [TarFS] [Info]");
+// FSM_FILE *file = kcalloc(sizeof(FSM_FILE), 1);
+ FSM_FILE file = {};
+
+ TarFS_ROOT* initrd = (TarFS_ROOT*) dpm_metadata_read(Disk);
+
+ for (int i = 1; i < initrd->Count; i++){
+ //qemu_log("[%d] '%s' != '%s'",strcmp(initrd->Files[i].Name,Path),initrd->Files[i].Name,Path);
+ if (!strcmpn(initrd->Files[i].Name,Path)) continue;
+// file->Ready = 1;
+ file.Ready = 1;
+ char* zpath = pathinfo(initrd->Files[i].Name, PATHINFO_DIRNAME);
+ //qemu_log("[%d] zpath: %s",strlen(zpath),zpath);
+// memcpy(file->Path,zpath,strlen(zpath));
+// memcpy(file->Name,initrd->Files[i].Name,strlen(initrd->Files[i].Name));
+// file->Mode = 'r';
+// file->Size = initrd->Files[i].Size;
+// file->Type = initrd->Files[i].Type - 48;
+
+
+ memcpy(file.Path,zpath,strlen(zpath));
+ memcpy(file.Name,initrd->Files[i].Name,strlen(initrd->Files[i].Name));
+ file.Mode = 'r';
+ file.Size = initrd->Files[i].Size;
+ file.Type = initrd->Files[i].Type - 48;
+
+ kfree(zpath);
+ //return dpm_read(Disk,initrd->Files[i].Addr+Offset,Size,Buffer);
+ break;
+ }
+
+// return file[0];
+ return file;
+}
+
+void fs_tarfs_label(const char Disk, char* Label){
+ memcpy(Label,"ustar",strlen("ustar"));
+}
+
+int fs_tarfs_detect(const char Disk){
+ char* Buffer = kmalloc(5);
+
+ dpm_read(Disk, 257, 5,Buffer);
+
+ bool isTarFS = ((Buffer[0] != 0x75 || Buffer[1] != 0x73 || Buffer[2] != 0x74 || Buffer[3] != 0x61 || Buffer[4] != 0x72)?false:true);
+ if (tarfs_debug) qemu_log("[0] = %x",Buffer[0]);
+ if (tarfs_debug) qemu_log("[1] = %x",Buffer[1]);
+ if (tarfs_debug) qemu_log("[2] = %x",Buffer[2]);
+ if (tarfs_debug) qemu_log("[3] = %x",Buffer[3]);
+ if (tarfs_debug) qemu_log("[4] = %x",Buffer[4]);
+ if (tarfs_debug) qemu_log("[TarFS] is: %d",isTarFS);
+ kfree(Buffer);
+ return (int)isTarFS;
+}
+
+FSM_DIR* fs_tarfs_dir(const char Disk,const char* Path){
+ if (tarfs_debug) qemu_log("[FSM] [TarFS] [Info] Disk:%d | Path:%s",Disk,Path);
+ FSM_DIR *Dir = kcalloc(sizeof(FSM_DIR), 1);
+ TarFS_ROOT* initrd = dpm_metadata_read(Disk); // noalloc
+ FSM_FILE *Files = kcalloc(sizeof(FSM_FILE), initrd->Count);
+
+ size_t CA = 0, CF = 0, CD = 0, CO = 0;
+ for (int i = 1;i < initrd->Count;i++){
+ //////////////////////////
+ //// Обращаю внимание, для за путь принимается сейчас R:\\Sayori\\
+ //// Если вам искать только файлы, то вот вариант
+ // char* zpath = pathinfo(initrd->Files[i].Name, PATHINFO_DIRNAME);
+ // qemu_log("[%d] %s",strcmpn(zpath,Path),zpath);
+ //// Но мне такой вариант, не подходит, мне нужно еще и папки.
+ /////////////////////////
+ bool isPassed = fsm_isPathToFile(Path, initrd->Files[i].Name) == 1;
+
+ if (!isPassed)
+ continue;
+
+ char* zpath = pathinfo(initrd->Files[i].Name, PATHINFO_DIRNAME);
+
+ fsm_convertUnix(atoi(initrd->Files[i].LastTime), &Files[CA].LastTime);
+
+ Files[CA].Mode = 'r';
+ Files[CA].Size = initrd->Files[i].Size;
+ Files[CA].Type = initrd->Files[i].Type - 48;
+ Files[CA].Ready = 1;
+
+ memcpy(Files[CA].Path, zpath, strlen(zpath));
+
+ substr(Files[CA].Name,
+ initrd->Files[i].Name,
+ strlen(Path),
+ strlen(initrd->Files[i].Name) - (Files[CA].Type == 5?1:0) - strlen(Path)
+ );
+
+ kfree(zpath);
+
+ if (Files[CA].Type == 0) {
+ /// Это файл
+ CF++;
+ } else if (Files[CA].Type == 5){
+ /// Это папка
+ CD++;
+ } else {
+ /// Рандомный элемент
+ CO++;
+ }
+ CA++;
+ }
+ Dir->Ready = 1;
+ Dir->Count = CA;
+ Dir->CountFiles = CF;
+ Dir->CountDir = CD;
+ Dir->CountOther = CO;
+ Dir->Files = Files;
+
+ return Dir;
+}
+
+size_t fs_tarfs_countFiles(const uint32_t in){
+ size_t count = 0;
+ uint8_t* ptr = (uint8_t*)in;
+
+ size_t pos = 0;
+ TarFS_Elem* elem = (TarFS_Elem*)ptr;
+
+ while (memcmp(elem->Signature, "ustar", 5) == 0) {
+ int filesize = oct2bin(elem->Size, 11);
+
+ count++;
+
+ pos = ALIGN(pos + sizeof(TarFS_Elem) + filesize, 512);
+ elem = (TarFS_Elem*)(ptr + pos);
+ }
+
+ return count;
+}
+
+TarFS_ROOT* fs_tarfs_init(uint32_t in, uint32_t size, int Mode){
+ uint8_t *ptr = (uint8_t*)in;
+ if(ptr[257] != 0x75
+ || ptr[258] != 0x73
+ || ptr[259] != 0x74
+ || ptr[260] != 0x61
+ || ptr[261] != 0x72) {
+ return kcalloc(sizeof(TarFS_ROOT), 1);
+ }
+
+ size_t count = fs_tarfs_countFiles(in);
+
+ if (tarfs_debug) qemu_log("Found %d entries.", count);
+
+ size_t currentInx = 0;
+ ssize_t sizeDir = -1;
+ TarFS_File* tffs = kmalloc((count+1) * sizeof(TarFS_File));
+ TarFS_ROOT* root = kmalloc(sizeof(TarFS_ROOT));
+
+ size_t pos = 0;
+
+ TarFS_Elem *file = (TarFS_Elem*) ptr;
+
+ while (memcmp(file->Signature, "ustar", 5) == 0) {
+ int filesize = oct2bin(file->Size, 11);
+
+ if (sizeDir == -1 && Mode == 1){
+ //qemu_log("Mode:1 | s:%d | m:%d",sizeDir,Mode);
+ sizeDir = strlen(file->Name);
+ } else if (sizeDir == -1) {
+ //qemu_log("Mode:0");
+ sizeDir = 2;
+ }
+
+ tffs[currentInx].Ready = (currentInx==0?0:1);
+ tffs[currentInx].Size = filesize;
+ tffs[currentInx].Type = (int)file->Type;
+ tffs[currentInx].Real = (uint32_t)(ptr + pos) + sizeof(TarFS_Elem);
+ tffs[currentInx].Addr = tffs[currentInx].Real - in;
+
+
+ memcpy(tffs[currentInx].Mode,file->Mode, 8);
+ memcpy(tffs[currentInx].LastTime,file->LastTime,12);
+ substr(tffs[currentInx].Name,file->Name,sizeDir,100-sizeDir);
+ //qemu_log("[%d] fix name:%s",strlen(tffs[currentInx].Name),tffs[currentInx].Name);
+ currentInx++;
+
+ if (tarfs_debug) qemu_log("[%x] Name: %s; Size: %d", file, file->Name, filesize);
+
+ pos = ALIGN(pos + sizeof(TarFS_Elem) + filesize, 512);
+ file = (TarFS_Elem*)(ptr + pos);
+ // ptr += (((filesize + 511) / 512) + 1) * 512;
+ }
+
+// while(1);
+
+ root->Ready = 1;
+ root->Count = count;
+ root->Files = tffs;
+
+ return root;
+}
+
+TarFS_File tarfs_infoFile(TarFS_ROOT* r,const char* name){
+ for (int i = 1;i < r->Count;i++){
+ if (!strcmpn(r->Files[i].Name,name)) continue;
+ return r->Files[i];
+ }
+ return r->Files[0];
+}
+
+char* tarfs_readFile(TarFS_ROOT* r, const char* name){
+ for (int i = 1; i < r->Count; i++) {
+ if (!strcmpn(r->Files[i].Name,name))
+ continue;
+
+ char* buffer = kmalloc(r->Files[i].Size);
+
+ memcpy(buffer, (char*)r->Files[i].Real, r->Files[i].Size);
+
+ return buffer;
+ }
+ return 0;
+}
+
diff --git a/kernel/src/gui/basics.c b/kernel/src/gui/basics.c
index 150e2b798..162cebfe3 100644
--- a/kernel/src/gui/basics.c
+++ b/kernel/src/gui/basics.c
@@ -1,9 +1,9 @@
#include
-#include
+#include "io/screen.h"
-void fill_screen(uint32_t color) {
- size_t w = getScreenWidth();
- size_t h = getScreenHeight();
+void fill_screen(const uint32_t color) {
+ const size_t w = getScreenWidth();
+ const size_t h = getScreenHeight();
for(int i = 0; i < h; i++) {
for(int j = 0; j < w; j++) {
@@ -12,7 +12,7 @@ void fill_screen(uint32_t color) {
}
}
-void draw_rectangle(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color) {
+void draw_rectangle(const uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color) {
for(size_t i = x, to = x+w; i < to; i++) {
set_pixel(i, y, color);
set_pixel(i, y+h, color);
@@ -25,7 +25,7 @@ void draw_rectangle(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t col
}
-void draw_filled_rectangle(size_t x, size_t y, size_t w, size_t h, uint32_t fill) {
+void draw_filled_rectangle(size_t x, size_t y, size_t w, size_t h, const uint32_t fill) {
for(int i = 0; i < h; i++) {
for(int j = 0; j < w; j++) {
set_pixel(x+j, y+i, fill);
diff --git a/kernel/src/gui/circle.c b/kernel/src/gui/circle.c
index e52dc9207..3c1807c99 100644
--- a/kernel/src/gui/circle.c
+++ b/kernel/src/gui/circle.c
@@ -1,4 +1,5 @@
-#include
+#include "common.h"
+#include "io/screen.h"
void draw_circle(int32_t xc, int32_t yc, int32_t radius, uint32_t color) {
int32_t x = 0;
diff --git a/kernel/src/gui/eki.c b/kernel/src/gui/eki.c
deleted file mode 100644
index 75bd36dea..000000000
--- a/kernel/src/gui/eki.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "gui/render.h"
-#include "gui/widget_button.h"
-#include "gui/widget_image.h"
-#include "gui/widget_label.h"
-
-void eki_start() {
- Window_t* eki_mainwindow = window_new("Eki");
- eki_mainwindow->x = 100;
- eki_mainwindow->y = 100;
- eki_mainwindow->width = 200;
- eki_mainwindow->height = 200;
- eki_mainwindow->canvas_bgcolor = 0x333333;
-
- Widget_t* hello_button = new_widget_button("Hi", 0x00ff00, 0x000000);
- hello_button->x = 50;
- hello_button->y = 50;
- hello_button->width += 30;
- hello_button->height += 15;
-
- window_add_widget(eki_mainwindow, hello_button);
-
- eki_mainwindow->state = DISPLAYING;
-}
\ No newline at end of file
diff --git a/kernel/src/gui/line.c b/kernel/src/gui/line.c
index 037f3657f..005a147f2 100644
--- a/kernel/src/gui/line.c
+++ b/kernel/src/gui/line.c
@@ -1,4 +1,7 @@
-#include
+#include
+#include
+#include "lib/math.h"
+#include "io/tty.h"
void draw_line(int x0, int y0, int x1, int y1, int thickness, int color) {
// Calculate the differences and absolute values of x and y coordinates
@@ -40,7 +43,7 @@ void draw_line(int x0, int y0, int x1, int y1, int thickness, int color) {
}
-void draw_line_extern(char* buffer, size_t width, size_t height, int x0, int y0, int x1, int y1, int thickness, int color) {
+void draw_line_extern(uint8_t *buffer, size_t width, size_t height, int x0, int y0, int x1, int y1, int thickness, int color) {
// Calculate the differences and absolute values of x and y coordinates
int dx = ABS(x1 - x0);
int dy = ABS(y1 - y0);
diff --git a/kernel/src/gui/widget_image.c b/kernel/src/gui/widget_image.c
deleted file mode 100644
index ac616e550..000000000
--- a/kernel/src/gui/widget_image.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include
-#include "gui/widget.h"
-#include "io/duke_image.h"
-#include "gui/widget_image.h"
-#include "io/duke_image.h"
-#include "io/port_io.h"
-
-void destroy_widget_image(Widget_t* widget);
-
-void widget_image_renderer(struct Widget* this, struct Window* window) {
- Widget_Image_t* this_data = (Widget_Image_t*)(this->custom_widget_data);
-
- duke_rawdraw(this_data->image_data, this_data->meta, this->x, this->y);
-}
-
-Widget_t* new_widget_image(char* path) {
- struct DukeImageMeta* metadata = kcalloc(sizeof(struct DukeImageMeta), 1);
- duke_get_image_metadata(path, metadata);
-
- // qemu_log("Load image metadata code: %x", code);
-
- // qemu_log("Image: %d x %d", metadata.width, metadata.height);
- // qemu_log("Allocating %d bytes for Widget Image", metadata.data_length);
- void* buffer_image = kcalloc(metadata->data_length, 1);
-
- qemu_log("Getting data");
- duke_get_image_data(path, *metadata, buffer_image);
- qemu_log("Okay");
-
- Widget_t* wgt = new_bare_widget(
- &widget_image_renderer,
- &destroy_widget_image,
- 0, 0,
- metadata->width, metadata->height
- );
-
- wgt->custom_widget_data = kcalloc(sizeof(Widget_Image_t), 1);
-
- Widget_Image_t* wgt_data = (Widget_Image_t*)wgt->custom_widget_data;
- wgt_data->path = path;
- wgt_data->display_mode = NORMAL;
- wgt_data->meta = metadata;
- wgt_data->image_data = buffer_image;
-
- return wgt;
-}
-
-void destroy_widget_image(Widget_t* widget) {
- Widget_Image_t* wgt_data = (Widget_Image_t*)(widget->custom_widget_data);
-
- // qemu_log("Freeing image data: %x", wgt_data->image_data);
- kfree(wgt_data->image_data);
- kfree(wgt_data->meta);
- // qemu_log("Freeing widget data: %x", widget->custom_widget_data);
- kfree(widget->custom_widget_data);
- // qemu_log("Freeing widget itself: %x", widget);
- // destroy_widget(widget);
-}
diff --git a/kernel/src/io/duke_image.c b/kernel/src/io/duke_image.c
deleted file mode 100755
index 33f6b4e17..000000000
--- a/kernel/src/io/duke_image.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/**
- * @file io/imaging.c
- * @author NDRAEY >_ (pikachu_andrey@vk.com)
- * @brief Встраиваемая библиотека рисования изображений формата Duke
- * @version 0.3.3
- * @date 2022-11-01
- * @copyright Copyright SayoriOS Team (c) 2022-2023
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-/**
- * @brief Получает метаданные изображения Duke.
- *
- * @param filename - Имя файла
- *
- * @return 0 при успехе, 1 при ошибке
- */
-char duke_get_image_metadata(char *filename, struct DukeImageMeta* meta) {
- if(vfs_exists(filename)) {
- int mount_addr_ = vfs_foundMount(filename);
- int file_index_ = vfs_findFile(filename);
- vfs_read(mount_addr_, file_index_, 0, sizeof(struct DukeImageMeta), meta);
- return 0;
- }
- return 1;
-}
-
-void duke_get_image_data(char* filename, struct DukeImageMeta meta, void* buf) {
- if(vfs_exists(filename)) {
- int mount_addr_ = vfs_foundMount(filename);
- int file_index_ = vfs_findFile(filename);
- vfs_read(mount_addr_, file_index_, sizeof(struct DukeImageMeta), meta.data_length, buf);
- }
-}
-
-char duke_draw_area_from_file(char *filename, int x, int y, int sx, int sy, int width, int height) {
- if(vfs_exists(filename)) {
- struct DukeImageMeta* meta = kmalloc(sizeof *meta);
-
- int mount_addr_ = vfs_foundMount(filename);
- int file_index_ = vfs_findFile(filename);
- vfs_read(mount_addr_, file_index_, 0, sizeof(struct DukeImageMeta), meta);
-
- if(width>meta->width) { width = meta->width; }
- if(height>meta->height) { height = meta->height; }
-
- char *imagedata = kmalloc(meta->data_length);
-
- vfs_read(mount_addr_, file_index_, sizeof(struct DukeImageMeta), meta->data_length, imagedata);
-
- int wx;
- int wy = sy;
- char mod = meta->alpha?4:3;
-
- while(wy<(height-sy)) {
- wx = sx;
- while((wx-sx)<(width)) {
- int px = PIXIDX(meta->width*mod, wx*mod, wy);
- char r = imagedata[px];
- char g = imagedata[px+1];
- char b = imagedata[px+2];
- char a = imagedata[px+3];
- int color = RGB_TO_UINT32(r, g, b);
- if(mod==4) {
- if(a != 0) {
- set_pixel(x+(wx-sx), y+(wy-sy), color);
- }
- }else{
- set_pixel(x+(wx-sx), y+(wy-sy), color);
- }
- wx++;
- }
- wy++;
- }
- kfree(imagedata);
- kfree(meta);
- }else{ return 1; }
- return 0;
-}
-
-
-
-/**
- * @brief Функция отрисовки изображения
- *
- * @param filename - Имя файла
- * @param sx - Координата x
- * @param sy - Координата y
- *
- * @return 0 - OK или 1 - ERROR
- */
-bool duke_draw_from_file(const char *filename, size_t sx, size_t sy) {
- DukeHeader_t* meta = kmalloc(sizeof *meta);
- FILE* fp = fopen(filename, "r");
-
- if(!fp) {
- kfree(meta);
- return 1;
- }
-
- fread(fp, 1, sizeof(DukeHeader_t), meta);
-
- qemu_log("Draw Duke Image!");
- qemu_log("W: %d; H: %d; SIZE: %d; ALPHA: %s;", meta->width, meta->height, meta->data_length, meta->alpha ? "true" : "false");
-
- char *imagedata = kcalloc(meta->data_length, 1);
- fread(fp, meta->data_length, 1, imagedata);
-
- size_t x = 0, y = 0;
- char mod = meta->alpha ? 4 : 3;
-
- // qemu_log("Pixel step is: %d", mod);
-
- while(y < meta->height) {
- x = 0;
- while(x < meta->width) {
- size_t px = PIXIDX(meta->width * mod, x * mod, y);
- uint8_t r = imagedata[px];
- uint8_t g = imagedata[px + 1];
- uint8_t b = imagedata[px + 2];
- uint32_t color = RGB_TO_UINT32(r, g, b);
-
- if(meta->alpha) {
- uint8_t a = imagedata[px + 3];
-
- if(a != 0)
- set_pixel(sx + x, sy + y, color);
- }else{
- set_pixel(sx + x, sy + y, color);
- }
- x++;
- }
- y++;
- }
-
- kfree(imagedata);
- fclose(fp);
- kfree(meta);
- qemu_log("Freed memory!!!");
- return 0;
-}
-
-void duke_rawdraw(const char *data, struct DukeImageMeta* meta, int sx, int sy){
- int x = 0, y = 0;
- char mod = meta->alpha?4:3;
-
- while(y < meta->height) {
- x = 0;
- while(x < meta->width) {
- int px = PIXIDX(meta->width * mod, x * mod, y);
-
- char r = data[px];
- char g = data[px+1];
- char b = data[px+2];
- char a = data[px+3];
- int color = ((r&0xff)<<16)|((g&0xff)<<8)|(b&0xff);
-
- if((mod==4 && a!=0) || mod==3) {
- set_pixel(sx+x, sy+y, color);
- }
-
- x++;
- }
- y++;
- }
-}
-
-void duke_rawdraw2(const char *data, int width, int height, int bpp, int sx, int sy){
- int x = 0, y = 0;
-
- while(y < height) {
- x = 0;
- while(x < width) {
- int px = PIXIDX(width * (bpp >> 3), x * (bpp >> 3), y);
-
- char r = data[px];
- char g = data[px+1];
- char b = data[px+2];
- char a = data[px+3];
- int color = ((r&0xff)<<16)|((g&0xff)<<8)|(b&0xff);
-
- if(((bpp >> 3) == 4 && a != 0) || (bpp >> 3) == 3) {
- set_pixel(sx+x, sy+y, color);
- }
-
- x++;
- }
- y++;
- }
-}
-
-
-void duke_scale(const char* pixels, unsigned int w1, unsigned int h1, int w2, int h2, char alpha, char* out) {
- int scr_w = (w1<<16)/w2;
- int scr_h = (h1<<16)/h2;
-
- int x = 0;
- int y = 0;
-
- int x2 = 0;
- int y2 = 0;
-
- char mod = alpha?4:3;
- while(y>16;
- y2 = (y*scr_h)>>16;
-
- out[PIXIDX(w2*mod, x*mod, y)] = pixels[PIXIDX(w1*mod, x2*mod, y2)];
- out[PIXIDX(w2*mod, x*mod, y)+1] = pixels[PIXIDX(w1*mod, x2*mod, y2)+1];
- out[PIXIDX(w2*mod, x*mod, y)+2] = pixels[PIXIDX(w1*mod, x2*mod, y2)+2];
- if(alpha) {
- out[PIXIDX(w2*mod, x*mod, y)+3] = pixels[PIXIDX(w1*mod, x2*mod, y2)+3];
- }
- x++;
- }
- y++;
- }
-}
-
-unsigned int duke_calculate_bufsize(unsigned int width, unsigned int height, unsigned int alpha) {
- return width*height*(alpha?4:3);
-}
-
-
-/*
-DUKE SCALING EXAMPLE:
-
- struct DukeImageMeta* frw = duke_get_image_metadata("/initrd/res/SynapseOSLogo.duke");
- if(frw==0) {tty_printf("Return 0!\n");}
-
- unsigned int bsize = duke_calculate_bufsize(frw->width, frw->height, frw->alpha);
-
- char* imdata = kheap_malloc(bsize);
- duke_get_image_data("/initrd/res/SynapseOSLogo.duke", *frw, imdata);
-
- unsigned int nsize = duke_calculate_bufsize(300, 300, 1);
- char *ndata = kheap_malloc(nsize);
-
- duke_scale(imdata, frw->width, frw->height, 300, 300, 1, ndata);
-
- kheap_free(imdata);
- frw->width = 300;
- frw->height= 300;
- duke_rawdraw(ndata, frw, getScreenWidth()-300, 0);
- kheap_free(ndata);
-*/
-
-char duke_draw_scaled(char* filename, int width, int height, int x, int y) {
- if(!vfs_exists(filename)) return 1;
- struct DukeImageMeta origimg;
-
- char errcode = duke_get_image_metadata(filename, &origimg);
- if(errcode != 0) return 1;
-
- unsigned int bsize = duke_calculate_bufsize(origimg.width, origimg.height, origimg.alpha);
-
- char* imdata = kmalloc(bsize);
- duke_get_image_data(filename, origimg, imdata);
-
- unsigned int nsize = duke_calculate_bufsize(width, height, origimg.alpha);
- char *ndata = kmalloc(nsize);
-
- duke_scale(imdata, origimg.width, origimg.height, width, height, origimg.alpha, ndata);
- kfree(imdata);
-
- origimg.width = width;
- origimg.height = height;
-
- duke_rawdraw(ndata, &origimg, x, y);
-
- kfree(ndata);
- return 0;
-}
diff --git a/kernel/src/io/ports.c b/kernel/src/io/ports.c
old mode 100755
new mode 100644
index 1eb0001f0..38991dd34
--- a/kernel/src/io/ports.c
+++ b/kernel/src/io/ports.c
@@ -2,43 +2,24 @@
* @file io/ports.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru)
* @brief Средства для работы с портами
- * @version 0.3.3
+ * @version 0.3.4
* @date 2022-11-01
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-#include
+
#include
#include
#include
+#include "io/serial_port.h"
+#include "sys/scheduler.h"
+#include "mem/vmm.h"
-/**
- * @brief Запись 32х битного числа в порт
- *
- * @param port - порт
- * @param val - число
- */
-void outl(uint16_t port, uint32_t val) {
- asm volatile ( "outl %0, %1" : : "a"(val), "Nd"(port) );
-}
-
+void (*default_qemu_printf)(const char *text, ...) = qemu_printf;
-/**
- * @brief Чтение 32х битного числа
- *
- * @param port - порт
- * @return uint32_t - число
- */
-uint32_t inl(uint16_t port) {
- uint32_t ret;
- asm volatile ( "inl %1, %0"
- : "=a"(ret)
- : "Nd"(port) );
- return ret;
+void switch_qemu_logging() {
+ default_qemu_printf = new_qemu_printf;
}
-
-
-
/**
* @brief Чтение длинного слова через порт
*
@@ -67,13 +48,13 @@ void outsl(uint16_t port, uint32_t *buffer, int32_t times) {
}
void insw(uint16_t __port, void *__buf, unsigned long __n) {
- asm volatile("cld; rep; insw"
+ __asm__ volatile("cld; rep; insw"
: "+D"(__buf), "+c"(__n)
: "d"(__port));
}
void outsw(uint16_t __port, const void *__buf, unsigned long __n) {
- asm volatile("cld; rep; outsw"
+ __asm__ volatile("cld; rep; outsw"
: "+S"(__buf), "+c"(__n)
: "d"(__port));
}
@@ -89,10 +70,29 @@ int32_t is_transmit_empty(uint16_t port) {
// Read 1 byte (char) from port.
uint8_t serial_readchar(uint16_t port) {
- while (is_signal_received(port) == 0);
+ //size_t to = 0;
+ while (is_signal_received(port) == 0){
+ //to++;
+ //qemu_warn("TIMEOUT: %d",to);
+ }
return inb(port);
}
+
+// Read 1 byte (char) from port.
+int8_t serial_readchar_timeout(uint16_t port,size_t timeout, bool Alert) {
+ size_t to = 0;
+ while (is_signal_received(port) == 0){
+ to++;
+ //qemu_warn("TIMEOUT: %d",to);
+ if (to >= timeout){
+ if (Alert) qemu_warn("TIMEOUT: %d",to);
+ return -1;
+ }
+ }
+ return inb(port);
+}
+
/**
* @brief Небольшая задержка используя порт 128(0x80)
*/
@@ -100,19 +100,6 @@ void io_wait(void) {
outb(0x80, 0);
}
-/**
- * @brief Чтение 16х битного числа
- *
- * @param port - порт
- * @return uint16_t - число
- */
-uint16_t inw(uint16_t port){
- uint16_t ret;
- asm volatile ("inw %1, %0":"=a"(ret):"dN"(port));
- return ret;
-}
-
-
/**
* @brief Проверка, читаем ли символ
*
@@ -134,44 +121,36 @@ int is_com_port(int port) {
switch (port) {
case PORT_COM1:
return 1;
- break;
case PORT_COM2:
return 2;
- break;
case PORT_COM3:
return 3;
- break;
case PORT_COM4:
return 4;
- break;
case PORT_COM5:
return 5;
- break;
case PORT_COM6:
return 6;
- break;
case PORT_COM7:
return 7;
- break;
case PORT_COM8:
return 8;
- break;
default:
return 0;
- break;
}
}
/**
* @brief Вывод QEMU через COM1 информации
*
- * @param text Строка с параметрами
+ * @param text Форматная строка
+ * @param ... Дополнительные параметры
*/
void qemu_printf(const char *text, ...) {
va_list args;
va_start(args, text);
- if (__com_getInit(1) == 1) {
+ if (__com_getInit(1)) {
scheduler_mode(false); // Stop scheduler
__com_pre_formatString(PORT_COM1, text, args);
@@ -183,19 +162,19 @@ void qemu_printf(const char *text, ...) {
}
void new_qemu_printf(const char *format, ...) {
- if (!__com_getInit(1))
+ if (!__com_getInit(1))
return;
-
+
va_list args;
va_start(args, format);
char* container;
-
+
vasprintf(&container, format, args);
+ va_end(args);
+
__com_writeString(PORT_COM1, container);
kfree(container);
-
- va_end(args);
}
diff --git a/kernel/src/io/rgb_image.c b/kernel/src/io/rgb_image.c
new file mode 100644
index 000000000..5b3c19467
--- /dev/null
+++ b/kernel/src/io/rgb_image.c
@@ -0,0 +1,83 @@
+//
+// Created by ndraey on 25.10.23.
+//
+
+#include
+#include "io/rgb_image.h"
+#include "io/ports.h"
+
+/**
+ * @brief Рисует изображение в виде массива байт в видеопамяти.
+ * @param data Массив данных изображения
+ * @param width Ширина изображения
+ * @param height Высота изображения
+ * @param bpp Количество бит на пиксель
+ * @param sx Начальная координата X
+ * @param sy Начальная координата Y
+ */
+void draw_rgb_image(const char *data, size_t width, size_t height, size_t bpp, int sx, int sy) {
+ int x, y = 0;
+
+ size_t bytes_pp = bpp >> 3;
+
+ while(y < height) {
+ x = 0;
+ while(x < width) {
+ int px = PIXIDX(width * bytes_pp, x * bytes_pp, y);
+
+ char r = data[px];
+ char g = data[px + 1];
+ char b = data[px + 2];
+ char a = data[px + 3];
+ size_t color = ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
+
+// if((bytes_pp == 4 && a != 0) || bytes_pp == 3) {
+ set_pixel(sx + x, sy + y, color);
+// } else {
+// qemu_log("FUCK! %x", a);
+// }
+
+ x++;
+ }
+ y++;
+ }
+}
+
+/**
+ * @brief Скалирует изображение (расширяет или уменьшает размер изображения).
+ * @param pixels Массив байт изображения в памяти
+ * @param w1 Начальная ширина
+ * @param h1 Начальная высота
+ * @param w2 Конечная ширина
+ * @param h2 Конечная высота
+ * @param alpha Имеется ли альфа-канал?
+ * @param out Выходной буффер изображения.
+ */
+void scale_rgb_image(const char* pixels, unsigned int w1, unsigned int h1, int w2, int h2, char alpha, char* out) {
+ int scr_w = (w1<<16)/w2;
+ int scr_h = (h1<<16)/h2;
+
+ int x = 0;
+ int y = 0;
+
+ int x2 = 0;
+ int y2 = 0;
+
+ char mod = alpha?4:3;
+ while(y>16;
+ y2 = (y*scr_h)>>16;
+
+ out[PIXIDX(w2*mod, x*mod, y)] = pixels[PIXIDX(w1*mod, x2*mod, y2)];
+ out[PIXIDX(w2*mod, x*mod, y)+1] = pixels[PIXIDX(w1*mod, x2*mod, y2)+1];
+ out[PIXIDX(w2*mod, x*mod, y)+2] = pixels[PIXIDX(w1*mod, x2*mod, y2)+2];
+ if(alpha) {
+ out[PIXIDX(w2*mod, x*mod, y)+3] = pixels[PIXIDX(w1*mod, x2*mod, y2)+3];
+ }
+ x++;
+ }
+ y++;
+ }
+}
\ No newline at end of file
diff --git a/kernel/src/io/screen.c b/kernel/src/io/screen.c
index 603460f18..6afcc718c 100644
--- a/kernel/src/io/screen.c
+++ b/kernel/src/io/screen.c
@@ -1,7 +1,13 @@
-#include
+#include
+#include
+#include
+#include
+#include
#include
+#include "mem/pmm.h"
+#include "mem/vmm.h"
-uint8_t *framebuffer_addr; ///< Точка монтирования
+uint8_t *framebuffer_addr = 0; ///< Точка монтирования
uint32_t framebuffer_pitch; ///< Частота обновления экрана
uint32_t framebuffer_bpp; ///< Глубина цвета экрана
uint32_t framebuffer_width; ///< Длина экрана
@@ -11,19 +17,6 @@ uint8_t *back_framebuffer_addr = 0; ///< Позиция буфера экран
bool lazyDraw = true; ///< Включен ли режим ленивой прорисовки
bool tty_oem_mode = false; ///< Режим работы
-/**
- * @brief Обновить информацию на основном экране
- */
-// void punch() {
-// fb_copier(framebuffer_addr, back_framebuffer_addr, framebuffer_size);
-// }
-
-// void punch() {
-// uint8_t* temp = back_framebuffer_addr;
-// back_framebuffer_addr = framebuffer_addr;
-// framebuffer_addr = temp;
-// }
-
/**
* @brief Получение адреса расположения драйвера экрана
*
@@ -55,23 +48,12 @@ uint32_t getDisplayBpp(){
return framebuffer_bpp;
}
-/**
- * @brief Получение размера буфера экрана
- *
- * @return uint32_t - Размер буфера экрана
- */
-size_t getDisplaySize(){
- return framebuffer_size;
-}
-
void create_back_framebuffer() {
qemu_log("^---- 1. Allocating");
- back_framebuffer_addr = (uint8_t*)kmalloc(framebuffer_size);
+ back_framebuffer_addr = (uint8_t*)kcalloc(framebuffer_size, 1);
qemu_log("framebuffer_size = %d (%dK) (%dM)", framebuffer_size, framebuffer_size/1024, framebuffer_size/(1024*1024));
qemu_log("back_framebuffer_addr = %x", back_framebuffer_addr);
-
- memset(back_framebuffer_addr, 0, framebuffer_size);
}
/**
@@ -80,48 +62,54 @@ void create_back_framebuffer() {
* @param mboot - информация полученная от загрузчика
*/
void init_vbe(multiboot_header_t *mboot) {
- svga_mode_info_t *svga_mode = (svga_mode_info_t*) mboot->vbe_mode_info;
- framebuffer_addr = (uint8_t*)svga_mode->physbase;
- framebuffer_pitch = svga_mode->pitch;
- framebuffer_bpp = svga_mode->bpp;
- framebuffer_width = svga_mode->screen_width;
- framebuffer_height = svga_mode->screen_height;
+ // FIXME: Something wrong with `svga_mode_info_t` structure!
+// svga_mode_info_t *svga_mode = (svga_mode_info_t*) mboot->vbe_mode_info;
+// framebuffer_addr = (uint8_t*)svga_mode->physbase;
+// framebuffer_pitch = svga_mode->pitch;
+// framebuffer_bpp = svga_mode->bpp;
+// framebuffer_width = svga_mode->screen_width;
+// framebuffer_height = svga_mode->screen_height;
+// framebuffer_size = framebuffer_height * framebuffer_pitch;
+
+// qemu_log("[VBE] [Install] Width: %d; Height: %d; Pitch: %d; BPP: %d; Size: %d; Address: %x",
+// framebuffer_width,
+// framebuffer_height,
+// framebuffer_pitch,
+// framebuffer_bpp,
+// framebuffer_size,
+// framebuffer_addr
+// );
+
+
+ framebuffer_addr = (uint8_t *) mboot->framebuffer_addr;
+ framebuffer_pitch = mboot->framebuffer_pitch;
+ framebuffer_bpp = mboot->framebuffer_bpp;
+ framebuffer_width = mboot->framebuffer_width;
+ framebuffer_height = mboot->framebuffer_height;
framebuffer_size = framebuffer_height * framebuffer_pitch;
- qemu_log("Booster is: %d", (framebuffer_size % 4 == 0 ? 4 : (framebuffer_size % 2 == 0 ? 2 : 1)));
-
- qemu_log("[VBE] [Install] Width: %d; Height: %d; Pitch: %d; BPP: %d; Size: %d; Address: %x",
- framebuffer_width,
- framebuffer_height,
- framebuffer_pitch,
- framebuffer_bpp,
- framebuffer_size,
- framebuffer_addr
- );
+ qemu_log("[VBE] [USING LEGACY INFO] Width: %d; Height: %d; Pitch: %d; BPP: %d; Size: %d; Address: %x",
+ mboot->framebuffer_width,
+ mboot->framebuffer_height,
+ mboot->framebuffer_pitch,
+ mboot->framebuffer_bpp,
+ mboot->framebuffer_height * mboot->framebuffer_pitch,
+ mboot->framebuffer_addr
+ );
- physaddr_t frame;
- virtual_addr_t virt;
- physaddr_t to;
+ physical_addr_t frame = (physical_addr_t)framebuffer_addr;
+ virtual_addr_t virt = (virtual_addr_t)framebuffer_addr;
- physaddr_t kdir = get_kernel_dir();
size_t start_tk = getTicks();
- for (frame = (physaddr_t)framebuffer_addr,
- virt = (virtual_addr_t)framebuffer_addr,
- to = (physaddr_t)(framebuffer_addr + framebuffer_size);
- frame < to;
- frame += PAGE_SIZE*2048,
- virt += PAGE_SIZE*2048) {
- // map_pages(kdir, frame, virt, PAGE_SIZE, (PAGE_PRESENT | PAGE_WRITEABLE));
-
- // FIXME: Why it doesn't run when setting size = 1? (Workaround is 2048)
- map_pages(kdir, frame, virt, 2048, (PAGE_PRESENT | PAGE_WRITEABLE));
- }
+ map_pages(get_kernel_page_directory(),
+ frame,
+ virt,
+ framebuffer_size,
+ PAGE_WRITEABLE);
qemu_log("Okay mapping! (took %d millis)", (getTicks() - start_tk)/(getFrequency()/1000));
- // map_pages(get_kernel_dir(), framebuffer_addr, framebuffer_addr,
- // framebuffer_size / PAGE_SIZE, 0x07);
qemu_log("Creating framebuffer");
create_back_framebuffer();
qemu_log("^---- OKAY");
@@ -130,8 +118,8 @@ void init_vbe(multiboot_header_t *mboot) {
/**
* @brief Получить цвет на пикселе по X и Y
*
- * @param int32_t x - X
- * @param int32_t y - Y
+ * @param x - X
+ * @param y - Y
*
* @return uint32_t - Цвет
*/
@@ -147,27 +135,6 @@ size_t getPixel(int32_t x, int32_t y){
return ((back_framebuffer_addr[where+2] & 0xff) << 16) + ((back_framebuffer_addr[where+1] & 0xff) << 8) + (back_framebuffer_addr[where] & 0xff);
}
-/**
- * @brief Вывод одного пикселя на экран
- *
- * @param x - позиция по x
- * @param y - позиция по y
- * @param color - цвет
- */
-void set_pixel(uint32_t x, uint32_t y, uint32_t color) {
- if (x < 0 || y < 0 ||
- x >= (int) VESA_WIDTH ||
- y >= (int) VESA_HEIGHT) {
- return;
- }
-
- uint8_t* pixels = back_framebuffer_addr + (x * (framebuffer_bpp >> 3)) + y * framebuffer_pitch;
-
- pixels[0] = color & 255;
- pixels[1] = (color >> 8) & 255;
- pixels[2] = (color >> 16) & 255;
-}
-
void rgba_blend(uint8_t result[4], const uint8_t fg[4], const uint8_t bg[4])
{
uint32_t alpha = fg[3] + 1;
@@ -179,10 +146,9 @@ void rgba_blend(uint8_t result[4], const uint8_t fg[4], const uint8_t bg[4])
result[3] = 0xff;
}
-void setPixelAlpha(int x, int y, rgba_color color) {
- if (x < 0 || y < 0 ||
- x >= (int) VESA_WIDTH ||
- y >= (int) VESA_HEIGHT) {
+void setPixelAlpha(uint32_t x, uint32_t y, rgba_color color) {
+ if (x >= VESA_WIDTH ||
+ y >= VESA_HEIGHT) {
return;
}
@@ -190,7 +156,6 @@ void setPixelAlpha(int x, int y, rgba_color color) {
if (color.a != 255) {
if (color.a != 0) {
-
uint8_t bg[4] = {back_framebuffer_addr[where], back_framebuffer_addr[where + 1], back_framebuffer_addr[where + 2], 255};
uint8_t fg[4] = {(uint8_t)color.b, (uint8_t)color.g, (uint8_t)color.r, (uint8_t)color.a};
uint8_t res[4];
@@ -243,10 +208,7 @@ uint32_t getScreenHeight(){
*
*/
void clean_screen(){
- // punch();
memset(back_framebuffer_addr, 0, framebuffer_size); // Optimized variant
-
- punch();
}
void rect_copy(int x, int y, int width, int height) {
diff --git a/kernel/src/io/port_io.c b/kernel/src/io/serial_port.c
similarity index 65%
rename from kernel/src/io/port_io.c
rename to kernel/src/io/serial_port.c
index 72fb898c8..08aa5a523 100644
--- a/kernel/src/io/port_io.c
+++ b/kernel/src/io/serial_port.c
@@ -2,13 +2,17 @@
* @file io/port_io.c
* @author Пиминов Никита (nikita.piminoff@yandex.ru), NDRAEY >_ (pikachu_andrey@vk.com)
* @brief Средства для работы с портами
- * @version 0.3.3
+ * @version 0.3.4
* @date 2023-01-07
* @copyright Copyright SayoriOS Team (c) 2022-2023
*/
-#include
-#include
+
+#include