├── .gitignore ├── .gitmodules ├── .vscode ├── c_cpp_properties.json └── settings.json ├── GNUmakefile ├── LICENSE ├── build-initrd.sh ├── kernel ├── GNUmakefile ├── get-deps ├── linker.ld └── src │ ├── arch │ └── x86_64 │ │ ├── cpu │ │ ├── asm │ │ │ └── gdt.asm │ │ ├── data.cpp │ │ ├── gdt.cpp │ │ ├── lapic.cpp │ │ └── sse.cpp │ │ ├── interrupts │ │ ├── asm │ │ │ ├── panic.asm │ │ │ └── stubs.asm │ │ ├── idt.cpp │ │ ├── ioapic.cpp │ │ ├── irq.cpp │ │ ├── panic.cpp │ │ ├── scheduling │ │ │ ├── asm │ │ │ │ ├── scheduling_end.asm │ │ │ │ └── scheduling_stub.asm │ │ │ └── scheduling.cpp │ │ └── syscalls │ │ │ ├── asm │ │ │ └── syscall.asm │ │ │ ├── ipc │ │ │ └── fd.cpp │ │ │ └── syscall.cpp │ │ └── main.asm │ ├── drivers │ ├── cmos │ │ └── cmos.cpp │ ├── hpet │ │ └── hpet.cpp │ ├── io │ │ └── io.cpp │ ├── pci │ │ └── pci.cpp │ ├── power_button │ │ └── power_button.cpp │ ├── ps2keyboard │ │ └── ps2keyboard.cpp │ ├── serial │ │ └── serial.cpp │ └── xhci │ │ └── xhci.cpp │ ├── generic │ ├── VFS │ │ ├── devfs.cpp │ │ ├── procfs.cpp │ │ ├── tmpfs.cpp │ │ ├── ustar.cpp │ │ └── vfs.cpp │ ├── acpi │ │ ├── acpi.cpp │ │ └── kernel_api.cpp │ ├── elf │ │ └── elf.cpp │ ├── limineA │ │ └── limineinfo.cpp │ ├── locks │ │ └── spinlock.cpp │ ├── memory │ │ ├── heap.cpp │ │ ├── paging.cpp │ │ ├── pmm.cpp │ │ └── vmm.cpp │ ├── mp │ │ └── mp.cpp │ └── tty │ │ └── tty.cpp │ ├── include │ ├── arch │ │ └── x86_64 │ │ │ ├── cpu │ │ │ ├── data.hpp │ │ │ ├── gdt.hpp │ │ │ ├── lapic.hpp │ │ │ └── sse.hpp │ │ │ ├── interrupts │ │ │ ├── idt.hpp │ │ │ ├── ioapic.hpp │ │ │ ├── irq.hpp │ │ │ └── syscalls │ │ │ │ ├── ipc │ │ │ │ ├── fd.hpp │ │ │ │ └── pipe.hpp │ │ │ │ └── syscall.hpp │ │ │ └── scheduling │ │ │ └── scheduling.hpp │ ├── config.hpp │ ├── drivers │ │ ├── cmos │ │ │ └── cmos.hpp │ │ ├── hpet │ │ │ └── hpet.hpp │ │ ├── io │ │ │ └── io.hpp │ │ ├── pci │ │ │ └── pci.hpp │ │ ├── power_button │ │ │ └── power_button.hpp │ │ ├── ps2keyboard │ │ │ └── ps2keyboard.hpp │ │ ├── serial │ │ │ └── serial.hpp │ │ └── xhci │ │ │ └── xhci.hpp │ ├── generic │ │ ├── VFS │ │ │ ├── devfs.hpp │ │ │ ├── procfs.hpp │ │ │ ├── tmpfs.hpp │ │ │ ├── ustar.hpp │ │ │ └── vfs.hpp │ │ ├── acpi │ │ │ └── acpi.hpp │ │ ├── elf │ │ │ └── elf.hpp │ │ ├── limineA │ │ │ └── limineinfo.hpp │ │ ├── locks │ │ │ └── spinlock.hpp │ │ ├── memory │ │ │ ├── heap.hpp │ │ │ ├── paging.hpp │ │ │ ├── pmm.hpp │ │ │ └── vmm.hpp │ │ ├── mp │ │ │ └── mp.hpp │ │ ├── status │ │ │ └── status.hpp │ │ └── tty │ │ │ └── tty.hpp │ ├── lib │ │ └── limineA │ │ │ └── limine.h │ └── other │ │ ├── assembly.hpp │ │ ├── assert.hpp │ │ ├── debug.hpp │ │ ├── hhdm.hpp │ │ ├── log.hpp │ │ ├── other.hpp │ │ ├── string.hpp │ │ └── unixlike.hpp │ ├── main.cpp │ └── other │ ├── hhdm.cpp │ ├── log.cpp │ ├── other.cpp │ ├── string.cpp │ └── unixlike.cpp ├── readme.md └── tools ├── base ├── etc │ ├── logo │ └── passwd └── root │ ├── .bash_history │ └── .bashrc ├── diffs ├── binutils.diff └── gcc.diff ├── get-linux-headers.sh ├── img └── work.png ├── limine.conf ├── pkg ├── bash │ ├── diff │ │ └── bash.diff │ ├── info.txt │ └── pkg.sh ├── build_pkg.sh ├── coreutils │ ├── diff │ │ └── coreutils.diff │ ├── info.txt │ └── pkg.sh ├── dep │ ├── hi │ └── ncurses │ │ ├── diff │ │ └── ncurses.diff │ │ ├── info.txt │ │ └── pkg.sh ├── fastfetch │ ├── diff │ │ └── fastfetch.diff │ ├── info.txt │ └── pkg.sh ├── lua │ ├── info.txt │ └── pkg.sh ├── memstat │ ├── info.txt │ ├── pkg.sh │ └── src │ │ └── main.c ├── nano │ ├── diff │ │ └── nano.diff │ ├── info.txt │ └── pkg.sh ├── pkg_lib.sh └── toolchain.cmake ├── test_init └── main.c └── toolchain ├── cpp.sh └── get.sh /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | orange 3 | orange.iso 4 | obj 5 | trash 6 | .code 7 | serial_output.txt 8 | kernel-deps 9 | limine 10 | initrd/usr/include 11 | kernel/bin 12 | kernel/cc-runtime 13 | kernel/cc-runtime-x86_64 14 | kernel/freestnd-c-hdrs 15 | kernel/freestnd-cxx-hdrs 16 | main.o 17 | serial.txt 18 | output.txt 19 | Orange-distro-build 20 | ovmf 21 | initrd/usr/lib 22 | initrd/usr/include 23 | initrd 24 | orange-mlibc 25 | ./initrd 26 | qemu_log.txt 27 | orange.hdd 28 | ./tools/toolchain/pack 29 | pack 30 | linux-headers 31 | initrd.tar -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "kernel/src/lib/uACPI"] 2 | path = kernel/src/lib/uACPI 3 | url = https://github.com/uACPI/uACPI.git 4 | [submodule "kernel/src/lib/flanterm"] 5 | path = kernel/src/lib/flanterm 6 | url = https://github.com/mintsuki/flanterm.git 7 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "${workspaceFolder}/kernel/src/include", 8 | "${workspaceFolder}/kernel/src/lib/uACPI/include", 9 | "${workspaceFolder}/kernel/freestnd-c-hdrs/x86_64/include", 10 | "${workspaceFolder}/kernel/freestnd-cxx-hdrs/x86_64/include" 11 | ], 12 | "defines": [], 13 | "compilerPath": "/usr/bin/clang", 14 | "cStandard": "c17", 15 | "cppStandard": "c++17", 16 | "intelliSenseMode": "linux-clang-x64" 17 | } 18 | ], 19 | "version": 4 20 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "ranges": "cpp", 4 | "array": "cpp", 5 | "bitset": "cpp", 6 | "initializer_list": "cpp", 7 | "span": "cpp", 8 | "string_view": "cpp", 9 | "rope": "cpp", 10 | "slist": "cpp", 11 | "format": "cpp", 12 | "stacktrace": "cpp", 13 | "regex": "cpp", 14 | "serial.hpp": "c", 15 | "*.tcc": "cpp", 16 | "thread": "cpp", 17 | "valarray": "cpp", 18 | "compare": "c", 19 | "cstdint": "c", 20 | "expected": "cpp", 21 | "optional": "cpp", 22 | "ratio": "cpp", 23 | "type_traits": "cpp", 24 | "charconv": "cpp", 25 | "chrono": "cpp", 26 | "system_error": "cpp", 27 | "functional": "cpp", 28 | "tuple": "cpp", 29 | "utility": "cpp", 30 | "string": "cpp", 31 | "cstddef": "cpp", 32 | "source_location": "cpp", 33 | "flanterm_private.h": "c", 34 | "stdio.h": "c", 35 | "typeindex": "cpp", 36 | "typeinfo": "cpp", 37 | "*.inc": "cpp", 38 | "__locale": "cpp", 39 | "ios": "cpp" 40 | } 41 | } -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | # Nuke built-in rules and variables. 2 | MAKEFLAGS += -rR 3 | .SUFFIXES: 4 | 5 | # Default user QEMU flags. These are appended to the QEMU command calls. 6 | QEMUFLAGS := -m 1G -no-reboot -serial stdio -M q35 -s -d int -smp 2 -trace usb_xhci_* -device qemu-xhci -device usb-kbd -enable-kvm 7 | override IMAGE_NAME := orange 8 | 9 | # Toolchain for building the 'limine' executable for the host. 10 | HOST_CC := cc 11 | HOST_CFLAGS := -g -pipe 12 | HOST_CPPFLAGS := 13 | HOST_LDFLAGS := 14 | HOST_LIBS := 15 | 16 | HOST_LD := ld 17 | HOST_TAR := tar 18 | 19 | CURRENT_DIR := $(shell realpath .) 20 | 21 | ifeq ($(shell uname), Darwin) 22 | HOST_LD = ld.lld 23 | HOST_TAR = gtar 24 | endif 25 | 26 | .PHONY: run-build 27 | run-build:all run 28 | 29 | .PHONY: uefi-run-build 30 | uefi-run-build: all run-uefi 31 | 32 | .PHONY: headers 33 | headers: 34 | rm -rf orange-cross-compiler-headers 35 | git clone https://github.com/cpplover0/orange-cross-compiler-headers 36 | mkdir -p initrd/usr/include 37 | rm -rf initrd/usr/include/* 38 | mkdir -p orange-cross-compiler-headers/include 39 | cp -rf orange-cross-compiler-headers/include initrd/usr 40 | rm -rf orange-cross-compiler-headers 41 | 42 | .PHONY: make-libc 43 | make-libc: 44 | rm -rf tools/orange-mlibc 45 | cd tools && git clone https://github.com/cpplover0/orange-mlibc --depth=1 46 | cd tools/orange-mlibc && sh build_to_cross.sh "$(CURRENT_DIR)" 47 | 48 | .PHONY: cross-compiler 49 | cross-compiler: make-libc 50 | cd tools/toolchain/ && sh get.sh "$(CURRENT_DIR)" 51 | 52 | .PHONY: check-cross 53 | check-cross: 54 | ifeq (, $(shell which x86_64-orange-gcc)) 55 | echo "It looks like you don't have cross-compiler, or you didn't add them to your PATH."; \ 56 | echo "If you built your cross compiler, add them to PATH with: "; \ 57 | echo 'export PATH="$$HOME/opt/cross/orange/bin:$$PATH"'; \ 58 | echo 'or build cross compiler with "make cross-compiler"'; \ 59 | exit 1; 60 | endif 61 | 62 | .PHONY: all 63 | all: $(IMAGE_NAME).iso 64 | 65 | .PHONY: all-hdd 66 | all-hdd: $(IMAGE_NAME).hdd 67 | 68 | .PHONY: run 69 | run: $(IMAGE_NAME).iso 70 | qemu-system-x86_64 \ 71 | -M q35 \ 72 | -cdrom $(IMAGE_NAME).iso \ 73 | -boot d \ 74 | $(QEMUFLAGS) 75 | 76 | .PHONY: run-uefi 77 | run-uefi: ovmf/ovmf-code-x86_64.fd $(IMAGE_NAME).iso 78 | qemu-system-x86_64 \ 79 | -M q35 \ 80 | -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-x86_64.fd,readonly=on \ 81 | -cdrom $(IMAGE_NAME).iso \ 82 | -boot d \ 83 | $(QEMUFLAGS) 84 | 85 | .PHONY: run-hdd 86 | run-hdd: $(IMAGE_NAME).hdd 87 | qemu-system-x86_64 \ 88 | -M q35 \ 89 | -hda $(IMAGE_NAME).hdd \ 90 | $(QEMUFLAGS) 91 | 92 | .PHONY: run-hdd-uefi 93 | run-hdd-uefi: ovmf/ovmf-code-x86_64.fd $(IMAGE_NAME).hdd 94 | qemu-system-x86_64 \ 95 | -M q35 \ 96 | -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-x86_64.fd,readonly=on \ 97 | -hda $(IMAGE_NAME).hdd \ 98 | $(QEMUFLAGS) 99 | 100 | ovmf/ovmf-code-x86_64.fd: 101 | mkdir -p ovmf 102 | curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-code-x86_64.fd 103 | 104 | limine/limine: 105 | rm -rf limine 106 | git clone https://github.com/limine-bootloader/limine.git --branch=v8.x-binary --depth=1 107 | $(MAKE) -C limine \ 108 | CC="$(HOST_CC)" \ 109 | CFLAGS="$(HOST_CFLAGS)" \ 110 | CPPFLAGS="$(HOST_CPPFLAGS)" \ 111 | LDFLAGS="$(HOST_LDFLAGS)" \ 112 | LIBS="$(HOST_LIBS)" 113 | 114 | kernel-deps: 115 | ./kernel/get-deps 116 | touch kernel-deps 117 | 118 | .PHONY: kernel 119 | kernel: kernel-deps 120 | rm -rf kernel/src/lib/uACPI/tests 121 | $(MAKE) -C kernel 122 | 123 | $(IMAGE_NAME).iso: limine/limine kernel 124 | rm -rf iso_root 125 | mkdir -p iso_root/boot 126 | cp -v kernel/bin/kernel iso_root/boot/ 127 | mkdir -p iso_root/boot/limine 128 | cp -v tools/limine.conf limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/ 129 | cp -rf tools/iso/* iso_root/ 130 | mkdir -p iso_root/EFI/BOOT 131 | cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/ 132 | cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT/ 133 | xorriso -as mkisofs -R -r -J -b boot/limine/limine-bios-cd.bin \ 134 | -no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \ 135 | -apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin \ 136 | -efi-boot-part --efi-boot-image --protective-msdos-label \ 137 | iso_root -o $(IMAGE_NAME).iso 138 | ./limine/limine bios-install $(IMAGE_NAME).iso 139 | rm -rf iso_root 140 | 141 | $(IMAGE_NAME).hdd: limine/limine kernel 142 | rm -f $(IMAGE_NAME).hdd 143 | dd if=/dev/zero bs=1M count=0 seek=64 of=$(IMAGE_NAME).hdd 144 | PATH=$$PATH:/usr/sbin:/sbin sgdisk $(IMAGE_NAME).hdd -n 1:2048 -t 1:ef00 145 | ./limine/limine bios-install $(IMAGE_NAME).hdd 146 | mformat -i $(IMAGE_NAME).hdd@@1M 147 | mmd -i $(IMAGE_NAME).hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine 148 | mcopy -i $(IMAGE_NAME).hdd@@1M kernel/bin/kernel ::/boot 149 | mcopy -i $(IMAGE_NAME).hdd@@1M limine.conf limine/limine-bios.sys ::/boot/limine 150 | mcopy -i $(IMAGE_NAME).hdd@@1M limine/BOOTX64.EFI ::/EFI/BOOT 151 | mcopy -i $(IMAGE_NAME).hdd@@1M limine/BOOTIA32.EFI ::/EFI/BOOT 152 | 153 | .PHONY: clean 154 | clean: 155 | $(MAKE) -C kernel clean 156 | rm -rf iso_root $(IMAGE_NAME).iso $(IMAGE_NAME).hdd 157 | 158 | .PHONY: distclean 159 | distclean: clean 160 | $(MAKE) -C kernel distclean 161 | rm -rf kernel-deps limine ovmf 162 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 cppLover0 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /build-initrd.sh: -------------------------------------------------------------------------------- 1 | 2 | CURRENT_DIR="$(realpath .)" 3 | 4 | export PATH="$HOME/opt/cross/orange/bin:$PATH" 5 | 6 | if [ ! "$(which x86_64-orange-gcc)" ]; then 7 | echo "It looks like you don't have the cross-compiler installed, or it isn't in your PATH." 8 | echo "If you built your cross-compiler, add it to your PATH with:" 9 | echo 'export PATH="$HOME/opt/cross/orange/bin:$PATH"' 10 | echo 'Alternatively, you can build the cross-compiler with: "make cross-compiler"' 11 | exit 1 12 | fi 13 | 14 | rm -rf tools/orange-mlibc 15 | rm -rf initrd 16 | mkdir -p initrd/lib 17 | cd tools 18 | sh get-linux-headers.sh "$CURRENT_DIR" 19 | git clone https://github.com/cpplover0/orange-mlibc --depth=1 20 | cd orange-mlibc 21 | bash build_to_cross.sh "$CURRENT_DIR" 22 | cd ../../ 23 | rm -rf initrd/lib/* 24 | cd initrd/lib 25 | ln -s ../usr/lib/ld.so ld64.so.1 26 | cd ../../ 27 | mkdir -p initrd/bin 28 | mkdir -p initrd/usr/bin 29 | x86_64-orange-gcc tools/test_init/main.c -o initrd/usr/bin/initrd -no-pie 30 | rm -rf tools/iso/boot/initrd.tar 31 | cd tools/pkg 32 | bash build_pkg.sh "$CURRENT_DIR/initrd/usr" 33 | cd ../../ 34 | 35 | mkdir -p initrd/lib 36 | mkdir -p initrd/bin 37 | 38 | cd initrd/lib 39 | 40 | echo Creating symlinks ./*.so 41 | for file in ../usr/lib/*.so; do 42 | echo $file "$(basename "$file")" 43 | ln -s "$file" "$(basename "$file")" 44 | done 45 | 46 | for file in ../usr/local/lib/*.so; do 47 | echo $file "$(basename "$file")" 48 | ln -s "$file" "$(basename "$file")" 49 | done 50 | 51 | cd ../bin 52 | 53 | echo Creating symlinks ./* 54 | for file in ../usr/bin/*; do 55 | echo $file "$(basename "$file")" 56 | ln -s "$file" "$(basename "$file")" 57 | done 58 | 59 | for file in ../usr/local/bin/*; do 60 | echo $file "$(basename "$file")" 61 | ln -s "$file" "$(basename "$file")" 62 | done 63 | 64 | 65 | cd ../../ 66 | 67 | rm -rf initrd/usr/local/lib/*.a 68 | rm -rf initrd/usr/lib/*.a 69 | rm -rf initrd/lib/*.a 70 | 71 | cp -rf tools/base/* initrd/ 72 | 73 | echo Building initrd is done 74 | 75 | mkdir -p tools/iso/boot 76 | tar -cf tools/iso/boot/initrd.tar -C initrd . 77 | 78 | -------------------------------------------------------------------------------- /kernel/GNUmakefile: -------------------------------------------------------------------------------- 1 | # Nuke built-in rules and variables. 2 | MAKEFLAGS += -rR 3 | .SUFFIXES: 4 | 5 | # This is the name that our final executable will have. 6 | # Change as needed. 7 | override OUTPUT := kernel 8 | 9 | # Install prefix; /usr/local is a good, standard default pick. 10 | PREFIX := /usr/local 11 | 12 | # User controllable C compiler command. 13 | CC := clang 14 | 15 | # User controllable C++ compiler command. 16 | CXX := clang++ 17 | 18 | # User controllable archiver command. 19 | AR := ar 20 | 21 | # User controllable C flags. 22 | CFLAGS := -g -pipe -I ./src/include -I ./src/lib/uACPI/include -Wno-writable-strings -O2 23 | 24 | LD := ld 25 | 26 | ifeq ($(shell uname), Darwin) 27 | LD = ld.lld 28 | endif 29 | 30 | # User controllable C++ flags. We default to same as C flags. 31 | CXXFLAGS := $(CFLAGS) 32 | 33 | # User controllable C/C++ preprocessor flags. We set none by default. 34 | CPPFLAGS := 35 | 36 | # User controllable nasm flags. 37 | NASMFLAGS := -F dwarf -g 38 | 39 | # User controllable linker flags. We set none by default. 40 | LDFLAGS := 41 | 42 | # Ensure the dependencies have been obtained. 43 | ifneq ($(shell ( test '$(MAKECMDGOALS)' = clean || test '$(MAKECMDGOALS)' = distclean ); echo $$?),0) 44 | ifeq ($(shell ( ! test -d freestnd-c-hdrs || ! test -d freestnd-cxx-hdrs || ! test -d cc-runtime ); echo $$?),0) 45 | $(error Please run the ./get-deps script first) 46 | endif 47 | endif 48 | 49 | # Check if CC is Clang. 50 | override CC_IS_CLANG := $(shell ! $(CC) --version 2>/dev/null | grep 'clang' >/dev/null 2>&1; echo $$?) 51 | 52 | # Check if CXX is Clang. 53 | override CXX_IS_CLANG := $(shell ! $(CXX) --version 2>/dev/null | grep 'clang' >/dev/null 2>&1; echo $$?) 54 | 55 | # If the C compiler is Clang, set the target as needed. 56 | ifeq ($(CC_IS_CLANG),1) 57 | override CC += \ 58 | -target x86_64-unknown-none 59 | endif 60 | 61 | # Likewise for the C++ compiler. 62 | ifeq ($(CXX_IS_CLANG),1) 63 | override CXX += \ 64 | -target x86_64-unknown-none 65 | endif 66 | 67 | # Internal flags shared by both C and C++ compilers. 68 | override SHARED_FLAGS := \ 69 | -Wall \ 70 | -Wextra \ 71 | -nostdinc \ 72 | -ffreestanding \ 73 | -fno-stack-protector \ 74 | -fno-stack-check \ 75 | -fno-PIC \ 76 | -ffunction-sections \ 77 | -fdata-sections \ 78 | -m64 \ 79 | -march=x86-64 \ 80 | -mno-80387 \ 81 | -mno-mmx \ 82 | -mno-sse \ 83 | -mno-sse2 \ 84 | -mno-red-zone \ 85 | -mcmodel=kernel 86 | 87 | # Internal C/C++ preprocessor flags that should not be changed by the user. 88 | override CPPFLAGS_C := \ 89 | -I src \ 90 | -isystem freestnd-c-hdrs/x86_64/include \ 91 | $(CPPFLAGS) \ 92 | -DLIMINE_API_REVISION=2 \ 93 | -MMD \ 94 | -MP 95 | 96 | # Internal C++ only preprocessor flags. 97 | override CPPFLAGS_CXX := \ 98 | -I src \ 99 | -isystem freestnd-c-hdrs/x86_64/include \ 100 | -isystem freestnd-cxx-hdrs/x86_64/include \ 101 | $(CPPFLAGS) \ 102 | -DLIMINE_API_REVISION=2 \ 103 | -MMD \ 104 | -MP 105 | 106 | # Internal C flags that should not be changed by the user. 107 | override CFLAGS += \ 108 | -std=gnu11 \ 109 | $(SHARED_FLAGS) 110 | 111 | # Internal C++ flags that should not be changed by the user. 112 | override CXXFLAGS += \ 113 | -std=gnu++20 \ 114 | -fno-rtti \ 115 | -fno-exceptions \ 116 | $(SHARED_FLAGS) 117 | 118 | # Internal nasm flags that should not be changed by the user. 119 | override NASMFLAGS += \ 120 | -Wall \ 121 | -f elf64 122 | 123 | # Internal linker flags that should not be changed by the user. 124 | override LDFLAGS += \ 125 | -m elf_x86_64 \ 126 | --build-id=none \ 127 | -nostdlib \ 128 | -static \ 129 | -z max-page-size=0x1000 \ 130 | --gc-sections \ 131 | -T linker.ld 132 | 133 | # Use "find" to glob all *.c, *.cpp, *.S, and *.asm files in the tree and obtain the 134 | # object and header dependency file names. 135 | override SRCFILES := $(shell cd src && find -L * -type f | LC_ALL=C sort) 136 | override CFILES := $(filter %.c,$(SRCFILES)) 137 | override CXXFILES := $(filter %.cpp,$(SRCFILES)) 138 | override ASFILES := $(filter %.S,$(SRCFILES)) 139 | override NASMFILES := $(filter %.asm,$(SRCFILES)) 140 | override OBJ := $(addprefix obj/,$(CFILES:.c=.c.o) $(CXXFILES:.cpp=.cpp.o) $(ASFILES:.S=.S.o) $(NASMFILES:.asm=.asm.o)) 141 | override HEADER_DEPS := $(addprefix obj/,$(CFILES:.c=.c.d) $(CXXFILES:.cpp=.cpp.d) $(ASFILES:.S=.S.d)) 142 | 143 | # Default target. This must come first, before header dependencies. 144 | .PHONY: all 145 | all: bin/$(OUTPUT) 146 | 147 | # Include header dependencies. 148 | -include $(HEADER_DEPS) 149 | 150 | # Link rules for building the C compiler runtime. 151 | cc-runtime-x86_64/cc-runtime.a: GNUmakefile cc-runtime/* 152 | rm -rf cc-runtime-x86_64 153 | cp -r cc-runtime cc-runtime-x86_64 154 | $(MAKE) -C cc-runtime-x86_64 -f cc-runtime.mk \ 155 | CC="$(CC)" \ 156 | AR="$(AR)" \ 157 | CFLAGS="$(CFLAGS)" \ 158 | CPPFLAGS='-isystem ../freestnd-c-hdrs/x86_64/include -DCC_RUNTIME_NO_FLOAT' 159 | 160 | # Link rules for the final executable. 161 | bin/$(OUTPUT): GNUmakefile linker.ld $(OBJ) cc-runtime-x86_64/cc-runtime.a 162 | mkdir -p "$$(dirname $@)" 163 | $(LD) $(LDFLAGS) $(OBJ) cc-runtime-x86_64/cc-runtime.a -o $@ 164 | 165 | # Compilation rules for *.c files. 166 | obj/%.c.o: src/%.c GNUmakefile 167 | mkdir -p "$$(dirname $@)" 168 | $(CC) $(CFLAGS) $(CPPFLAGS_C) -c $< -o $@ 169 | 170 | # Compilation rules for *.cpp files. 171 | obj/%.cpp.o: src/%.cpp GNUmakefile 172 | mkdir -p "$$(dirname $@)" 173 | $(CXX) $(CXXFLAGS) $(CPPFLAGS_CXX) -c $< -o $@ 174 | 175 | # Compilation rules for *.S files. 176 | obj/%.S.o: src/%.S GNUmakefile 177 | mkdir -p "$$(dirname $@)" 178 | $(CC) $(CFLAGS) $(CPPFLAGS_C) -c $< -o $@ 179 | 180 | # Compilation rules for *.asm (nasm) files. 181 | obj/%.asm.o: src/%.asm GNUmakefile 182 | mkdir -p "$$(dirname $@)" 183 | nasm $(NASMFLAGS) $< -o $@ 184 | 185 | # Remove object files and the final executable. 186 | .PHONY: clean 187 | clean: 188 | rm -rf bin obj cc-runtime-x86_64 189 | 190 | # Remove everything built and generated including downloaded dependencies. 191 | .PHONY: distclean 192 | distclean: clean 193 | rm -rf freestnd-c-hdrs freestnd-cxx-hdrs cc-runtime src/limine.h 194 | 195 | # Install the final built executable to its final on-root location. 196 | .PHONY: install 197 | install: all 198 | install -d "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)" 199 | install -m 644 bin/$(OUTPUT) "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)/" 200 | 201 | # Try to undo whatever the "install" target did. 202 | .PHONY: uninstall 203 | uninstall: 204 | rm -f "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)/$(OUTPUT)" 205 | -rmdir "$(DESTDIR)$(PREFIX)/share/$(OUTPUT)" 206 | -------------------------------------------------------------------------------- /kernel/get-deps: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | set -ex 4 | 5 | srcdir="$(dirname "$0")" 6 | test -z "$srcdir" && srcdir=. 7 | 8 | cd "$srcdir" 9 | 10 | clone_repo_commit() { 11 | if test -d "$2/.git"; then 12 | git -C "$2" reset --hard 13 | git -C "$2" clean -fd 14 | if ! git -C "$2" checkout $3; then 15 | rm -rf "$2" 16 | fi 17 | else 18 | if test -d "$2"; then 19 | set +x 20 | echo "error: '$2' is not a Git repository" 21 | exit 1 22 | fi 23 | fi 24 | if ! test -d "$2"; then 25 | git clone $1 "$2" 26 | if ! git -C "$2" checkout $3; then 27 | rm -rf "$2" 28 | exit 1 29 | fi 30 | fi 31 | } 32 | 33 | download_by_hash() { 34 | DOWNLOAD_COMMAND="curl -Lo" 35 | if ! command -v $DOWNLOAD_COMMAND >/dev/null 2>&1; then 36 | DOWNLOAD_COMMAND="wget -O" 37 | if ! command -v $DOWNLOAD_COMMAND >/dev/null 2>&1; then 38 | set +x 39 | echo "error: Neither curl nor wget found" 40 | exit 1 41 | fi 42 | fi 43 | SHA256_COMMAND="sha256sum" 44 | if ! command -v $SHA256_COMMAND >/dev/null 2>&1; then 45 | SHA256_COMMAND="sha256" 46 | if ! command -v $SHA256_COMMAND >/dev/null 2>&1; then 47 | set +x 48 | echo "error: Cannot find sha256(sum) command" 49 | exit 1 50 | fi 51 | fi 52 | if ! test -f "$2" || ! $SHA256_COMMAND "$2" | grep $3 >/dev/null 2>&1; then 53 | rm -f "$2" 54 | mkdir -p "$2" && rm -rf "$2" 55 | $DOWNLOAD_COMMAND "$2" $1 56 | if ! $SHA256_COMMAND "$2" | grep $3 >/dev/null 2>&1; then 57 | set +x 58 | echo "error: Cannot download file '$2' by hash" 59 | echo "incorrect hash:" 60 | $SHA256_COMMAND "$2" 61 | rm -f "$2" 62 | exit 1 63 | fi 64 | fi 65 | } 66 | 67 | clone_repo_commit \ 68 | https://github.com/osdev0/freestnd-c-hdrs.git \ 69 | freestnd-c-hdrs \ 70 | 2a75fc37ab374e52bd5862adb785169cc26cdb50 71 | 72 | clone_repo_commit \ 73 | https://github.com/osdev0/freestnd-cxx-hdrs.git \ 74 | freestnd-cxx-hdrs \ 75 | 674dcb02b37d55c77f7171c5c46efd5cd3dc0f5f 76 | 77 | clone_repo_commit \ 78 | https://github.com/osdev0/cc-runtime.git \ 79 | cc-runtime \ 80 | 9c281448fe40498a6341d74f55c9af4f642c0b1d 81 | 82 | download_by_hash \ 83 | https://github.com/limine-bootloader/limine/raw/7cddb61183685d9bddd2eb13d42223d929c2abe6/limine.h \ 84 | src/include/lib/limine/limine.h \ 85 | c00e7d4cd6e2674eca481f978b64a7fb8c8479cc32c466ec35aad2207761bf01 86 | -------------------------------------------------------------------------------- /kernel/linker.ld: -------------------------------------------------------------------------------- 1 | /* Tell the linker that we want an x86_64 ELF64 output file */ 2 | OUTPUT_FORMAT(elf64-x86-64) 3 | 4 | /* We want the symbol kmain to be our entry point */ 5 | ENTRY(kmain_s) 6 | 7 | /* Define the program headers we want so the bootloader gives us the right */ 8 | /* MMU permissions; this also allows us to exert more control over the linking */ 9 | /* process. */ 10 | PHDRS 11 | { 12 | limine_requests PT_LOAD; 13 | text PT_LOAD; 14 | rodata PT_LOAD; 15 | data PT_LOAD; 16 | } 17 | 18 | SECTIONS 19 | { 20 | /* We want to be placed in the topmost 2GiB of the address space, for optimisations */ 21 | /* and because that is what the Limine spec mandates. */ 22 | /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */ 23 | /* that is the beginning of the region. */ 24 | . = 0xffffffff80000000; 25 | 26 | kernel_start = .; 27 | 28 | /* Define a section to contain the Limine requests and assign it to its own PHDR */ 29 | .limine_requests : { 30 | KEEP(*(.limine_requests_start)) 31 | KEEP(*(.limine_requests)) 32 | KEEP(*(.limine_requests_end)) 33 | } :limine_requests 34 | 35 | /* Move to the next memory page for .text */ 36 | . = ALIGN(CONSTANT(MAXPAGESIZE)); 37 | 38 | .text : { 39 | *(.text .text.*) 40 | } :text 41 | 42 | /* Move to the next memory page for .rodata */ 43 | . = ALIGN(CONSTANT(MAXPAGESIZE)); 44 | 45 | .rodata : { 46 | *(.rodata .rodata.*) 47 | } :rodata 48 | 49 | /* C++ is a language that allows for global constructors. In order to obtain the */ 50 | /* address of the ".init_array" section we need to define a symbol for it. */ 51 | .init_array : { 52 | __init_array = .; 53 | KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 54 | KEEP(*(.init_array .ctors)) 55 | __init_array_end = .; 56 | } :rodata 57 | 58 | /* Move to the next memory page for .data */ 59 | . = ALIGN(CONSTANT(MAXPAGESIZE)); 60 | 61 | .data : { 62 | *(.data .data.*) 63 | } :data 64 | 65 | /* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */ 66 | /* unnecessary zeros will be written to the binary. */ 67 | /* If you need, for example, .init_array and .fini_array, those should be placed */ 68 | /* above this. */ 69 | .bss : { 70 | *(.bss .bss.*) 71 | *(COMMON) 72 | } :data 73 | 74 | kernel_end = .; 75 | 76 | /* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */ 77 | /DISCARD/ : { 78 | *(.eh_frame*) 79 | *(.note .note.*) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/cpu/asm/gdt.asm: -------------------------------------------------------------------------------- 1 | global loadGDT 2 | loadGDT: 3 | lgdt [rdi] 4 | mov ax,0 5 | mov ds,ax 6 | mov es,ax 7 | mov fs,ax 8 | mov gs,ax 9 | mov ss,ax 10 | pop rdi 11 | mov rax,0x08 12 | push rax 13 | push rdi 14 | retfq 15 | 16 | global loadTSS 17 | loadTSS: 18 | mov ax,0x28 19 | ltr ax 20 | ret -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/cpu/data.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | cpudata_t* CpuData::Access() { 7 | cpudata_t* data = (cpudata_t*)__rdmsr(0xC0000101); 8 | if(!data) { 9 | data = new cpudata_t; 10 | __wrmsr(0xC0000101,(uint64_t)data); 11 | } 12 | return data; 13 | } -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/cpu/gdt.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | gdt_t original_gdt = { 13 | {0,0,0,0,0,0}, // 0x0 null 14 | {0,0,0,0x9a,0xa2,0}, // 0x08 64 bit code 15 | {0,0,0,0x92,0xa0,0}, // 0x10 64 bit data 16 | {0,0,0,0xF2,0,0}, // 0x18 user data 17 | {0,0,0,0xFA,0x20,0}, // 0x20 user code 18 | {0x68,0,0,0x89,0x20,0,0,0} // 0x28 tss 19 | }; 20 | 21 | extern "C" { 22 | 23 | extern void loadTSS(); 24 | extern void loadGDT(void* gdtr); 25 | 26 | } 27 | 28 | void GDT::Init() { 29 | cpudata_t* data = CpuData::Access(); 30 | String::memset(data,0,sizeof(cpudata_t)); 31 | String::memcpy(&data->gdt.gdt,&original_gdt,sizeof(gdt_t)); 32 | gdt_t* gdt = &data->gdt.gdt; 33 | tss_t* tss = &data->gdt.tss; 34 | uint64_t stack_1 = (uint64_t)PMM::VirtualBigAlloc(TSS_STACK_IN_PAGES); // for rsp[0] 35 | uint64_t stack_2 = (uint64_t)PMM::VirtualBigAlloc(TSS_STACK_IN_PAGES); // for ist 1 (exceptions) 36 | uint64_t stack_3 = (uint64_t)PMM::VirtualBigAlloc(TSS_STACK_IN_PAGES); // for ist 2 (some irqs) 37 | uint64_t stack_4 = (uint64_t)PMM::VirtualBigAlloc(TSS_STACK_IN_PAGES); // for ist 3 (timer) 38 | tss->rsp[0] = stack_1 + (TSS_STACK_IN_PAGES * PAGE_SIZE); 39 | tss->ist[0] = stack_2 + (TSS_STACK_IN_PAGES * PAGE_SIZE); 40 | tss->ist[1] = stack_3 + (TSS_STACK_IN_PAGES * PAGE_SIZE); 41 | tss->ist[2] = stack_4 + (TSS_STACK_IN_PAGES * PAGE_SIZE); 42 | tss->iopb_offsset = sizeof(tss); 43 | gdt->tss.baselow16 = (uint64_t)tss & 0xFFFF; 44 | gdt->tss.basemid8 = ((uint64_t)tss >> 16) & 0xFF; 45 | gdt->tss.basehigh8 = ((uint64_t)tss >> 24) & 0xFF; 46 | gdt->tss.baseup32 = (uint64_t)tss >> 32; 47 | Paging::alwaysMappedAdd(stack_1,TSS_STACK_IN_PAGES * PAGE_SIZE); 48 | Paging::alwaysMappedAdd(stack_2,TSS_STACK_IN_PAGES * PAGE_SIZE); 49 | Paging::alwaysMappedAdd(stack_3,TSS_STACK_IN_PAGES * PAGE_SIZE); 50 | Paging::alwaysMappedAdd(stack_4,TSS_STACK_IN_PAGES * PAGE_SIZE); 51 | gdt_pointer_t* gdtr = &data->gdt.gdtr; 52 | gdtr->size = sizeof(gdt_t) -1; 53 | gdtr->base = (uint64_t)gdt; 54 | 55 | loadGDT(gdtr); 56 | loadTSS(); 57 | } -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/cpu/lapic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | char __lapic_init = 0; 10 | 11 | void Lapic::Init() { 12 | __cli(); // if interrupts is enabled disable it 13 | __wrmsr(0x1B,__rdmsr(0x1B)); 14 | Paging::KernelMap(__rdmsr(0x1b) & 0xfffff000); 15 | Write(0xF0,0xFF | 0x100); 16 | Write(0x3E0,0x3); 17 | Write(0x320, 32 | (1 << 16)); 18 | Write(0x380,0xFFFFFFFF); 19 | HPET::Sleep(1000); 20 | uint64_t calibration_ticks = 0xFFFFFFFF - Read(0x390); 21 | Write(0x320,32 | (1 << 17)); 22 | Write(0x3E0,0x3); 23 | Write(0x380,calibration_ticks); 24 | __lapic_init = 1; 25 | } 26 | 27 | uint32_t Lapic::Read(uint32_t reg) { 28 | return *(volatile uint32_t*)(Base() + reg); 29 | } 30 | 31 | void Lapic::Write(uint32_t reg,uint32_t val) { 32 | *(volatile uint32_t*)(Base() + reg) = val; 33 | } 34 | 35 | void Lapic::EOI() { 36 | Write(0xB0,0); 37 | } 38 | 39 | uint32_t Lapic::ID() { 40 | if(!__lapic_init) 41 | return 0; 42 | return Read(0x20) >> 24; 43 | } 44 | 45 | uint64_t Lapic::Base() { 46 | return (uint64_t)HHDM::toVirt(__rdmsr(0x1b) & 0xfffff000); 47 | } -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/cpu/sse.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | uint64_t __sse_size = 0; 9 | char __sse_is_initializied = 0; 10 | char __sse_legacy_save = 0; 11 | 12 | uint64_t __sse_cr4_read() { 13 | uint64_t val; 14 | asm volatile("mov %%cr4, %0" : "=r"(val)); 15 | return val; 16 | } 17 | 18 | void __sse_cr4_write(uint64_t val) { 19 | asm volatile("mov %0, %%cr4" : : "r"(val) : "memory"); 20 | } 21 | 22 | uint64_t __sse_cr0_read() { 23 | uint64_t val; 24 | asm volatile("mov %%cr0, %0" : "=r"(val)); 25 | return val; 26 | } 27 | 28 | void __sse_cr0_write(uint64_t val) { 29 | asm volatile("mov %0, %%cr0" : : "r"(val) : "memory"); 30 | } 31 | 32 | 33 | void __sse_xsetbv(uint64_t val) { 34 | asm volatile("xsetbv" : : "a"(val), "d"(val >> 32),"c"(0) : "memory"); 35 | } 36 | 37 | uint64_t __sse_xgetbv() { 38 | uint32_t a,d; 39 | asm volatile("xgetbv" : "=a"(a),"=d"(d) : "c"(0) : "memory"); 40 | return ((uint64_t)d << 32) | a; 41 | } 42 | 43 | void __sse_xsave(void* buf) { 44 | uint64_t xcr0 = __sse_xgetbv(); 45 | asm volatile("xsave (%0)" :: "r"(buf), "a"(xcr0 & 0xFFFFFFFF), "d"(xcr0 >> 32), "c"(0): "memory"); 46 | } 47 | 48 | void __sse_xrstor(void* buf) { 49 | uint64_t xcr0 = __sse_xgetbv(); 50 | asm volatile("xrstor (%0)" :: "r"(buf), "a"(xcr0 & 0xFFFFFFFF), "d"(xcr0 >> 32), "c"(0): "memory"); 51 | } 52 | 53 | void SSE::Init() { 54 | uint32_t a,b,c,d; 55 | __cpuid(1,0,&a,&b,&c,&d); 56 | if(!__sse_is_initializied) { 57 | if(c & SSE_XSAVE_SUPPORT) { 58 | __cpuid(13,0,&a,&b,&c,&d); 59 | INFO("CPU Supports SSE_XSAVE with size %d\n",c); 60 | __sse_legacy_save = 0; 61 | __sse_size = c; 62 | } else { 63 | INFO("CPU Doesn't supports SSE_XSAVE\n"); 64 | __sse_legacy_save = 1; 65 | __sse_size = 512; 66 | } 67 | __sse_is_initializied = 1; 68 | } 69 | uint64_t cr4 = __sse_cr4_read(); 70 | 71 | cr4 |= DEFAULT_SSE_FLAGS; 72 | 73 | uint64_t cr0 = __sse_cr0_read(); 74 | 75 | cr0 &= ~(1 << 2); 76 | cr0 |= (1 << 1); 77 | 78 | __sse_cr0_write(cr0); 79 | 80 | uint64_t sse_control = 0; 81 | 82 | __sse_cr4_write(cr4); 83 | 84 | __cpuid(1,0,&a,&b,&c,&d); 85 | if(c & SSE_XSAVE_SUPPORT) 86 | cr4 |= SSE_XSAVE_CR4; 87 | else 88 | return; 89 | 90 | __sse_cr4_write(cr4); 91 | 92 | __cpuid(13,0,&a,&b,&c,&d); 93 | 94 | sse_control |= SSE_CONTROL_DEFAULT; 95 | SSE_CHECK_AND_SET((1 << 2)); 96 | SSE_CHECK_AND_SET((1 << 9)); 97 | SSE_CHECK_AND_SET((0b11 < 3)); 98 | SSE_CHECK_AND_SET((0b11 < 17)) 99 | SSE_CHECK_AND_SET((0b111 < 5)); 100 | 101 | __sse_xsetbv(sse_control); 102 | } 103 | 104 | uint64_t SSE::Size() { 105 | return __sse_size; 106 | } 107 | 108 | void SSE::Save(uint8_t* buf) { 109 | if(__sse_legacy_save) 110 | asm volatile("fxsave (%0)" : : "r"(buf)); 111 | else 112 | __sse_xsave(buf); 113 | } 114 | 115 | void SSE::Load(uint8_t* buf) { 116 | if(__sse_legacy_save) 117 | asm volatile("fxrstor (%0)" : : "r"(buf)); 118 | else 119 | __sse_xrstor(buf); 120 | } -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/asm/panic.asm: -------------------------------------------------------------------------------- 1 | extern CPanic 2 | 3 | global Panic 4 | Panic: 5 | cli 6 | push qword 0 7 | push rsp 8 | pushfq 9 | push qword 0 10 | push qword 0 11 | push qword 0 12 | push qword 0 13 | push r15 14 | push r14 15 | push r13 16 | push r12 17 | push r11 18 | push r10 19 | push r9 20 | push r8 21 | push rbp 22 | push rdi 23 | push rsi 24 | push rdx 25 | push rcx 26 | push rbx 27 | push rax 28 | mov rax,cr3 29 | push rax 30 | mov rsi,rsp 31 | jmp CPanic -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/asm/stubs.asm: -------------------------------------------------------------------------------- 1 | 2 | %macro isr_err_stub 1 3 | isr_stub_%+%1: 4 | cli 5 | cmp byte [rsp + 8],0x08 6 | jz .cont 7 | swapgs 8 | .cont: 9 | 10 | push qword (%+%1) 11 | jmp asmException 12 | cli 13 | hlt 14 | %endmacro 15 | 16 | %macro isr_no_err_stub 1 17 | isr_stub_%+%1: 18 | cli 19 | cmp byte [rsp + 8],0x08 20 | jz .cont 21 | swapgs 22 | .cont: 23 | 24 | push qword 0 25 | push qword (%+%1) 26 | jmp asmException 27 | cli 28 | hlt 29 | %endmacro 30 | 31 | global ignoreStub 32 | ignoreStub: 33 | iretq 34 | 35 | extern keyHandler 36 | 37 | global keyStub 38 | keyStub: 39 | cli 40 | 41 | cmp byte [rsp + 8],0x08 42 | jz .cont 43 | swapgs 44 | 45 | .cont: 46 | 47 | push qword 0 48 | push qword 0 49 | push r15 50 | push r14 51 | push r13 52 | push r12 53 | push r11 54 | push r10 55 | push r9 56 | push r8 57 | push rbp 58 | push rdi 59 | push rsi 60 | push rdx 61 | push rcx 62 | push rbx 63 | push rax 64 | mov rax,cr3 65 | push rax 66 | mov rdi,rsp 67 | call keyHandler 68 | pop rax 69 | mov cr3,rax 70 | pop rax 71 | pop rbx 72 | pop rcx 73 | pop rdx 74 | pop rsi 75 | pop rdi 76 | pop rbp 77 | pop r8 78 | pop r9 79 | pop r10 80 | pop r11 81 | pop r12 82 | pop r13 83 | pop r14 84 | pop r15 85 | add rsp,16 86 | 87 | cmp byte [rsp + 8],0x08 88 | jz .cont2 89 | swapgs 90 | 91 | 92 | .cont2: 93 | iretq 94 | 95 | extern CPUKernelPanic 96 | asmException: 97 | push r15 98 | push r14 99 | push r13 100 | push r12 101 | push r11 102 | push r10 103 | push r9 104 | push r8 105 | push rbp 106 | push rdi 107 | push rsi 108 | push rdx 109 | push rcx 110 | push rbx 111 | push rax 112 | mov rax,cr3 113 | push rax 114 | mov rdi,rsp 115 | jmp CPUKernelPanic 116 | 117 | isr_no_err_stub 0 118 | isr_no_err_stub 1 119 | isr_no_err_stub 2 120 | isr_no_err_stub 3 121 | isr_no_err_stub 4 122 | isr_no_err_stub 5 123 | isr_no_err_stub 6 124 | isr_no_err_stub 7 125 | isr_err_stub 8 126 | isr_no_err_stub 9 127 | isr_err_stub 10 128 | isr_err_stub 11 129 | isr_err_stub 12 130 | isr_err_stub 13 131 | isr_err_stub 14 132 | isr_no_err_stub 15 133 | isr_no_err_stub 16 134 | isr_err_stub 17 135 | isr_no_err_stub 18 136 | isr_no_err_stub 19 137 | isr_no_err_stub 20 138 | isr_no_err_stub 21 139 | isr_no_err_stub 22 140 | isr_no_err_stub 23 141 | isr_no_err_stub 24 142 | isr_no_err_stub 25 143 | isr_no_err_stub 26 144 | isr_no_err_stub 27 145 | isr_no_err_stub 28 146 | isr_no_err_stub 29 147 | isr_err_stub 30 148 | isr_no_err_stub 31 149 | 150 | global isrTable 151 | isrTable: 152 | %assign i 0 153 | %rep 32 154 | dq isr_stub_%+i 155 | %assign i i+1 156 | %endrep 157 | 158 | %macro irq_stub 1 159 | irq_stub_%+%1: 160 | cli 161 | cmp byte [rsp + 8],0x08 162 | jz .cont 163 | swapgs 164 | .cont: 165 | 166 | push qword 0 167 | push qword (%+%1) 168 | jmp irqStub 169 | cli 170 | hlt 171 | %endmacro 172 | 173 | irq_stub 0 174 | irq_stub 1 175 | irq_stub 2 176 | irq_stub 3 177 | irq_stub 4 178 | irq_stub 5 179 | irq_stub 6 180 | irq_stub 7 181 | irq_stub 8 182 | irq_stub 9 183 | irq_stub 10 184 | irq_stub 11 185 | irq_stub 12 186 | irq_stub 13 187 | irq_stub 14 188 | irq_stub 15 189 | irq_stub 16 190 | irq_stub 17 191 | irq_stub 18 192 | irq_stub 19 193 | irq_stub 20 194 | irq_stub 21 195 | irq_stub 22 196 | irq_stub 23 197 | irq_stub 24 198 | irq_stub 25 199 | irq_stub 26 200 | irq_stub 27 201 | irq_stub 28 202 | irq_stub 29 203 | irq_stub 30 204 | irq_stub 31 205 | irq_stub 32 206 | 207 | global irqTable 208 | irqTable: 209 | %assign i 0 210 | %rep 32 211 | dq irq_stub_%+i 212 | %assign i i+1 213 | %endrep 214 | 215 | extern irqHandler 216 | irqStub: 217 | push r15 218 | push r14 219 | push r13 220 | push r12 221 | push r11 222 | push r10 223 | push r9 224 | push r8 225 | push rbp 226 | push rdi 227 | push rsi 228 | push rdx 229 | push rcx 230 | push rbx 231 | push rax 232 | mov rax,cr3 233 | push rax 234 | mov rdi,rsp 235 | call irqHandler 236 | pop rax 237 | mov cr3,rax 238 | pop rax 239 | pop rbx 240 | pop rcx 241 | pop rdx 242 | pop rsi 243 | pop rdi 244 | pop rbp 245 | pop r8 246 | pop r9 247 | pop r10 248 | pop r11 249 | pop r12 250 | pop r13 251 | pop r14 252 | pop r15 253 | add rsp,16 254 | 255 | cmp byte [rsp + 8],0x08 256 | jz .cont2 257 | swapgs 258 | 259 | .cont2: 260 | iretq -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/idt.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | idt_entry_t idt[256]; 8 | uint8_t vectors_idt[256]; 9 | idtr_t idtr; 10 | 11 | idt_entry_t* IDT::SetEntry(uint8_t vec,void* base,uint8_t flags) { 12 | idt_entry_t* entry = &idt[vec]; 13 | entry->base_low = (uint64_t)base & 0xFFFF; 14 | entry->cs = 0x08; 15 | entry->ist = 0; 16 | entry->attr = flags; 17 | entry->base_mid = ((uint64_t)base >> 16) & 0xFFFF; 18 | entry->base_high = ((uint64_t)base >> 32) & 0xFFFFFFFF; 19 | entry->reserved = 0; 20 | vectors_idt[vec] = 1; 21 | return entry; 22 | } 23 | 24 | uint8_t IDT::AllocEntry() { 25 | for(uint8_t vec = 32;vec < 256;vec++) { 26 | if(!vectors_idt[vec]) 27 | return vec; 28 | } 29 | return 0; 30 | } 31 | 32 | void IDT::FreeEntry(uint8_t vec) { 33 | vectors_idt[vec] = 0; 34 | } 35 | 36 | extern void* isrTable[]; 37 | extern void* ignoreStub; 38 | 39 | void IDT::Load() { 40 | __asm__ volatile ("lidt %0" : : "m"(idtr)); 41 | } 42 | 43 | void IDT::Init() { 44 | 45 | String::memset(vectors_idt,0,sizeof(char) * 256); 46 | 47 | idtr.base = (uint64_t)&idt[0]; 48 | idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1; 49 | 50 | for(uint8_t vec = 0;vec <32;vec++){ 51 | idt_entry_t* entry = SetEntry(vec,isrTable[vec],0x8E); 52 | entry->ist = 1; 53 | } 54 | for(uint8_t vec = 32;vec < 255;vec++) { 55 | idt_entry_t* entry = SetEntry(vec,ignoreStub,0x8E); 56 | vectors_idt[vec] = 0; 57 | entry->ist = 2; 58 | } 59 | 60 | vectors_idt[32] = 1; 61 | __asm__ volatile ("lidt %0" : : "m"(idtr)); 62 | 63 | } -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/ioapic.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | struct acpi_madt_ioapic io_apics[24]; 16 | char ioapic_entries = 0; 17 | 18 | struct acpi_madt_interrupt_source_override iso[24]; 19 | char iso_entries = 0; 20 | 21 | void IOAPIC::Write(uint64_t phys_base,uint32_t reg,uint32_t value) { 22 | uint64_t virt = HHDM::toVirt(phys_base); 23 | *(volatile uint32_t*)virt = reg; 24 | *(volatile uint32_t*)(virt + 0x10) = value; 25 | } 26 | 27 | uint32_t IOAPIC::Read(uint64_t phys_base,uint32_t reg) { 28 | uint64_t virt = HHDM::toVirt(phys_base); 29 | *(volatile uint32_t*)virt = reg; 30 | return *(volatile uint32_t*)(virt + 0x10); 31 | } 32 | 33 | void __pic_disable() { 34 | IO::OUT(0x20,0x11,1); 35 | IO::OUT(0xA0,0x11,1); 36 | IO::OUT(0x21,0x20,1); 37 | IO::OUT(0xA1,0x28,1); 38 | IO::OUT(0x21,0x2,1); 39 | IO::OUT(0xA1,0x4,1); 40 | IO::OUT(0x21,1,1); 41 | IO::OUT(0xA1,1,1); 42 | IO::OUT(0x21,0xFF,1); 43 | IO::OUT(0xA1,0xFF,1); 44 | } 45 | 46 | void IOAPIC::Init() { 47 | __pic_disable(); 48 | struct uacpi_table apic_table; 49 | uacpi_status ret = uacpi_table_find_by_signature(ACPI_MADT_SIGNATURE,&apic_table); 50 | pAssert(ret == UACPI_STATUS_OK,"Can't find APIC Table"); 51 | 52 | struct acpi_madt* apic = (struct acpi_madt*)apic_table.virt_addr; 53 | struct acpi_entry_hdr* current = (struct acpi_entry_hdr*)apic->entries; 54 | 55 | char entry = 0; 56 | 57 | INFO("IOAPIC: Start: 0x%p, End: 0x%p\n",(uint64_t)apic->entries,(uint64_t)apic->entries + apic->hdr.length); 58 | 59 | while(1) { 60 | 61 | if((uint64_t)current >= (uint64_t)apic->entries + apic->hdr.length - sizeof(acpi_madt)) 62 | break; 63 | 64 | INFO("MADT Entry %d: Length: 0x%p, Type: 0x%p, Addr: 0x%p\n",entry,current->length,current->type,current); 65 | 66 | switch(current->type) { 67 | 68 | case ACPI_MADT_ENTRY_TYPE_IOAPIC: { 69 | struct acpi_madt_ioapic* current_ioapic = (acpi_madt_ioapic*)current; 70 | Paging::KernelMap(current_ioapic->address); 71 | INFO("IOAPIC %d: Base: 0x%p, GSI_Base: 0x%p\n",ioapic_entries,current_ioapic->address,current_ioapic->gsi_base); 72 | String::memcpy(&io_apics[ioapic_entries],current_ioapic,sizeof(acpi_madt_ioapic)); 73 | ioapic_entries++; 74 | break; 75 | } 76 | 77 | case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: { 78 | struct acpi_madt_interrupt_source_override* current_iso = (struct acpi_madt_interrupt_source_override*)current; 79 | INFO("ISO %d: Source: %d, GSI: %d, Bus: %d, Flags: 0x%p\n",iso_entries,current_iso->source,current_iso->gsi,current_iso->bus,current_iso->flags); 80 | String::memcpy(&iso[iso_entries],current_iso,sizeof(acpi_madt_interrupt_source_override)); 81 | iso_entries++; 82 | break; 83 | } 84 | 85 | default: 86 | break; 87 | 88 | } 89 | 90 | current = (acpi_entry_hdr*)((uint64_t)current + current->length); 91 | 92 | entry++; 93 | 94 | } 95 | 96 | } 97 | 98 | void IOAPIC::SetEntry(uint8_t vector,uint8_t irq,uint64_t flags,uint64_t lapic) { 99 | 100 | struct acpi_madt_ioapic* current_ioapic; 101 | struct acpi_madt_interrupt_source_override* current_iso; 102 | char is_success = 0; 103 | 104 | for(char i = 0;i < iso_entries;i++) { 105 | current_iso = &iso[i]; 106 | 107 | if(current_iso->source == irq) { 108 | is_success = 1; 109 | break; 110 | } 111 | 112 | } 113 | 114 | uint64_t ioapic_info = (lapic << 56) | flags | (vector & 0xFF); 115 | 116 | if(!is_success) 117 | current_iso = 0; 118 | 119 | is_success = 0; 120 | 121 | if(current_iso) { 122 | char polarity = (current_iso->flags & 0b11) == 0b11 ? 1 : 0; 123 | char mode = ((current_iso->flags >> 2) & 0b11) == 0b11 ? 1 : 0; 124 | ioapic_info = ((uint64_t)lapic << 56) | (mode << 15) | (polarity << 13) | (vector & 0xFF) | flags; 125 | } 126 | 127 | for(char i = 0;i < ioapic_entries;i++) { 128 | current_ioapic = &io_apics[i]; 129 | uint32_t apic_ver = Read(current_ioapic->address,1); 130 | uint32_t max_redirection_entries = apic_ver >> 16; 131 | if(current_ioapic->gsi_base <= irq && current_ioapic->gsi_base + max_redirection_entries > irq) { 132 | is_success = 1; 133 | break; 134 | } 135 | } 136 | 137 | pAssert(is_success == 1,"Can't find a free IOAPIC entry for IRQ"); 138 | 139 | uint32_t irq_register = ((irq - current_ioapic->gsi_base) * 2) + 0x10; 140 | Write(current_ioapic->address,irq_register,(uint32_t)ioapic_info); 141 | Write(current_ioapic->address,irq_register + 1,(uint32_t)((uint64_t)ioapic_info >> 32)); 142 | 143 | } -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/irq.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | irq_t irq_table[255]; 12 | uint16_t irq_ptr = 0; 13 | 14 | extern void* irqTable[]; 15 | 16 | extern "C" void irqHandler(int_frame_t* ctx) { 17 | 18 | __cli(); 19 | LogUnlock(); 20 | 21 | Paging::EnableKernel(); 22 | 23 | irq_table[ctx->vec].func(irq_table[ctx->vec].arg); 24 | 25 | if(ctx->cs == 0x20) { 26 | ctx->cs |= 3; 27 | ctx->ss |= 3; 28 | } 29 | 30 | if(ctx->ss == 0x18) { 31 | ctx->cs |= 3; 32 | ctx->ss |= 3; 33 | } 34 | 35 | Lapic::EOI(); 36 | 37 | } 38 | 39 | uint8_t IRQ::Create(uint16_t irq,uint8_t type,void (*func)(void* arg),void* arg,uint64_t flags) { 40 | 41 | uint8_t entry = IDT::AllocEntry(); 42 | idt_entry_t* idt_entry = IDT::SetEntry(entry,irqTable[irq_ptr],0x8E); 43 | if(type == IRQ_TYPE_LEGACY) // configure ioapic 44 | IOAPIC::SetEntry(entry,irq,flags,Lapic::ID()); 45 | 46 | 47 | idt_entry->ist = 2; 48 | 49 | irq_table[irq_ptr].arg = arg; 50 | irq_table[irq_ptr++].func = func; 51 | 52 | return entry; 53 | 54 | } -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/panic.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | typedef struct stackframe { 14 | struct stackframe* rbp; 15 | uint64_t rip; 16 | } __attribute__((packed)) stackframe_t; 17 | 18 | extern "C" void CPanic(const char* msg,int_frame_t* frame1) { 19 | __cli(); 20 | Paging::EnableKernel(); 21 | LogUnlock(); 22 | 23 | int_frame_t* frame = frame1; 24 | 25 | uint64_t cr2; 26 | asm volatile("mov %%cr2, %0" : "=r"(cr2) : : "memory"); 27 | 28 | NLog("\n\n\nKernel panic\n"); 29 | 30 | NLog("\nReason: %s\nCPU: %d\nVector: %d/0x%p (error code: %d/0x%p)\nProc: 0x%p, ID: %d, is_user: %d start_rsp: 0x%p stack_end: 0x%p proc_userspace_stack: 0x%p\n",msg,Lapic::ID(),frame->vec,frame->vec,frame->err_code,frame->err_code,CpuData::Access()->current,CpuData::Access()->current ? CpuData::Access()->current->id : 0,CpuData::Access()->current ? CpuData::Access()->current->user : 0,CpuData::Access()->current ? CpuData::Access()->current->stack_start : 0,CpuData::Access()->current ? (uint64_t)CpuData::Access()->current->stack : 0,CpuData::Access()->current ? (uint64_t)CpuData::Access()->current->user_stack_start : 0); 31 | NLog("Proc FS: 0x%p, Last syscall: %d, originalcr3: 0x%p\n",CpuData::Access()->current ? CpuData::Access()->current->fs_base : 0,CpuData::Access()->last_syscall,CpuData::Access()->current ? CpuData::Access()->current->nah_cr3 : 0); 32 | NLog("Registers dump\n"); 33 | NLog("RIP: 0x%p, SS: 0x%p, CS: 0x%p, RFLAGS: 0x%p, RSP: 0x%p\nRAX: 0x%p, RBX: 0x%p, RCX: 0x%p, RDX: 0x%p, RSI: 0x%p\nRDI: 0x%p, RBP: 0x%p, R8: 0x%p, R9: 0x%p, R10: 0x%p, CR2: 0x%p\nR11: 0x%p, R12: 0x%p, R13: 0x%p, R14: 0x%p, R15: 0x%p CR3: 0x%p\n", 34 | frame->rip,frame->ss,frame->cs,frame->rflags,frame->rsp,frame->rax,frame->rbx,frame->rcx,frame->rdx,frame->rsi,frame->rdi,frame->rbp,frame->r8,frame->r9,frame->r10,cr2,frame->r11,frame->r12,frame->r13,frame->r14,frame->r15,frame->cr3); 35 | 36 | NLog("Kernel cr3: 0x%p\n",Paging::KernelGet()); 37 | 38 | cpudata_t* data = CpuData::Access(); 39 | NLog("CPU Data: 0x%p, UserStack: 0x%p, KernelStack: 0x%p\n",CpuData::Access(),CpuData::Access()->user_stack,CpuData::Access()->kernel_stack); 40 | asm volatile("swapgs"); 41 | NLog("CPU Data: 0x%p, UserStack: 0x%p, KernelStack: 0x%p\n",CpuData::Access(),CpuData::Access()->user_stack,CpuData::Access()->kernel_stack); 42 | asm volatile("swapgs"); 43 | 44 | NLog("4k page allocation: 0x%p\n",PMM::Alloc()); 45 | 46 | process_t* proc = CpuData::Access()->current; 47 | 48 | if(!proc) {// exception occured in kernel, we can backtrace 49 | 50 | stackframe_t* rbp = (stackframe_t*)frame1->rbp; 51 | 52 | NLog("\nBack Trace\n"); 53 | for(unsigned int frame = 0; rbp && frame < 10; ++frame) 54 | { 55 | NLog("Address #%d: 0x%p\n",frame,rbp->rip); 56 | rbp = rbp->rbp; 57 | } 58 | 59 | } 60 | 61 | 62 | if(0){ 63 | 64 | VMM::Dump(proc); 65 | 66 | if(proc->parent_process) { 67 | process_t* parent = Process::ByID(proc->parent_process); 68 | if(parent) { 69 | frame = &parent->ctx; 70 | 71 | NLog("\nParent: id: %d, is_user: %d, start_rsp: 0x%p, stack_end: 0x%p\n",parent->id,parent->user,parent->stack_start,parent->stack); 72 | 73 | NLog("\nParent Registers dump\n"); 74 | NLog("RIP: 0x%p, SS: 0x%p, CS: 0x%p, RFLAGS: 0x%p, RSP: 0x%p\nRAX: 0x%p, RBX: 0x%p, RCX: 0x%p, RDX: 0x%p, RSI: 0x%p\nRDI: 0x%p, RBP: 0x%p, R8: 0x%p, R9: 0x%p, R10: 0x%p, CR2: 0x%p\nR11: 0x%p, R12: 0x%p, R13: 0x%p, R14: 0x%p, R15: 0x%p CR3: 0x%p\n", 75 | frame->rip,frame->ss,frame->cs,frame->rflags,frame->rsp,frame->rax,frame->rbx,frame->rcx,frame->rdx,frame->rsi,frame->rdi,frame->rbp,frame->r8,frame->r9,frame->r10,cr2,frame->r11,frame->r12,frame->r13,frame->r14,frame->r15,frame->cr3); 76 | 77 | NLog("Stack difference: 0x%p\n",((uint64_t)parent->stack - parent->ctx.rsp)); 78 | 79 | VMM::Dump(parent); 80 | 81 | } 82 | } 83 | } 84 | 85 | while(1) { 86 | __cli(); 87 | __hlt(); 88 | } 89 | } 90 | 91 | extern "C" void CPUKernelPanic(int_frame_t* frame) { 92 | CPanic("CPU Exception",frame); 93 | __cli(); 94 | __hlt(); 95 | } 96 | -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/scheduling/asm/scheduling_end.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | global schedulingEnd 4 | schedulingEnd: 5 | cli 6 | mov rsp,rdi 7 | 8 | mov cr3,rsi 9 | 10 | pop rax 11 | 12 | pop rax 13 | pop rbx 14 | pop rcx 15 | pop rdx 16 | pop rsi 17 | pop rdi 18 | pop rbp 19 | pop r8 20 | pop r9 21 | pop r10 22 | pop r11 23 | pop r12 24 | pop r13 25 | pop r14 26 | pop r15 27 | add rsp,16 28 | 29 | cmp byte [rsp + 8],0x08 30 | jz .end 31 | swapgs 32 | .end: 33 | iretq 34 | -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/scheduling/asm/scheduling_stub.asm: -------------------------------------------------------------------------------- 1 | 2 | extern schedulingSchedule 3 | 4 | global schedulingScheduleStack 5 | schedulingScheduleStack: 6 | mov rsp,qword [gs:8] 7 | jmp schedulingSchedule 8 | 9 | global schedulingStub 10 | schedulingStub: 11 | 12 | cli 13 | cmp byte [rsp + 8],0x08 14 | jz .continue 15 | swapgs 16 | .continue: 17 | 18 | push qword 0 19 | push qword 0 20 | push r15 21 | push r14 22 | push r13 23 | push r12 24 | push r11 25 | push r10 26 | push r9 27 | push r8 28 | push rbp 29 | push rdi 30 | push rsi 31 | push rdx 32 | push rcx 33 | push rbx 34 | push rax 35 | mov rax,cr3 36 | push rax 37 | mov rdi,rsp 38 | cld 39 | jmp schedulingSchedule -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/syscalls/asm/syscall.asm: -------------------------------------------------------------------------------- 1 | 2 | extern c_syscall_handler 3 | 4 | global syscall_handler 5 | syscall_handler: 6 | cli 7 | swapgs 8 | mov qword [gs:0],rsp ;save stack 9 | mov rsp, qword [gs:8] 10 | push qword (0x20 | 3) 11 | push qword [gs:0] 12 | push qword r11 13 | push qword (0x18 | 3) 14 | push qword rcx 15 | push qword 0 16 | push qword 0 17 | push r15 18 | push r14 19 | push r13 20 | push r12 21 | push r11 22 | push r10 23 | push r9 24 | push r8 25 | push rbp 26 | push rdi 27 | push rsi 28 | push rdx 29 | push rcx 30 | push rbx 31 | push rax 32 | mov rax,cr3 33 | push rax 34 | mov rdi,rsp 35 | call c_syscall_handler 36 | pop rax 37 | mov cr3,rax 38 | pop rax 39 | pop rbx 40 | pop rcx 41 | pop rdx 42 | pop rsi 43 | pop rdi 44 | pop rbp 45 | pop r8 46 | pop r9 47 | pop r10 48 | pop r11 49 | pop r12 50 | pop r13 51 | pop r14 52 | pop r15 53 | mov rsp,[gs:0] 54 | swapgs 55 | o64 sysret 56 | 57 | global syscall_end 58 | syscall_end: 59 | mov rsp,rdi 60 | pop rax 61 | mov cr3,rax 62 | pop rax 63 | pop rbx 64 | pop rcx 65 | pop rdx 66 | pop rsi 67 | pop rdi 68 | pop rbp 69 | pop r8 70 | pop r9 71 | pop r10 72 | pop r11 73 | pop r12 74 | pop r13 75 | pop r14 76 | pop r15 77 | add rsp,40 78 | pop rsp 79 | swapgs 80 | o64 sysret 81 | 82 | global syscall_read_stage_2_asm 83 | extern syscall_read_stage_2 84 | 85 | syscall_read_stage_2_asm: 86 | mov rsp,rdi 87 | mov rdi,rsi 88 | mov rsi,rdx 89 | jmp syscall_read_stage_2 90 | 91 | global syscall_waitpid_stage2_asm 92 | extern syscall_waitpid_stage2 93 | syscall_waitpid_stage2_asm: 94 | mov rsp,rdi 95 | mov rdi,rsi 96 | mov rsi,rdx 97 | jmp syscall_waitpid_stage2 -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/interrupts/syscalls/ipc/fd.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | char fd_lock = 0; 12 | 13 | int FD::Create(process_t* proc,char is_pipe) { 14 | 15 | spinlock_lock(&fd_lock); 16 | 17 | // search for non allocated fd 18 | 19 | fd_t* last = (fd_t*)proc->last_fd; 20 | 21 | fd_t* current = (fd_t*)proc->start_fd; 22 | 23 | char is_success = 0; 24 | 25 | while(current) { 26 | if(current->type == FD_NONE) { 27 | is_success = 1; 28 | break; 29 | } 30 | current = current->next; 31 | } 32 | 33 | if(!is_success) { 34 | current = (fd_t*)PMM::VirtualAlloc(); 35 | current->index = last->index + 1; 36 | last->next = current; 37 | current->parent = last; 38 | proc->last_fd = (char*)current; 39 | } 40 | 41 | current->pipe.buffer = 0; 42 | current->pipe.buffer_size = 0; 43 | current->pipe.is_received = 0; 44 | current->pipe.type = PIPE_WAIT; 45 | current->is_pipe_pointer = 0; 46 | 47 | current->pipe.is_used = 0; 48 | 49 | String::memset(¤t->pipe.termios,0,sizeof(termios_t)); 50 | 51 | current->type = is_pipe ? FD_PIPE : FD_FILE; 52 | current->proc = proc; 53 | current->seek_offset = 0; 54 | 55 | if(is_pipe) { 56 | current->pipe.buffer = (char*)PMM::VirtualBigAlloc(16); 57 | String::memset(current->pipe.buffer,0,16 * 4096); 58 | } 59 | 60 | spinlock_unlock(&fd_lock); 61 | return current->index; 62 | 63 | } 64 | 65 | fd_t* FD::Search(process_t* proc,int index) { 66 | fd_t* current = (fd_t*)proc->start_fd; 67 | while(current) { 68 | if(current->index == index) { 69 | return current; 70 | } 71 | current = current->next; 72 | } 73 | return 0; 74 | } -------------------------------------------------------------------------------- /kernel/src/arch/x86_64/main.asm: -------------------------------------------------------------------------------- 1 | 2 | extern kmain 3 | global kmain_s 4 | kmain_s: 5 | cli 6 | mov rsp,stack_end 7 | jmp kmain 8 | 9 | section .bss 10 | 11 | stack_start: 12 | resb 1024*1024*128 13 | stack_end: -------------------------------------------------------------------------------- /kernel/src/drivers/cmos/cmos.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | static inline uint8_t cmos_read(uint8_t reg) { 7 | IO::OUT(CMOS_ADDRESS, reg,1); 8 | return IO::IN(CMOS_DATA,1); 9 | } 10 | 11 | static inline uint8_t bcd_to_binary(uint8_t bcd) { 12 | return (bcd & 0x0F) + ((bcd / 16) * 10); 13 | } 14 | 15 | uint8_t CMOS::Second() { 16 | uint8_t seconds = cmos_read(CMOS_SECONDS); 17 | return bcd_to_binary(seconds); 18 | } 19 | 20 | uint8_t CMOS::Minute() { 21 | uint8_t minutes = cmos_read(CMOS_MINUTES); 22 | return bcd_to_binary(minutes); 23 | } 24 | 25 | uint8_t CMOS::Hour() { 26 | uint8_t hours = cmos_read(CMOS_HOURS); 27 | return bcd_to_binary(hours); 28 | } 29 | 30 | uint8_t CMOS::Day() { 31 | uint8_t day = cmos_read(CMOS_DAY); 32 | return bcd_to_binary(day); 33 | } 34 | 35 | uint8_t CMOS::Month() { 36 | uint8_t month = cmos_read(CMOS_MONTH); 37 | return bcd_to_binary(month); 38 | } 39 | 40 | uint16_t CMOS::Year() { 41 | uint8_t year = cmos_read(CMOS_YEAR); 42 | return 2000 + bcd_to_binary(year); 43 | } -------------------------------------------------------------------------------- /kernel/src/drivers/hpet/hpet.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | char hpet_is_32_bit; 16 | uint64_t hpet_base; 17 | uint32_t hpet_clock_period; 18 | uint32_t hpet_clock_period_nano; 19 | 20 | void HPET::Init() { 21 | uacpi_table hpet; 22 | uacpi_status ret = uacpi_table_find_by_signature("HPET",&hpet); 23 | pAssert(ret == UACPI_STATUS_OK,"HPET is disabled"); 24 | struct acpi_hpet* hpet_table = ((struct acpi_hpet*)hpet.virt_addr); 25 | hpet_base = HHDM::toVirt(hpet_table->address.address); 26 | Paging::KernelMap(hpet_table->address.address); 27 | *(volatile uint64_t*)(hpet_base + 0x10) |= 1; 28 | hpet_is_32_bit = (*(volatile uint64_t*)hpet_base & (1 << 13)) ? 0 : 1; 29 | hpet_clock_period = *(volatile uint32_t*)(hpet_base + 4); 30 | hpet_clock_period_nano = hpet_clock_period / 1000000; 31 | INFO("%s HPET: 0x%p\n",hpet_is_32_bit ? "32 Bit" : "64 Bit",hpet_base); 32 | } 33 | 34 | uint64_t hpet_counter() { 35 | return hpet_is_32_bit ? *(volatile uint32_t*)(hpet_base + 0xf0) : *(volatile uint64_t*)(hpet_base + 0xf0); 36 | } 37 | 38 | uint64_t HPET::NanoCurrent() { 39 | return hpet_counter() * hpet_clock_period_nano; 40 | } 41 | 42 | void HPET::Sleep(uint64_t usec) { 43 | uint64_t start = hpet_counter(); 44 | uint64_t nanoseconds = usec * 1000; 45 | while((hpet_counter() - start) * hpet_clock_period_nano < nanoseconds) { 46 | __nop(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /kernel/src/drivers/io/io.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | uint32_t IO::IN(uint16_t port,uint8_t bytewidth) { 6 | uint32_t result; 7 | uint16_t result16; 8 | uint8_t result8; 9 | switch(bytewidth) { 10 | case 1: 11 | asm volatile("inb %1,%0" : "=a"(result8) : "Nd"(port)); 12 | return result8; 13 | case 2: 14 | asm volatile("inw %1,%0" : "=a"(result16) : "Nd"(port)); 15 | return result16; 16 | case 4: 17 | asm volatile("inl %1,%0" : "=a"(result) : "Nd"(port)); 18 | return result; 19 | default: 20 | return 0; 21 | } 22 | } 23 | 24 | void IO::OUT(uint16_t port,uint32_t value,uint8_t bytewidth) { 25 | uint8_t value8 = value; 26 | uint16_t value16 = value; 27 | switch (bytewidth) 28 | { 29 | case 1: 30 | asm volatile("outb %0,%1" : : "a"(value8), "Nd"(port)); 31 | return; 32 | 33 | case 2: 34 | asm volatile("outw %0,%1" : : "a"(value16), "Nd"(port)); 35 | return; 36 | 37 | case 4: 38 | asm volatile("outl %0,%1" : : "a"(value), "Nd"(port)); 39 | return; 40 | 41 | } 42 | } -------------------------------------------------------------------------------- /kernel/src/drivers/pci/pci.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | char pci_spinlock = 0; 8 | 9 | pci_driver_t pci_drivers[256]; 10 | 11 | uint32_t pci_read_config32(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset) { 12 | uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset); 13 | IO::OUT(0xCF8, address,4); 14 | return IO::IN(0xCFC,4); 15 | } 16 | 17 | uint16_t pci_read_config16(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset) { 18 | uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset & 0xfc); 19 | IO::OUT(0xCF8, address,4); 20 | return (uint16_t)((IO::IN(0xCFC,4) >> ((offset & 2) * 8)) & 0xffff); 21 | } 22 | 23 | uint8_t pci_read_config8(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset) { 24 | uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset); 25 | IO::OUT(0xCF8, address,4); 26 | return (uint8_t)((IO::IN(0xCFC,4) >> ((offset & 3) * 8)) & 0xff); 27 | } 28 | 29 | void pci_write_config32(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset, uint32_t value) { 30 | uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset); 31 | IO::OUT(0xCF8, address,4); 32 | IO::OUT(0xCFC, value,4); 33 | } 34 | 35 | void pci_write_config16(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset, uint32_t value) { 36 | uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset & 0xfc); 37 | IO::OUT(0xCF8, address,4); 38 | IO::OUT(0xCFC,(IO::IN(0xCFC,4) & ~(0xffff << ((offset & 2) * 8))) | (value << ((offset & 2) * 8)),4); 39 | } 40 | 41 | void pci_write_config8(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset, uint8_t value) { 42 | uint32_t address = (1 << 31) | (bus << 16) | (num << 11) | (function << 8) | (offset & 0xfc); 43 | IO::OUT(0xCF8, address,4); 44 | IO::OUT(0xCFC, ((IO::IN(0xCFC,4) & ~(0xFF << (offset & 3))) | (value << ((offset & 3) * 8))),4); 45 | } 46 | 47 | uint32_t PCI::IN(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset,uint8_t bytewidth) { 48 | uint32_t value = 0; 49 | spinlock_lock(&pci_spinlock); 50 | switch(bytewidth) { 51 | case 1: 52 | value = pci_read_config8(bus,num,function,offset); 53 | break; 54 | case 2: 55 | value = pci_read_config16(bus,num,function,offset); 56 | break; 57 | case 4: 58 | value = pci_read_config32(bus,num,function,offset); 59 | break; 60 | default: 61 | break; 62 | } 63 | 64 | spinlock_unlock(&pci_spinlock); 65 | 66 | return value; 67 | 68 | } 69 | 70 | void PCI::OUT(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset,uint32_t value,uint8_t bytewidth) { 71 | spinlock_lock(&pci_spinlock); 72 | switch(bytewidth) { 73 | case 1: 74 | pci_write_config8(bus,num,function,offset,(uint8_t)value); 75 | break; 76 | case 2: 77 | pci_write_config16(bus,num,function,offset,(uint16_t)value); 78 | break; 79 | case 4: 80 | pci_write_config32(bus,num,function,offset,(uint32_t)value); 81 | break; 82 | default: 83 | break; 84 | } 85 | spinlock_unlock(&pci_spinlock); 86 | } 87 | 88 | pci_t __pci_load(uint8_t bus, uint8_t num, uint8_t function) { 89 | pci_t pciData; 90 | uint16_t *p = (uint16_t *)&pciData; 91 | for (uint8_t i = 0; i < 32; i++) { 92 | p[i] = pci_read_config16(bus, num, function, i * 2); 93 | } 94 | return pciData; 95 | } 96 | 97 | uint8_t PCI::Reg(void (*pcidrv)(pci_t, uint8_t, uint8_t, uint8_t), uint8_t _class, uint8_t subclass) { 98 | for (uint16_t i = 0; i < 256; i++) { 99 | if (!pci_drivers[i].used) { 100 | pci_drivers[i].used = true; 101 | pci_drivers[i]._class = _class; 102 | pci_drivers[i].subclass = subclass; 103 | pci_drivers[i].pcidrv = pcidrv; 104 | return true; 105 | } 106 | } 107 | return false; 108 | } 109 | 110 | void __pci_launch(pci_t pci, uint8_t bus, uint8_t device, uint8_t function) { 111 | for (uint16_t i = 0; i < 256; i++) { 112 | if (pci_drivers[i].used && pci_drivers[i]._class == pci._class && pci_drivers[i].subclass == pci.subclass) { 113 | pci_drivers[i].pcidrv(pci, bus, device, function); 114 | return; 115 | } 116 | } 117 | } 118 | 119 | void PCI::Init() { 120 | pci_t c_pci; 121 | for (uint16_t bus = 0; bus < 256; bus++) { 122 | c_pci = __pci_load(bus, 0, 0); 123 | if (c_pci.vendorID != 0xFFFF) { 124 | for (uint8_t device = 0; device < 32; device++) { 125 | c_pci = __pci_load(bus, device, 0); 126 | if (c_pci.vendorID != 0xFFFF) { 127 | __pci_launch(c_pci, bus, device, 0); 128 | for (uint8_t function = 1; function < 8; function++) { 129 | pci_t pci = __pci_load(bus, device, function); 130 | if (pci.vendorID != 0xFFFF) { 131 | __pci_launch(pci, bus, device, function); 132 | } 133 | } 134 | } 135 | } 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /kernel/src/drivers/power_button/power_button.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void PowerButton::Hook( uacpi_interrupt_ret (*func)(uacpi_handle ctx)) { 10 | uacpi_status ret = uacpi_install_fixed_event_handler(UACPI_FIXED_EVENT_POWER_BUTTON,func,UACPI_NULL); 11 | Assert(ret == UACPI_STATUS_OK,"Can't install power button !"); 12 | } 13 | -------------------------------------------------------------------------------- /kernel/src/drivers/ps2keyboard/ps2keyboard.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void (*keyboard_handler)(); 15 | char kmap[255] = { 16 | 17 | '\0', '\0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 18 | (char)127, '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 19 | '\n', '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 20 | '\0', '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', ' ', '*', 21 | '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 22 | '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', '\0', 23 | '\0' 24 | 25 | }; 26 | 27 | char __shift_pressed = 0; 28 | 29 | char __ps_2_to_upper(char c) { 30 | 31 | if (c >= 'a' && c <= 'z') { 32 | return c - ('a' - 'A'); 33 | 34 | } 35 | 36 | switch (c) { 37 | 38 | case '1': return '!'; 39 | case '2': return '@'; 40 | case '3': return '#'; 41 | case '4': return '$'; 42 | case '5': return '%'; 43 | case '6': return '^'; 44 | case '7': return '&'; 45 | case '8': return '*'; 46 | case '9': return '('; 47 | case '0': return ')'; 48 | case '-': return '_'; 49 | case '=': return '+'; 50 | case '`': return '~'; 51 | case '.': return '>'; 52 | case ',': return '<'; 53 | case '\\': return '|'; 54 | 55 | default: break; 56 | 57 | } 58 | 59 | if (c == '\'') { 60 | return '\"'; 61 | } 62 | 63 | return c; 64 | } 65 | 66 | #define SHIFT_PRESSED 0x2A 67 | #define SHIFT_RELEASED 0xAA 68 | #define CTRL_PRESSED 29 69 | #define CTRL_RELEASED 157 70 | #define CTRL_PRESSED_OFFSET 96 71 | 72 | char __ctrl_pressed = 0; 73 | 74 | char __ps2_read(char keycodeps2) { 75 | 76 | unsigned char keycode = keycodeps2; 77 | 78 | if(keycode == SHIFT_PRESSED) 79 | __shift_pressed = 1; 80 | 81 | if(keycode == SHIFT_RELEASED) 82 | __shift_pressed = 0; 83 | 84 | if(keycode == CTRL_PRESSED) 85 | __ctrl_pressed = 1; 86 | else if(keycode == CTRL_RELEASED) 87 | __ctrl_pressed = 0; 88 | 89 | 90 | if(keycode <= 0x58 && keycode != CTRL_PRESSED) { 91 | keycode = kmap[keycode]; 92 | 93 | if(__shift_pressed && !__ctrl_pressed) 94 | keycode = __ps_2_to_upper(keycode); 95 | 96 | if(__ctrl_pressed) 97 | keycode = keycode - CTRL_PRESSED_OFFSET; 98 | 99 | } 100 | 101 | if(keycode & (1 << 7)) 102 | return '\0'; 103 | 104 | return keycode; 105 | 106 | return 0; 107 | 108 | } 109 | 110 | char __last_key = 0; 111 | 112 | int kbd_read(char* buffer,long hint_size) { 113 | 114 | if(!buffer) return 10; 115 | 116 | *buffer = __last_key; 117 | 118 | return 0; 119 | } 120 | 121 | ps2keyboard_pipe_struct_t* head_ps2pipe; 122 | ps2keyboard_pipe_struct_t* last_ps2pipe; 123 | 124 | ps2keyboard_pipe_struct_t* __kbd_allocate_pipe() { 125 | 126 | if(!head_ps2pipe) { 127 | head_ps2pipe = new ps2keyboard_pipe_struct_t; 128 | head_ps2pipe->is_used_anymore = 0; 129 | } 130 | 131 | ps2keyboard_pipe_struct_t* current = head_ps2pipe; 132 | while(current) { 133 | if(!current->is_used_anymore) 134 | break; 135 | current = current->next; 136 | } 137 | 138 | if(!current) { 139 | current = new ps2keyboard_pipe_struct_t; 140 | last_ps2pipe->next = current; 141 | last_ps2pipe = current; 142 | } 143 | 144 | return current; 145 | 146 | 147 | } 148 | 149 | void __kbd_send_ipc(uint8_t keycode) { 150 | 151 | if(!head_ps2pipe) { 152 | head_ps2pipe = new ps2keyboard_pipe_struct_t; 153 | head_ps2pipe->is_used_anymore = 0; 154 | } 155 | 156 | ps2keyboard_pipe_struct_t* current = head_ps2pipe; 157 | while(current) { 158 | 159 | if(current->is_used_anymore && current->pipe) { 160 | current->pipe->buffer[0] = keycode; 161 | current->pipe->buffer_size = 1; 162 | if(current->pipe->type == PIPE_WAIT) 163 | current->is_used_anymore = 0; 164 | current->pipe->is_received = 0; 165 | } 166 | current = current->next; 167 | } 168 | 169 | } 170 | 171 | int kbd_askforpipe(pipe_t* pipe) { 172 | 173 | ps2keyboard_pipe_struct_t* pip = __kbd_allocate_pipe(); 174 | 175 | pip->pipe = pipe; 176 | pip->is_used_anymore = 1; 177 | pip->pipe->type = PIPE_INSTANT; 178 | pip->pipe->is_used = 1; 179 | 180 | return 0; 181 | 182 | } 183 | 184 | short PS2Keyboard::Get() { 185 | char status = IO::IN(0x64,1); 186 | 187 | if(status & 0x01) { 188 | uint8_t keycode = IO::IN(0x60,1); 189 | 190 | if(keycode == SHIFT_PRESSED) 191 | __shift_pressed = 1; 192 | 193 | if(keycode == SHIFT_RELEASED) 194 | __shift_pressed = 0; 195 | 196 | __last_key = keycode; 197 | uint8_t vt100_keycode = __ps2_read(keycode); 198 | if(vt100_keycode) { 199 | __tty_receive_ipc(vt100_keycode); 200 | } 201 | 202 | __kbd_send_ipc(keycode); 203 | 204 | return __last_key; 205 | 206 | } 207 | 208 | return 0; 209 | 210 | } 211 | 212 | void ps2_keyboard_handler(void* arg) { 213 | PS2Keyboard::Get(); 214 | } 215 | 216 | static uacpi_iteration_decision match_ps2k(void *user, uacpi_namespace_node *node, uacpi_u32 depth) 217 | { 218 | 219 | uacpi_resources *kb_res; 220 | 221 | uacpi_status ret = uacpi_get_current_resources(node, &kb_res); 222 | if (uacpi_unlikely_error(ret)) { 223 | INFO("PS/2 Keyboard is not initializied\n"); 224 | return UACPI_ITERATION_DECISION_NEXT_PEER; 225 | } 226 | 227 | uacpi_resource* current_res; 228 | int i = 0; 229 | 230 | for(current_res = &kb_res->entries[0];i < kb_res->length;i += current_res->length) { 231 | 232 | current_res = UACPI_NEXT_RESOURCE(current_res); 233 | if(!current_res->length) 234 | break; 235 | 236 | if(current_res->type == UACPI_RESOURCE_TYPE_IRQ) { 237 | for(int v = 0; v < current_res->irq.num_irqs;v++) { 238 | INFO("Found PS/2 Keyboard IRQ %d !\n",current_res->irq.irqs[v]); 239 | 240 | int vector = IRQ::Create(current_res->irq.irqs[v],IRQ_TYPE_LEGACY,ps2_keyboard_handler,0,(current_res->irq.polarity ? 1 : 0 << 13)); 241 | INFO("Registered PS/2 Keyboard IRQ at %d\n",vector); 242 | 243 | } 244 | } 245 | 246 | } 247 | 248 | devfs_reg_device("/kbd",0,kbd_read,kbd_askforpipe,0,0); 249 | 250 | INFO("PS/2 Keyboard is initializied !\n"); 251 | 252 | uacpi_free_resources(kb_res); 253 | UACPI_RESOURCE_TYPE_IRQ; 254 | 255 | return UACPI_ITERATION_DECISION_CONTINUE; 256 | } 257 | 258 | void PS2Keyboard::EOI() { 259 | Lapic::EOI(); 260 | } 261 | 262 | 263 | void PS2Keyboard::Init(void (*key)()) 264 | { 265 | keyboard_handler = key; 266 | uacpi_find_devices(PS2K_PNP_ID, match_ps2k, NULL); 267 | } -------------------------------------------------------------------------------- /kernel/src/drivers/serial/serial.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | char serial_spinlock = 0; 12 | 13 | void Serial::Init() { 14 | spinlock_lock(&serial_spinlock); 15 | IO::OUT(COM1 + 1,0,1); 16 | IO::OUT(COM1 + 3,(1 << 7),1); 17 | IO::OUT(COM1 + 1,0,1); 18 | IO::OUT(COM1,12,1); 19 | IO::OUT(COM1 + 3,0,1); 20 | IO::OUT(COM1 + 3,(1 << 1) | (1 << 0),1); 21 | IO::OUT(COM1 + 4,(1 << 0) | (1 << 2) | (1 << 3),1); 22 | IO::OUT(COM1 + 4,(1 << 1) | (1 << 2) | (1 << 3) | (1 << 4),1); 23 | IO::OUT(COM1,0xAE,1); 24 | if(IO::IN(COM1,1) != 0xAE) { 25 | spinlock_unlock(&serial_spinlock); 26 | return; 27 | } 28 | IO::OUT(COM1 + 4,(1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),1); 29 | spinlock_unlock(&serial_spinlock); 30 | } 31 | 32 | void __serial_process_fetch() { 33 | 34 | IO::IN(COM1,1); 35 | while(1) { 36 | uint8_t key = Serial::Read(); 37 | if(key && key != 255) // idk why but it spamming with 255 to console 38 | __tty_receive_ipc(key); 39 | } 40 | } 41 | 42 | uint8_t Serial::Read() { 43 | //spinlock_lock(&serial_spinlock); 44 | while(!(IO::IN(COM1 + 5,1) & 1)) {} 45 | uint8_t value = IO::IN(COM1,1); 46 | //spinlock_unlock(&serial_spinlock); 47 | return value; 48 | } 49 | 50 | void Serial::Write(uint8_t data) { 51 | spinlock_lock(&serial_spinlock); 52 | while(IO::IN(COM1 + 5,1) & (1 << 5) == 0) {} 53 | IO::OUT(COM1,data,1); 54 | spinlock_unlock(&serial_spinlock); 55 | } 56 | 57 | void Serial::WriteArray(uint8_t* data,uint64_t len) { 58 | for(uint64_t i = 0; i < len;i++) { 59 | Write(data[i]); 60 | } 61 | } 62 | 63 | void Serial::WriteString(const char* str) { 64 | Serial::WriteArray((uint8_t*)str,String::strlen((char*)str)); 65 | } 66 | 67 | void Serial::printf(char* format, ...) { 68 | va_list args; 69 | va_start(args, format); 70 | int i = 0; 71 | while (i < String::strlen(format)) { 72 | if (format[i] == '%') { 73 | i++; 74 | char buffer[256]; 75 | if (format[i] == 'd' || format[i] == 'i') { 76 | String::itoa(va_arg(args, uint64_t), buffer,10); 77 | buffer[255] = 0; 78 | WriteString(buffer); 79 | } else if (format[i] == 's') { 80 | WriteString(va_arg(args, char*)); 81 | } else if (format[i] == 'p') { 82 | String::itoa(va_arg(args,uint64_t),buffer,16); 83 | buffer[255] = 0; 84 | WriteString(buffer); 85 | } 86 | } else { 87 | Write(format[i]); 88 | } 89 | i++; 90 | } 91 | va_end(args); 92 | } 93 | -------------------------------------------------------------------------------- /kernel/src/generic/VFS/devfs.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | devfs_dev_t* head_dev = 0; 12 | devfs_dev_t* last_dev = 0; 13 | 14 | devfs_dev_t* devfs_find_dev(const char* loc) { 15 | 16 | devfs_dev_t* dev = head_dev; 17 | while(dev) { 18 | 19 | if(!String::strcmp(loc,dev->loc)) { 20 | return dev; 21 | } 22 | 23 | dev = dev->next; 24 | } 25 | 26 | return 0; 27 | 28 | } 29 | 30 | int devfs_read(char* buffer,char* filename,long hint_size) { 31 | 32 | if(!filename) return 1; 33 | if(!buffer) return 2; 34 | 35 | devfs_dev_t* dev = devfs_find_dev(filename); 36 | 37 | if(!dev) return 3; 38 | if(!dev->read) return 4; 39 | 40 | return dev->read(buffer,hint_size); 41 | } 42 | 43 | int devfs_write(char* buffer,char* filename,uint64_t size,char is_symlink_path,uint64_t offset) { 44 | if(!filename) return 1; 45 | if(!buffer) return 2; 46 | if(!size) return 3; 47 | 48 | devfs_dev_t* dev = devfs_find_dev(filename); 49 | 50 | if(!dev) return 4; 51 | if(!dev->write) return 5; 52 | 53 | return dev->write(buffer,size); 54 | 55 | } 56 | 57 | int devfs_ioctl(char* filename,unsigned long request, void *arg, int *result) { 58 | if(!filename) return 1; 59 | 60 | devfs_dev_t* dev = devfs_find_dev(filename); 61 | 62 | if(!dev) return 4; 63 | if(!dev->ioctl) return 0; 64 | 65 | return dev->ioctl(request,arg,(void*)result); 66 | 67 | } 68 | 69 | 70 | int devfs_askforpipe(char* filename,pipe_t* pipe) { 71 | 72 | if(!filename) return 1; 73 | 74 | if(!pipe) return 2; 75 | 76 | devfs_dev_t* dev = devfs_find_dev(filename); 77 | 78 | if(!dev) return 4; 79 | if(!dev->askforpipe) return 5; 80 | 81 | return dev->askforpipe(pipe); 82 | 83 | } 84 | 85 | int devfs_instantreadpipe(char* filename,pipe_t* pipe) { 86 | if(!filename) return 1; 87 | 88 | if(!pipe) return 2; 89 | 90 | devfs_dev_t* dev = devfs_find_dev(filename); 91 | 92 | if(!dev) return 4; 93 | if(!dev->instantreadpipe) return 5; 94 | 95 | return dev->instantreadpipe(pipe); 96 | } 97 | 98 | void devfs_reg_device(const char* name,int (*write)(char* buffer,uint64_t size),int (*read)(char* buffer,long hint_size),int (*askforpipe)(pipe_t* pipe),int (*instantreadpipe)(pipe_t* pipe),int (*ioctl)(unsigned long request, void *arg, void* result)) { 99 | 100 | struct devfs_dev* dev = (devfs_dev_t*)PMM::VirtualAlloc(); 101 | 102 | if(dev) { 103 | String::memset(dev,0,4096); 104 | String::memcpy(dev->loc,name,String::strlen((char*)name)); 105 | dev->write = write; 106 | dev->read = read; 107 | dev->askforpipe = askforpipe; 108 | dev->instantreadpipe = instantreadpipe; 109 | dev->ioctl = ioctl; 110 | 111 | if(!head_dev) { 112 | head_dev = dev; 113 | last_dev = dev; 114 | } else { 115 | last_dev->next = dev; 116 | last_dev = dev; 117 | } 118 | 119 | } else { 120 | KHeap::Free(dev); 121 | } 122 | 123 | } 124 | 125 | /* 126 | 127 | Some basic devfs 128 | 129 | */ 130 | 131 | int zero_read(char* buffer,long hint_size) { 132 | if(!hint_size) return 7; 133 | if(hint_size > TMPFS_MAX_SIZE) return 8; 134 | 135 | String::memset(buffer,0,hint_size < 0 ? hint_size * (-1) : hint_size); 136 | 137 | return 0; 138 | 139 | } 140 | 141 | void devfs_init(filesystem_t* fs) { 142 | devfs_reg_device("/zero",0,zero_read,0,0,0); 143 | devfs_reg_device("/null",0,zero_read,0,0,0); 144 | 145 | fs->create = 0; 146 | fs->disk = 0; 147 | fs->exists = 0; 148 | fs->is_in_ram = 1; 149 | fs->readfile = devfs_read; 150 | fs->writefile = devfs_write; 151 | fs->askforpipe = devfs_askforpipe; 152 | fs->ioctl = devfs_ioctl; 153 | fs->touch = 0; 154 | fs->stat = 0; 155 | fs->rm = 0; 156 | 157 | } -------------------------------------------------------------------------------- /kernel/src/generic/VFS/procfs.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | procfs_data_t* head_procdata = 0; 12 | procfs_data_t* last_procdata = 0; 13 | 14 | void procfs_reg(char* loc,int (*read)(char* buffer,long hint_size)) { 15 | if(!head_procdata) { 16 | head_procdata = (procfs_data_t*)PMM::VirtualAlloc(); 17 | String::memcpy(head_procdata->loc,loc,String::strlen(loc)); 18 | head_procdata->read = read; 19 | last_procdata = head_procdata; 20 | } else { 21 | procfs_data_t* data = (procfs_data_t*)PMM::VirtualAlloc(); 22 | String::memcpy(data->loc,loc,String::strlen(loc)); 23 | data->read = read; 24 | last_procdata = data; 25 | } 26 | } 27 | 28 | int procfs_read(char* buffer,char* filename,long hint_size) { 29 | procfs_data_t* data = head_procdata; 30 | procfs_data_t* find_data = 0; 31 | 32 | while(data) { 33 | if(!String::strcmp(data->loc,filename)) { 34 | find_data = data; 35 | break; 36 | } 37 | data = data->next; 38 | } 39 | 40 | if(!find_data) 41 | return ENOENT; 42 | 43 | if(!data->read) 44 | return ENOENT; 45 | 46 | return data->read(buffer,hint_size); 47 | 48 | } 49 | 50 | void ProcFS::Init(filesystem_t* fs) { 51 | fs->readfile = procfs_read; 52 | } -------------------------------------------------------------------------------- /kernel/src/generic/VFS/ustar.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include // it have align macros 11 | 12 | inline int oct2bin(unsigned char *str, int size) { 13 | uint64_t n = 0; 14 | volatile unsigned char *c = str; 15 | for(int i = 0;i < size;i++) { 16 | n *= 8; 17 | n += *c - '0'; 18 | c++; 19 | 20 | } 21 | return n; 22 | } 23 | 24 | #define MAX_PATH 1024 25 | #define MAX_PARTS 100 26 | 27 | char* __ustar__strtok(char* str, const char* delim) { 28 | static char* next_token = 0; 29 | char* token; 30 | 31 | if (str != 0) { 32 | next_token = str; 33 | } 34 | 35 | if (next_token == 0 || *next_token == '\0') { 36 | return 0; 37 | } 38 | 39 | while (*next_token != '\0') { 40 | const char* d = delim; 41 | int is_delim = 0; 42 | while (*d != '\0') { 43 | if (*next_token == *d) { 44 | is_delim = 1; 45 | break; 46 | } 47 | d++; 48 | } 49 | if (!is_delim) { 50 | break; 51 | } 52 | next_token++; 53 | } 54 | 55 | if (*next_token == '\0') { 56 | next_token = 0; 57 | return 0; 58 | } 59 | 60 | token = next_token; 61 | 62 | while (*next_token != '\0') { 63 | const char* d = delim; 64 | while (*d != '\0') { 65 | if (*next_token == *d) { 66 | *next_token = '\0'; 67 | next_token++; 68 | return token; 69 | } 70 | d++; 71 | } 72 | next_token++; 73 | } 74 | 75 | next_token = 0; 76 | return token; 77 | } 78 | 79 | uint64_t resolve_count(char* str,uint64_t sptr,char delim) { 80 | char* current = str; 81 | uint16_t att = 0; 82 | uint64_t ptr = sptr; 83 | uint64_t ptr_count = 0; 84 | while(current[ptr] != delim) { 85 | if(att > 1024) 86 | return 0; 87 | att++; 88 | 89 | if(ptr != 0) { 90 | ptr_count++; 91 | ptr--; 92 | } 93 | } 94 | return ptr; 95 | } 96 | 97 | int normalize_path(const char* src, char* dest, uint64_t dest_size) { 98 | if (!src ||!dest || dest_size < 2) return -1; 99 | uint64_t j = 0; 100 | int prev_slash = 0; 101 | for (uint64_t i = 0; src[i] && j < dest_size - 1; i++) { 102 | if (src[i] == '/') { 103 | if (!prev_slash) { 104 | dest[j++] = '/'; 105 | prev_slash = 1; 106 | } 107 | } else { 108 | dest[j++] = src[i]; 109 | prev_slash = 0; 110 | } 111 | } 112 | 113 | if (j > 1 && dest[j-1] == '/') j--; 114 | if (j >= dest_size) { 115 | dest[0] = '\0'; 116 | return -1; 117 | } 118 | dest[j] = '\0'; 119 | return 0; 120 | } 121 | 122 | void resolve_path(const char* inter,const char* base, char *result, char spec) { 123 | char buffer_in_stack[1024]; 124 | char buffer2_in_stack[1024]; 125 | char* buffer = (char*)buffer_in_stack; 126 | char* final_buffer = (char*)buffer2_in_stack; 127 | uint64_t ptr = String::strlen((char*)base); 128 | char is_first = 1; 129 | char is_full = 0; 130 | 131 | String::memset(buffer_in_stack,0,1024); 132 | String::memset(buffer2_in_stack,0,1024); 133 | 134 | String::memcpy(final_buffer,base,String::strlen((char*)base)); 135 | 136 | if(String::strlen((char*)inter) == 1 && inter[0] == '.') { 137 | String::memset(result,0,1024); 138 | String::memcpy(result,base,String::strlen((char*)base)); 139 | return; 140 | } 141 | 142 | if(!String::strcmp(inter,"/")) { 143 | String::memset(result,0,1024); 144 | String::memcpy(result,inter,String::strlen((char*)inter)); 145 | return; 146 | } 147 | 148 | if(inter[0] == '/') { 149 | ptr = 0; 150 | String::memset(final_buffer,0,1024); 151 | is_full = 1; 152 | } 153 | 154 | if(spec) 155 | is_first = 0; 156 | 157 | buffer = __ustar__strtok((char*)inter,"/"); 158 | while(buffer) { 159 | 160 | if(is_first && !is_full) { 161 | uint64_t mm = resolve_count(final_buffer,ptr,'/'); 162 | 163 | if(ptr < mm) { 164 | final_buffer[0] = '/'; 165 | final_buffer[1] = '\0'; 166 | ptr = 1; 167 | continue; 168 | } 169 | 170 | ptr = mm; 171 | final_buffer[ptr] = '\0'; 172 | is_first = 0; 173 | } 174 | 175 | if(!String::strcmp(buffer,"..")) { 176 | uint64_t mm = resolve_count(final_buffer,ptr,'/'); 177 | 178 | if(ptr < mm) { 179 | final_buffer[0] = '/'; 180 | final_buffer[1] = '\0'; 181 | ptr = 1; 182 | continue; 183 | } 184 | 185 | ptr = mm; 186 | final_buffer[ptr] = '\0'; 187 | 188 | 189 | 190 | } else if(String::strcmp(buffer,"./") && String::strcmp(buffer,".")) { 191 | 192 | final_buffer[ptr] = '/'; 193 | ptr++; 194 | 195 | uint64_t mm = String::strlen(buffer); 196 | String::memcpy((char*)((uint64_t)final_buffer + ptr),buffer,mm); 197 | ptr += mm; 198 | final_buffer[ptr] = '\0'; 199 | } 200 | 201 | buffer = __ustar__strtok(0,"/"); 202 | } 203 | 204 | String::memset(result,0,1024); 205 | normalize_path(final_buffer,result,2048); 206 | 207 | //Log("F %s\n",result); 208 | 209 | } 210 | 211 | void USTAR::ParseAndCopy() { 212 | LimineInfo info; 213 | pAssert(info.initrd,"Can't continue without initrd"); 214 | 215 | ustar_t* current = (ustar_t*)info.initrd->modules[0]->address; 216 | 217 | INFO("Initrd address 0x%p\n",current); 218 | 219 | limine_file* initrd = info.initrd->modules[0]; 220 | 221 | pAssert(!String::strncmp(current->ustar,"ustar",5),"Invalid initrd"); 222 | INFO("Valid initrd !\n"); 223 | 224 | uint64_t actual_tar_ptr_end = ((uint64_t)initrd->address + initrd->size) - 1024; //substract first header and his content 225 | 226 | while((uint64_t)current < actual_tar_ptr_end) { 227 | uint8_t type = oct2bin((uint8_t*)¤t->type,1); 228 | uint64_t aligned_size; 229 | if(type == 0) { 230 | 231 | char* filename = (char*)((uint64_t)current->file_name + 1); 232 | 233 | int _2 = VFS::Create(filename,0); 234 | 235 | int size = oct2bin((uint8_t*)current->file_size,String::strlen(current->file_size)); 236 | 237 | aligned_size = CALIGNPAGEUP(oct2bin((uint8_t*)¤t->file_size,String::strlen(current->file_size)),512); 238 | 239 | VFS::Write((char*)((uint64_t)current + 512),filename,size,0,0); 240 | VFS::Chmod(filename,(uint64_t)current->file_mode); 241 | 242 | } else if(type == 5) { 243 | 244 | char* filename = (char*)((uint64_t)current->file_name + 1); 245 | 246 | int _2 = VFS::Create(filename,1); 247 | 248 | int size = oct2bin((uint8_t*)current->file_size,String::strlen(current->file_size)); 249 | 250 | aligned_size = CALIGNPAGEUP(oct2bin((uint8_t*)¤t->file_size,String::strlen(current->file_size)),512); 251 | 252 | } else if(type == 2) { 253 | char* filename = (char*)((uint64_t)current->file_name + 1); 254 | 255 | int _2 = VFS::Create(filename,2); 256 | 257 | int size = oct2bin((uint8_t*)current->file_size,String::strlen(current->file_size)); 258 | 259 | aligned_size = CALIGNPAGEUP(oct2bin((uint8_t*)¤t->file_size,String::strlen(current->file_size)),512); 260 | 261 | char result_path[MAX_PATH]; 262 | String::memset(result_path,0,MAX_PATH); 263 | 264 | resolve_path(current->name_linked,filename,result_path,0); 265 | 266 | //Log("PATH: %s\n",result_path); 267 | 268 | VFS::Write((char*)result_path,filename,String::strlen(result_path),1,0); 269 | } else { 270 | DEBUG("Unknown ustar type: %d with name \"%s\"\n",type,current->file_name); 271 | aligned_size = 512; 272 | } 273 | current = (ustar_t*)((uint64_t)current + aligned_size + 512); 274 | 275 | } 276 | 277 | //tmpfs_dump(); 278 | 279 | } -------------------------------------------------------------------------------- /kernel/src/generic/VFS/vfs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | mount_location_t mount_points[MAX_MOUNT_POINTS]; 12 | uint16_t mount_points_ptr = 0; 13 | 14 | char vfs_spinlock = 0; 15 | 16 | mount_location_t* vfs_find_the_nearest_mount(char* loc) { 17 | if (!loc) return 0; 18 | 19 | mount_location_t* nearest = 0; 20 | int max_match = 0; 21 | 22 | for(uint16_t i = 0;i < MAX_MOUNT_POINTS;i++) { 23 | if(mount_points[i].loc) { 24 | int temp_match = 0; 25 | int mount_length = String::strlen(mount_points[i].loc); 26 | int loc_length = String::strlen(loc); 27 | if(mount_length <= loc_length) { 28 | for(int b = 0;b < loc_length;b++) { 29 | if(mount_points[i].loc[b]) { 30 | if(mount_points[i].loc[b] == loc[b]) 31 | temp_match++; 32 | else 33 | break; 34 | } else 35 | break; 36 | } 37 | if(temp_match > max_match) { 38 | max_match = temp_match; 39 | nearest = &mount_points[i]; 40 | } 41 | } 42 | } 43 | } 44 | 45 | return nearest; 46 | } 47 | 48 | int VFS::Read(char* buffer,char* filename,long hint_size) { 49 | if(!filename) return -1; 50 | 51 | spinlock_lock(&vfs_spinlock); 52 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 53 | 54 | if(!fs) return -1; 55 | if(!fs->fs->readfile) return 0; 56 | 57 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); // /somemount/file to /file 58 | int status = fs->fs->readfile(buffer,filename_as_fs,hint_size); 59 | spinlock_unlock(&vfs_spinlock); 60 | return status; 61 | } 62 | 63 | int VFS::Write(char* buffer,char* filename,uint64_t size,char is_symlink_path,uint64_t offset) { 64 | if(!filename) return -1; 65 | 66 | spinlock_lock(&vfs_spinlock); 67 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 68 | 69 | if(!fs) return -1; 70 | if(!fs->fs->writefile) return 0; 71 | 72 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 73 | int status = fs->fs->writefile(buffer,filename_as_fs,size,is_symlink_path,offset); 74 | spinlock_unlock(&vfs_spinlock); 75 | return status; 76 | } 77 | 78 | int VFS::Touch(char* filename) { 79 | if(!filename) return -1; 80 | 81 | //spinlock_lock(&vfs_spinlock); 82 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 83 | 84 | if(!fs) return -1; 85 | if(!fs->fs->touch) return 0; 86 | 87 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 88 | int status = fs->fs->touch(filename_as_fs); 89 | //spinlock_unlock(&vfs_spinlock); 90 | return status; 91 | } 92 | 93 | int VFS::Create(char* filename,int type) { 94 | if(!filename) return -1; 95 | 96 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 97 | 98 | //Log(LOG_LEVEL_DEBUG,"Creating %s\n",filename); 99 | 100 | if(!fs) return -1; 101 | if(!fs->fs->create) return 0; 102 | 103 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 104 | int status = fs->fs->create(filename_as_fs,type); 105 | return status; 106 | } 107 | 108 | int VFS::Remove(char* filename) { 109 | if(!filename) return -1; 110 | 111 | spinlock_lock(&vfs_spinlock); 112 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 113 | 114 | if(!fs) return -1; 115 | if(!fs->fs->rm) return 0; 116 | 117 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 118 | int status = fs->fs->rm(filename_as_fs); 119 | spinlock_unlock(&vfs_spinlock); 120 | return status; 121 | } 122 | 123 | char VFS::Exists(char* filename) { 124 | if(!filename) return -1; 125 | 126 | //spinlock_lock(&vfs_spinlock); 127 | 128 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 129 | 130 | if(!fs) return -1; 131 | if(!fs->fs->exists) return 0; 132 | 133 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 134 | int status = fs->fs->exists(filename_as_fs); 135 | //spinlock_unlock(&vfs_spinlock); 136 | return status; 137 | } 138 | 139 | int VFS::Stat(char* filename, char* buffer,char follow_symlinks) { 140 | if(!filename) return -1; 141 | 142 | //spinlock_lock(&vfs_spinlock); 143 | 144 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 145 | 146 | if(!fs) return -1; 147 | if(!fs->fs->stat) return -15; 148 | 149 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 150 | int status = fs->fs->stat(filename_as_fs,buffer,follow_symlinks); 151 | //spinlock_unlock(&vfs_spinlock); 152 | return status; 153 | } 154 | 155 | int VFS::AskForPipe(char* filename,pipe_t* pipe) { 156 | if(!filename) return -1; 157 | 158 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 159 | 160 | if(!fs) return -1; 161 | 162 | if(!fs->fs->askforpipe) return -15; 163 | 164 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 165 | int status = fs->fs->askforpipe(filename_as_fs,pipe); 166 | return status; 167 | } 168 | 169 | int VFS::InstantPipeRead(char* filename,pipe_t* pipe) { 170 | if(!filename) return -1; 171 | 172 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 173 | 174 | if(!fs) return -1; 175 | 176 | if(!fs->fs->instantreadpipe) return -15; 177 | 178 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 179 | int status = fs->fs->instantreadpipe(filename_as_fs,pipe); 180 | return status; 181 | } 182 | 183 | int VFS::Ioctl(char* filename,unsigned long request, void *arg, int *result) { 184 | if(!filename) return -1; 185 | 186 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 187 | 188 | if(!fs) return -1; 189 | 190 | if(!fs->fs->ioctl) return 0; 191 | 192 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 193 | int status = fs->fs->ioctl(filename_as_fs,request,arg,result); 194 | return status; 195 | } 196 | 197 | int VFS::Iterate(char* filename,filestat_t* stat) { 198 | if(!filename) return -1; 199 | 200 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 201 | 202 | if(!fs) return -1; 203 | if(!fs->fs->iterate) return -15; 204 | if(!stat) return 0; 205 | 206 | int status = fs->fs->iterate(stat); 207 | return status; 208 | } 209 | 210 | int VFS::Chmod(char* filename,uint64_t mode) { 211 | if(!filename) return -1; 212 | 213 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 214 | 215 | if(!fs) return -1; 216 | if(!fs->fs->chmod) return -15; 217 | 218 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 219 | int status = fs->fs->chmod(filename_as_fs,mode); 220 | 221 | vfs_spinlock = 0; 222 | 223 | return status; 224 | } 225 | 226 | int VFS::Count(char* filename,int idx,int count) { 227 | if(!filename) return -1; 228 | 229 | mount_location_t* fs = vfs_find_the_nearest_mount(filename); 230 | 231 | if(!fs) return -1; 232 | if(!fs->fs->count) return 0; 233 | 234 | char* filename_as_fs = (char*)((uint64_t)filename + (String::strlen(fs->loc) - 1)); 235 | int status = fs->fs->count(filename,idx,count); 236 | return status; 237 | } 238 | 239 | void VFS::Init() { 240 | filesystem_t* tmpfs = new filesystem_t; 241 | mount_points[0].loc = "/"; 242 | mount_points[0].fs = tmpfs; 243 | TMPFS::Init(tmpfs); 244 | INFO("TmpFS initializied\n"); 245 | 246 | filesystem_t* devfs = new filesystem_t; 247 | mount_points[1].loc = "/dev/"; 248 | mount_points[1].fs = devfs; 249 | devfs_init(devfs); 250 | 251 | INFO("DevFS initializied\n"); 252 | 253 | } -------------------------------------------------------------------------------- /kernel/src/generic/acpi/acpi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // ill no use it 15 | void ACPI::InitTables() { 16 | uacpi_status ret = uacpi_setup_early_table_access(PMM::VirtualBigAlloc(256),256 * PAGE_SIZE); 17 | } 18 | 19 | void ACPI::fullInit() { 20 | uacpi_status ret = uacpi_initialize(0); 21 | 22 | HPET::Init(); 23 | INFO("HPET Initializied\n"); 24 | 25 | IOAPIC::Init(); 26 | INFO("IOAPIC Initializied\n"); 27 | 28 | ret = uacpi_namespace_load(); 29 | 30 | ret = uacpi_set_interrupt_model(UACPI_INTERRUPT_MODEL_IOAPIC); 31 | 32 | ret = uacpi_namespace_initialize(); 33 | ret = uacpi_finalize_gpe_initialization(); 34 | } -------------------------------------------------------------------------------- /kernel/src/generic/limineA/limineinfo.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | namespace { 7 | 8 | __attribute__((used, section(".limine_requests"))) 9 | volatile LIMINE_BASE_REVISION(3); 10 | 11 | } 12 | 13 | // The Limine requests can be placed anywhere, but it is important that 14 | // the compiler does not optimise them away, so, usually, they should 15 | // be made volatile or equivalent, _and_ they should be accessed at least 16 | // once or marked as used with the "used" attribute as done here. 17 | 18 | namespace { 19 | 20 | __attribute__((used, section(".limine_requests"))) 21 | volatile limine_framebuffer_request framebuffer_request = { 22 | .id = LIMINE_FRAMEBUFFER_REQUEST, 23 | .revision = 0, 24 | .response = nullptr 25 | }; 26 | 27 | __attribute__((used, section(".limine_requests"))) 28 | volatile limine_memmap_request memmap_request = { 29 | .id = LIMINE_MEMMAP_REQUEST, 30 | .revision = 0, 31 | .response = nullptr 32 | }; 33 | 34 | __attribute__((used, section(".limine_requests"))) 35 | volatile limine_executable_address_request keraddr_request = { 36 | .id = LIMINE_EXECUTABLE_ADDRESS_REQUEST, 37 | .revision = 0, 38 | .response = nullptr 39 | }; 40 | 41 | __attribute__((used, section(".limine_requests"))) 42 | volatile limine_bootloader_info_request bootloader_request = { 43 | .id = LIMINE_BOOTLOADER_INFO_REQUEST, 44 | .revision = 0, 45 | .response = nullptr 46 | }; 47 | 48 | __attribute__((used, section(".limine_requests"))) 49 | volatile LIMINE_MP(request) smp_request = { 50 | .id = LIMINE_MP_REQUEST, 51 | .revision = 0, 52 | .response = nullptr 53 | }; 54 | 55 | __attribute__((used, section(".limine_requests"))) 56 | volatile limine_rsdp_request rsdp_request = { 57 | .id = LIMINE_RSDP_REQUEST, 58 | .revision = 0, 59 | .response = nullptr 60 | }; 61 | 62 | __attribute__((used, section(".limine_requests"))) 63 | volatile limine_hhdm_request hhdm_request = { 64 | .id = LIMINE_HHDM_REQUEST, 65 | .revision = 0, 66 | .response = nullptr 67 | }; 68 | 69 | __attribute__((used, section(".limine_requests"))) 70 | volatile limine_module_request initrd_request = { 71 | .id = LIMINE_MODULE_REQUEST, 72 | .revision = 0, 73 | .response = nullptr 74 | }; 75 | 76 | } 77 | 78 | // Finally, define the start and end markers for the Limine requests. 79 | // These can also be moved anywhere, to any .cpp file, as seen fit. 80 | 81 | namespace { 82 | 83 | __attribute__((used, section(".limine_requests_start"))) 84 | volatile LIMINE_REQUESTS_START_MARKER; 85 | 86 | __attribute__((used, section(".limine_requests_end"))) 87 | volatile LIMINE_REQUESTS_END_MARKER; 88 | 89 | } 90 | 91 | LimineInfo::LimineInfo() { 92 | fb_info = framebuffer_request.response->framebuffers[0]; 93 | memmap = memmap_request.response; 94 | ker_addr = keraddr_request.response; 95 | bootloader_name = bootloader_request.response->name; 96 | bootloader_version = bootloader_request.response->version; 97 | hhdm_offset = hhdm_request.response->offset; 98 | rsdp_address = (uint64_t)rsdp_request.response->address; 99 | smp = smp_request.response; 100 | initrd = initrd_request.response; 101 | } -------------------------------------------------------------------------------- /kernel/src/generic/locks/spinlock.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | char is_ignored = 1; 5 | 6 | void spinlock_lock(char* lock) { 7 | 8 | if(is_ignored) 9 | return; 10 | 11 | while(__sync_lock_test_and_set(lock,1)) 12 | __builtin_ia32_pause(); 13 | } 14 | 15 | void spinlock_unlock(char* lock) { 16 | __sync_lock_release(lock); 17 | *lock = 0; 18 | } -------------------------------------------------------------------------------- /kernel/src/generic/memory/heap.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | char heap_lock = 0; 11 | uint64_t kmalloc_base; 12 | 13 | void KHeap::Init() { 14 | kernel_heap_block_t* head = (kernel_heap_block_t*)PMM::VirtualBigAlloc(SIZE_KHEAP_IN_PAGES); 15 | head->size = PAGE_SIZE * SIZE_KHEAP_IN_PAGES; 16 | head->isfree = 1; 17 | head->next = nullptr; 18 | kmalloc_base = (uint64_t)head; 19 | Paging::alwaysMappedAdd((uint64_t)head,PAGE_SIZE * SIZE_KHEAP_IN_PAGES); 20 | } 21 | 22 | kernel_heap_block_t* current = 0; 23 | 24 | void* KHeap::Malloc(uint64_t size) { 25 | spinlock_lock(&heap_lock); 26 | if(!current) { 27 | current = (kernel_heap_block_t*)kmalloc_base; 28 | } 29 | uint64_t totalsize = size + sizeof(kernel_heap_block_t); 30 | while(current) { 31 | if(current->isfree && current->size >= totalsize) { 32 | if(current->size > totalsize + sizeof(kernel_heap_block_t)) { 33 | kernel_heap_block_t* nextblock = (kernel_heap_block_t*)((uint8_t*)current + totalsize); 34 | nextblock->size = current->size - totalsize; 35 | nextblock->isfree = 1; 36 | nextblock->next = current->next; 37 | current->size = totalsize; 38 | current->next = nextblock; 39 | } 40 | current->isfree = 0; 41 | spinlock_unlock(&heap_lock); 42 | return (void*)((uint8_t*)current + sizeof(kernel_heap_block_t)); 43 | } 44 | current=current->next; 45 | if(!current) { 46 | current = (kernel_heap_block_t*)kmalloc_base; 47 | } 48 | } 49 | spinlock_unlock(&heap_lock); 50 | return (void*)0; 51 | } 52 | 53 | void KHeap::Free(void* ptr) { 54 | spinlock_lock(&heap_lock); 55 | kernel_heap_block_t* block = (kernel_heap_block_t*)((uint8_t*)ptr - sizeof(kernel_heap_block_t)); 56 | block->isfree = 1; 57 | spinlock_unlock(&heap_lock); 58 | } -------------------------------------------------------------------------------- /kernel/src/generic/memory/paging.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | uint64_t paging_num_pages = 0; 15 | 16 | uint64_t* __paging_next_level(uint64_t* table,uint64_t index,uint64_t flags) { 17 | if(!(table[index] & PTE_PRESENT)) { 18 | table[index] = (uint64_t)PMM::Alloc() | PTE_USER | flags; 19 | paging_num_pages++; 20 | } 21 | 22 | 23 | if(!(table[index] & PTE_MASK_VALUE)) { 24 | Log(LOG_LEVEL_ERROR,"Paging fault ! some pmm bug, halting kernel\n"); 25 | __cli(); 26 | __hlt(); 27 | } 28 | 29 | return (uint64_t*)HHDM::toVirt(table[index] & PTE_MASK_VALUE); 30 | } 31 | 32 | uint64_t* kernel_cr3; 33 | 34 | uint64_t* Paging::KernelGet() { 35 | return kernel_cr3; 36 | } 37 | 38 | void* Paging::Map(uint64_t* cr3,uint64_t phys,uint64_t virt,uint64_t flags) { 39 | uint64_t aligned_virt = ALIGNPAGEDOWN(virt); 40 | uint64_t aligned_phys = ALIGNPAGEDOWN(phys); 41 | uint64_t* pml3 = __paging_next_level(cr3,PTE_INDEX(aligned_virt,39),flags); 42 | uint64_t* pml2 = __paging_next_level(pml3,PTE_INDEX(aligned_virt,30),flags); 43 | uint64_t* pml = __paging_next_level(pml2,PTE_INDEX(aligned_virt,21),flags); 44 | pml[PTE_INDEX(aligned_virt,12)] = aligned_phys | flags; 45 | return (void*)virt; 46 | } 47 | 48 | uint64_t Paging::PhysFromVirt(uint64_t* cr3,uint64_t virt) { 49 | uint64_t aligned_virt = ALIGNPAGEDOWN(virt); 50 | uint64_t* pml3 = __paging_next_level(cr3,PTE_INDEX(aligned_virt,39),PTE_PRESENT | PTE_RW); 51 | uint64_t* pml2 = __paging_next_level(pml3,PTE_INDEX(aligned_virt,30),PTE_PRESENT | PTE_RW); 52 | uint64_t* pml = __paging_next_level(pml2,PTE_INDEX(aligned_virt,21),PTE_PRESENT | PTE_RW); 53 | return pml[PTE_INDEX(aligned_virt,12)] & PTE_MASK_VALUE; 54 | } 55 | 56 | void Paging::Unmap(uint64_t* cr3, uint64_t virt, uint64_t size_in_pages) { 57 | uint64_t aligned_virt = ALIGNPAGEDOWN(virt); 58 | for(uint64_t i = aligned_virt;i < aligned_virt + (size_in_pages * PAGE_SIZE);i+= PAGE_SIZE) { 59 | uint64_t* pml3 = __paging_next_level(cr3,PTE_INDEX(i,39),PTE_PRESENT | PTE_RW); 60 | uint64_t* pml2 = __paging_next_level(pml3,PTE_INDEX(i,30),PTE_PRESENT | PTE_RW); 61 | uint64_t* pml = __paging_next_level(pml2,PTE_INDEX(i,21),PTE_PRESENT | PTE_RW); 62 | pml[PTE_INDEX(i,12)] = 0; 63 | } 64 | } 65 | 66 | 67 | void* Paging::HHDMMap(uint64_t* cr3,uint64_t phys,uint64_t flags) { 68 | return Map(cr3,phys,HHDM::toVirt(phys),flags); 69 | } 70 | 71 | void* Paging::KernelMap(uint64_t phys) { 72 | return Map(kernel_cr3,phys,HHDM::toVirt(phys),PTE_PRESENT | PTE_RW); 73 | } 74 | 75 | void Paging::Kernel(uint64_t* cr3) { 76 | LimineInfo c; 77 | extern uint64_t kernel_start; 78 | extern uint64_t kernel_end; 79 | uint64_t align_kernel_start = ALIGNPAGEDOWN((uint64_t)&kernel_start); 80 | uint64_t align_kernel_end = ALIGNPAGEUP((uint64_t)&kernel_end); 81 | for(uint64_t i = align_kernel_start;i < align_kernel_end;i+=PAGE_SIZE) { 82 | Paging::Map(cr3,i - c.ker_addr->virtual_base + c.ker_addr->physical_base,i,PTE_PRESENT | PTE_RW); 83 | } 84 | } 85 | 86 | void Paging::MemoryEntry(uint64_t* cr3,uint32_t type,uint64_t flags) { 87 | struct limine_memmap_entry* current_entry; 88 | LimineInfo b; 89 | for(uint64_t i = 0;i < b.memmap->entry_count;i++) { 90 | current_entry = b.memmap->entries[i]; 91 | if(current_entry->type == type) { 92 | for(uint64_t i = current_entry->base;i < current_entry->base + current_entry->length;i+=PAGE_SIZE) { 93 | HHDMMap(cr3,i,flags); 94 | } 95 | } 96 | } 97 | } 98 | 99 | void Paging::Pat(uint8_t index, uint8_t type) { 100 | uint64_t pat = __rdmsr(0x277); 101 | pat &= ~(0xFFULL << (index * 8)); 102 | pat |= ((uint64_t)type << (index * 8)); 103 | __wrmsr(0x277, pat); 104 | } 105 | 106 | void Paging::EnablePaging(uint64_t* virt_cr3) { 107 | asm volatile("mov %0, %%cr3" : : "r" (HHDM::toPhys((uint64_t)virt_cr3)) : "memory"); 108 | } 109 | 110 | void Paging::EnableKernel() { 111 | EnablePaging(kernel_cr3); 112 | } 113 | 114 | alwaysMapped_t head_map; 115 | alwaysMapped_t* last_map; 116 | char maplock; 117 | 118 | void Paging::alwaysMappedAdd(uint64_t base,uint64_t size) { 119 | if(head_map.base == 0) { //kheap 120 | head_map.base = base; 121 | head_map.size = size; 122 | head_map.is_phys = 0; 123 | last_map = &head_map; 124 | } else { 125 | // it will not be atomic so i need a lock 126 | spinlock_lock(&maplock); 127 | alwaysMapped_t* map = new alwaysMapped_t; 128 | LimineInfo info; 129 | map->base = base; 130 | map->size = size; 131 | last_map->next = map; 132 | last_map = map; 133 | head_map.is_phys = base < info.hhdm_offset ? 1 : 0; 134 | spinlock_unlock(&maplock); 135 | } 136 | } 137 | 138 | void Paging::alwaysMappedMap(uint64_t* cr3) { 139 | alwaysMapped_t* current_map = &head_map; 140 | while(current_map) { 141 | //Log("Always mapped: 0x%p 0x%p\n",current_map->base,current_map->next); 142 | for(uint64_t i = current_map->base;i < current_map->base + current_map->size;i += PAGE_SIZE) { 143 | HHDMMap(cr3,current_map->is_phys ? i : HHDM::toPhys(i),PTE_PRESENT | PTE_RW); 144 | } 145 | current_map = current_map->next; 146 | } 147 | } 148 | 149 | 150 | 151 | void Paging::Copy(uint64_t* dest_cr3,uint64_t* src_cr3) { 152 | 153 | } 154 | 155 | void Paging::Init() { 156 | Pat(1,1); 157 | Pat(2,0); 158 | kernel_cr3 = (uint64_t*)PMM::VirtualAlloc(); 159 | SINFO("Mapping usable memory\n"); 160 | MemoryEntry(kernel_cr3,LIMINE_MEMMAP_USABLE,PTE_PRESENT | PTE_RW); 161 | SINFO("Mapping framebuffer\n"); 162 | MemoryEntry(kernel_cr3,LIMINE_MEMMAP_FRAMEBUFFER,PTE_PRESENT | PTE_RW | PTE_WC); 163 | SINFO("Mapping bootloader reclaimable\n"); 164 | MemoryEntry(kernel_cr3,LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE,PTE_PRESENT | PTE_RW); 165 | SINFO("Activating paging\n"); 166 | MemoryEntry(kernel_cr3,LIMINE_MEMMAP_EXECUTABLE_AND_MODULES,PTE_PRESENT | PTE_RW); 167 | SINFO("Mapping kernel\n"); 168 | Kernel(kernel_cr3); 169 | EnableKernel(); 170 | } -------------------------------------------------------------------------------- /kernel/src/generic/mp/mp.cpp: -------------------------------------------------------------------------------- 1 | 2 | // SMP or MP idk source 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | uint64_t how_much_cpus = 0; 20 | uint64_t temp_how_much_cpus = 0; 21 | 22 | void __mp_bootstrap(struct LIMINE_MP(info)* smp_info) { 23 | 24 | __cli(); 25 | __wrmsr(0xC0000101,0); // write to zero cuz idk what can be in this msr 26 | 27 | Paging::EnableKernel(); 28 | 29 | GDT::Init(); 30 | __hlt(); 31 | CpuData::Access()->smp_info = smp_info; 32 | 33 | IDT::Load(); 34 | 35 | Syscall::Init(); 36 | 37 | SSE::Init(); 38 | 39 | Lapic::Init(); 40 | INFO("CPU %d is online !\n",smp_info->lapic_id); 41 | 42 | uint64_t stack = (uint64_t)PMM::VirtualBigAlloc(TSS_STACK_IN_PAGES); // for syscall 43 | Paging::alwaysMappedAdd(stack,TSS_STACK_IN_PAGES * PAGE_SIZE); 44 | CpuData::Access()->kernel_stack = stack + (TSS_STACK_IN_PAGES * PAGE_SIZE); 45 | CpuData::Access()->user_stack = 0; 46 | 47 | //Log("stack: 0x%p\n",stack); 48 | 49 | //Log("Waiting for other CPUs...\n"); 50 | MP::Sync(); 51 | __sti(); 52 | while(1) { 53 | __hlt(); 54 | } 55 | 56 | } 57 | 58 | void MP::Init() { 59 | LimineInfo limine_info; 60 | how_much_cpus = limine_info.smp->cpu_count; 61 | temp_how_much_cpus = 0; 62 | for(uint64_t i = 0;i < limine_info.smp->cpu_count;i++) { 63 | if(i != limine_info.smp->bsp_lapic_id) { 64 | limine_info.smp->cpus[i]->goto_address = __mp_bootstrap; // in x86 it atomic soooo 65 | } 66 | } 67 | INFO("CPUs count: %d\n",how_much_cpus); 68 | } 69 | 70 | void MP::Sync() { 71 | temp_how_much_cpus++; 72 | while(how_much_cpus != temp_how_much_cpus) {__nop();} 73 | HPET::Sleep(50000); // perform 50 ms sleep to sync 74 | temp_how_much_cpus = 0; 75 | } -------------------------------------------------------------------------------- /kernel/src/generic/tty/tty.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // flanterm_context* ft_ctx; 16 | 17 | void __tty_helper_write(const char* msg) { 18 | extern flanterm_context* ft_ctx; 19 | flanterm_write(ft_ctx,(char*)msg,String::strlen((char*)msg)); 20 | } 21 | 22 | 23 | termios_t tty_termios; 24 | 25 | ps2keyboard_pipe_struct_t* head_ttypipe; 26 | ps2keyboard_pipe_struct_t* last_ttypipe; 27 | 28 | ps2keyboard_pipe_struct_t* __tty_allocate_pipe() { 29 | 30 | if(!head_ttypipe) { 31 | head_ttypipe = new ps2keyboard_pipe_struct_t; 32 | head_ttypipe->is_used_anymore = 0; 33 | last_ttypipe = head_ttypipe; 34 | } 35 | 36 | ps2keyboard_pipe_struct_t* current = head_ttypipe; 37 | while(current) { 38 | if(!current->is_used_anymore) 39 | break; 40 | current = current->next; 41 | } 42 | 43 | if(!current) { 44 | current = new ps2keyboard_pipe_struct_t; 45 | last_ttypipe->next = current; 46 | last_ttypipe = current; 47 | } 48 | 49 | return current; 50 | 51 | 52 | } 53 | 54 | void __tty_send_ipc(uint8_t keycode) { 55 | 56 | if(!head_ttypipe) { 57 | head_ttypipe = new ps2keyboard_pipe_struct_t; 58 | head_ttypipe->is_used_anymore = 0; 59 | } 60 | 61 | ps2keyboard_pipe_struct_t* current = head_ttypipe; 62 | while(current) { 63 | 64 | if(current->is_used_anymore && current->pipe) { 65 | current->pipe->buffer[current->pipe->buffer_size] = keycode; 66 | current->pipe->buffer_size++; 67 | } 68 | current = current->next; 69 | } 70 | 71 | } 72 | 73 | void __tty_remove_ipc() { 74 | if(!head_ttypipe) { 75 | head_ttypipe = new ps2keyboard_pipe_struct_t; 76 | head_ttypipe->is_used_anymore = 0; 77 | } 78 | 79 | ps2keyboard_pipe_struct_t* current = head_ttypipe; 80 | while(current) { 81 | 82 | if(current->is_used_anymore && current->pipe) { 83 | current->pipe->buffer[current->pipe->buffer_size] = '\0'; 84 | current->pipe->buffer_size--; 85 | } 86 | current = current->next; 87 | } 88 | } 89 | 90 | void __tty_end_ipc() { 91 | //Log(LOG_LEVEL_DEBUG,"Ending ipc \n"); 92 | ps2keyboard_pipe_struct_t* current = head_ttypipe; 93 | while(current) { 94 | 95 | if(current->is_used_anymore && current->pipe) { 96 | if(current->pipe->type == PIPE_WAIT) 97 | current->is_used_anymore = 0; 98 | 99 | //Log(LOG_LEVEL_DEBUG,"Bufer size %d\n",current->pipe->buffer_size); 100 | current->pipe->is_received = 0; 101 | } 102 | current = current->next; 103 | } 104 | 105 | } 106 | 107 | 108 | int tty_askforpipe(pipe_t* pipe) { 109 | 110 | ps2keyboard_pipe_struct_t* pip = __tty_allocate_pipe(); 111 | 112 | pip->pipe = pipe; 113 | pip->is_used_anymore = 1; 114 | if(tty_termios.c_lflag & ICANON) 115 | pip->pipe->type = PIPE_WAIT; 116 | else 117 | pip->pipe->type = PIPE_WAIT; 118 | pip->pipe->is_used = 1; 119 | 120 | return 0; 121 | 122 | } 123 | 124 | int tty_write(char* buffer,uint64_t size) { 125 | extern flanterm_context* ft_ctx; 126 | flanterm_write(ft_ctx,buffer,size); 127 | Serial::WriteArray((uint8_t*)buffer,size); 128 | return 0; 129 | } 130 | 131 | int tty_ioctl(unsigned long request, void* arg, void* result) { 132 | 133 | //Log(LOG_LEVEL_DEBUG,"Requesting ioctl 0x%p\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nn\\nn\n\n\n",request); 134 | 135 | switch(request) { 136 | case TCGETS: 137 | String::memcpy(arg,&tty_termios,sizeof(termios_t)); 138 | break; 139 | case TCSETS: 140 | String::memcpy(&tty_termios,arg,sizeof(termios_t)); 141 | break; 142 | case TIOCGWINSZ: { 143 | winsize_t buf; 144 | size_t cols = 0; 145 | size_t rows = 0; 146 | extern flanterm_context* ft_ctx; 147 | flanterm_get_dimensions(ft_ctx,&cols,&rows); 148 | buf.ws_col = cols; 149 | buf.ws_row = rows; 150 | String::memcpy(arg,&buf,sizeof(winsize_t)); 151 | break; 152 | } 153 | default: 154 | return 0; 155 | } 156 | 157 | return 0; 158 | 159 | } 160 | 161 | int is_printable(char c) { 162 | return (c >= 32 && c <= 126) || c == 10; 163 | } 164 | 165 | int p = 0; 166 | 167 | void __tty_receive_ipc(uint8_t keycode) { 168 | extern flanterm_context* ft_ctx; 169 | 170 | uint8_t raw_keycode = keycode; 171 | 172 | if(!(tty_termios.c_lflag & ICANON)) { 173 | 174 | if(raw_keycode == '\n') 175 | raw_keycode = 13; // nano want it :sob: 176 | 177 | if((tty_termios.c_lflag & ECHO) && is_printable(raw_keycode)) { 178 | flanterm_write(ft_ctx,(char*)&keycode,1); 179 | Serial::Write(keycode); 180 | } 181 | if(tty_termios.c_cc[VMIN] >= p) { 182 | p = 0; 183 | __tty_send_ipc(raw_keycode); 184 | __tty_end_ipc(); 185 | } else { 186 | p++; 187 | } 188 | 189 | return; 190 | 191 | } 192 | 193 | if(keycode != 127) { 194 | if(keycode == 13) 195 | keycode = '\n'; 196 | 197 | if((tty_termios.c_lflag & ECHO) && is_printable((char)keycode)) { 198 | flanterm_write(ft_ctx,(char*)&keycode,1); 199 | Serial::Write(keycode); 200 | p++; 201 | } 202 | 203 | if(tty_termios.c_lflag & ICANON) { 204 | if(is_printable((char)keycode)) 205 | __tty_send_ipc(keycode); 206 | if((char)keycode == '\n') { 207 | __tty_end_ipc(); 208 | p = 0; 209 | } 210 | } else if(tty_termios.c_cc[VMIN] >= p) { 211 | p = 0; 212 | __tty_send_ipc(raw_keycode); 213 | __tty_end_ipc(); 214 | } else { 215 | p++; 216 | } 217 | } else { 218 | if(p != 0) { 219 | __tty_remove_ipc(); 220 | __tty_helper_write("\b \b"); 221 | Serial::WriteArray((uint8_t*)"\b \b",String::strlen("\b \b")); 222 | p--; 223 | } 224 | } 225 | 226 | } 227 | 228 | void TTY::Init() { 229 | extern flanterm_context* ft_ctx; 230 | 231 | devfs_reg_device("/tty",tty_write,0,tty_askforpipe,0,tty_ioctl); 232 | __tty_helper_write("\033[2J \033[1;1H"); 233 | String::memset(&tty_termios,0,sizeof(termios_t)); 234 | tty_termios.c_cc[VMIN] = 1; 235 | tty_termios.c_lflag = ECHO | ICANON; 236 | tty_termios.c_cflag = CS8 | CREAD | HUPCL; 237 | tty_termios.c_oflag = OPOST | ONLCR; 238 | tty_termios.c_iflag = ICRNL | IXON; 239 | 240 | } -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/cpu/data.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct { 11 | uint64_t user_stack; 12 | uint64_t kernel_stack; 13 | GDT gdt; 14 | struct LIMINE_MP(info)* smp_info; 15 | process_t* current; 16 | int_frame_t temp_frame; 17 | int last_syscall; 18 | } __attribute__((packed)) cpudata_t; 19 | 20 | 21 | class CpuData { 22 | public: 23 | static cpudata_t* Access(); 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/cpu/gdt.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | extern "C" { 5 | 6 | typedef struct __attribute__((packed)) { 7 | uint16_t size; 8 | uint64_t base; 9 | } gdt_pointer_t; 10 | 11 | typedef struct __attribute__((packed)) { 12 | uint16_t limit; 13 | uint16_t baselow16; 14 | uint8_t basemid8; 15 | uint8_t access; 16 | uint8_t granularity; 17 | uint8_t basehigh8; 18 | } gdt_entry_t; 19 | 20 | typedef struct __attribute__((packed)) { 21 | uint16_t length; 22 | uint16_t baselow16; 23 | uint8_t basemid8; 24 | uint8_t flags0; 25 | uint8_t flags1; 26 | uint8_t basehigh8; 27 | uint32_t baseup32; 28 | uint32_t reserved; 29 | } tss_entry_t; 30 | 31 | typedef struct __attribute__((packed)) { 32 | uint32_t reserved0; 33 | uint64_t rsp[3]; 34 | uint64_t reserved1; 35 | uint64_t ist[7]; 36 | uint32_t reserved2; 37 | uint32_t reserved3; 38 | uint16_t reserved4; 39 | uint16_t iopb_offsset; 40 | } tss_t; 41 | 42 | typedef struct __attribute__((packed)) { 43 | gdt_entry_t zero; 44 | gdt_entry_t _64bitcode; 45 | gdt_entry_t _64bitdata; 46 | gdt_entry_t usercode; 47 | gdt_entry_t userdata; 48 | tss_entry_t tss; 49 | } gdt_t; 50 | 51 | } 52 | 53 | class GDT { 54 | public: 55 | 56 | gdt_t gdt; 57 | tss_t tss; 58 | gdt_pointer_t gdtr; 59 | 60 | static void Init(); 61 | 62 | }; 63 | 64 | #pragma once -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/cpu/lapic.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | class Lapic { 5 | public: 6 | static void Init(); 7 | 8 | static uint32_t Read(uint32_t reg); 9 | 10 | static void Write(uint32_t reg,uint32_t val); 11 | 12 | static void EOI(); 13 | 14 | static uint32_t ID(); 15 | 16 | static uint64_t Base(); 17 | 18 | }; -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/cpu/sse.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #pragma once 5 | 6 | #define DEFAULT_SSE_FLAGS ((1 << 9) | (1 << 10) | (1 << 1)) 7 | #define SSE_XSAVE_SUPPORT (1 << 26) 8 | #define SSE_XSAVE_CR4 (1 << 18) 9 | 10 | #define SSE_CONTROL_DEFAULT ((1 << 0) | (1 << 1)) 11 | 12 | #define SSE_CHECK_AND_SET(bit) \ 13 | if(a & bit) \ 14 | sse_control |= bit; 15 | 16 | typedef struct { 17 | uint16_t dumb0; 18 | uint32_t dumb1; 19 | uint16_t dumb2; 20 | uint64_t dumb3; 21 | uint64_t dumb4; 22 | uint32_t dumb5; 23 | } __attribute__((packed)) fpu_head_t; 24 | 25 | class SSE { 26 | public: 27 | static void Init(); 28 | static uint64_t Size(); 29 | static void Save(uint8_t* buf); 30 | static void Load(uint8_t* buf); 31 | }; -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/interrupts/idt.hpp: -------------------------------------------------------------------------------- 1 | 2 | // i will not use a per cpu idt, so idt will be for all cpus 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | typedef struct { 9 | uint16_t limit; 10 | uint64_t base; 11 | } __attribute__((packed)) idtr_t; 12 | 13 | typedef struct { 14 | uint16_t base_low; 15 | uint16_t cs; 16 | uint8_t ist; 17 | uint8_t attr; 18 | uint16_t base_mid; 19 | uint32_t base_high; 20 | uint32_t reserved; 21 | } __attribute__((packed)) idt_entry_t; 22 | 23 | typedef struct { 24 | uint64_t cr3; 25 | uint64_t rax; 26 | uint64_t rbx; 27 | uint64_t rcx; 28 | uint64_t rdx; 29 | uint64_t rsi; 30 | uint64_t rdi; 31 | uint64_t rbp; 32 | uint64_t r8; 33 | uint64_t r9; 34 | uint64_t r10; 35 | uint64_t r11; 36 | uint64_t r12; 37 | uint64_t r13; 38 | uint64_t r14; 39 | uint64_t r15; 40 | uint64_t vec; 41 | uint64_t err_code; 42 | uint64_t rip; 43 | uint64_t cs; 44 | uint64_t rflags; 45 | uint64_t rsp; 46 | uint64_t ss; 47 | } __attribute__((packed)) int_frame_t; 48 | 49 | class IDT { 50 | public: 51 | static void Init(); 52 | static idt_entry_t* SetEntry(uint8_t vec,void* base,uint8_t flags); 53 | static uint8_t AllocEntry(); 54 | static void FreeEntry(uint8_t vec); 55 | static void Load(); 56 | }; -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/interrupts/ioapic.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | 6 | class IOAPIC { 7 | public: 8 | static void Init(); 9 | 10 | static void SetEntry(uint8_t vector,uint8_t irq,uint64_t flags,uint64_t lapic); 11 | 12 | static void Write(uint64_t phys_base,uint32_t reg,uint32_t value); 13 | static uint32_t Read(uint64_t phys_base,uint32_t reg); 14 | }; -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/interrupts/irq.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define IRQ_TYPE_OTHER 0 5 | #define IRQ_TYPE_LEGACY 1 // default irq, will be automatic configured with ioapic 6 | #define IRQ_TYPE_MSI 2 // can me msi-x too, need to be configured from pci driver 7 | 8 | typedef struct { 9 | void (*func)(void* arg); 10 | void* arg; 11 | } irq_t; 12 | 13 | class IRQ { 14 | public: 15 | static uint8_t Create(uint16_t irq,uint8_t type,void (*func)(void* arg),void* arg,uint64_t flags); 16 | }; -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/interrupts/syscalls/ipc/fd.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma once 8 | 9 | #define FD_NONE 0 10 | #define FD_FILE 1 11 | #define FD_PIPE 2 12 | 13 | #define PIPE_WAIT 0 14 | #define PIPE_INSTANT 1 15 | 16 | /* indices for the c_cc array in struct termios */ 17 | #define VINTR 0 18 | #define VQUIT 1 19 | #define VERASE 2 20 | #define VKILL 3 21 | #define VEOF 4 22 | #define VTIME 5 23 | #define VMIN 6 24 | #define VSWTC 7 25 | #define VSTART 8 26 | #define VSTOP 9 27 | #define VSUSP 10 28 | #define VEOL 11 29 | #define VREPRINT 12 30 | #define VDISCARD 13 31 | #define VWERASE 14 32 | #define VLNEXT 15 33 | #define VEOL2 16 34 | 35 | /* bitwise flags for c_iflag in struct termios */ 36 | #define IGNBRK 0000001 37 | #define BRKINT 0000002 38 | #define IGNPAR 0000004 39 | #define PARMRK 0000010 40 | #define INPCK 0000020 41 | #define ISTRIP 0000040 42 | #define INLCR 0000100 43 | #define IGNCR 0000200 44 | #define ICRNL 0000400 45 | #define IUCLC 0001000 46 | #define IXON 0002000 47 | #define IXANY 0004000 48 | #define IXOFF 0010000 49 | #define IMAXBEL 0020000 50 | #define IUTF8 0040000 51 | 52 | /* bitwise flags for c_oflag in struct termios */ 53 | #define OPOST 0000001 54 | #define OLCUC 0000002 55 | #define ONLCR 0000004 56 | #define OCRNL 0000010 57 | #define ONOCR 0000020 58 | #define ONLRET 0000040 59 | #define OFILL 0000100 60 | #define OFDEL 0000200 61 | 62 | #define NLDLY 0000400 63 | #define NL0 0000000 64 | #define NL1 0000400 65 | 66 | #define CRDLY 0003000 67 | #define CR0 0000000 68 | #define CR1 0001000 69 | #define CR2 0002000 70 | #define CR3 0003000 71 | 72 | #define TABDLY 0014000 73 | #define TAB0 0000000 74 | #define TAB1 0004000 75 | #define TAB2 0010000 76 | #define TAB3 0014000 77 | 78 | #define BSDLY 0020000 79 | #define BS0 0000000 80 | #define BS1 0020000 81 | 82 | #define FFDLY 0100000 83 | #define FF0 0000000 84 | #define FF1 0100000 85 | 86 | #define VTDLY 0040000 87 | #define VT0 0000000 88 | #define VT1 0040000 89 | 90 | /* bitwise constants for c_cflag in struct termios */ 91 | #define CSIZE 0000060 92 | #define CS5 0000000 93 | #define CS6 0000020 94 | #define CS7 0000040 95 | #define CS8 0000060 96 | 97 | #define CSTOPB 0000100 98 | #define CREAD 0000200 99 | #define PARENB 0000400 100 | #define PARODD 0001000 101 | #define HUPCL 0002000 102 | #define CLOCAL 0004000 103 | 104 | /* bitwise constants for c_lflag in struct termios */ 105 | #define ISIG 0000001 106 | #define ICANON 0000002 107 | #define ECHO 0000010 108 | #define ECHOE 0000020 109 | #define ECHOK 0000040 110 | #define ECHONL 0000100 111 | #define NOFLSH 0000200 112 | #define TOSTOP 0000400 113 | #define IEXTEN 0100000 114 | 115 | #define EXTA 0000016 116 | #define EXTB 0000017 117 | #define CBAUD 0010017 118 | #define CBAUDEX 0010000 119 | #define CIBAUD 002003600000 120 | #define CMSPAR 010000000000 121 | #define CRTSCTS 020000000000 122 | 123 | #define XCASE 0000004 124 | #define ECHOCTL 0001000 125 | #define ECHOPRT 0002000 126 | #define ECHOKE 0004000 127 | #define FLUSHO 0010000 128 | #define PENDIN 0040000 129 | #define EXTPROC 0200000 130 | 131 | #define TCGETS 0x5401 132 | #define TCSETS 0x5402 133 | #define TCSETSW 0x5403 134 | #define TCSETSF 0x5404 135 | #define TCGETA 0x5405 136 | #define TCSETA 0x5406 137 | #define TCSETAW 0x5407 138 | #define TCSETAF 0x5408 139 | #define TCSBRK 0x5409 140 | #define TCXONC 0x540A 141 | #define TCFLSH 0x540B 142 | #define TIOCEXCL 0x540C 143 | #define TIOCNXCL 0x540D 144 | #define TIOCSCTTY 0x540E 145 | #define TIOCGPGRP 0x540F 146 | #define TIOCSPGRP 0x5410 147 | #define TIOCOUTQ 0x5411 148 | #define TIOCSTI 0x5412 149 | #define TIOCGWINSZ 0x5413 150 | #define TIOCSWINSZ 0x5414 151 | #define TIOCMGET 0x5415 152 | #define TIOCMBIS 0x5416 153 | #define TIOCMBIC 0x5417 154 | #define TIOCMSET 0x5418 155 | #define TIOCGSOFTCAR 0x5419 156 | #define TIOCSSOFTCAR 0x541A 157 | #define FIONREAD 0x541B 158 | #define TIOCLINUX 0x541C 159 | #define TIOCCONS 0x541D 160 | #define TIOCGSERIAL 0x541E 161 | #define TIOCSSERIAL 0x541F 162 | #define TIOCPKT 0x5420 163 | #define FIONBIO 0x5421 164 | #define TIOCNOTTY 0x5422 165 | #define TIOCSETD 0x5423 166 | #define TIOCGETD 0x5424 167 | #define TCSBRKP 0x5425 168 | #define TIOCSBRK 0x5427 169 | #define TIOCCBRK 0x5428 170 | #define TIOCGSID 0x5429 171 | #define TCGETS2 3 172 | #define TCSETS2 3 173 | #define TCSETSW2 3 174 | #define TCSETSF2 3 175 | #define TIOCGRS485 0x542E 176 | #define TIOCSRS485 0x542F 177 | #define TIOCGPTN 3 178 | #define TIOCSPTLCK 3 179 | #define TIOCGDEV 3 180 | #define TCGETX 0x5432 181 | #define TCSETX 0x5433 182 | #define TCSETXF 0x5434 183 | #define TCSETXW 0x5435 184 | #define TIOCSIG 0x36 185 | #define TIOCVHANGUP 0x5437 186 | #define TIOCGPKT 3 187 | #define TIOCGPTLCK 3 188 | #define TIOCGEXCL 3 189 | #define TIOCGPTPEER 3 190 | #define TIOCGISO7816 3 191 | #define TIOCSISO7816 3 192 | #define FIONCLEX 0x5450 193 | #define FIOCLEX 0x5451 194 | #define FIOASYNC 0x5452 195 | #define TIOCSERCONFIG 0x5453 196 | #define TIOCSERGWILD 0x5454 197 | #define TIOCSERSWILD 0x5455 198 | #define TIOCGLCKTRMIOS 0x5456 199 | #define TIOCSLCKTRMIOS 0x5457 200 | #define TIOCSERGSTRUCT 0x5458 201 | #define TIOCSERGETLSR 0x5459 202 | #define TIOCSERGETMULTI 0x545A 203 | #define TIOCSERSETMULTI 0x545B 204 | #define TIOCMIWAIT 0x545C 205 | #define TIOCGICOUNT 0x545D 206 | #define TIOCPKT_DATA 0 207 | #define TIOCPKT_FLUSHREAD 1 208 | #define TIOCPKT_FLUSHWRITE 2 209 | #define TIOCPKT_STOP 4 210 | #define TIOCPKT_START 8 211 | #define TIOCPKT_NOSTOP 16 212 | #define TIOCPKT_DOSTOP 32 213 | #define TIOCPKT_IOCTL 64 214 | #define TIOCSER_TEMT 0x01 215 | 216 | typedef struct { 217 | unsigned short ws_row; 218 | unsigned short ws_col; 219 | unsigned short ws_xpixel; 220 | unsigned short ws_ypixel; 221 | } __attribute__((packed)) winsize_t; 222 | 223 | #define XTABS 0014000 224 | 225 | #define PIPE_SIDE_WRITE 1 226 | #define PIPE_SIDE_READ 2 227 | 228 | typedef struct fd_struct { 229 | int index; 230 | 231 | process_t* proc; 232 | struct fd_struct* parent; 233 | struct fd_struct* next; 234 | 235 | long seek_offset; 236 | 237 | char type; 238 | 239 | char pipe_side; 240 | 241 | uint8_t is_pipe_pointer; 242 | uint8_t old_is_pipe_pointer; 243 | pipe_t pipe; 244 | pipe_t* old_p_pipe; 245 | pipe_t* p_pipe; 246 | 247 | uint64_t flags; 248 | filestat_t reserved_stat; 249 | 250 | char is_pipe_dup2; 251 | 252 | char old_type; 253 | 254 | char path_point[2048]; 255 | 256 | } __attribute__((packed)) fd_t; 257 | 258 | class FD { 259 | public: 260 | static int Create(process_t* proc,char is_pipe); 261 | static fd_t* Search(process_t* proc,int index); 262 | }; -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/interrupts/syscalls/ipc/pipe.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #pragma once 5 | 6 | typedef unsigned char cc_t; 7 | typedef unsigned int speed_t; 8 | typedef unsigned int tcflag_t; 9 | 10 | #define NCCS 32 11 | 12 | typedef struct { 13 | tcflag_t c_iflag; 14 | tcflag_t c_oflag; 15 | tcflag_t c_cflag; 16 | tcflag_t c_lflag; 17 | cc_t c_line; 18 | cc_t c_cc[NCCS]; 19 | speed_t ibaud; 20 | speed_t obaud; 21 | } __attribute__((packed)) termios_t; 22 | 23 | typedef struct pipe { 24 | 25 | char* buffer; 26 | char* old_buffer; 27 | uint64_t buffer_size; 28 | 29 | uint64_t buffer_read_ptr; 30 | 31 | process_t* parent; 32 | 33 | int type; 34 | int is_used; 35 | char is_eof; 36 | 37 | char connected_pipes; 38 | 39 | uint32_t reserved; 40 | 41 | termios_t termios; 42 | 43 | _Atomic char is_received; 44 | 45 | } __attribute__((packed)) pipe_t; -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/interrupts/syscalls/syscall.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #define STAR_MSR 0xC0000081 6 | #define LSTAR 0xC0000082 7 | #define STAR_MASK 0xC0000084 8 | #define EFER 0xC0000080 9 | 10 | typedef struct { 11 | uint32_t num; 12 | int (*func)(int_frame_t* frame); 13 | } syscall_t; 14 | 15 | #define S_IFMT 0x0F000 16 | #define S_IFBLK 0x06000 17 | #define S_IFCHR 0x02000 18 | #define S_IFIFO 0x01000 19 | #define S_IFREG 0x08000 20 | #define S_IFDIR 0x04000 21 | #define S_IFLNK 0x0A000 22 | #define S_IFSOCK 0x0C000 23 | 24 | #define EPERM 1 25 | #define ENOENT 2 26 | #define ESRCH 3 27 | #define EINTR 4 28 | #define EIO 5 29 | #define ENXIO 6 30 | #define E2BIG 7 31 | #define ENOEXEC 8 32 | #define EBADF 9 33 | #define ECHILD 10 34 | #define EAGAIN 11 35 | #define ENOMEM 12 36 | #define EACCES 13 37 | #define EFAULT 14 38 | #define ENOTBLK 15 39 | #define EBUSY 16 40 | #define EEXIST 17 41 | #define EXDEV 18 42 | #define ENODEV 19 43 | #define ENOTDIR 20 44 | #define EISDIR 21 45 | #define EINVAL 22 46 | #define ENFILE 23 47 | #define EMFILE 24 48 | #define ENOTTY 25 49 | #define ETXTBSY 26 50 | #define EFBIG 27 51 | #define ENOSPC 28 52 | #define ESPIPE 29 53 | #define EROFS 30 54 | #define EMLINK 31 55 | #define EPIPE 32 56 | #define EDOM 33 57 | #define ERANGE 34 58 | #define EDEADLK 35 59 | #define ENAMETOOLONG 36 60 | #define ENOLCK 37 61 | #define ENOSYS 38 62 | #define ENOTEMPTY 39 63 | #define ELOOP 40 64 | #define EWOULDBLOCK EAGAIN 65 | #define ENOMSG 42 66 | #define EIDRM 43 67 | #define ECHRNG 44 68 | #define EL2NSYNC 45 69 | #define EL3HLT 46 70 | #define EL3RST 47 71 | #define ELNRNG 48 72 | #define EUNATCH 49 73 | #define ENOCSI 50 74 | #define EL2HLT 51 75 | #define EBADE 52 76 | #define EBADR 53 77 | #define EXFULL 54 78 | #define ENOANO 55 79 | #define EBADRQC 56 80 | #define EBADSLT 57 81 | #define EDEADLOCK EDEADLK 82 | #define EBFONT 59 83 | #define ENOSTR 60 84 | #define ENODATA 61 85 | #define ETIME 62 86 | #define ENOSR 63 87 | #define ENONET 64 88 | #define ENOPKG 65 89 | #define EREMOTE 66 90 | #define ENOLINK 67 91 | #define EADV 68 92 | #define ESRMNT 69 93 | #define ECOMM 70 94 | #define EPROTO 71 95 | #define EMULTIHOP 72 96 | #define EDOTDOT 73 97 | #define EBADMSG 74 98 | #define EOVERFLOW 75 99 | #define ENOTUNIQ 76 100 | #define EBADFD 77 101 | #define EREMCHG 78 102 | #define ELIBACC 79 103 | #define ELIBBAD 80 104 | #define ELIBSCN 81 105 | #define ELIBMAX 82 106 | #define ELIBEXEC 83 107 | #define EILSEQ 84 108 | #define ERESTART 85 109 | #define ESTRPIPE 86 110 | #define EUSERS 87 111 | #define ENOTSOCK 88 112 | #define EDESTADDRREQ 89 113 | #define EMSGSIZE 90 114 | #define EPROTOTYPE 91 115 | #define ENOPROTOOPT 92 116 | #define EPROTONOSUPPORT 93 117 | #define ESOCKTNOSUPPORT 94 118 | #define EOPNOTSUPP 95 119 | #define ENOTSUP EOPNOTSUPP 120 | #define EPFNOSUPPORT 96 121 | #define EAFNOSUPPORT 97 122 | #define EADDRINUSE 98 123 | #define EADDRNOTAVAIL 99 124 | #define ENETDOWN 100 125 | #define ENETUNREACH 101 126 | #define ENETRESET 102 127 | #define ECONNABORTED 103 128 | #define ECONNRESET 104 129 | #define ENOBUFS 105 130 | #define EISCONN 106 131 | #define ENOTCONN 107 132 | #define ESHUTDOWN 108 133 | #define ETOOMANYREFS 109 134 | #define ETIMEDOUT 110 135 | #define ECONNREFUSED 111 136 | #define EHOSTDOWN 112 137 | #define EHOSTUNREACH 113 138 | #define EALREADY 114 139 | #define EINPROGRESS 115 140 | #define ESTALE 116 141 | #define EUCLEAN 117 142 | #define ENOTNAM 118 143 | #define ENAVAIL 119 144 | #define EISNAM 120 145 | #define EREMOTEIO 121 146 | #define EDQUOT 122 147 | #define ENOMEDIUM 123 148 | #define EMEDIUMTYPE 124 149 | #define ECANCELED 125 150 | #define ENOKEY 126 151 | #define EKEYEXPIRED 127 152 | #define EKEYREVOKED 128 153 | #define EKEYREJECTED 129 154 | #define EOWNERDEAD 130 155 | #define ENOTRECOVERABLE 131 156 | #define ERFKILL 132 157 | #define EHWPOISON 133 158 | 159 | #define S_IRWXU 0700 160 | #define S_IRUSR 0400 161 | #define S_IWUSR 0200 162 | #define S_IXUSR 0100 163 | #define S_IRWXG 070 164 | #define S_IRGRP 040 165 | #define S_IWGRP 020 166 | #define S_IXGRP 010 167 | #define S_IRWXO 07 168 | #define S_IROTH 04 169 | #define S_IWOTH 02 170 | #define S_IXOTH 01 171 | #define S_ISUID 04000 172 | #define S_ISGID 02000 173 | #define S_ISVTX 01000 174 | 175 | #define AT_FDCWD -100 176 | #define AT_SYMLINK_NOFOLLOW 0x100 177 | #define AT_REMOVEDIR 0x200 178 | #define AT_SYMLINK_FOLLOW 0x400 179 | #define AT_EACCESS 0x200 180 | #define AT_NO_AUTOMOUNT 0x800 181 | #define AT_EMPTY_PATH 0x1000 182 | 183 | struct timespec { 184 | long tv_sec; 185 | long tv_nsec; 186 | }; 187 | 188 | typedef unsigned long dev_t; 189 | 190 | typedef struct { 191 | unsigned long st_dev; 192 | unsigned long st_ino; 193 | unsigned long st_nlink; 194 | unsigned int st_mode; 195 | unsigned int st_uid; 196 | unsigned int st_gid; 197 | unsigned int __pad0; 198 | unsigned long st_rdev; 199 | long st_size; 200 | long st_blksize; 201 | long st_blocks; 202 | 203 | } __attribute__((packed)) stat_t; 204 | 205 | #define __MLIBC_DIRENT_BODY uint64_t d_ino; \ 206 | uint64_t d_off; \ 207 | unsigned short d_reclen; \ 208 | unsigned char d_type; \ 209 | char d_name[1024]; 210 | 211 | typedef struct { 212 | __MLIBC_DIRENT_BODY 213 | } dirent_t; 214 | 215 | #define O_PATH 010000000 216 | 217 | #define O_ACCMODE (03 | O_PATH) 218 | #define O_RDONLY 00 219 | #define O_WRONLY 01 220 | #define O_RDWR 02 221 | 222 | #define O_CREAT 0100 223 | #define O_EXCL 0200 224 | #define O_NOCTTY 0400 225 | #define O_TRUNC 01000 226 | #define O_APPEND 02000 227 | #define O_NONBLOCK 04000 228 | #define O_DSYNC 010000 229 | #define O_ASYNC 020000 230 | #define O_DIRECT 040000 231 | #define O_DIRECTORY 0200000 232 | #define O_NOFOLLOW 0400000 233 | #define O_CLOEXEC 02000000 234 | #define O_SYNC 04010000 235 | #define O_RSYNC 04010000 236 | #define O_LARGEFILE 0100000 237 | #define O_NOATIME 01000000 238 | #define O_TMPFILE 020000000 239 | 240 | typedef struct { 241 | char sysname[65]; 242 | char nodename[65]; 243 | char release[65]; 244 | char version[65]; 245 | char machine[65]; 246 | } __attribute__((packed)) utsname_t; 247 | 248 | enum 249 | { 250 | DT_UNKNOWN = 0, 251 | # define DT_UNKNOWN DT_UNKNOWN 252 | DT_FIFO = 1, 253 | # define DT_FIFO DT_FIFO 254 | DT_CHR = 2, 255 | # define DT_CHR DT_CHR 256 | DT_DIR = 4, 257 | # define DT_DIR DT_DIR 258 | DT_BLK = 6, 259 | # define DT_BLK DT_BLK 260 | DT_REG = 8, 261 | # define DT_REG DT_REG 262 | DT_LNK = 10, 263 | # define DT_LNK DT_LNK 264 | DT_SOCK = 12, 265 | # define DT_SOCK DT_SOCK 266 | DT_WHT = 14 267 | # define DT_WHT DT_WHT 268 | }; 269 | 270 | class Syscall { 271 | public: 272 | static void Init(); 273 | }; -------------------------------------------------------------------------------- /kernel/src/include/arch/x86_64/scheduling/scheduling.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #pragma once 6 | 7 | #define PROCESS_TYPE_PROCESS 0 8 | #define PROCESS_TYPE_THREAD 1 9 | #define PROCESS_TYPE_STACK_DEALLOCATED 2 10 | 11 | #define PROCESS_STATUS_RUN 0 12 | #define PROCESS_STATUS_IN_USE 1 13 | #define PROCESS_STATUS_KILLED 2 14 | #define PROCESS_STATUS_BLOCKED 3 15 | #define PROCESS_STATUS_WAITING 4 16 | 17 | typedef struct process_struct { 18 | uint64_t id; 19 | int return_status; 20 | 21 | struct process_struct* next; 22 | 23 | char type; 24 | char status; 25 | char user; 26 | char* cwd; 27 | char* name; 28 | 29 | char* vmm_start; 30 | char* vmm_last; 31 | 32 | uint64_t* stack; 33 | uint64_t* stack_start; // to free if process killed 34 | 35 | uint64_t user_stack_start; 36 | 37 | uint64_t* wait_stack; // to waitings in syscall 38 | int_frame_t* syscall_wait_ctx; 39 | 40 | uint64_t fs_base; 41 | 42 | uint64_t parent_process; // for threads 43 | 44 | int* futex; // for futex 45 | 46 | int fd_ptr; 47 | char* start_fd; // i cant include loop sooo i just put char* 48 | char* last_fd; // optimizations 49 | 50 | uint8_t cs; 51 | uint8_t ss; 52 | 53 | char* wait_pipe; 54 | 55 | char is_eoi; 56 | char is_cli; 57 | 58 | char is_waitpid_used; 59 | 60 | uint64_t nah_cr3; 61 | 62 | int_frame_t ctx; 63 | char* sse_ctx; 64 | } __attribute__((packed)) process_t; 65 | 66 | extern "C" void schedulingEnd(int_frame_t* ctx,uint64_t* cr3); 67 | extern "C" void schedulingStub(); 68 | 69 | extern "C" void schedulingSchedule(int_frame_t* frame); 70 | extern "C" void schedulingScheduleStack(int_frame_t* frame); 71 | 72 | process_t* get_head_proc(); 73 | 74 | class Process { 75 | public: 76 | 77 | static void Init(); 78 | 79 | static process_t* ByID(uint64_t id); 80 | 81 | static uint64_t createProcess(uint64_t rip,char is_thread,char is_user,uint64_t* cr3_parent,uint64_t parent_id); 82 | 83 | static void WakeUp(uint64_t id); 84 | 85 | static uint64_t createThread(uint64_t rip,uint64_t parent); 86 | 87 | static int loadELFProcess(uint64_t procid,char* path,uint8_t* elf,char** argv,char** envp); 88 | 89 | static void futexWait(process_t* proc, int* lock,int val); 90 | 91 | static void futexWake(process_t* parent,int* lock); 92 | 93 | static void Kill(process_t* proc,int return_status); 94 | 95 | }; -------------------------------------------------------------------------------- /kernel/src/include/config.hpp: -------------------------------------------------------------------------------- 1 | #define PAGE_SIZE 4096 2 | #define SIZE_KHEAP_IN_PAGES 4096 // 16 MB kernel heap :^) 3 | #define TSS_STACK_IN_PAGES 64 4 | #define MAX_MOUNT_POINTS 512 5 | #define PROCESS_STACK_SIZE 256 6 | #define TMPFS_MAX_SIZE 1073741824 // 1G 7 | #define XHCI_RESET_TIMEOUT 1000 8 | 9 | #define DEBUG_PRINT 10 | 11 | // #define NO_DEBUG_LEVEL -------------------------------------------------------------------------------- /kernel/src/include/drivers/cmos/cmos.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #pragma once 5 | 6 | #define CMOS_ADDRESS 0x70 7 | #define CMOS_DATA 0x71 8 | #define CMOS_SECONDS 0x00 9 | #define CMOS_MINUTES 0x02 10 | #define CMOS_HOURS 0x04 11 | #define CMOS_DAY 0x07 12 | #define CMOS_MONTH 0x08 13 | #define CMOS_YEAR 0x09 14 | 15 | class CMOS { 16 | public: 17 | static uint8_t Second(); 18 | 19 | static uint8_t Minute(); 20 | 21 | static uint8_t Hour(); 22 | 23 | static uint8_t Day(); 24 | 25 | static uint8_t Month(); 26 | 27 | static uint16_t Year(); 28 | 29 | }; -------------------------------------------------------------------------------- /kernel/src/include/drivers/hpet/hpet.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | 6 | class HPET { 7 | public: 8 | static void Init(); 9 | static void Sleep(uint64_t usec); 10 | static uint64_t NanoCurrent(); 11 | }; -------------------------------------------------------------------------------- /kernel/src/include/drivers/io/io.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | 6 | typedef struct { 7 | uint64_t base; 8 | uint64_t len; 9 | } __attribute__((packed)) uacpi_io_struct_t; 10 | 11 | class IO { 12 | public: 13 | 14 | static uint32_t IN(uint16_t port,uint8_t bytewidth); 15 | 16 | static void OUT(uint16_t port,uint32_t value,uint8_t bytewidth); 17 | 18 | }; 19 | -------------------------------------------------------------------------------- /kernel/src/include/drivers/pci/pci.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #pragma once 5 | 6 | typedef struct { 7 | uint16_t vendorID; 8 | uint16_t deviceID; 9 | uint16_t command; 10 | uint16_t status; 11 | uint8_t revisionID; 12 | uint8_t progIF; 13 | uint8_t subclass; 14 | uint8_t _class; 15 | uint8_t cacheLineSize; 16 | uint8_t latencyTimer; 17 | uint8_t headerType; 18 | uint8_t bist; 19 | uint32_t bar0; 20 | uint32_t bar1; 21 | uint32_t bar2; 22 | uint32_t bar3; 23 | uint32_t bar4; 24 | uint32_t bar5; 25 | uint32_t cardbusCISPointer; 26 | uint16_t subsystemVendorID; 27 | uint16_t subsystemID; 28 | uint32_t expansionROMBaseAddress; 29 | uint8_t capabilitiesPointer; 30 | uint8_t reserved0; 31 | uint16_t reserved1; 32 | uint32_t reserved2; 33 | uint8_t irq; 34 | uint8_t interruptPIN; 35 | uint8_t minGrant; 36 | uint8_t maxLatency; 37 | } __attribute__((packed)) pci_t; 38 | 39 | typedef struct { 40 | int used; 41 | uint8_t _class; 42 | uint8_t subclass; 43 | void (*pcidrv)(pci_t, uint8_t, uint8_t, uint8_t); 44 | } __attribute__((packed)) pci_driver_t; 45 | 46 | #define PCI_BAR_MASK ((1 << 0) | (1 << 1)) 47 | 48 | class PCI { 49 | public: 50 | static uint32_t IN(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset,uint8_t bytewidth); 51 | 52 | static void OUT(uint8_t bus, uint8_t num, uint8_t function, uint8_t offset,uint32_t value,uint8_t bytewidth); 53 | 54 | static uint8_t Reg(void (*pcidrv)(pci_t, uint8_t, uint8_t, uint8_t), uint8_t _class, uint8_t subclass); 55 | 56 | static void Init(); 57 | }; -------------------------------------------------------------------------------- /kernel/src/include/drivers/power_button/power_button.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #pragma once 5 | 6 | class PowerButton { 7 | public: 8 | static void Hook( uacpi_interrupt_ret (*func)(uacpi_handle ctx)); 9 | 10 | }; -------------------------------------------------------------------------------- /kernel/src/include/drivers/ps2keyboard/ps2keyboard.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #pragma once 6 | 7 | #define PS2K_PNP_ID "PNP0303" 8 | #define SHIFT_PRESSED 0x2A 9 | #define SHIFT_RELEASED 0xAA 10 | 11 | typedef struct ps2keyboard_pipe_struct { 12 | _Atomic char is_used_anymore; 13 | pipe_t* pipe; 14 | struct ps2keyboard_pipe_struct* next; 15 | } __attribute__((packed)) ps2keyboard_pipe_struct_t; 16 | 17 | class PS2Keyboard { 18 | public: 19 | static void Init(void (*key)()); 20 | static void EOI(); 21 | static short Get(); 22 | }; -------------------------------------------------------------------------------- /kernel/src/include/drivers/serial/serial.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define COM1 0x3F8 9 | 10 | void __serial_process_fetch(); 11 | 12 | class Serial { 13 | public: 14 | static void Init(); 15 | static uint8_t Read(); 16 | static void Write(uint8_t data); 17 | static void WriteArray(uint8_t* data,uint64_t len); 18 | static void WriteString(const char* str); 19 | static void printf(char* format, ...); 20 | }; 21 | -------------------------------------------------------------------------------- /kernel/src/include/drivers/xhci/xhci.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #pragma once 5 | 6 | typedef struct { 7 | uint32_t maxslots : 8; 8 | uint32_t maxintrs : 11; 9 | uint32_t reserved1 : 5; 10 | uint32_t maxports : 8; 11 | } __attribute__((packed)) hcsparams1_t; 12 | 13 | typedef struct { 14 | uint32_t ist : 4; 15 | uint32_t erstmax : 4; 16 | uint32_t reserved1 : 13; 17 | uint32_t max_scratchpad_hi : 5; 18 | uint32_t spr : 1; 19 | uint32_t max_scratchpad_lo : 5; 20 | } __attribute__((packed)) hcsparams2_t; 21 | 22 | typedef struct { 23 | uint8_t caplength; 24 | uint8_t reserved; 25 | uint16_t hciversion; 26 | hcsparams1_t hcsparams1; 27 | hcsparams2_t hcsparams2; 28 | uint32_t hcsparams3; 29 | uint32_t hccparams1; 30 | uint32_t dboff; 31 | uint32_t rtsoff; 32 | uint32_t hccparms2; 33 | } xhci_cap_regs_t; 34 | 35 | typedef struct { 36 | uint32_t usbcmd; 37 | uint32_t usbsts; 38 | uint32_t pagesize; 39 | uint32_t reserved1[2]; 40 | uint32_t dnctrl; 41 | uint64_t crcr; 42 | uint32_t reserved2[4]; 43 | uint64_t dcbaap; 44 | uint32_t config; 45 | } xhci_op_regs_t; 46 | 47 | #define XHCI_USBCMD_RS (1 << 0) 48 | #define XHCI_USBCMD_HOSTCONTROLLERREST (1 << 1) 49 | 50 | typedef struct { 51 | uint32_t portsc; 52 | uint32_t portpmsc; 53 | uint32_t portli; 54 | } xhci_port_regs_t; 55 | 56 | typedef struct { 57 | uint64_t erst_segment : 3; 58 | uint64_t event_busy : 1; 59 | uint64_t event_ring_pointer : 60; 60 | } xhci_erdp_t; 61 | 62 | typedef struct { 63 | uint32_t iman; 64 | uint32_t imod; 65 | uint32_t erstsz; 66 | uint32_t reserved0; 67 | uint64_t erstba; 68 | union { 69 | xhci_erdp_t erdp; 70 | uint64_t erdp_val; 71 | }; 72 | } IR_t; 73 | 74 | typedef struct { 75 | uint32_t mfindex; 76 | uint32_t reserved1[7]; 77 | IR_t int_regs[1024]; 78 | } xhci_runtime_regs_t; 79 | 80 | typedef struct { 81 | uint64_t base; 82 | uint32_t size; 83 | uint32_t reserved0; 84 | } xhci_erst_t; 85 | 86 | typedef struct { 87 | uint32_t cycle : 1; 88 | uint32_t nexttrb : 1; 89 | uint32_t interruptonshort : 1; 90 | uint32_t nosnoop : 1; 91 | uint32_t chain : 1; 92 | uint32_t intoncompletion : 1; 93 | uint32_t immediate : 1; 94 | uint32_t reserved1 : 2; 95 | uint32_t blockeventint : 1; 96 | uint32_t type : 6; 97 | uint32_t reserved2 : 16; 98 | } xhci_trb_info_t; 99 | 100 | typedef struct { 101 | uint64_t base; 102 | uint32_t status; 103 | union { 104 | xhci_trb_info_t info_s; 105 | uint32_t info; 106 | }; 107 | } xhci_trb_t; 108 | 109 | typedef struct { 110 | uint8_t cycle; 111 | uint16_t trb_limit; 112 | uint64_t queue; 113 | xhci_trb_t* trb; 114 | } xhci_command_ring_ctx_t; 115 | 116 | typedef struct { 117 | uint16_t trb_limit; 118 | uint64_t queue; 119 | uint8_t cycle; 120 | IR_t* father; 121 | xhci_trb_t* trb; 122 | xhci_erst_t* table; 123 | } xhci_event_ring_ctx_t; 124 | 125 | typedef struct xhci_device { 126 | uint64_t xhci_phys_base; 127 | uint64_t xhci_virt_base; 128 | uint64_t dcbaa; // i can read from op->dcbaap but its will return 0 129 | uint16_t calculated_scratchpad_count; 130 | xhci_cap_regs_t* cap; 131 | xhci_op_regs_t* op; 132 | xhci_port_regs_t* port; 133 | xhci_runtime_regs_t* runtime; 134 | uint32_t* doorbell; 135 | xhci_command_ring_ctx_t* com_ring; 136 | xhci_event_ring_ctx_t* event_ring; 137 | struct xhci_device* next; 138 | } __attribute__((packed)) xhci_device_t; 139 | 140 | class XHCI { 141 | public: 142 | static void Init(); 143 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/VFS/devfs.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #pragma once 6 | 7 | typedef struct devfs_dev { 8 | 9 | int (*write)(char* buffer,uint64_t size); 10 | int (*read)(char* buffer,long hint_size); 11 | int (*askforpipe)(pipe_t* pipe); 12 | int (*instantreadpipe)(pipe_t* pipe); 13 | int (*ioctl)(unsigned long request, void* arg, void* result); 14 | 15 | struct devfs_dev* next; 16 | 17 | char loc[2048]; 18 | 19 | 20 | } __attribute__((packed)) devfs_dev_t; 21 | 22 | void devfs_reg_device(const char* name,int (*write)(char* buffer,uint64_t size),int (*read)(char* buffer,long hint_size),int (*askforpipe)(pipe_t* pipe),int (*instantreadpipe)(pipe_t* pipe),int (*ioctl)(unsigned long request, void* arg, void* result)); 23 | 24 | void devfs_init(filesystem_t* fs); -------------------------------------------------------------------------------- /kernel/src/include/generic/VFS/procfs.hpp: -------------------------------------------------------------------------------- 1 | 2 | // i'll use it only for neofetch :^) 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | 9 | typedef struct procfs_data { 10 | 11 | int (*read)(char* buffer,long hint_size); 12 | 13 | struct procfs_data* next; 14 | char loc[2048]; 15 | 16 | } __attribute__((packed)) procfs_data_t; 17 | 18 | class ProcFS { 19 | public: 20 | static void Init(filesystem_t* fs); 21 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/VFS/tmpfs.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma once 8 | 9 | #define TMPFS_TYPE_FILE 0 10 | #define TMPFS_TYPE_DIRECTORY 1 11 | #define TMPFS_TYPE_SYMLINK 2 12 | 13 | typedef struct data_file { 14 | int count[2]; 15 | char type; 16 | char* name; 17 | char* content; 18 | char protection; 19 | uint32_t mode; 20 | uint32_t size_of_content; 21 | uint64_t file_create_date; 22 | uint64_t file_change_date; 23 | struct data_file* next; 24 | struct data_file* parent; 25 | } __attribute__((packed)) data_file_t; 26 | 27 | void tmpfs_dump(); 28 | 29 | class TMPFS { 30 | public: 31 | static void Init(filesystem_t* fs); 32 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/VFS/ustar.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | typedef struct { 5 | char file_name[100]; 6 | char file_mode[8]; 7 | char owner_id[8]; 8 | char group_id[8]; 9 | char file_size[12]; 10 | char last_modific[12]; 11 | char checksum[8]; 12 | char type; 13 | char name_linked[100]; 14 | char ustar[6]; 15 | char ustar_ver[2]; 16 | char owner_name[32]; 17 | char group_name[32]; 18 | char dev_major_num[8]; 19 | char dev_minor_num[8]; 20 | char filename_prefix[155]; 21 | } __attribute__((packed)) ustar_t; 22 | 23 | void resolve_path(const char* inter,const char* base, char *result,char spec); // path resolver 24 | 25 | class USTAR { 26 | public: 27 | static void ParseAndCopy(); 28 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/VFS/vfs.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #pragma once 6 | 7 | #define STATUS_OK 0 8 | #define STATUS_NOT_IMPLEMENTED -1 9 | #define STATUS_ERROR -2 10 | 11 | #define VFS_TYPE_FILE 0 12 | #define VFS_TYPE_DIRECTORY 1 13 | #define VFS_TYPE_SYMLINK 2 14 | 15 | #define SUBSTATUS_TTY 99 16 | 17 | typedef struct { 18 | char i; // not implemented 19 | } disk_t; 20 | 21 | typedef struct { 22 | 23 | char type; 24 | char sub_type; 25 | 26 | char* name; 27 | 28 | char* content; 29 | 30 | uint64_t mode; 31 | uint32_t size; 32 | 33 | int idx; 34 | 35 | uint64_t file_create_date; 36 | uint64_t file_change_date; 37 | 38 | char fs_prefix1; 39 | char fs_prefix2; 40 | char fs_prefix3; 41 | 42 | } __attribute__((packed)) filestat_t; 43 | 44 | typedef struct { 45 | int (*readfile)(char* buffer,char* filename,long hint_size); 46 | int (*writefile)(char* buffer,char* filename,uint64_t size,char is_symlink_path,uint64_t offset); 47 | int (*touch)(char* filename); 48 | int (*create)(char* filename,int type); 49 | int (*rm)(char* filename); 50 | 51 | char (*exists)(char* filename); 52 | int (*stat)(char* filename,char* buffer,char follow_symlinks); 53 | 54 | int (*iterate)(filestat_t* stat); 55 | 56 | int (*askforpipe)(char* filename,pipe_t* pipe); 57 | int (*instantreadpipe)(char* filename, pipe_t* pipe); 58 | 59 | int (*chmod)(char* filename,uint64_t mode); 60 | 61 | int (*count)(char* filename,int idx,int count); 62 | 63 | int (*ioctl)(char* filename,unsigned long request, void *arg, int *result); 64 | 65 | char is_in_ram; 66 | disk_t* disk; 67 | 68 | } filesystem_t; 69 | 70 | typedef struct { 71 | char* loc; 72 | filesystem_t* fs; 73 | } mount_location_t; 74 | 75 | class VFS { 76 | public: 77 | static void Init(); 78 | static int Read(char* buffer,char* filename,long hint_size); 79 | static int Write(char* buffer,char* filename,uint64_t size,char is_symlink_path,uint64_t offset); 80 | static int Touch(char* filename); 81 | static int Create(char* filename,int type); 82 | static int Remove(char* filename); 83 | static char Exists(char* filename); 84 | static int Stat(char* filename,char* buffer,char follow_symlinks); 85 | static int AskForPipe(char* filename,pipe_t* pipe); 86 | static int InstantPipeRead(char* filename,pipe_t* pipe); 87 | static int Iterate(char* filename,filestat_t* stat); 88 | static int Chmod(char* filename,uint64_t mode); 89 | static int Ioctl(char* filename,unsigned long request, void *arg, int *result); 90 | static int Count(char* filename,int idx,int count); 91 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/acpi/acpi.hpp: -------------------------------------------------------------------------------- 1 | 2 | class ACPI { 3 | public: 4 | static void InitTables(); 5 | static void fullInit(); 6 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/elf/elf.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #pragma once 6 | 7 | #define MIN2(a, b) ((a) < (b) ? (a) : (b)) 8 | #define MAX2(a, b) ((a) > (b) ? (a) : (b)) 9 | 10 | typedef struct { 11 | unsigned char e_ident[16]; 12 | uint16_t e_type; 13 | uint16_t e_machine; 14 | uint32_t e_version; 15 | uint64_t e_entry; 16 | uint64_t e_phoff; 17 | uint64_t e_shoff; 18 | uint32_t e_flags; 19 | uint16_t e_ehsize; 20 | uint16_t e_phentsize; 21 | uint16_t e_phnum; 22 | uint16_t e_shentsize; 23 | uint16_t e_shnum; 24 | uint16_t e_shstrndx; 25 | } __attribute__((packed)) elfheader_t; 26 | 27 | typedef struct { 28 | uint32_t p_type; 29 | uint32_t p_flags; 30 | uint64_t p_offset; 31 | uint64_t p_vaddr; 32 | uint64_t p_paddr; 33 | uint64_t p_filesz; 34 | uint64_t p_memsz; 35 | uint64_t p_align; 36 | } __attribute__((packed)) elfprogramheader_t; 37 | 38 | typedef struct { 39 | void (*entry)(); 40 | uint64_t* ready_stack; 41 | uint64_t argc; 42 | char** argv; 43 | char** envp; 44 | uint64_t* phys_cr3; 45 | } __attribute__((packed)) ELFLoadResult; 46 | 47 | enum ELF_Type { 48 | PT_NULL, 49 | PT_LOAD, 50 | PT_DYNAMIC, 51 | PT_INTERP, 52 | PT_NOTE, 53 | PT_SHLIB, 54 | PT_PHDR, 55 | PT_LOPROC=0x70000000, //reserved 56 | PT_HIPROC=0x7FFFFFFF //reserved 57 | }; 58 | 59 | typedef enum { 60 | ET_NONE = 0, 61 | ET_REL = 1, 62 | ET_EXEC = 2, 63 | ET_DYN = 3, 64 | ET_CORE = 4, 65 | ET_LOPROC = 0xff00, 66 | ET_HIPROC = 0xffff 67 | } obj_type_t; 68 | 69 | typedef enum { 70 | AT_NULL = 0, 71 | AT_IGNORE = 1, 72 | AT_EXECFD = 2, 73 | AT_PHDR = 3, 74 | AT_PHENT = 4, 75 | AT_PHNUM = 5, 76 | AT_PAGESZ = 6, 77 | AT_BASE = 7, 78 | AT_FLAGS = 8, 79 | AT_ENTRY = 9, 80 | AT_NOTELF = 10, 81 | AT_UID = 11, 82 | AT_EUID = 12, 83 | AT_GID = 13, 84 | AT_EGID = 14, 85 | AT_PLATFORM = 15, 86 | AT_HWCAP = 16, 87 | AT_CLKTCK = 17, 88 | AT_SECURE = 23, 89 | AT_BASE_PLATFORM = 24, 90 | AT_RANDOM = 25, 91 | AT_HWCAP2 = 26, 92 | AT_RSEQ_FEATURE_SIZE = 27, 93 | AT_RSEQ_ALIGN = 28, 94 | AT_HWCAP3 = 29, 95 | AT_HWCAP4 = 30, 96 | AT_EXECFN = 31 97 | } auxv_t; 98 | 99 | class ELF { 100 | public: 101 | static ELFLoadResult Load(uint8_t* base,uint64_t* cr3,uint64_t flags,uint64_t* stack,char** argv,char** envp,process_t* proc); 102 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/limineA/limineinfo.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #pragma once 6 | 7 | class LimineInfo { 8 | public: 9 | 10 | struct limine_memmap_response* memmap; 11 | struct limine_executable_address_response* ker_addr; 12 | struct limine_framebuffer* fb_info; 13 | struct limine_module_response* initrd; 14 | struct LIMINE_MP(response)* smp; 15 | uint64_t rsdp_address; 16 | uint64_t hhdm_offset; 17 | char* bootloader_name; 18 | char* bootloader_version; 19 | 20 | LimineInfo(); 21 | 22 | 23 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/locks/spinlock.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | void spinlock_lock(char* lock); 5 | 6 | void spinlock_unlock(char* lock); -------------------------------------------------------------------------------- /kernel/src/include/generic/memory/heap.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #pragma once 5 | 6 | typedef struct kernel_heap_block { 7 | uint64_t size; 8 | uint8_t isfree; 9 | struct kernel_heap_block* next; 10 | } kernel_heap_block_t; 11 | 12 | class KHeap { 13 | public: 14 | static void* Malloc(uint64_t size); 15 | 16 | static void Free(void* ptr); 17 | 18 | static void Init(); 19 | 20 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/memory/paging.hpp: -------------------------------------------------------------------------------- 1 | 2 | // i'll use hhdm 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | #define PTE_PRESENT (1ull << 0) 10 | #define PTE_RW (1ull << 1) 11 | #define PTE_USER (1ull << 2) 12 | #define PTE_WC (1ull << 3) 13 | #define PTE_MMIO (1ull << 4) 14 | 15 | #define ROUNDUP(VALUE,ROUND) ((VALUE + (ROUND - 1)) / ROUND) 16 | #define ALIGNPAGEUP(VALUE) (ROUNDUP(VALUE,PAGE_SIZE) * PAGE_SIZE) 17 | #define ALIGNPAGEDOWN(VALUE) ((VALUE / PAGE_SIZE) * PAGE_SIZE) 18 | 19 | #define CROUNDUP(VALUE,ROUND) ((VALUE + (ROUND - 1)) / ROUND) 20 | #define CALIGNPAGEUP(VALUE,c) ((VALUE + c - 1) & ~(c - 1)) 21 | #define CALIGNPAGEDOWN(VALUE,c) ((VALUE / c) * c) 22 | 23 | #define PTE_MASK_VALUE 0x000ffffffffff000 24 | 25 | #define PTE_INDEX(address,bit) ((address & (uint64_t)0x1FF << bit) >> bit) 26 | 27 | typedef struct alwaysMapped { 28 | uint64_t base; 29 | uint64_t size; 30 | char is_phys; 31 | struct alwaysMapped* next; 32 | } alwaysMapped_t; 33 | 34 | class Paging { 35 | public: 36 | static void Init(); 37 | 38 | static void* Map(uint64_t* cr3,uint64_t phys,uint64_t virt,uint64_t flags); 39 | 40 | static void* HHDMMap(uint64_t* cr3,uint64_t phys,uint64_t flags); 41 | 42 | static void* KernelMap(uint64_t phys); 43 | 44 | static void Kernel(uint64_t* cr3); 45 | 46 | static void MemoryEntry(uint64_t* cr3,uint32_t type,uint64_t flags); 47 | 48 | static void Pat(uint8_t index, uint8_t type); 49 | 50 | static void alwaysMappedMap(uint64_t* cr3); 51 | 52 | static void alwaysMappedAdd(uint64_t base,uint64_t size); 53 | 54 | static void EnablePaging(uint64_t* virt_cr3); 55 | 56 | static void EnableKernel(); 57 | 58 | static uint64_t PhysFromVirt(uint64_t* cr3,uint64_t virt); 59 | 60 | static void Unmap(uint64_t* cr3, uint64_t virt, uint64_t size_in_pages); 61 | 62 | static uint64_t* KernelGet(); 63 | 64 | static void Copy(uint64_t* dest_cr3, uint64_t* src_cr3); 65 | 66 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/memory/pmm.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #pragma once 6 | 7 | #define SIZE_TO_PAGES(size) (((size) + 4095) / 4096) 8 | #define LEVEL_TO_SIZE(level) (1U << (level)) 9 | 10 | #define MAX_LEVEL 26 11 | 12 | typedef struct { 13 | int64_t level : 8; 14 | int64_t is_free : 1; 15 | int64_t is_splitted : 1; 16 | int64_t is_was_splitted : 1; 17 | int64_t split_x : 1; 18 | int64_t parent_id : 48; 19 | } buddy_info_field_t; 20 | 21 | typedef struct buddy_info { 22 | uint64_t phys_pointer; 23 | buddy_info_field_t information; 24 | } __attribute__((packed)) buddy_info_t; 25 | 26 | typedef struct { 27 | buddy_info_t* first_buddy; 28 | buddy_info_t* second_buddy; 29 | } __attribute__((packed)) buddy_split_result_t; 30 | 31 | typedef struct buddy_t { 32 | uint64_t hello_buddy; 33 | uint64_t total_available_size; 34 | buddy_info_t* mem; 35 | } __attribute__((packed)) buddy_t; 36 | 37 | void buddy_dump(); 38 | 39 | class PMM { 40 | public: 41 | static void Init(limine_memmap_response* mem_map); 42 | 43 | static uint64_t Alloc(); 44 | 45 | static uint64_t BigAlloc(uint64_t size_pages); 46 | 47 | static void* VirtualAlloc(); 48 | 49 | static void* VirtualBigAlloc(uint64_t size_pages); 50 | 51 | static void Free(uint64_t phys); 52 | 53 | static void VirtualFree(void* ptr); 54 | 55 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/memory/vmm.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #pragma once 6 | 7 | typedef struct vmm_obj { 8 | uint64_t base; 9 | uint64_t phys; 10 | uint64_t len; 11 | uint64_t flags; 12 | 13 | uint64_t src_len; 14 | 15 | struct vmm_obj* next; 16 | } __attribute__((packed)) vmm_obj_t; 17 | 18 | class VMM { 19 | public: 20 | static void Init(process_t* proc); 21 | static void* Alloc(process_t* proc,uint64_t length,uint64_t flags); 22 | static void* Map(process_t* proc,uint64_t base,uint64_t length,uint64_t flags); 23 | static void* CustomAlloc(process_t* proc,uint64_t virt,uint64_t length,uint64_t flags); 24 | static void* Mark(process_t* proc,uint64_t base,uint64_t phys,uint64_t length,uint64_t flags); // mark some regions as already used 25 | static void Clone(process_t* dest_proc,process_t* src_proc); 26 | static void Modify(process_t* proc,uint64_t dest_base,uint64_t new_phys); 27 | static vmm_obj_t* Get(process_t* proc,uint64_t base); 28 | 29 | static void Free(process_t* proc); 30 | 31 | static void Reload(process_t* proc); 32 | 33 | static void Dump(process_t* proc); 34 | 35 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/mp/mp.hpp: -------------------------------------------------------------------------------- 1 | 2 | // MP or SMP idk header 3 | 4 | class MP { 5 | public: 6 | static void Init(); 7 | 8 | static void Sync(); 9 | 10 | }; -------------------------------------------------------------------------------- /kernel/src/include/generic/status/status.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | /* 5 | 6 | Orange status 7 | 0 bit - is initializied 8 | 1 bit - is something wrong 9 | 2 bit - is not supported 10 | 3 bit - is all ok 11 | 3-20 bits - status code (u16) 12 | 20-31 not used 13 | 14 | */ 15 | 16 | #define ORANGE_STATUS_INITIALIZIED_STATE (1 << 0) 17 | #define ORANGE_STATUS_SOMETHING_WRONG_STATE (1 << 1) 18 | #define ORANGE_STATUS_NOT_SUPPORTED (1 << 2) 19 | #define ORANGE_STATUS_IS_ALL_OK (1 << 3) 20 | 21 | typedef unsigned int orange_status; -------------------------------------------------------------------------------- /kernel/src/include/generic/tty/tty.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | void __tty_receive_ipc(uint8_t keycode); 5 | 6 | 7 | 8 | class TTY { 9 | public: 10 | static void Init(); 11 | }; -------------------------------------------------------------------------------- /kernel/src/include/other/assembly.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #pragma once 5 | 6 | inline uint64_t __rdmsr(uint32_t msr) { 7 | uint32_t lo, hi; 8 | __asm__ volatile ("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr)); 9 | return ((uint64_t)hi << 32) | lo; 10 | } 11 | 12 | inline void __wrmsr(uint32_t msr, uint64_t value) { 13 | uint32_t lo = (uint32_t)(value & 0xFFFFFFFF); 14 | uint32_t hi = (uint32_t)(value >> 32); 15 | __asm__ volatile ("wrmsr" : : "c"(msr), "a"(lo), "d"(hi)); 16 | } 17 | 18 | inline void __nop() { 19 | __asm__ volatile ("nop"); 20 | } 21 | 22 | inline void __cli() { 23 | __asm__ volatile ("cli"); 24 | } 25 | 26 | inline void __sti() { 27 | __asm__ volatile ("sti"); 28 | } 29 | 30 | inline void __hlt() { 31 | __asm__ volatile ("hlt"); 32 | } 33 | 34 | inline void __invlpg(unsigned long long virt) { 35 | __asm__ volatile ("invlpg (%0)" : : "r" (virt) : "memory"); 36 | } 37 | 38 | inline void __cpuid(int code, int code2, uint32_t *a, uint32_t *b, uint32_t *c , uint32_t *d) { 39 | __asm__ volatile("cpuid":"=a"(*a),"=b"(*b),"=c"(*c),"=d"(*d):"a"(code),"c"(code2)); 40 | } 41 | 42 | inline int __cpuid_string(int code, uint32_t where[4]) { 43 | __asm__ volatile("cpuid":"=a"(*where),"=b"(*(where+1)),"=c"(*(where+2)),"=d"(*(where+3)):"a"(code)); 44 | return (int)where[0]; 45 | } 46 | -------------------------------------------------------------------------------- /kernel/src/include/other/assert.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | extern "C" void Panic(const char* msg); 5 | 6 | #define Assert(condition,msg) if(!(condition)) {\ 7 | Log(LOG_LEVEL_INFO,msg); \ 8 | return; \ 9 | } 10 | 11 | #define pAssert(condition,msg) if(!(condition)) {\ 12 | Panic(msg); \ 13 | __builtin_unreachable(); \ 14 | } -------------------------------------------------------------------------------- /kernel/src/include/other/debug.hpp: -------------------------------------------------------------------------------- 1 | 2 | #define BREAKPOINT Log(LOG_LEVEL_INFO,"BreakPoint at %s:%d\n",__FILE__,__LINE__); -------------------------------------------------------------------------------- /kernel/src/include/other/hhdm.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #pragma once 5 | 6 | class HHDM { 7 | public: 8 | 9 | static void applyHHDM(uint64_t offset); 10 | 11 | static uint64_t toVirt(uint64_t phys); 12 | 13 | static uint64_t toPhys(uint64_t virt); 14 | 15 | static uint64_t* toVirtPointer(uint64_t phys); 16 | 17 | }; -------------------------------------------------------------------------------- /kernel/src/include/other/log.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #define LOG_LEVEL_INFO 1 5 | #define LOG_LEVEL_WARNING 2 6 | #define LOG_LEVEL_ERROR 3 7 | #define LOG_LEVEL_DEBUG 4 8 | 9 | void Log(int level,char* format, ...); 10 | 11 | #define WARN(x,...) Log(LOG_LEVEL_WARNING, "%s(): " x, __func__, ##__VA_ARGS__) 12 | #define INFO(x,...) Log(LOG_LEVEL_INFO, "%s(): " x, __func__, ##__VA_ARGS__) 13 | #define DEBUG(x,...) Log(LOG_LEVEL_DEBUG, "%s(): " x, __func__, ##__VA_ARGS__) 14 | #define ERROR(x,...) Log(LOG_LEVEL_ERROR, "%s(): " x, __func__, ##__VA_ARGS__) 15 | 16 | void SLog(int level,char* format, ...); 17 | 18 | #define SWARN(x,...) SLog(LOG_LEVEL_WARNING, "%s(): " x, __func__, ##__VA_ARGS__) 19 | #define SINFO(x,...) SLog(LOG_LEVEL_INFO, "%s(): " x, __func__, ##__VA_ARGS__) 20 | #define SDEBUG(x,...) SLog(LOG_LEVEL_DEBUG, "%s(): " x, __func__, ##__VA_ARGS__) 21 | #define SERROR(x,...) SLog(LOG_LEVEL_ERROR, "%s(): " x, __func__, ##__VA_ARGS__) 22 | 23 | void DLog(char* format, ...); 24 | void NLog(char* format, ...); 25 | void LogUnlock(); 26 | void LogBuffer(char* buffer,uint64_t size); 27 | 28 | void LogInit(char* ctx); -------------------------------------------------------------------------------- /kernel/src/include/other/other.hpp: -------------------------------------------------------------------------------- 1 | 2 | char* join_paths(const char* path1, const char* path2); 3 | 4 | char* cwd_get(const char *path); -------------------------------------------------------------------------------- /kernel/src/include/other/string.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class String { 8 | public: 9 | 10 | static uint64_t strlen(char* str); 11 | 12 | static char* itoa(uint64_t value, char* str, int base ); 13 | 14 | static uint64_t strncmp(const char* str1, const char* str2, uint64_t n); 15 | 16 | // From meaty skeleton implementation 17 | static void* memset(void* bufptr, int value, uint64_t size); 18 | 19 | // From meaty skeleton implementation 20 | static void* memcpy(void* dstptr, const void* srcptr, uint64_t size); 21 | 22 | static char* strtok(char *s, const char *delim); 23 | 24 | static char* strchr(const char *str, int ch); 25 | 26 | static char* strtok(char *str, const char *delim, char** saveptr); 27 | 28 | static int strcmp(const char *str1, const char *str2); 29 | 30 | static char* strncpy(char* dest, const char* src, uint64_t n); 31 | 32 | static char* strncat(char* dest, const char* src, uint64_t n); 33 | 34 | static char* strdup(const char* str); 35 | 36 | }; -------------------------------------------------------------------------------- /kernel/src/include/other/unixlike.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | uint64_t convertToUnixTime(); -------------------------------------------------------------------------------- /kernel/src/main.cpp: -------------------------------------------------------------------------------- 1 | #define FLANTERM_IN_FLANTERM 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | extern void (*__init_array[])(); 43 | extern void (*__init_array_end[])(); 44 | 45 | int initrd = 0; 46 | 47 | void _1() { 48 | while(1) { 49 | //Serial::printf(" _1 "); 50 | __hlt(); 51 | 52 | } 53 | } 54 | 55 | void _2() { 56 | while(1) { 57 | __cli(); 58 | NLog("2"); 59 | __sti(); 60 | __hlt(); 61 | } 62 | } 63 | 64 | uint32_t default_fg = 0xFFFFFFFF; 65 | 66 | int sec = 0; 67 | int min = 0; 68 | 69 | extern "C" void keyStub(); 70 | extern "C" uacpi_interrupt_ret handle_power_button(uacpi_handle ctx); 71 | 72 | extern "C" void kmain() { 73 | 74 | for (size_t i = 0; &__init_array[i] != __init_array_end; i++) { 75 | __init_array[i](); 76 | } 77 | 78 | Serial::Init(); 79 | 80 | Serial::printf("Serial initializied\n"); 81 | LimineInfo info; 82 | 83 | sec = CMOS::Second(); 84 | min = CMOS::Minute(); 85 | 86 | struct flanterm_context *ft_ctx = flanterm_fb_init( 87 | NULL, 88 | NULL, 89 | (uint32_t*)info.fb_info->address, info.fb_info->width, info.fb_info->height, info.fb_info->pitch, 90 | info.fb_info->red_mask_size, info.fb_info->red_mask_shift, 91 | info.fb_info->green_mask_size, info.fb_info->green_mask_shift, 92 | info.fb_info->blue_mask_size, info.fb_info->blue_mask_shift, 93 | NULL, 94 | NULL, NULL, 95 | NULL, &default_fg, 96 | NULL, &default_fg, 97 | NULL, 0, 0, 1, 98 | 0, 0, 99 | 0 100 | ); 101 | 102 | //ft_ctx->set_text_fg_bright(ft_ctx,0xFFFFFFFF); 103 | //ft_ctx->set_text_fg_rgb(ft_ctx,0xFFFFFFFF); 104 | ft_ctx->cursor_enabled = 0; 105 | ft_ctx->clear(ft_ctx,1); 106 | 107 | LogInit((char*)ft_ctx); 108 | 109 | INFO("This is info message !\n"); 110 | WARN("This is warning message !\n"); 111 | ERROR("This is error message !\n"); 112 | 113 | INFO("Bootloader: %s %s\n",info.bootloader_name,info.bootloader_version); 114 | INFO("RSDP: 0x%p\n",info.rsdp_address); 115 | INFO("HHDM: 0x%p\n",info.hhdm_offset); 116 | INFO("Kernel: Phys: 0x%p, Virt: 0x%p\n",info.ker_addr->physical_base,info.ker_addr->virtual_base); 117 | INFO("Framebuffer: Addr: 0x%p, Resolution: %dx%dx%d\n",info.fb_info->address,info.fb_info->width,info.fb_info->height,info.fb_info->bpp); 118 | INFO("Memmap: Start: 0x%p, Entry_count: %d\n",info.memmap->entries,info.memmap->entry_count); 119 | 120 | extern char is_ignored; 121 | 122 | is_ignored = 0; 123 | 124 | ft_ctx->cursor_enabled = 1; 125 | 126 | HHDM::applyHHDM(info.hhdm_offset); 127 | 128 | PMM::Init(info.memmap); 129 | INFO("PMM Initializied\n"); //it will be initializied anyway 130 | 131 | Paging::Init(); 132 | INFO("Paging Initializied\n"); //it will be initializied anyway 133 | KHeap::Init(); 134 | INFO("KHeap Initializied\n"); 135 | 136 | cpudata_t* data = CpuData::Access(); 137 | INFO("BSP CPU Data test: 1:0x%p 2:0x%p\n",data,CpuData::Access()); 138 | 139 | GDT::Init(); 140 | INFO("GDT Initializied\n"); 141 | 142 | IDT::Init(); 143 | INFO("IDT Initializied\n"); 144 | 145 | ACPI::fullInit(); 146 | INFO("ACPI Initializied\n"); 147 | 148 | Lapic::Init(); 149 | INFO("LAPIC Initializied\n"); 150 | 151 | MP::Init(); 152 | INFO("MP Initializied\n"); 153 | 154 | PowerButton::Hook(handle_power_button); 155 | INFO("PowerButton initializied\n"); 156 | 157 | VFS::Init(); 158 | INFO("VFS Initializied\n"); 159 | 160 | //tmpfs_dump(); 161 | 162 | PS2Keyboard::Init(keyStub); 163 | 164 | SSE::Init(); 165 | INFO("SSE Is enabled (or not) \n"); 166 | 167 | Process::Init(); 168 | INFO("Scheduling initializied\n"); 169 | 170 | Syscall::Init(); 171 | INFO("Syscall initializied\n"); 172 | 173 | XHCI::Init(); 174 | 175 | PCI::Init(); 176 | INFO("PCI initializied\n"); 177 | 178 | USTAR::ParseAndCopy(); 179 | INFO("Loaded initrd\n"); 180 | 181 | cpudata_t* cpu_data = CpuData::Access(); 182 | 183 | uint64_t stack_5 = (uint64_t)PMM::VirtualBigAlloc(TSS_STACK_IN_PAGES); // for syscall 184 | Paging::alwaysMappedAdd(stack_5,TSS_STACK_IN_PAGES * PAGE_SIZE); 185 | cpu_data->kernel_stack = stack_5 + (TSS_STACK_IN_PAGES * PAGE_SIZE); 186 | cpu_data->user_stack = 0; 187 | 188 | VMM::Init(0); 189 | //VMM::Alloc(0,0,0); 190 | //__hlt(); 191 | 192 | filestat_t stat; 193 | 194 | VFS::Stat("/usr/bin/initrd",(char*)&stat,1); 195 | 196 | char* elf = (char*)PMM::VirtualBigAlloc(CALIGNPAGEUP(stat.size,4096) / 4096); 197 | VFS::Read(elf,"/usr/bin/initrd",0); 198 | 199 | INFO("Loaded initrd !\n"); 200 | 201 | //res.entry(); 202 | 203 | initrd = Process::createProcess(0,0,1,0,0); 204 | 205 | for(int i = 0;i < 2;i++) { 206 | int proc = Process::createProcess((uint64_t)_1,0,0,0,0); 207 | Process::WakeUp(proc); 208 | } 209 | 210 | int serial = Process::createProcess((uint64_t)__serial_process_fetch,0,0,0,0); 211 | 212 | process_t* serial_proc = Process::ByID(serial); 213 | serial_proc->ctx.cr3 = HHDM::toPhys((uint64_t)Paging::KernelGet()); 214 | Process::WakeUp(serial); 215 | 216 | const char* pa = "/usr/bin/initrd"; 217 | const char* ea = "="; 218 | 219 | char* initrd_argv[2]; 220 | initrd_argv[0] = (char*)pa; 221 | initrd_argv[1] = 0; 222 | 223 | char* initrd_envp[2]; 224 | initrd_envp[0] = (char*)ea; 225 | initrd_envp[1] = 0; 226 | 227 | Process::loadELFProcess(initrd,"/usr/bin/initrd",(uint8_t*)elf,initrd_argv,initrd_envp); 228 | 229 | process_t* initrd_proc = Process::ByID(initrd); 230 | 231 | Process::WakeUp(initrd); 232 | 233 | INFO("Waiting for interrupts...\n"); 234 | 235 | TTY::Init(); 236 | 237 | //__hlt(); 238 | 239 | //MP::Sync(); 240 | 241 | int res_sec = 0; 242 | if(CMOS::Minute() - min) 243 | res_sec *= (CMOS::Minute() - min); 244 | 245 | res_sec += CMOS::Second() - sec; 246 | 247 | INFO("Kernel is initializied for %d seconds\n",res_sec); 248 | 249 | __sti(); 250 | 251 | while(1) { 252 | __hlt(); 253 | } 254 | 255 | } 256 | -------------------------------------------------------------------------------- /kernel/src/other/hhdm.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | uint64_t hhdm_offset; 6 | 7 | void HHDM::applyHHDM(uint64_t offset) { 8 | hhdm_offset = offset; 9 | } 10 | 11 | uint64_t HHDM::toVirt(uint64_t phys) { 12 | return phys + hhdm_offset; 13 | } 14 | 15 | uint64_t HHDM::toPhys(uint64_t virt) { 16 | return virt - hhdm_offset; 17 | } 18 | 19 | uint64_t* HHDM::toVirtPointer(uint64_t phys) { 20 | return (uint64_t*)(phys + hhdm_offset); 21 | } 22 | -------------------------------------------------------------------------------- /kernel/src/other/other.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | extern "C" { 9 | 10 | void *memcpy(void *dest, const void *src, std::size_t n) { 11 | std::uint8_t *pdest = static_cast(dest); 12 | const std::uint8_t *psrc = static_cast(src); 13 | 14 | for (std::size_t i = 0; i < n; i++) { 15 | pdest[i] = psrc[i]; 16 | } 17 | 18 | return dest; 19 | } 20 | 21 | void *memset(void *s, int c, std::size_t n) { 22 | std::uint8_t *p = static_cast(s); 23 | 24 | for (std::size_t i = 0; i < n; i++) { 25 | p[i] = static_cast(c); 26 | } 27 | 28 | return s; 29 | } 30 | 31 | void *memmove(void *dest, const void *src, std::size_t n) { 32 | std::uint8_t *pdest = static_cast(dest); 33 | const std::uint8_t *psrc = static_cast(src); 34 | 35 | if (src > dest) { 36 | for (std::size_t i = 0; i < n; i++) { 37 | pdest[i] = psrc[i]; 38 | } 39 | } else if (src < dest) { 40 | for (std::size_t i = n; i > 0; i--) { 41 | pdest[i-1] = psrc[i-1]; 42 | } 43 | } 44 | 45 | return dest; 46 | } 47 | 48 | int memcmp(const void *s1, const void *s2, std::size_t n) { 49 | const std::uint8_t *p1 = static_cast(s1); 50 | const std::uint8_t *p2 = static_cast(s2); 51 | 52 | for (std::size_t i = 0; i < n; i++) { 53 | if (p1[i] != p2[i]) { 54 | return p1[i] < p2[i] ? -1 : 1; 55 | } 56 | } 57 | 58 | return 0; 59 | } 60 | 61 | char* strrchr(const char *str, int c) { 62 | char* last = NULL; 63 | while (*str) { 64 | if (*str == c) { 65 | last = (char *)str; 66 | } 67 | str++; 68 | } 69 | 70 | if (*str == c) { 71 | last = (char *)str; 72 | } 73 | return last; 74 | } 75 | 76 | } 77 | 78 | namespace { 79 | 80 | void hcf() { 81 | for (;;) { 82 | asm ("hlt"); 83 | } 84 | } 85 | 86 | } 87 | 88 | extern "C" { 89 | int __cxa_atexit(void (*)(void *), void *, void *) { return 0; } 90 | void __cxa_pure_virtual() { hcf(); } 91 | void *__dso_handle; 92 | } 93 | 94 | void *operator new(size_t size) 95 | { 96 | return KHeap::Malloc(size); 97 | } 98 | 99 | void *operator new[](size_t size) 100 | { 101 | return KHeap::Malloc(size); 102 | } 103 | 104 | void operator delete(void *p) 105 | { 106 | KHeap::Free(p); 107 | } 108 | 109 | void operator delete[](void *p) 110 | { 111 | KHeap::Free(p); 112 | } 113 | 114 | #include 115 | #include 116 | #include 117 | #include 118 | #include 119 | #include 120 | #include 121 | #include 122 | #include 123 | #include 124 | 125 | extern "C" void keyHandler(int_frame_t* ctx) { 126 | __cli(); 127 | LogUnlock(); 128 | Paging::EnableKernel(); 129 | char key = PS2Keyboard::Get(); 130 | PS2Keyboard::EOI(); 131 | if(ctx->cs == 0x20) { 132 | ctx->cs |= 3; 133 | ctx->ss |= 3; 134 | } 135 | 136 | if(ctx->ss == 0x18) { 137 | ctx->cs |= 3; 138 | ctx->ss |= 3; 139 | } 140 | 141 | } 142 | 143 | extern "C" uacpi_interrupt_ret handle_power_button(uacpi_handle ctx) { 144 | LogUnlock(); 145 | Paging::EnableKernel(); 146 | NLog("\n"); 147 | Log(LOG_LEVEL_WARNING,"Shutdowning system in 5 seconds"); 148 | 149 | __cli(); //yes i know lapic waiting for my eoi but why not ? 150 | 151 | for(char i =0; i < 5;i++) { 152 | NLog("."); 153 | HPET::Sleep(1*1000*1000); 154 | } 155 | 156 | Log(LOG_LEVEL_INFO,"Bye.\n"); 157 | 158 | uacpi_status ret = uacpi_prepare_for_sleep_state(UACPI_SLEEP_STATE_S5); 159 | ret = uacpi_enter_sleep_state(UACPI_SLEEP_STATE_S5); 160 | 161 | __hlt(); 162 | } 163 | 164 | char* cwd_get(const char *path) { 165 | 166 | char* result = (char*)PMM::VirtualAlloc(); 167 | memcpy(result,path,String::strlen((char*)path)); 168 | 169 | char *last_slash = strrchr(result, '/'); 170 | 171 | if (last_slash != NULL) { 172 | if (last_slash != result) { 173 | *last_slash = '\0'; 174 | } else { 175 | *(last_slash + 1) = '\0'; 176 | } 177 | } else { 178 | result[0] = '\0'; 179 | } 180 | 181 | return result; 182 | 183 | } 184 | char* join_paths(const char* path1, const char* path2) { 185 | char* result = (char*)PMM::VirtualAlloc(); 186 | if (!result) { 187 | return 0; 188 | } 189 | 190 | if (path2[0] == '/') { 191 | int i = 0; 192 | while (path2[i] != '\0' && i < 4095) { 193 | result[i] = path2[i]; 194 | i++; 195 | } 196 | result[i] = '\0'; 197 | return result; 198 | } 199 | 200 | int len1 = 0; 201 | while (path1[len1] != '\0') { 202 | len1++; 203 | } 204 | 205 | if (len1 > 0 && path1[len1-1] == '/') { 206 | len1--; 207 | } 208 | 209 | if (len1 == 1 && path1[0] == '/') { 210 | int i = 0; 211 | result[0] = '/'; 212 | i = 1; 213 | int j = 0; 214 | while (path2[j] != '\0' && i < 4095) { 215 | result[i] = path2[j]; 216 | i++; 217 | j++; 218 | } 219 | result[i] = '\0'; 220 | return result; 221 | } 222 | 223 | int offset2 = 0; 224 | if (path2[0] == '.' && path2[1] == '/') { 225 | path2 += 2; 226 | offset2 = 2; 227 | } else if (path2[0] == '.' && path2[1] == '.' && path2[2] == '/') { 228 | while (len1 > 0 && path1[len1-1] != '/') { 229 | len1--; 230 | } 231 | if (len1 > 0) { 232 | len1--; 233 | } 234 | path2 += 3; 235 | offset2 = 3; 236 | } 237 | 238 | int i = 0; 239 | for (int j = 0; j < len1 && i < 4095; j++) { 240 | result[i] = path1[j]; 241 | i++; 242 | } 243 | 244 | if (i < 4095) { 245 | result[i] = '/'; 246 | i++; 247 | } 248 | 249 | int j = offset2; 250 | while (path2[j-offset2] != '\0' && i < 4095) { 251 | result[i] = path2[j-offset2]; 252 | i++; 253 | j++; 254 | } 255 | 256 | result[i] = '\0'; 257 | 258 | return result; 259 | } -------------------------------------------------------------------------------- /kernel/src/other/string.cpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | uint64_t String::strlen(char* str) { 10 | uint64_t len = 0; 11 | while(str[len]) 12 | len++; 13 | return len; 14 | } 15 | 16 | char* String::itoa(uint64_t value, char* str, int base ) { 17 | char * rc; 18 | char * ptr; 19 | char * low; 20 | if ( base < 2 || base > 36 ) 21 | { 22 | *str = '\0'; 23 | return str; 24 | } 25 | rc = ptr = str; 26 | if ( value < 0 && base == 10 ) 27 | { 28 | *ptr++ = '-'; 29 | } 30 | low = ptr; 31 | do 32 | { 33 | *ptr++ = "ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[35 + value % base]; 34 | value /= base; 35 | } while ( value ); 36 | *ptr-- = '\0'; 37 | while ( low < ptr ) 38 | { 39 | char tmp = *low; 40 | *low++ = *ptr; 41 | *ptr-- = tmp; 42 | } 43 | return rc; 44 | } 45 | 46 | // From meaty skeleton implementation 47 | void* String::memset(void* bufptr, int value, uint64_t size) { 48 | unsigned char* buf = (unsigned char*) bufptr; 49 | for (uint64_t i = 0; i < size; i++) 50 | buf[i] = (unsigned char) value; 51 | return bufptr; 52 | } 53 | 54 | // From meaty skeleton implementation 55 | void* String::memcpy(void* dstptr, const void* srcptr, uint64_t size) { 56 | unsigned char* dst = (unsigned char*) dstptr; 57 | const unsigned char* src = (const unsigned char*) srcptr; 58 | for (uint64_t i = 0; i < size; i++) 59 | dst[i] = src[i]; 60 | return dstptr; 61 | } 62 | 63 | uint64_t String::strncmp(const char* str1, const char* str2, uint64_t n) { 64 | uint64_t i = 0; 65 | 66 | while (i < n && str1[i] != '\0' && str2[i] != '\0') { 67 | if (str1[i] != str2[i]) { 68 | return (unsigned char)str1[i] - (unsigned char)str2[i]; 69 | } 70 | i++; 71 | } 72 | 73 | if (i == n) 74 | return 0; 75 | 76 | return (unsigned char)str1[i] - (unsigned char)str2[i]; 77 | } 78 | 79 | char* String::strdup(const char* str) { 80 | uint64_t size = String::strlen((char*)str); 81 | char* buffer = (char*)KHeap::Malloc(size); 82 | String::memcpy(buffer,str,size); 83 | return buffer; 84 | } 85 | 86 | char * String::strchr(const char *str, int ch) { 87 | while (*str) { 88 | if (*str == (char)ch) { 89 | return (char *)str; 90 | } 91 | str++; 92 | } 93 | 94 | if (ch == '\0') { 95 | return (char *)str; 96 | } 97 | 98 | return NULL; 99 | } 100 | 101 | char* String::strtok(char *str, const char *delim, char** saveptr) { 102 | char *start; 103 | char *delim_pos; 104 | 105 | if (str == NULL) { 106 | str = *saveptr; 107 | } 108 | 109 | while (*str && strchr(delim, *str)) { 110 | str++; 111 | } 112 | 113 | if (*str == '\0') { 114 | *saveptr = str; 115 | return NULL; 116 | } 117 | 118 | start = str; 119 | 120 | while (*str && (delim_pos = strchr(delim, *str)) == NULL) { 121 | str++; 122 | } 123 | 124 | if (*str) { 125 | *str = '\0'; 126 | *saveptr = str + 1; 127 | } else { 128 | *saveptr = str; 129 | } 130 | 131 | return start; 132 | } 133 | 134 | int String::strcmp(const char *str1, const char *str2) { 135 | while (*str1 && (*str1 == *str2)) { 136 | str1++; 137 | str2++; 138 | } 139 | return *(unsigned char *)str1 - *(unsigned char *)str2; 140 | } 141 | 142 | 143 | char* String::strncpy(char* dest, const char* src, uint64_t n) { 144 | uint64_t i; 145 | for (i = 0; i < n && src[i] != '\0'; i++) { 146 | dest[i] = src[i]; 147 | } 148 | for (; i < n; i++) { 149 | dest[i] = '\0'; 150 | } 151 | return dest; 152 | } 153 | 154 | char* String::strncat(char* dest, const char* src, uint64_t n) { 155 | uint64_t dest_len = 0; 156 | while (dest[dest_len] != '\0') { 157 | dest_len++; 158 | } 159 | uint64_t i; 160 | for (i = 0; i < n && src[i] != '\0'; i++) { 161 | dest[dest_len + i] = src[i]; 162 | } 163 | dest[dest_len + i] = '\0'; 164 | 165 | return dest; 166 | } 167 | 168 | // Yes, i'm lazy -------------------------------------------------------------------------------- /kernel/src/other/unixlike.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | bool isLeapYear(int year) { 7 | return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); 8 | } 9 | 10 | int daysInMonth(int month, int year) { 11 | int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 12 | if (month == 2 && isLeapYear(year)) { 13 | return 29; 14 | } 15 | return days[month - 1]; 16 | } 17 | 18 | uint64_t convertToUnixTime() { 19 | int year = CMOS::Year(); 20 | int month = CMOS::Month(); 21 | int day = CMOS::Day(); 22 | int hour = CMOS::Hour(); 23 | int minute = CMOS::Minute(); 24 | int second = CMOS::Second(); 25 | 26 | long long daysSinceEpoch = 0; 27 | for (int y = 1970; y < year; ++y) { 28 | daysSinceEpoch += isLeapYear(y) ? 366 : 365; 29 | } 30 | 31 | for (int m = 1; m < month; ++m) { 32 | daysSinceEpoch += daysInMonth(m, year); 33 | } 34 | 35 | daysSinceEpoch += (day - 1); 36 | 37 | long long secondsSinceEpoch = daysSinceEpoch * 86400; 38 | 39 | secondsSinceEpoch += hour * 3600; 40 | secondsSinceEpoch += minute * 60; 41 | secondsSinceEpoch += second; 42 | 43 | return secondsSinceEpoch; 44 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Orange 3 | 4 | Orange is my unix-like x86_64 OS 5 | Currenly it have bash,coreutils,lua and fastfetch ports 6 | 7 | [![GitHub top language](https://img.shields.io/github/languages/top/cpplover0/orange?logo=c&label=)](https://github.com/cpplover0/orange/blob/main/kernel/GNUmakefile) 8 | [![GitHub license](https://img.shields.io/github/license/cpplover0/orange)](https://github.com/cpplover0/orange/blob/master/LICENSE) 9 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/e78ad48f394f46d1bb98f1942c7e1f21)]() 10 | [![GitHub contributors](https://img.shields.io/github/contributors/cpplover0/orange)](https://github.com/cpplover0/orange/graphs/contributors) 11 | [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/cpplover0/orange)](https://github.com/cpplover0/orange/commits) 12 | 13 | ## Preview 14 | ![fastfetch and lua](https://github.com/cppLover0/Orange/blob/main/tools/img/work.png?raw=true) 15 | 16 | # Build 17 | 18 | Build kernel 19 | ```sh 20 | make all 21 | ``` 22 | 23 | Build initrd (You should build it before running os) 24 | ```sh 25 | sh build-initrd.sh 26 | ``` 27 | 28 | Build kernel and run iso 29 | ```sh 30 | make 31 | ``` 32 | 33 | 34 | ## Base x86 TODO 35 | 36 | - [x] Build 37 | - [x] Locking 38 | - [x] GFX (flanterm) 39 | - [x] PMM 40 | - [x] Paging 41 | - [x] Some heap 42 | - [x] GDT 43 | - [x] IDT 44 | - [x] TSS 45 | - [x] ACPI 46 | - [x] HPET 47 | - [x] LAPIC 48 | - [x] MP 49 | - [x] IOAPIC 50 | - [x] Initrd support 51 | - [x] ELF parsing 52 | - [x] Scheduling 53 | - [x] End of x86 pain 54 | 55 | ## Unix-like TODO 56 | 57 | - [x] Syscalls 58 | - [x] Start libc porting 59 | - [ ] End libc porting 60 | 61 | ## Porting TODO 62 | 63 | - [x] bash 64 | - [x] coreutils 65 | - [ ] doom2 66 | - [ ] nasm 67 | - [ ] gcc 68 | - [x] lua 69 | - [ ] python 70 | - [ ] etc. apps 71 | 72 | ## Driver TODO 73 | 74 | - [x] IO 75 | - [x] Serial 76 | - [x] PCI 77 | - [x] CMOS 78 | - [x] PS2 Keyboard 79 | - [ ] Speaker 80 | - [ ] AHCI 81 | - [ ] XHCI/HID/USB 82 | - [ ] NVME 83 | - [ ] Networking 84 | - [ ] Intel HDA 85 | - [ ] End of driver pain 86 | 87 | ## Filesystem TODO 88 | 89 | - [x] VFS 90 | - [x] TMPFS 91 | - [x] USTAR 92 | - [x] DevFS 93 | - [ ] ProcFS 94 | - [ ] ISO9660 95 | - [ ] FAT32 96 | - [ ] EXT4 97 | - [ ] End of filesystem pain 98 | 99 | ## Final TODO 100 | 101 | - [ ] The end ? -------------------------------------------------------------------------------- /tools/base/etc/passwd: -------------------------------------------------------------------------------- 1 | root:x:0:0::/root:/bin/bash -------------------------------------------------------------------------------- /tools/base/root/.bash_history: -------------------------------------------------------------------------------- 1 | exit -------------------------------------------------------------------------------- /tools/base/root/.bashrc: -------------------------------------------------------------------------------- 1 | PS1='\e[92m\u\e[0m@\e[38;5;214morange\e[0m-# ' 2 | export TERM="vt100" 3 | 4 | echo -e "\033[2J\033[H" 5 | -------------------------------------------------------------------------------- /tools/diffs/binutils.diff: -------------------------------------------------------------------------------- 1 | diff -Naur binutils-2.38/bfd/config.bfd binutils-patched/bfd/config.bfd 2 | --- binutils-2.38/bfd/config.bfd 2022-01-22 15:14:07.000000000 +0300 3 | +++ binutils-patched/bfd/config.bfd 2025-05-20 13:53:59.007878617 +0300 4 | @@ -656,11 +656,21 @@ 5 | targ_selvecs= 6 | targ64_selvecs=x86_64_elf64_vec 7 | ;; 8 | + i[3-7]86-*-orange*) 9 | + targ_defvec=i386_elf32_vec 10 | + targ_selvecs= 11 | + targ64_selvecs=x86_64_elf64_vec 12 | + ;; 13 | #ifdef BFD64 14 | x86_64-*-cloudabi*) 15 | targ_defvec=x86_64_elf64_cloudabi_vec 16 | want64=true 17 | ;; 18 | + x86_64-*-orange*) 19 | + targ_defvec=x86_64_elf64_vec 20 | + targ_selvecs=i386_elf32_vec 21 | + want64=true 22 | + ;; 23 | x86_64-*-darwin*) 24 | targ_defvec=x86_64_mach_o_vec 25 | targ_selvecs="i386_mach_o_vec mach_o_le_vec mach_o_be_vec mach_o_fat_vec pef_vec pef_xlib_vec sym_vec" 26 | diff -Naur binutils-2.38/config.sub binutils-patched/config.sub 27 | --- binutils-2.38/config.sub 2022-01-22 15:14:07.000000000 +0300 28 | +++ binutils-patched/config.sub 2025-05-20 13:51:16.721951465 +0300 29 | @@ -1750,7 +1750,7 @@ 30 | | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ 31 | | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ 32 | | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ 33 | - | skyos* | haiku* | rdos* | toppers* | drops* | es* \ 34 | + | skyos* | orange* | haiku* | rdos* | toppers* | drops* | es* \ 35 | | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ 36 | | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ 37 | | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ 38 | diff -Naur binutils-2.38/gas/configure.tgt binutils-patched/gas/configure.tgt 39 | --- binutils-2.38/gas/configure.tgt 2022-01-22 15:14:08.000000000 +0300 40 | +++ binutils-patched/gas/configure.tgt 2025-05-20 13:55:11.117623594 +0300 41 | @@ -233,6 +233,7 @@ 42 | i386-*-knetbsd*-gnu | \ 43 | i386-*-netbsd* | \ 44 | i386-*-openbsd*) fmt=elf em=nbsd ;; 45 | + i386-*-orange*) fmt=elf em=gnu ;; 46 | i386-*-linux-*) fmt=elf em=linux 47 | case ${cpu}-${os} in 48 | x86_64*-linux-gnux32) arch=x86_64:32 ;; 49 | diff -Naur binutils-2.38/ld/configure.tgt binutils-patched/ld/configure.tgt 50 | --- binutils-2.38/ld/configure.tgt 2022-01-22 17:19:36.000000000 +0300 51 | +++ binutils-patched/ld/configure.tgt 2025-05-20 13:58:35.200562165 +0300 52 | @@ -403,6 +403,15 @@ 53 | ;; 54 | i[3-7]86-*-haiku*) targ_emul=elf_i386_haiku 55 | ;; 56 | +i[3-7]86-*-orange*) 57 | + targ_emul=elf_i386_orange 58 | + targ_extra_emuls=elf_i386 59 | + targ64_extra_emuls="elf_x86_64_orange elf_x86_64" 60 | + ;; 61 | +x86_64-*-orange*) 62 | + targ_emul=elf_x86_64_orange 63 | + targ_extra_emuls="elf_i386_orange elf_x86_64 elf_i386" 64 | + ;; 65 | i[3-7]86-*-vxworks*) targ_emul=elf_i386_vxworks 66 | ;; 67 | i[3-7]86-*-chaos) targ_emul=elf_i386_chaos 68 | diff -Naur binutils-2.38/ld/emulparams/elf_i386_orange.sh binutils-patched/ld/emulparams/elf_i386_orange.sh 69 | --- binutils-2.38/ld/emulparams/elf_i386_orange.sh 1970-01-01 03:00:00.000000000 +0300 70 | +++ binutils-patched/ld/emulparams/elf_i386_orange.sh 2025-05-20 13:58:57.848110210 +0300 71 | @@ -0,0 +1,2 @@ 72 | +source_sh ${srcdir}/emulparams/elf_i386.sh 73 | +TEXT_START_ADDR=0x08000000 74 | diff -Naur binutils-2.38/ld/emulparams/elf_x86_64_orange.sh binutils-patched/ld/emulparams/elf_x86_64_orange.sh 75 | --- binutils-2.38/ld/emulparams/elf_x86_64_orange.sh 1970-01-01 03:00:00.000000000 +0300 76 | +++ binutils-patched/ld/emulparams/elf_x86_64_orange.sh 2025-05-20 13:59:14.619516061 +0300 77 | @@ -0,0 +1 @@ 78 | +source_sh ${srcdir}/emulparams/elf_x86_64.sh 79 | diff -Naur binutils-2.38/ld/Makefile.am binutils-patched/ld/Makefile.am 80 | --- binutils-2.38/ld/Makefile.am 2022-01-22 15:14:09.000000000 +0300 81 | +++ binutils-patched/ld/Makefile.am 2025-05-20 14:00:18.033050595 +0300 82 | @@ -281,6 +281,7 @@ 83 | eelf_i386_be.c \ 84 | eelf_i386_fbsd.c \ 85 | eelf_i386_haiku.c \ 86 | + eelf_i386_orange.c \ 87 | eelf_i386_ldso.c \ 88 | eelf_i386_sol2.c \ 89 | eelf_i386_vxworks.c \ 90 | @@ -463,6 +464,7 @@ 91 | eelf_x86_64_cloudabi.c \ 92 | eelf_x86_64_fbsd.c \ 93 | eelf_x86_64_haiku.c \ 94 | + eelf_x86_64_orange.c \ 95 | eelf_x86_64_sol2.c \ 96 | ehppa64linux.c \ 97 | ei386pep.c \ 98 | -------------------------------------------------------------------------------- /tools/get-linux-headers.sh: -------------------------------------------------------------------------------- 1 | if [ ! -d "./linux-headers" ]; then 2 | mkdir -p temp 3 | mkdir -p linux-headers 4 | git clone https://github.com/torvalds/linux.git --depth=1 5 | cd linux 6 | make headers_install ARCH=x86_64 INSTALL_HDR_PATH="$(realpath ../temp)" 7 | cd .. 8 | cp -rf temp/include/* linux-headers 9 | rm -rf temp 10 | rm -rf linux 11 | fi 12 | 13 | echo Copying linux-headers... 14 | mkdir -p "$1/initrd/usr/include" 15 | cp -rf linux-headers/* "$1/initrd/usr/include" 16 | -------------------------------------------------------------------------------- /tools/img/work.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppLover0/Orange/7456dee8ab6d160bad1b8593b8de037a880e7fbd/tools/img/work.png -------------------------------------------------------------------------------- /tools/limine.conf: -------------------------------------------------------------------------------- 1 | # Timeout in seconds that Limine will use before automatically booting. 2 | timeout: 0 3 | 4 | # The entry name that will be displayed in the boot menu. 5 | /Orange 6 | protocol: limine 7 | path: boot():/boot/kernel 8 | module_path: boot():/boot/initrd.tar 9 | -------------------------------------------------------------------------------- /tools/pkg/bash/diff/bash.diff: -------------------------------------------------------------------------------- 1 | diff -Naur bash-5.2/support/config.sub bash-patched/support/config.sub 2 | --- bash-5.2/support/config.sub 2022-01-11 22:38:29.000000000 +0300 3 | +++ bash-patched/support/config.sub 2025-05-20 21:13:50.415630202 +0300 4 | @@ -1750,7 +1750,7 @@ 5 | | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ 6 | | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ 7 | | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ 8 | - | skyos* | haiku* | rdos* | toppers* | drops* | es* \ 9 | + | skyos* | orange* | haiku* | rdos* | toppers* | drops* | es* \ 10 | | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ 11 | | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ 12 | | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ 13 | -------------------------------------------------------------------------------- /tools/pkg/bash/info.txt: -------------------------------------------------------------------------------- 1 | bash-5.2.21 -------------------------------------------------------------------------------- /tools/pkg/bash/pkg.sh: -------------------------------------------------------------------------------- 1 | 2 | . ../pkg_lib.sh 3 | 4 | rm -rf pack 5 | 6 | mkdir -p pack 7 | 8 | cd pack 9 | 10 | echo $1 11 | 12 | install_gnu bash bash 5.2.21 13 | mkdir -p bash-build 14 | 15 | cd bash-5.2.21 16 | diff_patch ../../diff/bash.diff 17 | cd .. 18 | 19 | cd bash-build 20 | ../bash-5.2.21/configure --host=x86_64-orange --prefix="$1" --disable-readline --with-curses --without-bash-malloc CFLAGS="-std=gnu17 -fPIC" 21 | make install -j$(nproc) 22 | 23 | cz=$(pwd) 24 | 25 | cd "$1/bin" 26 | ln -s bash sh 27 | 28 | cd "$cz" 29 | 30 | clear_share "$1" 31 | 32 | cd .. -------------------------------------------------------------------------------- /tools/pkg/build_pkg.sh: -------------------------------------------------------------------------------- 1 | 2 | echo "Building orange's libraries" 3 | 4 | for dir in ./dep/*; do 5 | cd "$dir" || continue 6 | if [ -f "pkg.sh" ]; then 7 | echo Building $(cat info.txt) 8 | bash pkg.sh $1 9 | fi 10 | cd ../.. 11 | done 12 | 13 | echo "Building orange's packages" 14 | 15 | for dir in */; do 16 | cd "$dir" || continue 17 | if [ -f "pkg.sh" ]; then 18 | echo Building $(cat info.txt) 19 | bash pkg.sh $1 20 | fi 21 | cd .. 22 | done 23 | 24 | -------------------------------------------------------------------------------- /tools/pkg/coreutils/diff/coreutils.diff: -------------------------------------------------------------------------------- 1 | diff -Naur coreutils/build-aux/config.sub coreutils-patched/build-aux/config.sub 2 | --- coreutils/build-aux/config.sub 2024-08-11 16:58:11.000000000 +0300 3 | +++ coreutils-patched/build-aux/config.sub 2025-05-25 12:55:11.367837322 +0300 4 | @@ -2012,6 +2012,7 @@ 5 | | glidix* \ 6 | | gnu* \ 7 | | go32* \ 8 | + | orange* \ 9 | | haiku* \ 10 | | hcos* \ 11 | | hiux* \ 12 | diff -Naur coreutils/gnulib-tests/getlocalename_l-unsafe.c coreutils-patched/gnulib-tests/getlocalename_l-unsafe.c 13 | --- coreutils/gnulib-tests/getlocalename_l-unsafe.c 2025-04-06 01:23:58.000000000 +0300 14 | +++ coreutils-patched/gnulib-tests/getlocalename_l-unsafe.c 2025-05-25 16:46:35.306435434 +0300 15 | @@ -469,6 +469,8 @@ 16 | struct gl_locale_category_t *plc = 17 | &locale->category[gl_log2_lcmask_to_index (gl_log2_lc_mask (category))]; 18 | return (struct string_with_storage) { plc->name, STORAGE_OBJECT }; 19 | +#elif defined __orange__ 20 | + return (struct string_with_storage) { "C", STORAGE_INDEFINITE }; 21 | #elif __GLIBC__ >= 2 && !defined __UCLIBC__ 22 | /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in 23 | glibc < 2.12. 24 | -------------------------------------------------------------------------------- /tools/pkg/coreutils/info.txt: -------------------------------------------------------------------------------- 1 | coreutils-9.7 -------------------------------------------------------------------------------- /tools/pkg/coreutils/pkg.sh: -------------------------------------------------------------------------------- 1 | 2 | . ../pkg_lib.sh 3 | 4 | rm -rf pack 5 | 6 | mkdir -p pack 7 | 8 | cd pack 9 | 10 | echo $1 11 | 12 | install_gnu coreutils coreutils 9.7 13 | mkdir -p coreutils-build 14 | 15 | cd coreutils-9.7 16 | diff_patch ../../diff/coreutils.diff 17 | cd .. 18 | 19 | cd coreutils-build 20 | ../coreutils-9.7/configure --host=x86_64-orange --prefix="$1" CFLAGS="-std=gnu17" 21 | make install -j$(nproc) 22 | 23 | clear_share "$1" 24 | 25 | cd .. -------------------------------------------------------------------------------- /tools/pkg/dep/hi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cppLover0/Orange/7456dee8ab6d160bad1b8593b8de037a880e7fbd/tools/pkg/dep/hi -------------------------------------------------------------------------------- /tools/pkg/dep/ncurses/diff/ncurses.diff: -------------------------------------------------------------------------------- 1 | diff -Naur ncurses-6.5/config.sub ncurses-patched/config.sub 2 | --- ncurses-6.5/config.sub 2023-12-27 17:41:27.000000000 +0300 3 | +++ ncurses-patched/config.sub 2025-06-02 08:30:55.408408771 +0300 4 | @@ -1764,7 +1764,7 @@ 5 | | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ 6 | | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ 7 | | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ 8 | - | skyos* | haiku* | rdos* | toppers* | drops* | es* \ 9 | + | skyos* | orange* | haiku* | rdos* | toppers* | drops* | es* \ 10 | | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ 11 | | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ 12 | | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ 13 | diff -Naur ncurses-6.5/configure ncurses-patched/configure 14 | --- ncurses-6.5/configure 2024-04-10 11:09:48.000000000 +0300 15 | +++ ncurses-patched/configure 2025-06-02 09:00:16.635459472 +0300 16 | @@ -6925,6 +6925,10 @@ 17 | LINK_PROGS="$SHELL ${rel_builddir}/mk_prog.sh" 18 | LINK_TESTS="$SHELL ${rel_builddir}/mk_prog.sh" 19 | ;; 20 | + (orange*) 21 | + CC_SHARED_OPTS='-fPIC' 22 | + MK_SHARED_LIB='${CC} -shared -o $@' 23 | + ;; 24 | (mingw*) 25 | cf_cv_shlib_version=mingw 26 | cf_cv_shlib_version_infix=mingw 27 | -------------------------------------------------------------------------------- /tools/pkg/dep/ncurses/info.txt: -------------------------------------------------------------------------------- 1 | ncurses-6.5 -------------------------------------------------------------------------------- /tools/pkg/dep/ncurses/pkg.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | . ../../pkg_lib.sh 5 | 6 | rm -rf pack 7 | 8 | mkdir -p pack 9 | 10 | cd pack 11 | 12 | echo $1 13 | 14 | install_gnu ncurses ncurses 6.5 15 | mkdir -p ncurses-build 16 | 17 | cd ncurses-6.5 18 | diff_patch ../../diff/ncurses.diff 19 | cd .. 20 | 21 | cd ncurses-build 22 | ../ncurses-6.5/configure --host=x86_64-orange CFLAGS="-std=gnu17" --prefix=/usr --with-shared --without-ada 23 | make -j$(nproc) 24 | 25 | path1="$(realpath $1/..)" 26 | make install -j$(nproc) DESTDIR="$path1" 27 | 28 | rm -rf "$1/lib/*.a" 29 | 30 | cz=$(pwd) 31 | 32 | cd "$1/lib" 33 | ln -s libncursesw.so libcurses.so 34 | ln -s libncursesw.so libcursesw.so 35 | 36 | cd "$cz" 37 | 38 | cd "$1/include/" 39 | 40 | for file in "ncurses/*"; do 41 | echo $file "$(basename "$file")" 42 | ln -s "$file" "$(basename "$file")" 43 | done 44 | 45 | cd "$cz" 46 | 47 | cd ../.. -------------------------------------------------------------------------------- /tools/pkg/fastfetch/info.txt: -------------------------------------------------------------------------------- 1 | fastfetch-2.44.0 -------------------------------------------------------------------------------- /tools/pkg/fastfetch/pkg.sh: -------------------------------------------------------------------------------- 1 | 2 | . ../pkg_lib.sh 3 | 4 | rm -rf pack 5 | 6 | mkdir -p pack 7 | 8 | cd pack 9 | 10 | echo $1 11 | 12 | wget https://github.com/fastfetch-cli/fastfetch/archive/refs/tags/2.44.0.tar.gz 13 | 14 | tar -xvf 2.44.0.tar.gz 15 | 16 | cd fastfetch-2.44.0 17 | diff_patch ../../diff/fastfetch.diff 18 | cd .. 19 | 20 | mkdir -p fastfetch-build 21 | cd fastfetch-build 22 | cmake ../fastfetch-2.44.0 -DCMAKE_TOOLCHAIN_FILE=$(realpath ../../../toolchain.cmake) -DCMAKE_INSTALL_PREFIX="$1" 23 | 24 | make -j$(nproc) 25 | make install 26 | 27 | cd .. -------------------------------------------------------------------------------- /tools/pkg/lua/info.txt: -------------------------------------------------------------------------------- 1 | lua-5.4.7 2 | -------------------------------------------------------------------------------- /tools/pkg/lua/pkg.sh: -------------------------------------------------------------------------------- 1 | 2 | . ../pkg_lib.sh 3 | 4 | rm -rf pack 5 | mkdir -p pack 6 | 7 | cd pack 8 | 9 | wget https://www.lua.org/ftp/lua-5.4.7.tar.gz 10 | 11 | tar -xvf lua-5.4.7.tar.gz 12 | cd lua-5.4.7 13 | 14 | make CC=x86_64-orange-gcc LD=x86_64-orange-ld generic -j$(nproc) 15 | cp -rf src/lua "$1/bin" 16 | cp -rf src/luac "$1/bin" 17 | 18 | clear_share "$1" 19 | 20 | cd .. 21 | -------------------------------------------------------------------------------- /tools/pkg/memstat/info.txt: -------------------------------------------------------------------------------- 1 | memstat -------------------------------------------------------------------------------- /tools/pkg/memstat/pkg.sh: -------------------------------------------------------------------------------- 1 | 2 | x86_64-orange-gcc src/main.c -o "$1/bin/memstat" -------------------------------------------------------------------------------- /tools/pkg/memstat/src/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | int main() { 5 | printf("MemStat Utility\n"); 6 | asm volatile("syscall" : : "a"(38) : "rcx","r11"); 7 | } -------------------------------------------------------------------------------- /tools/pkg/nano/diff/nano.diff: -------------------------------------------------------------------------------- 1 | diff -Naur nano-8.4/config.sub nano-patched/config.sub 2 | --- nano-8.4/config.sub 2022-01-31 17:43:17.000000000 +0300 3 | +++ nano-patched/config.sub 2025-06-02 10:06:02.670396019 +0300 4 | @@ -1750,7 +1750,7 @@ 5 | | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ 6 | | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ 7 | | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ 8 | - | skyos* | haiku* | rdos* | toppers* | drops* | es* \ 9 | + | skyos* | orange* | haiku* | rdos* | toppers* | drops* | es* \ 10 | | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ 11 | | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ 12 | | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ 13 | -------------------------------------------------------------------------------- /tools/pkg/nano/info.txt: -------------------------------------------------------------------------------- 1 | nano-8.4 -------------------------------------------------------------------------------- /tools/pkg/nano/pkg.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | . ../pkg_lib.sh 4 | 5 | rm -rf pack 6 | 7 | mkdir -p pack 8 | 9 | cd pack 10 | 11 | echo $1 12 | 13 | install_gnu nano nano 8.4 14 | mkdir -p nano-build 15 | 16 | cd nano-8.4 17 | diff_patch ../../diff/nano.diff 18 | cd .. 19 | 20 | cd nano-build 21 | ../nano-8.4/configure --host=x86_64-orange CFLAGS="-std=gnu17" --prefix=$1 gl_cv_func_strcasecmp_works=yes 22 | 23 | make -j$(nproc) 24 | make install -j$(nproc) 25 | 26 | cd ../ -------------------------------------------------------------------------------- /tools/pkg/pkg_lib.sh: -------------------------------------------------------------------------------- 1 | 2 | GNU_MIRROR=https://mirror.dogado.de/ 3 | 4 | clear_share() { 5 | echo no 6 | } 7 | 8 | install_gnu() { 9 | 10 | pkg_name=$1 11 | name=$2 12 | version=$3 13 | 14 | wget -nc "$GNU_MIRROR/gnu/$pkg_name/$name-$version.tar.gz" 15 | tar -xvf "$name-$version.tar.gz" 16 | 17 | rm -rf "$name-$version.tar.gz" 18 | 19 | } 20 | 21 | diff_patch() { 22 | patch -p1 < "$1" 23 | } -------------------------------------------------------------------------------- /tools/pkg/toolchain.cmake: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_SYSTEM_NAME Orange) 3 | set(CMAKE_SYSTEM_PROCESSOR x86_64) 4 | 5 | set(CMAKE_C_COMPILER x86_64-orange-gcc) 6 | set(CMAKE_LINKER x86_64-orange-ld) 7 | 8 | set(CMAKE_CXX_EXTENSIONS ON) 9 | set(CMAKE_C_EXTENSIONS ON) -------------------------------------------------------------------------------- /tools/test_init/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | char kmap[255] = { 7 | 8 | '\0', '\0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 9 | '\0', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 10 | '\n', '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 11 | '\0', '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', ' ', '*', 12 | '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 13 | '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', '\0', 14 | '\0' 15 | 16 | }; 17 | 18 | char __shift_pressed = 0; 19 | 20 | char __ps_2_to_upper(char c) { 21 | 22 | if (c >= 'a' && c <= 'z') { 23 | return c - ('a' - 'A'); 24 | 25 | } 26 | 27 | switch (c) { 28 | 29 | case '1': return '!'; 30 | case '2': return '@'; 31 | case '3': return '#'; 32 | case '4': return '$'; 33 | case '5': return '%'; 34 | case '6': return '^'; 35 | case '7': return '&'; 36 | case '8': return '*'; 37 | case '9': return '('; 38 | case '0': return ')'; 39 | case '-': return '_'; 40 | case '=': return '+'; 41 | case '`': return '~'; 42 | 43 | default: break; 44 | 45 | } 46 | 47 | if (c == '\'') { 48 | return '\"'; 49 | } 50 | 51 | return c; 52 | } 53 | 54 | #define SHIFT_PRESSED 0x2A 55 | 56 | #define SHIFT_RELEASED 0xAA 57 | 58 | char __ps2_read(char keycodeps2) { 59 | 60 | unsigned char keycode = keycodeps2; 61 | 62 | if(keycode == SHIFT_PRESSED) 63 | __shift_pressed = 1; 64 | 65 | if(keycode == SHIFT_RELEASED) 66 | __shift_pressed = 0; 67 | 68 | if(keycode <= 0x58) { 69 | keycode = kmap[keycode]; 70 | 71 | if(__shift_pressed) 72 | keycode = __ps_2_to_upper(keycode); 73 | 74 | } 75 | 76 | if(keycode & (1 << 7)) 77 | return '\0'; 78 | 79 | return keycode; 80 | 81 | return 0; 82 | 83 | } 84 | 85 | void forkandexec(const char* name) { 86 | int ia = fork(); 87 | printf("Fokr %d\n",ia); 88 | if(ia == 0) { 89 | printf("Execin\n"); 90 | execl(name,name,NULL); 91 | } 92 | 93 | return; 94 | 95 | } 96 | 97 | #include 98 | 99 | int main() { 100 | 101 | printf("SSE test\n"); 102 | 103 | float i = 10.25; 104 | float no = 9.104; 105 | float fin = i + no; 106 | 107 | printf("SSE 10.25 + 9.104 = %.6f\n",fin); 108 | 109 | printf("Executing bash\n"); 110 | execl("/usr/bin/bash","/usr/bin/bash",NULL); 111 | 112 | 113 | } 114 | -------------------------------------------------------------------------------- /tools/toolchain/cpp.sh: -------------------------------------------------------------------------------- 1 | 2 | cd pack/gcc-build 3 | make all-target-libstdc++-v3 4 | make install-target-libstdc++-v3 5 | cd ../../ -------------------------------------------------------------------------------- /tools/toolchain/get.sh: -------------------------------------------------------------------------------- 1 | 2 | set -e 3 | 4 | GNU_MIRROR=https://mirror.dogado.de/ 5 | CURRENT_DIR="$(realpath .)" 6 | 7 | rm -rf "$HOME/opt/cross/orange" 8 | 9 | rm -rf pack 10 | 11 | echo Downloading binutils and gcc 12 | 13 | mkdir -p pack 14 | 15 | mkdir -p $1/initrd/usr/include 16 | mkdir -p $1/initrd/usr/lib 17 | 18 | cd pack 19 | 20 | wget -nc $GNU_MIRROR/gnu/gcc/gcc-11.4.0/gcc-11.4.0.tar.gz 21 | wget -nc $GNU_MIRROR/gnu/binutils/binutils-2.38.tar.gz 22 | 23 | echo Unpacking binutils and gcc 24 | 25 | tar -xvf gcc-11.4.0.tar.gz 26 | tar -xvf binutils-2.38.tar.gz 27 | 28 | echo Patching binutils and gcc 29 | 30 | cd binutils-2.38 31 | patch -p1 <"$CURRENT_DIR/../diffs/binutils.diff" 32 | cd ../gcc-11.4.0 33 | patch -p1 <"$CURRENT_DIR/../diffs/gcc.diff" 34 | cd .. 35 | 36 | echo Downloading prerequisites 37 | cd gcc-11.4.0 38 | ./contrib/download_prerequisites 39 | cd .. 40 | 41 | echo Donwloading and installing automake and autoconf 42 | 43 | wget -nc $GNU_MIRROR/gnu/automake/automake-1.15.1.tar.gz 44 | wget -nc $GNU_MIRROR/gnu/autoconf/autoconf-2.69.tar.gz 45 | 46 | tar -xvf automake-1.15.1.tar.gz 47 | tar -xvf autoconf-2.69.tar.gz 48 | 49 | cd automake-1.15.1 50 | ./configure --prefix="$HOME/opt/cross/orange" 51 | make 52 | make install 53 | cd .. 54 | 55 | cd autoconf-2.69 56 | ./configure --prefix="$HOME/opt/cross/orange" 57 | make 58 | make install 59 | cd .. 60 | 61 | export PATH="$HOME/opt/cross/orange/bin:$PATH" 62 | 63 | cd binutils-2.38/ld 64 | automake 65 | cd ../../gcc-11.4.0/libstdc++-v3 66 | autoconf 67 | cd ../../ 68 | 69 | echo Building binutils and gcc 70 | 71 | mkdir -p binutils-build 72 | cd binutils-build 73 | mkdir -p $1/initrd 74 | ../binutils-2.38/configure --target=x86_64-orange --prefix="$HOME/opt/cross/orange" --with-sysroot="$(realpath $1)/initrd" --enable-shared 75 | make -j$(nproc) 76 | make install -j$(nproc) 77 | 78 | cd .. 79 | mkdir -p gcc-build 80 | cd gcc-build 81 | ../gcc-11.4.0/configure --target=x86_64-orange --prefix="$HOME/opt/cross/orange" --with-sysroot="$(realpath $1)/initrd" --enable-languages=c,c++,go --disable-nls --enable-linker-build-id --enable-default-pie --enable-default-ssp --disable-multilib --enable-initfini-array --enable-shared --enable-host-shared CFLAGS="" 82 | 83 | make all-gcc -j$(nproc) 84 | make all-target-libgcc -j$(nproc) 85 | make install-gcc -j$(nproc) 86 | make install-target-libgcc -j$(nproc) 87 | make all-target-libstdc++-v3 88 | make install-target-libstdc++-v3 89 | 90 | echo Done 91 | --------------------------------------------------------------------------------