├── .gitignore ├── .gitmodules ├── .vscode └── launch.json ├── CMakeLists.txt ├── LICENSE ├── README.md ├── documentation ├── Doxyfile ├── Doxyfile_Syscalls ├── driver_communication.md └── signals.md ├── isodir ├── EFI │ └── BOOT │ │ ├── BOOTAA64.EFI │ │ └── BOOTIA32.EFI ├── limine.cfg ├── limine │ ├── limine-bios-cd.bin │ ├── limine-bios-pxe.bin │ ├── limine-bios.sys │ └── limine-uefi-cd.bin ├── obos │ ├── font.bin │ ├── initrd.tar │ ├── initrd │ │ ├── boot.cfg │ │ ├── fatDriver │ │ ├── gptDriver │ │ ├── mbrDriver │ │ ├── obos │ │ │ └── init │ │ ├── ps2KeyboardDriver │ │ └── sataDriver │ ├── initrdDriver │ └── oboskrnl └── testProgram ├── out ├── acpiDriver ├── fatDriver ├── gptDriver ├── init ├── initrdDriver ├── mbrDriver ├── obos.iso ├── oboskrnl ├── ps2KeyboardDriver ├── sataDriver └── test_program ├── ovmf ├── OVMF_CODE_4M.fd └── OVMF_VARS_4M.fd ├── screenshots ├── 1511_2023-11-11.png ├── 2023-11-13_20-59.png ├── 2023-12-02_1126.png ├── 2023-12-03_0937.png ├── 20230112_2053.png ├── 20231128_1838.png ├── 20231213_2020.png ├── 20231224_1909.png ├── 20231225_1914.png ├── 20231228_1202.png ├── 20231228_1951.png ├── 20231229_0831.png ├── 2023_12_10-1143.png ├── 2023_12_10-1149.png ├── 2023_12_10-1204.png ├── 20240103_1012.png ├── 20240103_1025.png ├── 20240103_1134.png ├── 20240104_0905.png ├── 20240116_1903.png ├── 20240116_1921.png ├── 20240117_1630.png ├── 20240117_1950.png ├── 20240117_1954.png ├── 20240120_2042.png ├── 20240121_0726.png ├── 20240121_1932.png ├── 20240126_0826.png ├── 20240126_0932.png ├── 20240126_0938.png ├── 20240126_0943.png ├── 20240126_1028.png ├── 2024012_1028.png ├── 20240201_2005.png ├── 20240201_2014.png ├── initrd_driver-reading.png ├── initrd_driver-working.png ├── kpanic_2023-10-12_0437PM.png ├── kpanic_2023-10-29.png ├── multitasking_1.png ├── new_kpanic-2023_10_28.png ├── smp_try1.png ├── vfs_test-2023-11-04.png └── vfs_test-2023-11-04_2.png ├── scripts ├── .gdbinit ├── find_addr.sh ├── launch_qemu.bat ├── launch_qemu.sh ├── make_initrd.bat └── make_initrd.sh └── src ├── drivers ├── generic │ ├── acpi │ │ ├── CMakeLists.txt │ │ ├── impl.cpp │ │ ├── main.cpp │ │ ├── makeshift_include │ │ │ ├── inttypes.h │ │ │ ├── stdio.h │ │ │ ├── stdlib.h │ │ │ ├── string.h │ │ │ └── uacpi_arch_helpers.h │ │ └── stdlib_impl.cpp │ ├── common │ │ └── new.cpp │ ├── fat │ │ ├── CMakeLists.txt │ │ ├── cache.cpp │ │ ├── cache.h │ │ ├── fat32_structs.h │ │ ├── fat_structs.h │ │ ├── interface.cpp │ │ └── main.cpp │ ├── gpt │ │ ├── CMakeLists.txt │ │ └── main.cpp │ └── initrd │ │ ├── CMakeLists.txt │ │ ├── interface.cpp │ │ ├── interface.h │ │ ├── main.cpp │ │ ├── parse.cpp │ │ └── parse.h └── x86_64 │ ├── mbr │ ├── CMakeLists.txt │ └── main.cpp │ ├── ps2Keyboard │ ├── CMakeLists.txt │ ├── dmain.cpp │ ├── scancodes.cpp │ └── scancodes.h │ └── sata │ ├── CMakeLists.txt │ ├── command.cpp │ ├── command.h │ ├── interface.cpp │ ├── main.cpp │ └── structs.h ├── oboskrnl ├── CMakeLists.txt ├── allocators │ ├── liballoc.cpp │ ├── liballoc.h │ ├── slab.cpp │ ├── slab.h │ └── vmm │ │ ├── arch.h │ │ ├── vmm.cpp │ │ └── vmm.h ├── arch │ ├── interrupt.h │ └── x86_64 │ │ ├── exception_handlers.cpp │ │ ├── fpu.asm │ │ ├── gdbstub │ │ ├── communicate.cpp │ │ ├── communicate.h │ │ ├── stub.cpp │ │ └── stub.h │ │ ├── gdt.asm │ │ ├── gdt.cpp │ │ ├── idt.asm │ │ ├── idt.cpp │ │ ├── int_handlers.asm │ │ ├── interrupt.h │ │ ├── irq │ │ ├── acpi.h │ │ ├── irq.cpp │ │ ├── irq.h │ │ ├── timer.cpp │ │ └── timer.h │ │ ├── memory_manager │ │ ├── physical │ │ │ ├── allocate.h │ │ │ ├── allocatePhys.cpp │ │ │ └── allocate_old.cpp │ │ └── virtual │ │ │ ├── allocate.cpp │ │ │ ├── initialize.cpp │ │ │ ├── initialize.h │ │ │ ├── internal.cpp │ │ │ ├── internal.h │ │ │ └── mapFile.cpp │ │ ├── signals.cpp │ │ ├── smp_start.cpp │ │ ├── smp_trampoline.asm │ │ ├── sse.asm │ │ ├── stack_canary.cpp │ │ ├── syscall │ │ ├── console.h │ │ ├── handle.cpp │ │ ├── handle.h │ │ ├── power_management.cpp │ │ ├── power_management.h │ │ ├── register.cpp │ │ ├── register.h │ │ ├── sconsole.cpp │ │ ├── signals.h │ │ ├── sys_signals.cpp │ │ ├── syscall_vmm.cpp │ │ ├── thread.cpp │ │ ├── thread.h │ │ ├── verify_pars.cpp │ │ ├── verify_pars.h │ │ ├── vfs │ │ │ ├── dir.cpp │ │ │ ├── dir.h │ │ │ ├── disk.cpp │ │ │ ├── disk.h │ │ │ ├── file.cpp │ │ │ └── file.h │ │ └── vmm.h │ │ └── trace.cpp ├── atomic.h ├── boot │ ├── cfg.cpp │ ├── cfg.h │ ├── kmain.cpp │ └── x86_64 │ │ └── kmain_arch.cpp ├── console.cpp ├── console.h ├── driverInterface │ ├── input_device.h │ ├── load.h │ ├── register.cpp │ ├── register.h │ ├── struct.h │ └── x86_64 │ │ ├── enumerate_pci.cpp │ │ ├── enumerate_pci.h │ │ ├── load.cpp │ │ └── scan.cpp ├── error.cpp ├── error.h ├── export.h ├── int.h ├── klog.cpp ├── klog.h ├── memory_manipulation.h ├── multitasking │ ├── arch.h │ ├── cpu_local.h │ ├── locks │ │ ├── mutex.cpp │ │ └── mutex.h │ ├── process │ │ ├── arch.h │ │ ├── process.cpp │ │ ├── process.h │ │ ├── signals.h │ │ └── x86_64 │ │ │ ├── loader │ │ │ ├── elf.cpp │ │ │ ├── elf.h │ │ │ └── elfStructures.h │ │ │ ├── procInfo.cpp │ │ │ └── procInfo.h │ ├── scheduler.cpp │ ├── scheduler.h │ ├── thread.h │ ├── threadAPI │ │ ├── thrHandle.cpp │ │ └── thrHandle.h │ └── x86_64 │ │ ├── arch_structs.h │ │ ├── calibrate_timer.asm │ │ ├── calibrate_timer_old.asm │ │ ├── scheduler_bootstrapper.cpp │ │ ├── setupFrameInfo.cpp │ │ └── taskSwitchImpl.asm ├── new ├── utils │ ├── hashmap.h │ ├── pair.h │ ├── stack.h │ ├── stb_sprintf.h │ ├── string.cpp │ ├── string.h │ └── vector.h ├── vfs │ ├── devManip │ │ ├── driveHandle.cpp │ │ ├── driveHandle.h │ │ ├── driveIterator.cpp │ │ ├── driveIterator.h │ │ ├── memcpy.h │ │ └── sectorStore.h │ ├── fileManip │ │ ├── directoryIterator.cpp │ │ ├── directoryIterator.h │ │ ├── fileHandle.cpp │ │ └── fileHandle.h │ ├── mount │ │ ├── mount.cpp │ │ └── mount.h │ ├── off_t.h │ └── vfsNode.h └── x86_64-utils │ ├── asm.asm │ ├── asm.h │ └── memory_manipulation.asm ├── programs └── x86-64 │ ├── common │ └── syscall.asm │ ├── init │ ├── CMakeLists.txt │ ├── liballoc.cpp │ ├── liballoc.h │ ├── logger.cpp │ ├── logger.h │ ├── main.cpp │ ├── new │ ├── stb_sprintf.h │ └── syscall.h │ └── testProgram │ ├── CMakeLists.txt │ └── main.cpp └── scripts-toolchains └── x86_64 ├── linker.ld └── toolchain.cmake /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /.vs 6 | /out/build 7 | /CMakePresets.json 8 | /oldCMakeSettings.json 9 | /out/Ubuntu 10 | /limine 11 | /qemu_log.txt 12 | /documentation/html 13 | /qemu_log.txt 14 | /.vscode 15 | /.VSCodeCounter 16 | /build 17 | /scripts/copy_files_to_disk.bat 18 | /bck 19 | /disk.img 20 | /scripts/mount_disk_image.sh 21 | /scripts/umount_disk_image.sh 22 | /documentation/doxygen 23 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/drivers/generic/acpi/uACPI"] 2 | path = src/drivers/generic/acpi/uACPI 3 | url = https://github.com/UltraOS/uACPI.git -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "oboskrnl-qemu", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "cwd": ".", 12 | "program": "./out/oboskrnl", 13 | "MIMode": "gdb", 14 | "miDebuggerPath": "gdb", 15 | "targetArchitecture": "x64", 16 | "miDebuggerServerAddress": ":1234", 17 | "logging": {}, 18 | "customLaunchSetupCommands": [ 19 | { 20 | "description": "Set Disassembly Flavor to Intel", 21 | "text": "-gdb-set disassembly-flavor intel", 22 | "ignoreFailures": true 23 | }, 24 | { 25 | "description": "Set architecture", 26 | "text": "-gdb-set architecture i386:x86_64", 27 | "ignoreFailures": true 28 | }, 29 | { 30 | "description": "Connect to qemu", 31 | "text": "-target-select extended-remote localhost:1234" 32 | }, 33 | { 34 | "description": "Load the kernel binary.", 35 | "text": "-file-exec-and-symbols /Code/obos/out/oboskrnl", 36 | "ignoreFailures": true 37 | }, 38 | { 39 | "description": "Load the init program binary.", 40 | "text": "-file-exec-and-symbols /Code/obos/out/init", 41 | "ignoreFailures": false 42 | } 43 | ], 44 | }, 45 | ] 46 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | cmake_minimum_required(VERSION 3.5) 6 | 7 | project(obos C CXX ASM_NASM) 8 | 9 | if (NOT DEFINED OUTPUT_DIR) 10 | set(OUTPUT_DIR "${CMAKE_SOURCE_DIR}/out") 11 | endif() 12 | if (NOT DEFINED GENERATE_BUILD_FILES_FOR_UNIX) 13 | set(GENERATE_BUILD_FILES_FOR_UNIX 1) 14 | endif() 15 | if (NOT DEFINED E9_HACK) 16 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") 17 | set(E9_HACK "1") 18 | else() 19 | set(E9_HACK "0") 20 | endif() 21 | endif() 22 | 23 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") 24 | set(DEBUG_SYMBOLS_OPT -g) 25 | else() 26 | set(DEBUG_SYMBOLS_OPT) 27 | endif() 28 | 29 | set (CXX_STANDARD 20) 30 | 31 | add_subdirectory("src/oboskrnl") 32 | add_subdirectory("src/drivers/generic/initrd") 33 | add_subdirectory("src/drivers/generic/gpt") 34 | add_subdirectory("src/drivers/generic/fat") 35 | add_subdirectory("src/drivers/generic/acpi") 36 | if (OBOS_ARCHITECTURE STREQUAL "x86_64") 37 | add_subdirectory("src/drivers/x86_64/sata") 38 | add_subdirectory("src/drivers/x86_64/mbr") 39 | add_subdirectory("src/drivers/x86_64/ps2Keyboard") 40 | add_subdirectory("src/programs/x86-64/init") 41 | endif() -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-2024 Omar Berrow 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OBOS 2 | ## Goals 3 | - [x] A module loader/interface 4 | - [x] An initrd driver 5 | - [x] A VFS 6 | - [x] PS2 Keyboard driver 7 | - [x] AHCI Driver 8 | - [ ] NVME Driver. 9 | - [x] A FAT driver. 10 | - [ ] Ext2/3/4 Driver. 11 | - [ ] POSIX Compatibility Layer 12 | - [ ] Porting mlibc. 13 | - [ ] A terminal. 14 | - [ ] Support for USB. 15 | - [x] Support for ACPI power management. 16 | - [x] Making a GCC/Binutils target for the os. 17 | - [ ] Porting binutils and GCC to the os. 18 | - [ ] Porting CMake and Make. 19 | - [ ] Porting tar. 20 | - [ ] A network stack. 21 | - [ ] An audio stack. 22 | - [ ] A GUI. 23 | - [ ] Porting python. 24 | - [ ] Porting 7zip. 25 | - [ ] Porting a browser and curl. 26 | - [ ] Porting qemu. 27 | ## Building 28 | ### Prerequisites 29 | - CMake 30 | - Ninja 31 | - Make 32 | - xorriso 33 | - An x86_64-elf-gcc cross compiler if you are building for x86_64. 34 | - WSL2 if you are on windows. 35 | ### Build Instructions (x86_64) 36 | 1. Open a terminal (or WSL if on windows), and clone the GitHub repository with these commands: 37 | ```bash 38 | git clone https://github.com/oberrow/obos.git 39 | cd obos 40 | git clone https://github.com/limine-bootloader/limine.git --branch=v5.2023-20241006.0-binary --depth=1 41 | ``` 42 | You can ignore any warnings.
43 | 2. Configure cmake with this command: 44 | ```bash 45 | cmake --toolchain src/scripts-toolchains/x86_64/toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -G Ninja . 46 | ``` 47 | 3. Finally, build the kernel with these commands: 48 | ```bash 49 | make -C limine 50 | ninja -j 0 51 | ``` 52 | 53 | The iso image will be stored in out/obos.iso
54 | If you have qemu installed, you can run a virtual machine with the os by running scripts/launch-qemu.sh 55 | -------------------------------------------------------------------------------- /documentation/signals.md: -------------------------------------------------------------------------------- 1 | # OBOS Signals 2 | ## Definition 3 | A callback (much like an interrupt) called by the kernel on a certain condition (ex: page fault). 4 | ## Signal values. 5 | | Signal | Value | Reason for signal | Default action | 6 | |---------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------| 7 | | SIGPF | 0x0000 | A page fault occurred that the kernel couldn't resolve (not related to demand paging or any VMM feature). | Kill the process. | 8 | | SIGPM | 0x0001 | Permission error. This occurs when the program tries to modify something other than memory that it is not allowed to modify. | Kill the process. | 9 | | SIGOF | 0x0002 | An integer overflow occurred | Kill the process. | 10 | | SIGME | 0x0003 | A math error occurred. This can occur on division by zero or any operation that involves math (like anything to do with floating point). This should not occur on integer overflow (see SIGOF). | Kill the process. | 11 | | SIGDG | 0x0004 | A debug exception occurred. This is architecture-specific. | Kill the process. | 12 | | SIGTIME | 0x0005 | A timer set by the thread finished. | Ignore | 13 | | SIGTERM | 0x0006 | A program made a request to terminate the program. This is provided so that the program can properly free any resources opened. | Kill the process. | 14 | | SIGINT | 0x0007 | A request to interrupt the process was made. | Kill the process. | 15 | | SIGUDOC | 0x0008 | An undefined opcode exception occurred. | Kill the process. | 16 | | SIGUEXC | 0x0009 | An exception with no signal happened. | Kill the process. | -------------------------------------------------------------------------------- /isodir/EFI/BOOT/BOOTAA64.EFI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/EFI/BOOT/BOOTAA64.EFI -------------------------------------------------------------------------------- /isodir/EFI/BOOT/BOOTIA32.EFI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/EFI/BOOT/BOOTIA32.EFI -------------------------------------------------------------------------------- /isodir/limine.cfg: -------------------------------------------------------------------------------- 1 | # Timeout in seconds that Limine will use before automatically booting. 2 | TIMEOUT=1 3 | QUIET=yes 4 | DEFAULT_ENTRY=1 5 | RANDOMIZE_MEMORY=no 6 | 7 | :OBOS 8 | PROTOCOL=limine 9 | 10 | KASLR=no 11 | 12 | MODULE_PATH=boot:///obos/font.bin 13 | MODULE_PATH=boot:///obos/initrdDriver 14 | MODULE_PATH=boot:///obos/initrd.tar 15 | KERNEL_PATH=boot:///obos/oboskrnl 16 | :Next Bootable Disk 17 | PROTOCOL=chainload_next -------------------------------------------------------------------------------- /isodir/limine/limine-bios-cd.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/limine/limine-bios-cd.bin -------------------------------------------------------------------------------- /isodir/limine/limine-bios-pxe.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/limine/limine-bios-pxe.bin -------------------------------------------------------------------------------- /isodir/limine/limine-bios.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/limine/limine-bios.sys -------------------------------------------------------------------------------- /isodir/limine/limine-uefi-cd.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/limine/limine-uefi-cd.bin -------------------------------------------------------------------------------- /isodir/obos/font.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/font.bin -------------------------------------------------------------------------------- /isodir/obos/initrd.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/initrd.tar -------------------------------------------------------------------------------- /isodir/obos/initrd/boot.cfg: -------------------------------------------------------------------------------- 1 | # oboskrnl boot configuration file. 2 | 3 | # The filesystem drivers to load at boot, these must be in the initrd image. 4 | FS_DRIVERS=[ 0:/fatDriver ] 5 | # Whether to load only trusted drivers at boot. 6 | # TODO: Implement. 7 | TRUSTED_DRIVERS_ONLY=false 8 | # The init program to start before finishing early-kernel boot. 9 | # This can specify any valid mount point, not just the initrd like FS_DRIVERS. 10 | # Although, to know the valid mount points, you need to run the kernel and see the various mount points printed. 11 | INIT_PROGRAM=0:/obos/init -------------------------------------------------------------------------------- /isodir/obos/initrd/fatDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/initrd/fatDriver -------------------------------------------------------------------------------- /isodir/obos/initrd/gptDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/initrd/gptDriver -------------------------------------------------------------------------------- /isodir/obos/initrd/mbrDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/initrd/mbrDriver -------------------------------------------------------------------------------- /isodir/obos/initrd/obos/init: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/initrd/obos/init -------------------------------------------------------------------------------- /isodir/obos/initrd/ps2KeyboardDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/initrd/ps2KeyboardDriver -------------------------------------------------------------------------------- /isodir/obos/initrd/sataDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/initrd/sataDriver -------------------------------------------------------------------------------- /isodir/obos/initrdDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/initrdDriver -------------------------------------------------------------------------------- /isodir/obos/oboskrnl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/obos/oboskrnl -------------------------------------------------------------------------------- /isodir/testProgram: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/isodir/testProgram -------------------------------------------------------------------------------- /out/acpiDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/acpiDriver -------------------------------------------------------------------------------- /out/fatDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/fatDriver -------------------------------------------------------------------------------- /out/gptDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/gptDriver -------------------------------------------------------------------------------- /out/init: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/init -------------------------------------------------------------------------------- /out/initrdDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/initrdDriver -------------------------------------------------------------------------------- /out/mbrDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/mbrDriver -------------------------------------------------------------------------------- /out/obos.iso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/obos.iso -------------------------------------------------------------------------------- /out/oboskrnl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/oboskrnl -------------------------------------------------------------------------------- /out/ps2KeyboardDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/ps2KeyboardDriver -------------------------------------------------------------------------------- /out/sataDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/sataDriver -------------------------------------------------------------------------------- /out/test_program: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/out/test_program -------------------------------------------------------------------------------- /ovmf/OVMF_CODE_4M.fd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/ovmf/OVMF_CODE_4M.fd -------------------------------------------------------------------------------- /ovmf/OVMF_VARS_4M.fd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/ovmf/OVMF_VARS_4M.fd -------------------------------------------------------------------------------- /screenshots/1511_2023-11-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/1511_2023-11-11.png -------------------------------------------------------------------------------- /screenshots/2023-11-13_20-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/2023-11-13_20-59.png -------------------------------------------------------------------------------- /screenshots/2023-12-02_1126.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/2023-12-02_1126.png -------------------------------------------------------------------------------- /screenshots/2023-12-03_0937.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/2023-12-03_0937.png -------------------------------------------------------------------------------- /screenshots/20230112_2053.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20230112_2053.png -------------------------------------------------------------------------------- /screenshots/20231128_1838.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20231128_1838.png -------------------------------------------------------------------------------- /screenshots/20231213_2020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20231213_2020.png -------------------------------------------------------------------------------- /screenshots/20231224_1909.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20231224_1909.png -------------------------------------------------------------------------------- /screenshots/20231225_1914.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20231225_1914.png -------------------------------------------------------------------------------- /screenshots/20231228_1202.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20231228_1202.png -------------------------------------------------------------------------------- /screenshots/20231228_1951.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20231228_1951.png -------------------------------------------------------------------------------- /screenshots/20231229_0831.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20231229_0831.png -------------------------------------------------------------------------------- /screenshots/2023_12_10-1143.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/2023_12_10-1143.png -------------------------------------------------------------------------------- /screenshots/2023_12_10-1149.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/2023_12_10-1149.png -------------------------------------------------------------------------------- /screenshots/2023_12_10-1204.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/2023_12_10-1204.png -------------------------------------------------------------------------------- /screenshots/20240103_1012.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240103_1012.png -------------------------------------------------------------------------------- /screenshots/20240103_1025.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240103_1025.png -------------------------------------------------------------------------------- /screenshots/20240103_1134.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240103_1134.png -------------------------------------------------------------------------------- /screenshots/20240104_0905.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240104_0905.png -------------------------------------------------------------------------------- /screenshots/20240116_1903.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240116_1903.png -------------------------------------------------------------------------------- /screenshots/20240116_1921.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240116_1921.png -------------------------------------------------------------------------------- /screenshots/20240117_1630.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240117_1630.png -------------------------------------------------------------------------------- /screenshots/20240117_1950.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240117_1950.png -------------------------------------------------------------------------------- /screenshots/20240117_1954.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240117_1954.png -------------------------------------------------------------------------------- /screenshots/20240120_2042.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240120_2042.png -------------------------------------------------------------------------------- /screenshots/20240121_0726.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240121_0726.png -------------------------------------------------------------------------------- /screenshots/20240121_1932.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240121_1932.png -------------------------------------------------------------------------------- /screenshots/20240126_0826.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240126_0826.png -------------------------------------------------------------------------------- /screenshots/20240126_0932.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240126_0932.png -------------------------------------------------------------------------------- /screenshots/20240126_0938.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240126_0938.png -------------------------------------------------------------------------------- /screenshots/20240126_0943.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240126_0943.png -------------------------------------------------------------------------------- /screenshots/20240126_1028.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240126_1028.png -------------------------------------------------------------------------------- /screenshots/2024012_1028.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/2024012_1028.png -------------------------------------------------------------------------------- /screenshots/20240201_2005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240201_2005.png -------------------------------------------------------------------------------- /screenshots/20240201_2014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/20240201_2014.png -------------------------------------------------------------------------------- /screenshots/initrd_driver-reading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/initrd_driver-reading.png -------------------------------------------------------------------------------- /screenshots/initrd_driver-working.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/initrd_driver-working.png -------------------------------------------------------------------------------- /screenshots/kpanic_2023-10-12_0437PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/kpanic_2023-10-12_0437PM.png -------------------------------------------------------------------------------- /screenshots/kpanic_2023-10-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/kpanic_2023-10-29.png -------------------------------------------------------------------------------- /screenshots/multitasking_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/multitasking_1.png -------------------------------------------------------------------------------- /screenshots/new_kpanic-2023_10_28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/new_kpanic-2023_10_28.png -------------------------------------------------------------------------------- /screenshots/smp_try1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/smp_try1.png -------------------------------------------------------------------------------- /screenshots/vfs_test-2023-11-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/vfs_test-2023-11-04.png -------------------------------------------------------------------------------- /screenshots/vfs_test-2023-11-04_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OBOS-dev/obos-old/d82cd2bd3e488f48e7c174040611a5dedb3ff93a/screenshots/vfs_test-2023-11-04_2.png -------------------------------------------------------------------------------- /scripts/.gdbinit: -------------------------------------------------------------------------------- 1 | set architecture i386:x86-64 2 | target remote :1234 3 | b *0x80 4 | c 5 | file ../out/oboskrnl -------------------------------------------------------------------------------- /scripts/find_addr.sh: -------------------------------------------------------------------------------- 1 | clear 2 | 3 | cd .. 4 | export address=$1 5 | export exe=$2 6 | if [ -z "$exe" ] 7 | then 8 | export exe=out/oboskrnl 9 | fi 10 | addr2line -e $exe -Cfpira 0x$address 11 | objdump -d $exe -C -M intel | grep --color -C 10 -n $address 12 | cd scripts 13 | -------------------------------------------------------------------------------- /scripts/launch_qemu.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd ../ 4 | 5 | del qemu_log.txt 6 | 7 | qemu-system-x86_64 ^ 8 | -device ahci,id=ahci1 ^ 9 | -drive id=disk1,file=out/obos.iso,if=none,format=raw -device ide-hd,drive=disk1,bus=ahci1.0 ^ 10 | -drive id=disk2,file=disk.img,if=none,format=raw -device ide-hd,drive=disk2,bus=ahci1.1 ^ 11 | -gdb tcp:0.0.0.0:1234 -S ^ 12 | -m 1G ^ 13 | -cpu qemu64,+nx,+pdpe1gb,+syscall,-fsgsbase,+smep,+smap,+sse,+sse2,+sse4.1,+sse4.2 ^ 14 | -monitor stdio ^ 15 | -debugcon file:CON ^ 16 | -serial tcp:0.0.0.0:1534,server,nowait ^ 17 | -smp cores=8,threads=1,sockets=1 ^ 18 | -d int ^ 19 | -D qemu_log.txt 20 | rem -drive if=pflash,format=raw,unit=1,file=ovmf/OVMF_VARS_4M.fd 21 | rem -drive if=pflash,format=raw,unit=0,file=ovmf/OVMF_CODE_4M.fd,readonly=on 22 | rem -M smm=off ^ 23 | rem -no-reboot 24 | rem -no-shutdown 25 | 26 | cd scripts -------------------------------------------------------------------------------- /scripts/launch_qemu.sh: -------------------------------------------------------------------------------- 1 | cd ../ 2 | 3 | qemu-system-x86_64 \ 4 | -drive id=disk1,file=out/obos.iso,if=none,format=raw -device ahci,id=ahci1 -device ide-hd,drive=disk1,bus=ahci1.0 \ 5 | -drive id=disk2,file=disk.img,if=none,format=raw -device ide-hd,drive=disk2,bus=ahci1.1 \ 6 | -gdb tcp:0.0.0.0:1234 -S \ 7 | -m 1G \ 8 | -cpu qemu64,+nx,+pdpe1gb,+syscall,+fsgsbase,+rdrand,+rdseed,+rdtscp,+smep,+smap \ 9 | -monitor stdio \ 10 | -debugcon file:/dev/stdout \ 11 | -serial tcp:0.0.0.0:1534,server,nowait \ 12 | -smp cores=4,threads=1,sockets=1 \ 13 | -M smm=off \ 14 | -d trace:*ahci*,int \ 15 | -D qemu_log.txt 16 | # \ 17 | # -no-reboot 18 | # -no-shutdown 19 | # -drive if=pflash,format=raw,unit=0,file=ovmf/OVMF_CODE_4M.fd,readonly=on \ 20 | # -drive if=pflash,format=raw,unit=1,file=ovmf/OVMF_VARS_4M.fd \ 21 | 22 | cd scripts -------------------------------------------------------------------------------- /scripts/make_initrd.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd ../isodir/obos/initrd 3 | tar --format ustar -cf ..\initrd.tar * 4 | cd ../../../scripts -------------------------------------------------------------------------------- /scripts/make_initrd.sh: -------------------------------------------------------------------------------- 1 | clear 2 | cd ../isodir/obos/initrd 3 | tar -H ustar -cf ../initrd.tar $(ls) 4 | cd ../../../scripts -------------------------------------------------------------------------------- /src/drivers/generic/acpi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # drivers/generic/acpi/CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | include("uACPI/uacpi.cmake") 6 | 7 | uacpi_add_sources() 8 | 9 | add_library(acpiDriver STATIC "main.cpp" "../common/new.cpp" ${UACPI_SOURCES} "impl.cpp" "stdlib_impl.cpp") 10 | 11 | target_compile_options(acpiDriver 12 | PRIVATE $<$:-fno-stack-protector -fno-stack-check -fno-lto> 13 | PRIVATE $<$:-fno-use-cxa-atexit> 14 | PRIVATE $<$:-fno-rtti> 15 | PRIVATE $<$:-nostdlib> 16 | PRIVATE $<$:-fno-exceptions> 17 | PRIVATE $<$:-ffreestanding> 18 | PRIVATE $<$:-Wall> 19 | PRIVATE $<$:-Wextra> 20 | PRIVATE $<$:${TARGET_COMPILE_OPTIONS_C}> 21 | PRIVATE $<$:${TARGET_COMPILE_OPTIONS_CPP}> 22 | PRIVATE "${DEBUG_SYMBOLS_OPT}" 23 | ) 24 | set_property (TARGET acpiDriver PROPERTY CXX_STANDARD 20) 25 | 26 | set_target_properties(acpiDriver PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") 27 | 28 | target_compile_definitions(acpiDriver PRIVATE OBOS_DRIVER=1 PRIVATE UACPI_OVERRIDE_ARCH_HELPERS=1) 29 | 30 | target_include_directories(acpiDriver PRIVATE "${CMAKE_SOURCE_DIR}/src/oboskrnl") 31 | target_include_directories(acpiDriver PRIVATE "${CMAKE_SOURCE_DIR}/limine") 32 | target_include_directories(acpiDriver PUBLIC "${CMAKE_SOURCE_DIR}/src/drivers/generic/acpi/makeshift_include") 33 | target_include_directories(acpiDriver PUBLIC ${UACPI_INCLUDES}) 34 | 35 | target_link_options(acpiDriver 36 | PRIVATE "-ffreestanding" 37 | PRIVATE "-nostdlib" 38 | ) -------------------------------------------------------------------------------- /src/drivers/generic/acpi/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/acpi/main.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #ifdef __x86_64__ 15 | #include 16 | #endif 17 | 18 | extern "C" 19 | { 20 | #include 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | } 27 | 28 | using namespace obos; 29 | 30 | #ifdef __GNUC__ 31 | #define DEFINE_IN_SECTION __attribute__((section(OBOS_DRIVER_HEADER_SECTION_NAME))) 32 | #else 33 | #define DEFINE_IN_SECTION 34 | #endif 35 | 36 | namespace obos 37 | { 38 | extern OBOS_EXPORT volatile limine_rsdp_request rsdp_request; 39 | extern OBOS_EXPORT volatile limine_hhdm_request hhdm_offset; 40 | } 41 | 42 | #define verify_status(st) \ 43 | if (st != UACPI_STATUS_OK)\ 44 | obos::logger::panic(nullptr, "uACPI Failed! Status code: %d, error message: %s\n", st, uacpi_status_to_string(st)); 45 | 46 | namespace obos 47 | { 48 | void InitializeUACPI() 49 | { 50 | uacpi_init_params params = { 51 | (uintptr_t)rsdp_request.response->address - hhdm_offset.response->offset, 52 | { UACPI_LOG_INFO, 0 } 53 | }; 54 | uacpi_status st = uacpi_initialize(¶ms); 55 | verify_status(st); 56 | 57 | st = uacpi_namespace_load(); 58 | verify_status(st); 59 | 60 | st = uacpi_namespace_initialize(); 61 | verify_status(st); 62 | } 63 | bool EnterSleepState(int sleepState) 64 | { 65 | if (sleepState < 0 || sleepState > 5) 66 | return false; 67 | uacpi_status ret; 68 | 69 | ret = uacpi_prepare_for_sleep_state((uacpi_sleep_state)sleepState); 70 | if (uacpi_unlikely_error(ret)) 71 | return false; 72 | 73 | #ifdef __x86_64__ 74 | cli(); 75 | #endif 76 | ret = uacpi_enter_sleep_state((uacpi_sleep_state)sleepState); 77 | #ifdef __x86_64__ 78 | sti(); 79 | #endif 80 | return ret == UACPI_STATUS_OK; 81 | // Keep this code as a souvenir of when uACPI didn't have sleep helpers when I (Omar Berrow) had implemented it. 82 | /*char objectName[5] = {}; 83 | logger::sprintf(objectName, "_S%d_", sleepState); 84 | uacpi_object* ret = nullptr; 85 | uacpi_status st = uacpi_eval(nullptr, objectName, nullptr, &ret); 86 | if (st != UACPI_STATUS_OK) 87 | return false; 88 | 89 | auto* obj = uacpi_create_object(UACPI_OBJECT_INTEGER); 90 | obj->integer = sleepState; 91 | uacpi_args args{ &obj, 1 }; 92 | st = uacpi_eval(nullptr, "_PTS", &args, nullptr); 93 | if (st != UACPI_STATUS_OK && st != UACPI_STATUS_NOT_FOUND) 94 | { 95 | uacpi_object_unref(obj); 96 | return false; 97 | } 98 | 99 | uacpi_table* t = nullptr; 100 | st = uacpi_table_find_by_type(UACPI_TABLE_TYPE_FADT, &t); 101 | if (st != UACPI_STATUS_OK) 102 | { 103 | uacpi_object_unref(obj); 104 | return false; 105 | } 106 | acpi_fadt* fadt = (acpi_fadt*)t->hdr; 107 | uacpi_handle pm1a_cnt_blk_hnd{}, pm1b_cnt_blk_hnd{}; 108 | if (uacpi_kernel_io_map(fadt->pm1a_cnt_blk, 2, &pm1a_cnt_blk_hnd) != UACPI_STATUS_OK) 109 | return false; 110 | if (fadt->pm1b_cnt_blk) 111 | { 112 | if (uacpi_kernel_io_map(fadt->pm1b_cnt_blk, 2, &pm1b_cnt_blk_hnd) != UACPI_STATUS_OK) 113 | { 114 | uacpi_kernel_io_unmap(pm1b_cnt_blk_hnd); 115 | return false; 116 | } 117 | } 118 | uacpi_kernel_io_write(pm1a_cnt_blk_hnd, 0, 2, (ret->package->objects[0]->integer << 10) | ((uint64_t)1 << 13)); 119 | if (fadt->pm1b_cnt_blk) 120 | uacpi_kernel_io_write(pm1b_cnt_blk_hnd, 0, 2, (ret->package->objects[1]->integer << 10) | ((uint64_t)1 << 13)); 121 | uacpi_object_unref(obj); 122 | uacpi_kernel_io_unmap(pm1a_cnt_blk_hnd); 123 | if (fadt->pm1b_cnt_blk) 124 | uacpi_kernel_io_unmap(pm1b_cnt_blk_hnd); 125 | return true;*/ 126 | } 127 | 128 | } -------------------------------------------------------------------------------- /src/drivers/generic/acpi/makeshift_include/inttypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define PRIx64 "x" 4 | #define PRIX64 "X" 5 | #define PRIu64 "u" -------------------------------------------------------------------------------- /src/drivers/generic/acpi/makeshift_include/stdio.h: -------------------------------------------------------------------------------- 1 | // Does nothing -------------------------------------------------------------------------------- /src/drivers/generic/acpi/makeshift_include/stdlib.h: -------------------------------------------------------------------------------- 1 | // Does nothing -------------------------------------------------------------------------------- /src/drivers/generic/acpi/makeshift_include/string.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef __cplusplus 6 | #define OBOS_EXTERN_C extern "C" 7 | #else 8 | #define OBOS_EXTERN_C 9 | #endif 10 | 11 | OBOS_EXTERN_C void* memcpy(void* src, const void* dest, size_t size); 12 | OBOS_EXTERN_C void* memset(void* dest, int val, size_t size); 13 | OBOS_EXTERN_C int memcmp(const void* p1, const void* p2, size_t cnt); 14 | OBOS_EXTERN_C int strncmp(const char* p1, const char* p2, size_t maxCnt); 15 | OBOS_EXTERN_C int strcmp(const char* p1, const char* p2); 16 | OBOS_EXTERN_C void* memmove(void* dest, const void* src, size_t size); 17 | OBOS_EXTERN_C size_t strnlen(const char* str, size_t maxCnt); 18 | OBOS_EXTERN_C size_t strlen(const char* str); 19 | OBOS_EXTERN_C uint64_t strtoull(const char* str, char** endptr, int base); 20 | OBOS_EXTERN_C int snprintf(char* dest, size_t maxLen, const char* format, ...); -------------------------------------------------------------------------------- /src/drivers/generic/acpi/makeshift_include/uacpi_arch_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define UACPI_ARCH_FLUSH_CPU_CACHE() asm volatile("wbinvd") -------------------------------------------------------------------------------- /src/drivers/generic/common/new.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/x86_64/common/new.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | [[nodiscard]] void* operator new(size_t count) noexcept 12 | { 13 | return kmalloc(count); 14 | } 15 | [[nodiscard]] void* operator new[](size_t count) noexcept 16 | { 17 | return operator new(count); 18 | } 19 | void operator delete(void* block) noexcept 20 | { 21 | kfree(block); 22 | } 23 | void operator delete[](void* block) noexcept 24 | { 25 | kfree(block); 26 | } 27 | void operator delete(void* block, size_t) 28 | { 29 | kfree(block); 30 | } 31 | void operator delete[](void* block, size_t) 32 | { 33 | kfree(block); 34 | } 35 | 36 | [[nodiscard]] void* operator new(size_t, void* ptr) noexcept 37 | { 38 | return ptr; 39 | } 40 | [[nodiscard]] void* operator new[](size_t, void* ptr) noexcept 41 | { 42 | return ptr; 43 | } 44 | void operator delete(void*, void*) noexcept 45 | {} 46 | void operator delete[](void*, void*) noexcept 47 | {} -------------------------------------------------------------------------------- /src/drivers/generic/fat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # drivers/generic/fat/CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | add_executable(fatDriver "main.cpp" "../common/new.cpp" "cache.cpp" "interface.cpp") 6 | 7 | target_compile_options(fatDriver 8 | PRIVATE $<$:-fno-stack-protector -fno-stack-check -fno-lto> 9 | PRIVATE $<$:-fno-use-cxa-atexit> 10 | PRIVATE $<$:-fno-rtti> 11 | PRIVATE $<$:-nostdlib> 12 | PRIVATE $<$:-fno-exceptions> 13 | PRIVATE $<$:-ffreestanding> 14 | PRIVATE $<$:-Wall> 15 | PRIVATE $<$:-Wextra> 16 | PRIVATE $<$:-fPIE> 17 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_CPP}> 18 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_C}> 19 | PRIVATE "${DEBUG_SYMBOLS_OPT}" 20 | ) 21 | set_property (TARGET fatDriver PROPERTY CXX_STANDARD 20) 22 | 23 | set_target_properties(fatDriver PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") 24 | 25 | target_compile_definitions(fatDriver PRIVATE OBOS_DRIVER=1) 26 | 27 | target_include_directories(fatDriver PRIVATE "${CMAKE_SOURCE_DIR}/src/oboskrnl") 28 | 29 | target_link_options(fatDriver 30 | PRIVATE "-ffreestanding" 31 | PRIVATE "-nostdlib" 32 | PRIVATE "-pie" 33 | ) 34 | 35 | add_dependencies(fatDriver oboskrnl) -------------------------------------------------------------------------------- /src/drivers/generic/fat/cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/fat/cache.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define fat32FirstSectorOfCluster(cluster, bpb, first_data_sector) (uint32_t)((((cluster) - 2) * (bpb).sectorsPerCluster) + (first_data_sector)) 15 | 16 | namespace fatDriver 17 | { 18 | struct cacheEntry 19 | { 20 | char* path = nullptr; 21 | uint8_t fileAttributes = 0; // See obos::driverInterface::fileAttributes 22 | size_t filesize = 0; // Shouldn't ever pass 0xffffffff because well, FAT32. 23 | obos::utils::Vector clusters; // Must be in growing order. 24 | struct partition* owner = nullptr; 25 | cacheEntry *next, *prev; 26 | }; 27 | enum class fatType 28 | { 29 | INVALID, 30 | FAT12 = 12, 31 | FAT16 = 16, 32 | FAT32 = 32, 33 | }; 34 | struct partition 35 | { 36 | uint32_t driveId = 0; 37 | uint32_t partitionId = 0; 38 | fatType fat_type = fatType::INVALID; 39 | cacheEntry *head = nullptr, 40 | *tail = nullptr; 41 | ::size_t nCacheEntries = 0; 42 | uint32_t FatSz = 0; 43 | uint32_t RootDirSectors = 0; 44 | uint32_t TotSec = 0; 45 | uint32_t DataSec = 0; 46 | uint32_t FirstDataSec = 0; 47 | uint32_t ClusterCount = 0; 48 | struct generic_bpb* bpb; 49 | }; 50 | bool operator==(const partition& first, const partition& second); 51 | extern obos::utils::Vector g_partitions; 52 | typedef obos::utils::pair partitionIdPair; 53 | extern obos::utils::Hashmap g_partitionToIndex; 54 | 55 | void ProbeDrives(); 56 | } -------------------------------------------------------------------------------- /src/drivers/generic/fat/fat32_structs.h: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/fat/fat32_structs.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace fatDriver 12 | { 13 | struct ebpb_fat32 14 | { 15 | uint32_t sectorsPerFAT; 16 | uint16_t flags; 17 | uint8_t version[2]; // version[0]: Minor Version, version[1]: Major Version 18 | uint32_t rootDirectoryCluster; 19 | uint16_t fsInfoSector; 20 | uint16_t backupBootSector; 21 | byte resv1[12]; 22 | uint8_t driveNumber; 23 | uint8_t resv2_or_ntFlags; 24 | uint8_t signature; // 0x28 or 0x29 25 | uint32_t volumeIDSerialNumber; 26 | char volumeLabel[11]; 27 | char sysIdentifierString[8]; 28 | uint8_t bootcode[420]; 29 | uint16_t mbrSignature; 30 | } __attribute__((packed)); 31 | } -------------------------------------------------------------------------------- /src/drivers/generic/fat/fat_structs.h: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/fat/fat_structs.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include "fat32_structs.h" 12 | 13 | namespace fatDriver 14 | { 15 | struct generic_bpb 16 | { 17 | uint8_t jmp[3]; 18 | char oem_identifer[8]; 19 | uint16_t bytesPerSector; 20 | uint8_t sectorsPerCluster; 21 | uint16_t nResvSectors; 22 | uint8_t nFats; 23 | uint16_t nRootDirectoryEntries; 24 | uint16_t totalSectorCountOnVolume16; // If zero, use totalSectorCountOnVolume32 25 | uint8_t mediaDescriptorType; 26 | uint16_t sectorsPerFAT; 27 | uint16_t sectorsPerTrack; 28 | uint16_t nHeadsSidesInMedia; 29 | uint32_t nHiddenSectors; 30 | uint32_t totalSectorCountOnVolume32; 31 | union 32 | { 33 | ebpb_fat32 fat32_ebpb; 34 | } ebpb; 35 | } __attribute__((packed)); 36 | struct fat_timestamp 37 | { 38 | byte second : 5; // Multiply value by two for the actual value. 39 | byte minute : 6; 40 | byte hour : 5; 41 | } __attribute__((packed)); 42 | struct fat_date 43 | { 44 | byte day : 5; 45 | byte month : 4; 46 | byte year1980 : 7; 47 | } __attribute__((packed)); 48 | static_assert(sizeof(fat_date) == 2, "sizeof(fat_date) isn't 2 bytes."); 49 | static_assert(sizeof(fat_timestamp) == 2, "sizeof(fat_timestamp) isn't 2 bytes."); 50 | struct fat_dirEntry 51 | { 52 | enum fat_dirEntryType 53 | { 54 | READ_ONLY = 0x01, 55 | HIDDEN = 0x02, 56 | SYSTEM = 0x04, 57 | VOLUME_ID = 0x08, 58 | DIRECTORY = 0x10, 59 | ARCHIVE = 0x20, 60 | LFN = READ_ONLY|HIDDEN|SYSTEM|VOLUME_ID, 61 | }; 62 | char fname[11]; 63 | byte fAttribs; 64 | byte ntResv; 65 | byte creationTimeHunderthsSec; 66 | fat_timestamp creationTime; 67 | fat_date creationDate; 68 | fat_date accessDate; 69 | uint16_t cluster16_31; 70 | fat_timestamp modifyTime; 71 | fat_date modifyDate; 72 | uint16_t cluster0_15; 73 | uint32_t filesize; 74 | } __attribute__((packed)); 75 | struct fat_lfn 76 | { 77 | uint8_t order; // To get the order, bitwise "and" with ~0x40. If (order & 0x40), the current LFN is the last. 78 | char16_t name1_5[5]; 79 | uint8_t attribs; // Must be fat_dirEntry::LFN 80 | uint8_t type; 81 | uint8_t checksum; 82 | char16_t name6_11[6]; 83 | uint16_t ignored; 84 | char16_t name12_13[2]; 85 | } __attribute__((packed)); 86 | static_assert(sizeof(generic_bpb) == 512, "sizeof(generic_bpb) isn't 512 bytes."); 87 | static_assert(sizeof(fat_dirEntry) == 32, "sizeof(fat_dirEntry) isn't 32 bytes."); 88 | static_assert(sizeof(fat_lfn) == 32, "sizeof(fat_dirEntry) isn't 32 bytes."); 89 | } -------------------------------------------------------------------------------- /src/drivers/generic/fat/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/fat/main.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include "cache.h" 17 | 18 | using namespace obos; 19 | 20 | #ifdef __GNUC__ 21 | #define DEFINE_IN_SECTION __attribute__((section(OBOS_DRIVER_HEADER_SECTION_NAME))) 22 | #else 23 | #define DEFINE_IN_SECTION 24 | #endif 25 | 26 | namespace fatDriver 27 | { 28 | bool QueryFileProperties( 29 | const char* path, 30 | uint32_t driveId, uint32_t partitionIdOnDrive, 31 | size_t* oFsizeBytes, 32 | driverInterface::fileAttributes* oFAttribs); 33 | bool FileIteratorCreate( 34 | uint32_t driveId, uint32_t partitionIdOnDrive, 35 | uintptr_t* oIter); 36 | bool FileIteratorNext( 37 | uintptr_t iter, 38 | const char** oFilepath, 39 | void(**freeFunction)(void* buf), 40 | size_t* oFsizeBytes, 41 | driverInterface::fileAttributes* oFAttribs); 42 | bool FileIteratorClose(uintptr_t iter); 43 | bool ReadFile( 44 | uint32_t driveId, uint32_t partitionIdOnDrive, 45 | const char* path, 46 | size_t nToSkip, 47 | size_t nToRead, 48 | char* buff); 49 | } 50 | 51 | driverInterface::driverHeader DEFINE_IN_SECTION g_driverHeader = { 52 | .magicNumber = obos::driverInterface::OBOS_DRIVER_HEADER_MAGIC, 53 | .driverId = 4, 54 | .driverType = obos::driverInterface::OBOS_SERVICE_TYPE_FILESYSTEM, 55 | .requests = driverInterface::driverHeader::REQUEST_SET_STACK_SIZE, 56 | .stackSize = 0x10000, 57 | .functionTable = { 58 | .GetServiceType = []()->driverInterface::serviceType { return driverInterface::serviceType::OBOS_SERVICE_TYPE_FILESYSTEM; }, 59 | .serviceSpecific = { 60 | .filesystem = { 61 | .QueryFileProperties = fatDriver::QueryFileProperties, 62 | .FileIteratorCreate = fatDriver::FileIteratorCreate, 63 | .FileIteratorNext = fatDriver::FileIteratorNext, 64 | .FileIteratorClose = fatDriver::FileIteratorClose, 65 | .ReadFile = fatDriver::ReadFile, 66 | .unused = { nullptr,nullptr,nullptr,nullptr } 67 | } 68 | } 69 | } 70 | }; 71 | 72 | extern "C" void _start() 73 | { 74 | logger::log("FAT Driver: Probing drives for FAT partitions.\n"); 75 | fatDriver::ProbeDrives(); 76 | g_driverHeader.driver_initialized = true; 77 | while (!g_driverHeader.driver_finished_loading); 78 | thread::ExitThread(0); 79 | } 80 | -------------------------------------------------------------------------------- /src/drivers/generic/gpt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # drivers/generic/gpt/CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | add_executable(gptDriver "main.cpp" "../common/new.cpp") 6 | 7 | target_compile_options(gptDriver 8 | PRIVATE $<$:-fno-stack-protector -fno-stack-check -fno-lto> 9 | PRIVATE $<$:-fno-use-cxa-atexit> 10 | PRIVATE $<$:-fno-rtti> 11 | PRIVATE $<$:-nostdlib> 12 | PRIVATE $<$:-fno-exceptions> 13 | PRIVATE $<$:-ffreestanding> 14 | PRIVATE $<$:-Wall> 15 | PRIVATE $<$:-Wextra> 16 | PRIVATE $<$:-fPIE> 17 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_CPP}> 18 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_C}> 19 | PRIVATE "${DEBUG_SYMBOLS_OPT}" 20 | ) 21 | set_property (TARGET gptDriver PROPERTY CXX_STANDARD 20) 22 | 23 | set_target_properties(gptDriver PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") 24 | 25 | target_compile_definitions(gptDriver PRIVATE OBOS_DRIVER=1) 26 | 27 | target_include_directories(gptDriver PRIVATE "${CMAKE_SOURCE_DIR}/src/oboskrnl") 28 | 29 | target_link_options(gptDriver 30 | PRIVATE "-ffreestanding" 31 | PRIVATE "-nostdlib" 32 | PRIVATE "-pie" 33 | ) 34 | 35 | add_dependencies(gptDriver oboskrnl) -------------------------------------------------------------------------------- /src/drivers/generic/initrd/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # drivers/generic/test/CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | add_executable(initrdDriver "main.cpp" "parse.cpp" "interface.cpp") 6 | 7 | target_compile_options(initrdDriver 8 | PRIVATE "-ffreestanding" 9 | PRIVATE "-nostdlib" 10 | PRIVATE "-fPIE" 11 | PRIVATE "-Wall" 12 | PRIVATE "-Wextra" 13 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_CPP}> 14 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_C}> 15 | PRIVATE "${DEBUG_SYMBOLS_OPT}" 16 | ) 17 | set_property (TARGET initrdDriver PROPERTY CXX_STANDARD 20) 18 | 19 | set_target_properties(initrdDriver PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") 20 | 21 | target_compile_definitions(initrdDriver PRIVATE OBOS_DRIVER=1) 22 | 23 | target_include_directories(initrdDriver PRIVATE "${CMAKE_SOURCE_DIR}/src/oboskrnl") 24 | 25 | target_link_options(initrdDriver 26 | PRIVATE "-ffreestanding" 27 | PRIVATE "-nostdlib" 28 | PRIVATE "-pie" 29 | ) 30 | 31 | add_dependencies(initrdDriver oboskrnl) -------------------------------------------------------------------------------- /src/drivers/generic/initrd/interface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/initrd/interface.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "interface.h" 13 | #include "parse.h" 14 | 15 | #include 16 | 17 | struct 18 | { 19 | fileIterator* head, * tail; 20 | size_t size; 21 | } g_iterators; 22 | 23 | namespace initrdInterface 24 | { 25 | bool QueryFileProperties( 26 | const char* path, 27 | uint32_t, uint32_t, 28 | size_t* oFsizeBytes, 29 | obos::driverInterface::fileAttributes* oFAttribs) 30 | { 31 | uint32_t fAttribs = 0; 32 | if (!::GetFileAttribute(path, oFsizeBytes, &fAttribs)) 33 | { 34 | if (oFAttribs) 35 | *oFAttribs = obos::driverInterface::FILE_DOESNT_EXIST; 36 | if (oFsizeBytes) 37 | *oFsizeBytes = 0; 38 | return false; 39 | } 40 | if (oFAttribs) 41 | *oFAttribs = (obos::driverInterface::fileAttributes)fAttribs; 42 | return true; 43 | 44 | } 45 | bool IterCreate( 46 | uint32_t, uint32_t, 47 | uintptr_t* oIter) 48 | { 49 | fileIterator* iter = (fileIterator*)kcalloc(1, sizeof(fileIterator)); 50 | if (!iter) 51 | return false; 52 | iter->currentNode = g_filesystemCache.head; 53 | if (g_iterators.tail) 54 | g_iterators.tail->next = iter; 55 | if (!g_iterators.head) 56 | g_iterators.head = iter; 57 | iter->prev = g_iterators.tail; 58 | g_iterators.tail = iter; 59 | g_iterators.size++; 60 | *oIter = (uintptr_t)iter; 61 | return true; 62 | } 63 | bool IterNext( 64 | uintptr_t _iter, 65 | const char** oFilepath, 66 | void(**freeFunction)(void* buf), 67 | size_t* oFsizeBytes, 68 | obos::driverInterface::fileAttributes* oFAttribs) 69 | { 70 | fileIterator* iter = (fileIterator*)_iter; 71 | fileIterator* _node = g_iterators.head; 72 | while (_node) 73 | { 74 | if (_node == iter) 75 | break; 76 | 77 | _node = _node->next; 78 | } 79 | if (_node != iter) 80 | return false; 81 | if (!iter->currentNode) 82 | { 83 | if (oFAttribs) 84 | *oFAttribs = obos::driverInterface::FILE_DOESNT_EXIST; 85 | if (oFsizeBytes) 86 | *oFsizeBytes = 0; 87 | return true; 88 | } 89 | bool ret = QueryFileProperties(iter->currentNode->cache->entry->path, 0,0, oFsizeBytes, oFAttribs); 90 | if (!ret) 91 | return false; 92 | size_t szFilepath = obos::utils::strlen(iter->currentNode->cache->entry->path); 93 | if (oFilepath) 94 | *oFilepath = (const char*)obos::utils::memcpy(kcalloc(szFilepath + 1, 1), iter->currentNode->cache->entry->path, szFilepath); 95 | if (freeFunction) 96 | *freeFunction = kfree; 97 | iter->currentNode = iter->currentNode->next; 98 | return true; 99 | } 100 | bool IterClose(uintptr_t _iter) 101 | { 102 | fileIterator* iter = (fileIterator*)_iter; 103 | fileIterator* _node = g_iterators.head; 104 | while (_node) 105 | { 106 | if (_node == iter) 107 | break; 108 | _node = _node->next; 109 | } 110 | if (_node != iter) 111 | return false; 112 | if (iter->next) 113 | iter->next->prev = iter->prev; 114 | if (iter->prev) 115 | iter->prev->next = iter->next; 116 | if (g_iterators.head == iter) 117 | g_iterators.head = iter->next; 118 | if (g_iterators.tail == iter) 119 | g_iterators.tail = iter->prev; 120 | g_iterators.size--; 121 | kfree(iter); 122 | return true; 123 | } 124 | bool ReadFile( 125 | uint32_t, uint32_t, 126 | const char* path, 127 | size_t nToSkip, 128 | size_t nToRead, 129 | char* buff) 130 | { 131 | auto cache = GetCacheForPath(path); 132 | if (!cache) 133 | return false; 134 | if (nToSkip >= cache->entryFilesize) 135 | return false; 136 | if ((nToSkip + nToRead) > cache->entryFilesize) 137 | return false; 138 | if (buff) 139 | obos::utils::memcpy(buff, cache->dataStart + nToSkip, nToRead); 140 | return true; 141 | } 142 | } -------------------------------------------------------------------------------- /src/drivers/generic/initrd/interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/initrd/interface.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace initrdInterface 14 | { 15 | bool QueryFileProperties ( 16 | const char* path, 17 | uint32_t driveId, uint32_t partitionIdOnDrive, 18 | size_t* oFsizeBytes, 19 | obos::driverInterface::fileAttributes* oFAttribs); 20 | bool IterCreate( 21 | uint32_t driveId, uint32_t partitionIdOnDrive, 22 | uintptr_t* oIter); 23 | bool IterNext( 24 | uintptr_t iter, 25 | const char** oFilepath, 26 | void(**freeFunction)(void* buf), 27 | size_t* oFsizeBytes, 28 | obos::driverInterface::fileAttributes* oFAttribs); 29 | bool IterClose(uintptr_t iter); 30 | bool ReadFile( 31 | uint32_t driveId, uint32_t partitionIdOnDrive, 32 | const char* path, 33 | size_t nToSkip, 34 | size_t nToRead, 35 | char* buff); 36 | } -------------------------------------------------------------------------------- /src/drivers/generic/initrd/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/initrd/main.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | #include "parse.h" 19 | #include "interface.h" 20 | 21 | using namespace obos; 22 | 23 | #ifdef __GNUC__ 24 | #define DEFINE_IN_SECTION __attribute__((section(OBOS_DRIVER_HEADER_SECTION_NAME))) 25 | #else 26 | #define DEFINE_IN_SECTION 27 | #endif 28 | 29 | driverInterface::driverHeader DEFINE_IN_SECTION g_driverHeader = { 30 | .magicNumber = obos::driverInterface::OBOS_DRIVER_HEADER_MAGIC, 31 | .driverId = 0, 32 | .driverType = obos::driverInterface::OBOS_SERVICE_TYPE_INITRD_FILESYSTEM, 33 | .requests = driverInterface::driverHeader::REQUEST_INITRD_LOCATION, 34 | .functionTable = { 35 | .GetServiceType = []()->driverInterface::serviceType { return driverInterface::serviceType::OBOS_SERVICE_TYPE_INITRD_FILESYSTEM; }, 36 | .serviceSpecific = { 37 | .filesystem = { 38 | .QueryFileProperties = initrdInterface::QueryFileProperties, 39 | .FileIteratorCreate = initrdInterface::IterCreate, 40 | .FileIteratorNext = initrdInterface::IterNext, 41 | .FileIteratorClose = initrdInterface::IterClose, 42 | .ReadFile = initrdInterface::ReadFile, 43 | .unused = { nullptr,nullptr,nullptr,nullptr } 44 | } 45 | } 46 | } 47 | }; 48 | 49 | extern void ConnectionHandler(uintptr_t); 50 | 51 | #ifdef __GNUC__ 52 | #define WEAK __attribute__((weak)) 53 | #else 54 | #define WEAK 55 | #endif 56 | 57 | extern "C" void _start() 58 | { 59 | if (!g_driverHeader.initrdLocationResponse.addr) 60 | logger::panic(nullptr, "InitRD Driver: No initrd image received from the kernel.\n"); 61 | logger::log("InitRD Driver: Initializing filesystem cache.\n"); 62 | InitializeFilesystemCache(); 63 | g_driverHeader.driver_initialized = true; 64 | while (!g_driverHeader.driver_finished_loading); 65 | thread::ExitThread(0); 66 | } 67 | -------------------------------------------------------------------------------- /src/drivers/generic/initrd/parse.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/initrd/parse.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "parse.h" 12 | 13 | #include 14 | 15 | #include 16 | 17 | 18 | using namespace obos; 19 | 20 | 21 | 22 | extern driverInterface::driverHeader g_driverHeader; 23 | 24 | int oct2bin(char* str, int size) 25 | { 26 | int n = 0; 27 | char* c = str; 28 | while (size-- > 0) { 29 | n *= 8; 30 | n += *c - '0'; 31 | c++; 32 | } 33 | return n; 34 | } 35 | 36 | [[noreturn]] extern void kpanic(const char* format, ...); 37 | 38 | filesystemCache g_filesystemCache = {}; 39 | 40 | void InitializeFilesystemCache() 41 | { 42 | ustarEntry* entry = (ustarEntry*)g_driverHeader.initrdLocationResponse.addr; 43 | if (!obos::utils::memcmp(&entry->indication, "ustar", 6)) 44 | obos::logger::panic(nullptr, "DRIVER 0, %s: Invalid or empty initrd image!\n", __func__); 45 | while (obos::utils::memcmp(&entry->indication, "ustar", 6)) 46 | { 47 | size_t filesize = oct2bin(entry->filesizeOctal, 11); 48 | ustarEntryCacheNode* node = (ustarEntryCacheNode*)kcalloc(1, sizeof(ustarEntryCacheNode)); 49 | ustarEntryCache* cache = node->cache = (ustarEntryCache*)kcalloc(1, sizeof(ustarEntryCache)); 50 | obos::utils::memzero(node, sizeof(*node)); 51 | cache->entry = entry; 52 | cache->entryFilesize = filesize; 53 | cache->dataStart = (uint8_t*)(entry + 1); 54 | if (filesize) 55 | cache->dataEnd = cache->dataStart + ((filesize / 512 + (filesize % 512 != 0)) * 512); 56 | else 57 | cache->dataEnd = cache->dataStart; 58 | node->cache = cache; 59 | switch (entry->type) 60 | { 61 | case ustarEntry::NORMAL_FILE: 62 | cache->entryAttributes = driverInterface::FILE_ATTRIBUTES_FILE | driverInterface::FILE_ATTRIBUTES_READ_ONLY; 63 | // TODO: Find out what the point of this was? 64 | //cache->entryFilesize++; // Add one to the filesize. 65 | break; 66 | case ustarEntry::DIRECTORY: 67 | cache->entryAttributes = driverInterface::FILE_ATTRIBUTES_DIRECTORY; 68 | break; 69 | case ustarEntry::HARD_LINK: 70 | cache->entryAttributes = driverInterface::FILE_ATTRIBUTES_HARDLINK; 71 | break; 72 | default: 73 | break; 74 | } 75 | if (g_filesystemCache.tail) 76 | g_filesystemCache.tail->next = node; 77 | if (!g_filesystemCache.head) 78 | g_filesystemCache.head = node; 79 | node->prev = g_filesystemCache.tail; 80 | g_filesystemCache.tail = node; 81 | g_filesystemCache.size++; 82 | entry = (ustarEntry*)cache->dataEnd; 83 | } 84 | } 85 | 86 | bool GetFileAttribute(const char* filepath, size_t* size, uint32_t* _attrib) 87 | { 88 | ustarEntryCache* entry = GetCacheForPath(filepath); 89 | if (!entry) 90 | { 91 | if (_attrib) 92 | *_attrib = driverInterface::fileAttributes::FILE_DOESNT_EXIST; 93 | if (size) 94 | *size = 0; 95 | return false; 96 | } 97 | if (_attrib) 98 | *_attrib = entry->entryAttributes; 99 | if (size) 100 | *size = entry->entryFilesize; 101 | return true; 102 | } 103 | bool FileExists(const char* filepath) 104 | { 105 | return GetCacheForPath(filepath) != nullptr; 106 | } 107 | 108 | ustarEntryCache* GetCacheForPath(const char* path) 109 | { 110 | ustarEntryCacheNode* entry = g_filesystemCache.head; 111 | while (entry) 112 | { 113 | if (obos::utils::strcmp(path, entry->cache->entry->path)) 114 | break; 115 | 116 | entry = entry->next; 117 | } 118 | 119 | return entry->cache; 120 | } 121 | -------------------------------------------------------------------------------- /src/drivers/generic/initrd/parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/generic/initrd/parse.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | struct ustarEntry 14 | { 15 | char path[100]; 16 | byte unused1[24]; 17 | char filesizeOctal[12]; 18 | byte unused2[12]; 19 | uint64_t unused3; 20 | enum __type 21 | { 22 | NORMAL_FILE = '0', 23 | HARD_LINK = '1', 24 | SYM_LINK = '2', 25 | CHAR_DEVICE = '3', 26 | BLOCK_DEVICE = '4', 27 | DIRECTORY = '5', 28 | NAMED_PIPE = '6', 29 | } __attribute__((packed)); 30 | __type type; 31 | char linkedFile[100]; 32 | char indication[6]; // should be "ustar\0" 33 | char version[2]; 34 | char unused4[80]; 35 | char filenamePrefix[155]; 36 | char padding[12]; 37 | } __attribute__((packed)); 38 | 39 | struct ustarEntryCache 40 | { 41 | ustarEntry* entry; 42 | size_t entryFilesize; 43 | uint32_t entryAttributes; 44 | byte* dataStart; 45 | byte* dataEnd; 46 | }; 47 | struct ustarEntryCacheNode 48 | { 49 | ustarEntryCacheNode *next, *prev; 50 | ustarEntryCache* cache; 51 | }; 52 | struct fileIterator 53 | { 54 | ustarEntryCacheNode* currentNode; 55 | fileIterator *next, *prev; // The next file iterator in the file iterator list. 56 | }; 57 | struct filesystemCache 58 | { 59 | ustarEntryCacheNode *head, *tail; 60 | size_t size; 61 | } extern g_filesystemCache; 62 | 63 | void InitializeFilesystemCache(); 64 | 65 | bool GetFileAttribute(const char* filepath, size_t* size, uint32_t* attrib); // OBOS_SERVICE_QUERY_FILE_DATA 66 | bool FileExists(const char* path); 67 | ustarEntryCache* GetCacheForPath(const char* path); -------------------------------------------------------------------------------- /src/drivers/x86_64/mbr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # drivers/x86_64/mbr/CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | add_executable(mbrDriver "main.cpp" "../../generic/common/new.cpp") 6 | 7 | target_compile_options(mbrDriver 8 | PRIVATE $<$:-fno-stack-protector -fno-stack-check -fno-lto> 9 | PRIVATE $<$:-fno-use-cxa-atexit> 10 | PRIVATE $<$:-fno-rtti> 11 | PRIVATE $<$:-nostdlib> 12 | PRIVATE $<$:-fno-exceptions> 13 | PRIVATE $<$:-ffreestanding> 14 | PRIVATE $<$:-Wall> 15 | PRIVATE $<$:-Wextra> 16 | PRIVATE $<$:-fPIE> 17 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_CPP}> 18 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_C}> 19 | PRIVATE "${DEBUG_SYMBOLS_OPT}" 20 | ) 21 | set_property (TARGET mbrDriver PROPERTY CXX_STANDARD 20) 22 | 23 | set_target_properties(mbrDriver PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") 24 | 25 | target_compile_definitions(mbrDriver PRIVATE OBOS_DRIVER=1) 26 | 27 | target_include_directories(mbrDriver PRIVATE "${CMAKE_SOURCE_DIR}/src/oboskrnl") 28 | 29 | target_link_options(mbrDriver 30 | PRIVATE "-ffreestanding" 31 | PRIVATE "-nostdlib" 32 | PRIVATE "-pie" 33 | ) 34 | 35 | add_dependencies(mbrDriver oboskrnl) -------------------------------------------------------------------------------- /src/drivers/x86_64/mbr/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/x86_64/mbr/main.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | using namespace obos; 17 | 18 | #ifdef __GNUC__ 19 | #define DEFINE_IN_SECTION __attribute__((section(OBOS_DRIVER_HEADER_SECTION_NAME))) 20 | #else 21 | #define DEFINE_IN_SECTION 22 | #endif 23 | 24 | bool RegisterMBRPartitionsOnDrive(uint32_t driveId, size_t* oNPartitions, driverInterface::partitionInfo** oPartInfo); 25 | 26 | driverInterface::driverHeader DEFINE_IN_SECTION g_driverHeader = { 27 | .magicNumber = driverInterface::OBOS_DRIVER_HEADER_MAGIC, 28 | .driverId = 2, // The kernel __depends__ on this being two, do not change. 29 | .driverType = driverInterface::OBOS_SERVICE_TYPE_PARTITION_MANAGER, 30 | .requests = driverInterface::driverHeader::REQUEST_NO_MAIN_THREAD, 31 | .functionTable = { 32 | .GetServiceType = []()->driverInterface::serviceType { return driverInterface::serviceType::OBOS_SERVICE_TYPE_STORAGE_DEVICE; }, 33 | .serviceSpecific = { 34 | .partitionManager = { 35 | .RegisterPartitionsOnDrive = RegisterMBRPartitionsOnDrive, 36 | .unused = {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,} 37 | } 38 | } 39 | } 40 | }; 41 | 42 | struct mbr_part 43 | { 44 | // Bit 7: Active partition. 45 | // Any other bits should be zero. 46 | uint8_t attribs; 47 | uint8_t startHead; 48 | uint8_t startSector; 49 | uint8_t startTrack; 50 | uint8_t osIndicator; 51 | uint8_t endHead; 52 | uint8_t endSector; 53 | uint8_t endTrack; 54 | uint32_t startingLBA; 55 | uint32_t endLBA; 56 | } __attribute__((packed)); 57 | struct mbr 58 | { 59 | uint8_t bootCode[440]; 60 | uint32_t uniqueMBRSignature; 61 | uint8_t unknown[2]; 62 | mbr_part partitions[4]; 63 | uint16_t signature; // If != 0x55AA, invalid MBR. 64 | } __attribute__((packed)); 65 | static_assert(sizeof(mbr) == 512, "struct mbr is not 512 bytes in length."); 66 | 67 | bool RegisterMBRPartitionsOnDrive(uint32_t driveId, size_t* oNPartitions, driverInterface::partitionInfo** oPartInfo) 68 | { 69 | char* path = new char[logger::sprintf(nullptr, "D%d:/", driveId) + 1]; 70 | logger::sprintf(path, "D%d:/", driveId); 71 | vfs::DriveHandle drive; 72 | drive.OpenDrive(path, vfs::DriveHandle::OpenOptions::OPTIONS_READ_ONLY); 73 | delete[] path; 74 | size_t sizeofSector; 75 | drive.QueryInfo(nullptr, &sizeofSector, nullptr); 76 | byte* firstSector = new byte[sizeofSector]; 77 | if (!drive.ReadSectors(firstSector, nullptr, 0, 1)) 78 | { 79 | delete[] firstSector; 80 | drive.Close(); 81 | return false; 82 | } 83 | mbr* driveMbr = (mbr*)firstSector; 84 | if (driveMbr->signature != 0xAA55) 85 | return false; 86 | size_t nPartitions = 0; 87 | driverInterface::partitionInfo* partitionInfo = nullptr; 88 | for (size_t part = 0; part < 4; part++) 89 | { 90 | // Active partition. 91 | if (driveMbr->partitions[part].attribs & 0x80) 92 | { 93 | partitionInfo = (driverInterface::partitionInfo*)krealloc(partitionInfo, ++nPartitions); 94 | partitionInfo[nPartitions - 1].id = nPartitions - 1; 95 | partitionInfo[nPartitions - 1].lbaOffset = driveMbr->partitions[part].startingLBA; 96 | partitionInfo[nPartitions - 1].sizeSectors = driveMbr->partitions[part].endLBA - driveMbr->partitions[part].startingLBA; 97 | } 98 | } 99 | if (oNPartitions) 100 | *oNPartitions = nPartitions; 101 | if (oPartInfo) 102 | *oPartInfo = partitionInfo; 103 | else 104 | delete[] oPartInfo; 105 | return true; 106 | } 107 | 108 | extern "C" void _start() 109 | {} -------------------------------------------------------------------------------- /src/drivers/x86_64/ps2Keyboard/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # drivers/x86_64/ps2KeyboardDriver/CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | add_executable (ps2KeyboardDriver "dmain.cpp" "scancodes.cpp" "../../generic/common/new.cpp") 6 | 7 | target_compile_options(ps2KeyboardDriver 8 | PRIVATE $<$:-fno-stack-protector -fno-stack-check -fno-lto> 9 | PRIVATE $<$:-fno-use-cxa-atexit> 10 | PRIVATE $<$:-fno-rtti> 11 | PRIVATE $<$:-nostdlib> 12 | PRIVATE $<$:-fno-exceptions> 13 | PRIVATE $<$:-ffreestanding> 14 | PRIVATE $<$:-Wall> 15 | PRIVATE $<$:-Wextra> 16 | PRIVATE $<$:-fPIE> 17 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_CPP}> 18 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_C}> 19 | PRIVATE "${DEBUG_SYMBOLS_OPT}" 20 | ) 21 | set_property (TARGET ps2KeyboardDriver PROPERTY CXX_STANDARD 20) 22 | 23 | set_target_properties(ps2KeyboardDriver PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") 24 | 25 | target_compile_definitions(ps2KeyboardDriver PRIVATE OBOS_DRIVER=1) 26 | 27 | target_include_directories(ps2KeyboardDriver PRIVATE "${CMAKE_SOURCE_DIR}/src/oboskrnl") 28 | 29 | target_link_options(ps2KeyboardDriver 30 | PRIVATE "-ffreestanding" 31 | PRIVATE "-nostdlib" 32 | PRIVATE "-pie" 33 | ) 34 | 35 | add_dependencies(ps2KeyboardDriver oboskrnl) -------------------------------------------------------------------------------- /src/drivers/x86_64/ps2Keyboard/scancodes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/x86_64/ps2Keyboard/scancodes.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include "scancodes.h" 8 | 9 | #include 10 | 11 | using namespace obos::driverInterface; 12 | 13 | #pragma GCC diagnostic ignored "-Wmissing-field-initializers" 14 | 15 | key g_keys[] = { 16 | { 0x00, 0,0, '\x00' }, 17 | { 0x01, 0,0, '\x1b' }, 18 | { 0x02, 0,0, '1', '!' }, 19 | { 0x03, 0,0, '2', '@' }, 20 | { 0x04, 0,0, '3', '#' }, 21 | { 0x05, 0,0, '4', '$' }, 22 | { 0x06, 0,0, '5', '%' }, 23 | { 0x07, 0,0, '6', '^' }, 24 | { 0x08, 0,0, '7', '&' }, 25 | { 0x09, 0,0, '8', '*' }, 26 | { 0x0A, 0,0, '9', '(' }, 27 | { 0x0B, 0,0, '0', ')' }, 28 | { 0x0C, 0,0, '-', '_'}, 29 | { 0x0D, 0,0, '=', '+' }, 30 | { 0x0E, 0,0, '\b' }, 31 | { 0x0F, 0,0, '\t' }, 32 | { 0x10, 0,0, 'Q' }, 33 | { 0x11, 0,0, 'W' }, 34 | { 0x12, 0,0, 'E' }, 35 | { 0x13, 0,0, 'R' }, 36 | { 0x14, 0,0, 'T' }, 37 | { 0x15, 0,0, 'Y' }, 38 | { 0x16, 0,0, 'U' }, 39 | { 0x17, 0,0, 'I' }, 40 | { 0x18, 0,0, 'O' }, 41 | { 0x19, 0,0, 'P' }, 42 | { 0x1A, 0,0, '[', '{' }, 43 | { 0x1B, 0,0, ']', '}' }, 44 | { 0x1C, 0,0, '\n', '\0', true, }, 45 | { 0x1D, 0,0, (uint16_t)SpecialKeys::LEFT_CONTROL, '\0', false, (uint16_t)SpecialKeys::RIGHT_CONTROL, }, 46 | { 0x1E, 0,0, 'A' }, 47 | { 0x1F, 0,0, 'S' }, 48 | { 0x20, 0,0, 'D' }, 49 | { 0x21, 0,0, 'F' }, 50 | { 0x22, 0,0, 'G' }, 51 | { 0x23, 0,0, 'H' }, 52 | { 0x24, 0,0, 'J' }, 53 | { 0x25, 0,0, 'K' }, 54 | { 0x26, 0,0, 'L' }, 55 | { 0x27, 0,0, ';', ':' }, 56 | { 0x28, 0,0, '\'', '\"' }, 57 | { 0x29, 0,0, '`', '~' }, 58 | { 0x2A, 0,0, (uint16_t)SpecialKeys::LEFT_ALT, '\0', true, }, 59 | { 0x2B, 0,0, '\\', '|'}, 60 | { 0x2C, 0,0, 'Z' }, 61 | { 0x2D, 0,0, 'X' }, 62 | { 0x2E, 0,0, 'C' }, 63 | { 0x2F, 0,0, 'V' }, 64 | { 0x30, 0,0, 'B' }, 65 | { 0x31, 0,0, 'N' }, 66 | { 0x32, 0,0, 'M' }, 67 | { 0x33, 0,0, ',', '<' }, 68 | { 0x34, 0,0, '.', '>' }, 69 | { 0x35, 0,0, '/', '?', true }, 70 | { 0x36, 0,0, '\0' }, 71 | { 0x37, 0,0, '*' }, 72 | { 0x38, 0,0, '\0', '\0', false, (uint16_t)SpecialKeys::RIGHT_ALT }, 73 | { 0x39, 0,0, ' ' }, 74 | { 0x3A, 0,0, '\0' }, 75 | { 0x3B, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F1 }, 76 | { 0x3C, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F2 }, 77 | { 0x3D, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F3 }, 78 | { 0x3E, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F4 }, 79 | { 0x3F, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F5 }, 80 | { 0x40, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F6 }, 81 | { 0x41, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F7 }, 82 | { 0x42, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F8 }, 83 | { 0x43, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F9 }, 84 | { 0x44, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F10 }, 85 | { 0x45, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::NUMLOCK }, 86 | { 0x46, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::SCROLL_LOCK }, 87 | { 0x47, 0,0, '7', '\0', false, (uint16_t)SpecialKeys::HOME, }, 88 | { 0x48, 0,0, '8', '\0', false, (uint16_t)SpecialKeys::UP_ARROW, }, 89 | { 0x49, 0,0, '9', '\0', false, (uint16_t)SpecialKeys::PAGE_UP, }, 90 | { 0x4A, 0,0, '-' }, 91 | { 0x4B, 0,0, '4', '\0', false, (uint16_t)SpecialKeys::LEFT_ARROW, }, 92 | { 0x4C, 0,0, '5' }, 93 | { 0x4D, 0,0, '6', '\0', false, (uint16_t)SpecialKeys::RIGHT_ARROW, }, 94 | { 0x4E, 0,0, '+' }, 95 | { 0x4F, 0,0, '1', '\0', false, (uint16_t)SpecialKeys::END, }, 96 | { 0x50, 0,0, '2', '\0', false, (uint16_t)SpecialKeys::DOWN_ARROW, }, 97 | { 0x51, 0,0, '3', '\0', false, (uint16_t)SpecialKeys::PAGE_DOWN, }, 98 | { 0x52, 0,0, '0', '\0', false, (uint16_t)SpecialKeys::INSERT, }, 99 | { 0x53, 0,0, '.', '\0', false, (uint16_t)SpecialKeys::DELETE, }, 100 | { 0x54, 0,0, '\0' }, 101 | { 0x55, 0,0, '\0' }, 102 | { 0x56, 0,0, '\0' }, 103 | { 0x57, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F11 }, 104 | { 0x58, 0,0, '\0', '\0', true, (uint16_t)SpecialKeys::F12 }, 105 | }; -------------------------------------------------------------------------------- /src/drivers/x86_64/ps2Keyboard/scancodes.h: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/x86_64/ps2Keyboard/scancodes.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | typedef struct _key 14 | { 15 | uint32_t scanCode; 16 | size_t nPressed; 17 | bool isPressed; 18 | uint16_t ch; 19 | char shiftAlias; 20 | bool skipExtended = false; 21 | uint16_t extendedCh; 22 | } key; 23 | 24 | extern key g_keys[89]; -------------------------------------------------------------------------------- /src/drivers/x86_64/sata/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # drivers/x86_64/sata/CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | add_executable(sataDriver "main.cpp" "../../generic/common/new.cpp" "command.cpp" "interface.cpp") 6 | 7 | target_compile_options(sataDriver 8 | PRIVATE $<$:-fno-stack-protector -fno-stack-check -fno-lto> 9 | PRIVATE $<$:-fno-use-cxa-atexit> 10 | PRIVATE $<$:-fno-rtti> 11 | PRIVATE $<$:-nostdlib> 12 | PRIVATE $<$:-fno-exceptions> 13 | PRIVATE $<$:-ffreestanding> 14 | PRIVATE $<$:-Wall> 15 | PRIVATE $<$:-Wextra> 16 | PRIVATE $<$:-fPIE> 17 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_CPP}> 18 | PRIVATE $<$:${TARGET_DRIVER_COMPILE_OPTIONS_C}> 19 | PRIVATE "${DEBUG_SYMBOLS_OPT}" 20 | ) 21 | set_property (TARGET sataDriver PROPERTY CXX_STANDARD 20) 22 | 23 | set_target_properties(sataDriver PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") 24 | 25 | target_compile_definitions(sataDriver PRIVATE OBOS_DRIVER=1) 26 | 27 | target_include_directories(sataDriver PRIVATE "${CMAKE_SOURCE_DIR}/src/oboskrnl") 28 | 29 | target_link_options(sataDriver 30 | PRIVATE "-ffreestanding" 31 | PRIVATE "-nostdlib" 32 | PRIVATE "-pie" 33 | ) 34 | 35 | add_dependencies(sataDriver oboskrnl) -------------------------------------------------------------------------------- /src/drivers/x86_64/sata/command.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/x86_64/sata/command.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "command.h" 11 | #include "structs.h" 12 | 13 | extern volatile HBA_MEM* g_generalHostControl; 14 | 15 | asm( 16 | ".global _Z17StopCommandEnginePV8HBA_PORT;" 17 | ".global _Z18StartCommandEnginePV8HBA_PORT;" 18 | ".global _Z11FindCMDSlotPV8HBA_PORT;" 19 | ".intel_syntax noprefix;" 20 | "_Z11FindCMDSlotPV8HBA_PORT:;" 21 | " mov eax, dword ptr [rdi+0x34];" 22 | " or eax, [rdi+0x38];" 23 | " mov esi, eax;" 24 | " not esi;" 25 | " bsf eax, esi;" 26 | " ret;" 27 | "_Z17StopCommandEnginePV8HBA_PORT:;" 28 | " push rbp;" 29 | " mov rbp, rsp;" 30 | " and dword ptr [rdi+0x18], ~(1<<0);" // Clear ST (bit 0) 31 | " and dword ptr [rdi+0x18], ~(1<<4);" // Clear FRE (bit 4) 32 | // Wait until FR (bit 14), CR (bit 15) are cleared 33 | "_Z17StopCommandEnginePV8HBA_PORT.loop:;" 34 | " test dword ptr [rdi+0x18], (1<<14);" 35 | " jnz _Z17StopCommandEnginePV8HBA_PORT.loop;" 36 | " test dword ptr [rdi+0x18], (1<<15);" 37 | " jnz _Z17StopCommandEnginePV8HBA_PORT.loop;" 38 | "_Z17StopCommandEnginePV8HBA_PORT.end:;" 39 | " leave;" 40 | " ret;" 41 | ".intel_syntax noprefix;" 42 | "_Z18StartCommandEnginePV8HBA_PORT:;" 43 | " push rbp;" 44 | " mov rbp, rsp;" 45 | "_Z18StartCommandEnginePV8HBA_PORT.loop:;" 46 | " test dword ptr [rdi+0x18], (1<<15);" 47 | " jnz _Z18StartCommandEnginePV8HBA_PORT.loop;" 48 | "_Z18StartCommandEnginePV8HBA_PORT.end:;" 49 | " or dword ptr [rdi+0x18], (1<<4);" 50 | " or dword ptr [rdi+0x18], (1<<0);" 51 | " leave;" 52 | " ret;" 53 | ".att_syntax prefix;" 54 | ); -------------------------------------------------------------------------------- /src/drivers/x86_64/sata/command.h: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/x86_64/sata/command.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | uint32_t FindCMDSlot(volatile struct HBA_PORT* pPort); 12 | void StopCommandEngine(volatile struct HBA_PORT* pPort); 13 | void StartCommandEngine(volatile struct HBA_PORT* pPort); -------------------------------------------------------------------------------- /src/oboskrnl/allocators/liballoc.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/allocators/liballoc.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #ifdef __cplusplus 13 | extern "C" 14 | { 15 | #endif 16 | 17 | OBOS_EXPORT void* kmalloc(size_t amount); 18 | OBOS_EXPORT void* kcalloc(size_t nobj, size_t szObj); 19 | OBOS_EXPORT void* krealloc(void* ptr, size_t newSize); 20 | OBOS_EXPORT void kfree(void* ptr); 21 | 22 | #ifdef __cplusplus 23 | } 24 | namespace obos 25 | { 26 | bool CanAllocateMemory(); 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /src/oboskrnl/arch/interrupt.h: -------------------------------------------------------------------------------- 1 | #if defined(__x86_64__) || defined(_WIN64) 2 | #include 3 | #endif -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/fpu.asm: -------------------------------------------------------------------------------- 1 | [BITS 64] 2 | 3 | global fpuInit 4 | fpuInit: 5 | fninit 6 | ret 7 | global _fxsave 8 | _fxsave: 9 | fxsave [rdi] 10 | ret -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/gdbstub/communicate.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/gdbstub/communicate.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace obos 12 | { 13 | namespace gdbstub 14 | { 15 | struct Packet 16 | { 17 | char* data; 18 | size_t len; 19 | }; 20 | void DefaultLockConnection(); 21 | void DefaultUnlockConnection(); 22 | void DefaultSendByteOnRawConnection(byte); 23 | byte DefaultRecvByteOnRawConnection(); 24 | bool DefaultByteInConnBuffer(); 25 | void InitDefaultConnection(); 26 | byte mod256(const char* data, size_t len); 27 | class Connection 28 | { 29 | public: 30 | Connection() 31 | : m_sendByteOnRawConnection{ DefaultSendByteOnRawConnection }, 32 | m_recvByteOnRawConnection{ DefaultRecvByteOnRawConnection }, 33 | m_lockConnection{ DefaultLockConnection }, 34 | m_unlockConnection{ DefaultUnlockConnection }, 35 | m_isByteInConnBuffer{ DefaultByteInConnBuffer } 36 | {} 37 | Connection(void(*sendByteOnRawConnection)(byte), byte(*recvByteOnRawConnection)(), void(*lockConnection)(), void(*unlockConnection)(), bool(*isByteInConnBuffer)()) 38 | : m_sendByteOnRawConnection{ sendByteOnRawConnection }, 39 | m_recvByteOnRawConnection{ recvByteOnRawConnection }, 40 | m_lockConnection{ lockConnection }, 41 | m_unlockConnection{ unlockConnection }, 42 | m_isByteInConnBuffer { isByteInConnBuffer } 43 | {} 44 | 45 | bool SendRawPacket(const Packet& packet); 46 | bool RecvRawPacket(Packet& packet); 47 | 48 | void SetSendingACK(bool val) { m_sendingACK = val; }; 49 | bool IsSendingACK() const { return m_sendingACK; }; 50 | 51 | bool CanReadByte() { return m_isByteInConnBuffer(); } 52 | private: 53 | void(*m_sendByteOnRawConnection)(byte); 54 | byte(*m_recvByteOnRawConnection)(); 55 | void(*m_lockConnection)(); 56 | void(*m_unlockConnection)(); 57 | bool(*m_isByteInConnBuffer)(); 58 | bool m_sendingACK = true; 59 | }; 60 | } 61 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/gdbstub/stub.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/gdbstub/stub.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace obos 14 | { 15 | namespace gdbstub 16 | { 17 | extern bool g_stubInitialized; 18 | void InititalizeGDBStub(Connection* conn); 19 | } 20 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/gdt.asm: -------------------------------------------------------------------------------- 1 | [BITS 64] 2 | 3 | segment .data 4 | 5 | align 16 6 | GDT: 7 | ; Null entry. 8 | dq 0 9 | ; Code segment. 10 | dq 0x00209A0000000000 11 | ; Data segment. 12 | dq 0x0000920000000000 13 | ; User mode data segment 14 | dq 0x00aff3000000ffff 15 | ; User mode code segment 16 | dq 0x00affb000000ffff 17 | align 1 18 | TSS: 19 | dq 0,0 20 | 21 | align 1 22 | 23 | GDT_Ptr: 24 | dw $- GDT - 1 25 | dq 0 26 | 27 | [GLOBAL TSS] 28 | [GLOBAL GDT] 29 | [GLOBAL GDT_Ptr] 30 | 31 | segment .text 32 | 33 | [GLOBAL _ZN4obos16InitializeGDTASMEv] 34 | 35 | _ZN4obos16InitializeGDTASMEv: 36 | push rbp 37 | mov rbp, rsp 38 | 39 | lea rax, [GDT] 40 | mov [GDT_Ptr+2], rax 41 | 42 | lgdt [GDT_Ptr] 43 | 44 | mov ax, 0x10 45 | mov ds, ax 46 | mov es, ax 47 | mov fs, ax 48 | mov gs, ax 49 | mov ss, ax 50 | 51 | push 0x8 52 | push .flush_tss 53 | retfq 54 | .flush_tss: 55 | mov ax, 0x28 56 | ltr ax 57 | 58 | leave 59 | ret -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/gdt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | arch/x86_64/gdt.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace obos 15 | { 16 | struct gdtEntry 17 | { 18 | uint16_t limitLow; 19 | uint16_t baseLow; 20 | uint8_t baseMiddle1; 21 | uint8_t access; 22 | uint8_t granularity; 23 | uint8_t baseMiddle2; 24 | uint64_t baseHigh; 25 | } __attribute__((packed)); 26 | 27 | struct tssEntry 28 | { 29 | uint32_t resv1; 30 | uint64_t rsp0; 31 | uint64_t rsp1; 32 | uint64_t rsp2; 33 | uint64_t resv2; 34 | uint64_t ist0; 35 | uint8_t unused1[0x3a]; 36 | uint16_t iopb; 37 | } __attribute__((packed)); 38 | 39 | extern "C" gdtEntry TSS[sizeof(gdtEntry)]; 40 | 41 | tssEntry s_tssEntry alignas(8); 42 | 43 | static_assert(sizeof(tssEntry) == 104, "sizeof(tssEntry) != 104"); 44 | 45 | extern void InitializeGDTASM(); 46 | 47 | void InitializeGdt() 48 | { 49 | utils::memzero(&s_tssEntry, sizeof(tssEntry)); 50 | 51 | gdtEntry* tss = (gdtEntry*)&TSS; 52 | 53 | uintptr_t base = reinterpret_cast(&s_tssEntry); 54 | tss->access = 0x89; 55 | tss->granularity = 0x40; 56 | tss->limitLow = sizeof(tssEntry) - 1; 57 | tss->baseLow = base & 0xFFFF; 58 | tss->baseMiddle1 = (base >> 16) & 0xFF; 59 | tss->baseMiddle2 = (base >> 24) & 0xFF; 60 | tss->baseHigh = base >> 32; 61 | s_tssEntry.iopb = 103; 62 | static char ist0_tstack[0x1800]; 63 | s_tssEntry.ist0 = (uint64_t)(ist0_tstack + 0x1800); 64 | 65 | InitializeGDTASM(); 66 | } 67 | void SetTSSStack(void* rsp) 68 | { 69 | if (thread::GetCurrentCpuLocalPtr()) 70 | thread::GetCurrentCpuLocalPtr()->arch_specific.tss.rsp0 = (uintptr_t)rsp; 71 | else 72 | s_tssEntry.rsp0 = (uintptr_t)rsp; 73 | } 74 | void SetIST(void* rsp) 75 | { 76 | if(thread::GetCurrentCpuLocalPtr()) 77 | thread::GetCurrentCpuLocalPtr()->arch_specific.tss.ist0 = (uint64_t)rsp; 78 | else 79 | s_tssEntry.ist0 = (uintptr_t)rsp; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/idt.asm: -------------------------------------------------------------------------------- 1 | ; oboskrnl/arch/x86_64/idt.asm 2 | 3 | ; Copyright (c) 2023-2024 Omar Berrow 4 | 5 | [BITS 64] 6 | 7 | section .bss 8 | align 1 9 | bad_idt: 10 | dq 0 11 | dw 0 12 | section .text 13 | 14 | global idtFlush 15 | global reset_idt 16 | 17 | idtFlush: 18 | lidt [rdi] 19 | ret 20 | reset_idt: 21 | lidt [bad_idt] 22 | ret -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/interrupt.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/interrupt_frame.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #define BITFIELD_FROM_BIT(n) (1< 10 | 11 | namespace obos 12 | { 13 | namespace acpi 14 | { 15 | struct ACPIRSDPHeader { 16 | char Signature[8]; 17 | uint8_t Checksum; 18 | char OEMID[6]; 19 | uint8_t Revision; 20 | uint32_t RsdtAddress; // Deprecated 21 | 22 | // Fields only valid if Revision != 0 23 | uint32_t Length; 24 | uint64_t XsdtAddress; 25 | uint8_t ExtendedChecksum; 26 | uint8_t reserved[3]; 27 | } __attribute__((packed)); 28 | struct ACPISDTHeader { 29 | char Signature[4]; 30 | uint32_t Length; 31 | uint8_t Revision; 32 | uint8_t Checksum; 33 | char OEMID[6]; 34 | char OEMTableID[8]; 35 | uint32_t OEMRevision; 36 | uint32_t CreatorID; 37 | uint32_t CreatorRevision; 38 | } __attribute__((packed)); 39 | struct MADTTable 40 | { 41 | ACPISDTHeader sdtHeader; 42 | uint32_t lapicAddress; 43 | uint32_t unwanted; 44 | // There are more entries. 45 | } __attribute__((packed)); 46 | struct MADT_EntryHeader 47 | { 48 | uint8_t type; 49 | uint8_t length; 50 | } __attribute__((packed)); 51 | struct MADT_EntryType0 52 | { 53 | MADT_EntryHeader entryHeader; 54 | uint8_t processorID; 55 | uint8_t apicID; 56 | uint32_t flags; 57 | } __attribute__((packed)); 58 | struct MADT_EntryType1 59 | { 60 | MADT_EntryHeader entryHeader; 61 | uint8_t ioApicID; 62 | uint8_t resv1; 63 | uint32_t ioapicAddress; 64 | uint32_t globalSystemInterruptBase; 65 | } __attribute__((packed)); 66 | struct MADT_EntryType2 67 | { 68 | MADT_EntryHeader entryHeader; 69 | uint8_t busSource; 70 | uint8_t irqSource; 71 | uint32_t globalSystemInterrupt; 72 | uint16_t flags; 73 | } __attribute__((packed)); 74 | struct MADT_EntryType3 75 | { 76 | MADT_EntryHeader entryHeader; 77 | uint8_t nmiSource; 78 | uint8_t resv; 79 | uint16_t flags; 80 | uint32_t globalSystemInterrupt; 81 | } __attribute__((packed)); 82 | struct MADT_EntryType4 83 | { 84 | MADT_EntryHeader entryHeader; 85 | uint8_t processorID; 86 | uint16_t flags; 87 | uint8_t lINT; 88 | } __attribute__((packed)); 89 | struct MADT_EntryType5 90 | { 91 | MADT_EntryHeader entryHeader; 92 | uint8_t resv1[2]; 93 | uintptr_t lapic_address; 94 | } __attribute__((packed)); 95 | struct MADT_EntryType9 96 | { 97 | MADT_EntryHeader entryHeader; 98 | uint8_t resv1[2]; 99 | uint32_t x2APIC_ID; 100 | uint32_t flags; 101 | uint32_t acpiID; 102 | } __attribute__((packed)); 103 | 104 | struct HPET_Addr 105 | { 106 | uint8_t addressSpaceId; 107 | uint8_t registerBitWidth; 108 | uint8_t registerBitOffset; 109 | uint8_t resv; 110 | uintptr_t address; 111 | } __attribute__((packed)); 112 | struct HPET_Table 113 | { 114 | ACPISDTHeader sdtHeader; 115 | uint32_t eventTimerBlockID; 116 | HPET_Addr baseAddress; 117 | uint8_t hpetNumber; 118 | uint16_t mainCounterMinimum/*ClockTickPeriodicMode*/; 119 | uint8_t pageProtectionAndOEMAttrib; 120 | } __attribute__((packed)); 121 | } 122 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/irq/timer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/irq/timer.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | namespace obos 17 | { 18 | void(*g_currentTimerHandler)(interrupt_frame*); 19 | static void IntermediateTimerIntHandler(interrupt_frame* frame) 20 | { 21 | if(g_currentTimerHandler) 22 | g_currentTimerHandler(frame); 23 | SendEOI(); 24 | } 25 | void ConfigureAPICTimer(void(*handler)(interrupt_frame* frame), byte isr, uint32_t initialCount, TimerConfig timerConfig, TimerDivisor divisor, bool mask) 26 | { 27 | uintptr_t savedFlags = saveFlagsAndCLI(); 28 | RegisterInterruptHandler(isr, IntermediateTimerIntHandler); 29 | g_currentTimerHandler = handler; 30 | divisor = (TimerDivisor)((int)divisor & 0b1101); 31 | if (timerConfig != 0 && timerConfig != TIMER_CONFIG_PERIODIC) 32 | timerConfig = TIMER_CONFIG_PERIODIC; 33 | g_localAPICAddr->divideConfig = divisor; 34 | g_localAPICAddr->lvtTimer = isr | timerConfig; 35 | MaskTimer(mask); 36 | g_localAPICAddr->initialCount = initialCount; 37 | restorePreviousInterruptStatus(savedFlags); 38 | } 39 | void MaskTimer(bool mask) 40 | { 41 | if(!mask) 42 | g_localAPICAddr->lvtTimer |= (1 << 16); 43 | else 44 | g_localAPICAddr->lvtTimer &= ~(1 << 16); 45 | } 46 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/irq/timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/irq/timer.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace obos 12 | { 13 | enum TimerConfig 14 | { 15 | TIMER_CONFIG_ONE_SHOT, 16 | TIMER_CONFIG_PERIODIC = 0x20000, 17 | }; 18 | enum TimerDivisor 19 | { 20 | TIMER_DIVISOR_TWO = 0b0000, 21 | TIMER_DIVISOR_FOUR = 0b0001, 22 | TIMER_DIVISOR_EIGHT = 0b0010, 23 | TIMER_DIVISOR_SIXTEEN = 0b0011, 24 | TIMER_DIVISOR_THIRTY_TWO = 0b1000, 25 | TIMER_DIVISOR_SIXTY_FOUR = 0b1001, 26 | TIMER_DIVISOR_ONE_HUNDERED_TWENTY_EIGHT = 0b1010, 27 | TIMER_DIVISOR_ONE = 0b1011, 28 | }; 29 | void ConfigureAPICTimer(void(*handler)(interrupt_frame* frame), byte isr, uint32_t initialCount, TimerConfig timerConfig, TimerDivisor divisor, bool maskIrq = true); 30 | void MaskTimer(bool mask); // Masks the timer interrupt. If !mask, the timer interrupt is disabled. 31 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/memory_manager/physical/allocate.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/memory_manager/allocate.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | namespace obos 13 | { 14 | namespace memory 15 | { 16 | void InitializePhysicalMemoryManager(); 17 | 18 | /// 19 | /// Allocates a physical page. 20 | /// 21 | /// The address of the page. Make sure to map this page before using it. 22 | OBOS_EXPORT uintptr_t allocatePhysicalPage(size_t nPages = 1); 23 | /// 24 | /// Marks a physical page as freed. 25 | /// 26 | /// The address of the page to free 27 | /// true on success, otherwise false. 28 | OBOS_EXPORT bool freePhysicalPage(uintptr_t addr, size_t nPages = 1); 29 | /// 30 | /// Queries whether a page is in the HHDM or not. 31 | /// 32 | /// The address of the page to check. 33 | /// true if the page is in the HHDM, otherwise false. 34 | OBOS_EXPORT bool PageInHHDM(uintptr_t addr); 35 | } 36 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/memory_manager/virtual/initialize.h: -------------------------------------------------------------------------------- 1 | /* 2 | arch/x86_64/memory_manager/virtual/initialize.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | namespace obos 13 | { 14 | namespace memory 15 | { 16 | OBOS_EXPORT uintptr_t* mapPageTable(uintptr_t* phys); 17 | 18 | class PageMap 19 | { 20 | public: 21 | PageMap() = delete; 22 | 23 | // L4 -> Page Map 24 | // L3 -> Page Directory Pointer 25 | // L2 -> Page Directory 26 | // L1 -> Page Table 27 | // L0 -> Page Table Entry 28 | 29 | OBOS_EXPORT uintptr_t* getPageMap() { return (uintptr_t*)this; } 30 | OBOS_EXPORT uintptr_t* getL4PageMapEntryAt(uintptr_t at); // pageMap[addressToIndex(at, 3)]; 31 | OBOS_EXPORT uintptr_t* getL3PageMapEntryAt(uintptr_t at); // getL4PageMapEntryAt()[addressToIndex(at,2)]; 32 | OBOS_EXPORT uintptr_t* getL2PageMapEntryAt(uintptr_t at); // getL3PageMapEntryAt()[addressToIndex(at,1)]; 33 | OBOS_EXPORT uintptr_t* getL1PageMapEntryAt(uintptr_t at); // getL2PageMapEntryAt()[addressToIndex(at,0)]; 34 | 35 | OBOS_EXPORT void switchToThis(); 36 | 37 | OBOS_EXPORT static size_t addressToIndex(uintptr_t address, uint8_t level) { return (address >> (9 * level + 12)) & 0x1FF; } 38 | }; 39 | 40 | OBOS_EXPORT PageMap* getCurrentPageMap(); 41 | 42 | OBOS_EXPORT size_t GetPhysicalAddressBits(); 43 | OBOS_EXPORT size_t GetVirtualAddressBits(); 44 | 45 | void InitializeVirtualMemoryManager(); 46 | 47 | OBOS_EXPORT bool CPUSupportsExecuteDisable(); 48 | 49 | // We don't export this because by the time a driver gets loaded it will be true. 50 | 51 | extern bool g_initialized; 52 | 53 | extern OBOS_EXPORT uintptr_t g_physAddrMask; 54 | } 55 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/memory_manager/virtual/internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/memory_manager/virtual/internal.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace obos 16 | { 17 | namespace memory 18 | { 19 | struct pageMapTuple { PageMap* pageMap; bool isUserMode; }; 20 | pageMapTuple GetPageMapFromProcess(process::Process* proc); 21 | bool CanAllocatePages(void* _base, size_t nPages, PageMap* pageMap); 22 | bool PagesAllocated(const void* _base, size_t nPages, PageMap* pageMap); 23 | uintptr_t DecodeProtectionFlags(uintptr_t _flags); 24 | 25 | uintptr_t* allocatePagingStructures(uintptr_t address, PageMap* pageMap, uintptr_t flags); 26 | void freePagingStructures(uintptr_t* _pageMap, uintptr_t _pageMapPhys, obos::memory::PageMap* pageMap, uintptr_t addr); 27 | 28 | // This includes non-committed pages (ie. pages that have bit 10 of the pte set, but not bit 0). 29 | void IteratePages( 30 | uintptr_t* headPM, 31 | uintptr_t* currentPM, 32 | uint8_t level, 33 | uintptr_t start, 34 | uintptr_t end, 35 | bool(*callback)(uintptr_t userdata, uintptr_t* pm, uintptr_t virt, uintptr_t entry), 36 | uintptr_t userdata, 37 | uintptr_t* indices // must be an array of at least 4 entries (anything over is ignored). 38 | ); 39 | 40 | void* MapPhysicalAddress(PageMap* pageMap, uintptr_t phys, void* to, uintptr_t cpuFlags); 41 | void* MapEntry(PageMap* pageMap, uintptr_t entry, void* to); 42 | void UnmapAddress(PageMap* pageMap, void* _addr); 43 | } 44 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/signals.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/signals.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | 21 | namespace obos 22 | { 23 | namespace process 24 | { 25 | template 26 | static bool testbit(i bitfield, uint8_t bit) 27 | { 28 | return (bitfield >> bit) & 1; 29 | } 30 | void __ImplCallSignal(thread::Thread* on, void(*handler)()) 31 | { 32 | on->flags |= thread::THREAD_FLAGS_IN_SIGNAL; 33 | bool isRunning = on->status & thread::THREAD_STATUS_RUNNING; 34 | __uint128_t affinity = on->affinity; 35 | on->status = thread::THREAD_STATUS_CAN_RUN | thread::THREAD_STATUS_PAUSED; 36 | if (isRunning) 37 | { 38 | // Find the cpu the thread is running on. 39 | uint32_t cpuId = bsf(affinity); 40 | // Call the scheduler on the cpu. 41 | SendIPI(DestinationShorthand::None, DeliveryMode::Fixed, 0x30, cpuId); 42 | } 43 | uintptr_t previousRip = on->context.frame.rip; 44 | on->context.frame.rip = (uintptr_t)handler; 45 | uintptr_t* returnAddress = (uintptr_t*)(on->context.frame.rsp -= 8); 46 | setAC(); 47 | *returnAddress = previousRip; 48 | clearAC(); 49 | on->status = thread::THREAD_STATUS_CAN_RUN; 50 | } 51 | 52 | bool CallSignal(thread::Thread* on, signals sig) 53 | { 54 | if (sig > SIGMAX) 55 | { 56 | SetLastError(OBOS_ERROR_INVALID_PARAMETER); 57 | return false; 58 | } 59 | logger::debug("Calling signal %d on thread %d, process id %d. Action on fail: Abort.\n", sig, on->tid, ((process::Process*)on->owner)->pid); 60 | auto process = (Process*)on->owner; 61 | auto handler = process->signal_table[sig]; 62 | if (!handler) 63 | { 64 | SetLastError(OBOS_ERROR_NULL_HANDLER); 65 | return false; 66 | } 67 | __ImplCallSignal(on, handler); 68 | return true; 69 | } 70 | bool CallSignalOrTerminate(thread::Thread* on, signals sig) 71 | { 72 | if (sig > SIGMAX) 73 | { 74 | SetLastError(OBOS_ERROR_INVALID_PARAMETER); 75 | return false; 76 | } 77 | logger::debug("Calling signal %d on thread %d, process id %d. Action on fail: Terminate thread's process.\n", sig, on->tid, ((process::Process*)on->owner)->pid); 78 | auto process = (Process*)on->owner; 79 | auto handler = process->signal_table[sig]; 80 | if (handler) 81 | __ImplCallSignal(on, handler); 82 | else 83 | TerminateProcess(process); 84 | return true; 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/smp_trampoline.asm: -------------------------------------------------------------------------------- 1 | ; arch/x86_64/smp_trampoline.asm 2 | ; 3 | ; Copyright (c) 2023-2024 Omar Berrow 4 | 5 | [BITS 16] 6 | 7 | segment .data 8 | 9 | global _strampoline 10 | global _etrampoline 11 | global loadGDT 12 | 13 | extern GDT_Ptr 14 | 15 | ; The start of the trampoline. 16 | _strampoline: 17 | db 0xEB, 0x38 18 | 19 | align 8 20 | gdt: 21 | dq 0 22 | ; 64-bit Code segment. 23 | dq 0x00209A0000000000 24 | ; 64-bit Data segment. 25 | dq 0x0000920000000000 26 | ; 32-bit Code segment. 27 | dd 0x0000FFFF 28 | dd 0x00CF9A00 29 | ; 32-bit Data segment. 30 | dd 0x0000FFFF 31 | dd 0x00CF9200 32 | gdt_end: 33 | gdt_ptr: 34 | %define gdt_ptr_addr 0x30 35 | align 1 36 | dw gdt_end-gdt-1 37 | dq 0x8 38 | 39 | ; The real-mode trampoline. 40 | ; We will always be loaded at nullptr, so we can assume some values. 41 | trampoline: 42 | 43 | .real_mode: 44 | cli 45 | 46 | ; Enter protected-mode 47 | mov eax, cr0 48 | or ax, 1 ; Enable protected mode. 49 | mov cr0, eax 50 | 51 | lgdt [gdt_ptr_addr] 52 | 53 | mov sp, 0xFD0 54 | 55 | mov ax, 0x20 56 | mov ds, ax 57 | mov es, ax 58 | mov ss, ax 59 | mov fs, ax 60 | mov gs, ax 61 | 62 | db 0xE8, 0x00, 0x00 ; call REL16 63 | pop ax 64 | add ax, 10 65 | mov byte [0x01], al 66 | 67 | db 0x9A, 0x00, 0x00, 0x18, 0x00 ; call 0x18:.protected_mode 68 | align 1 69 | .protected_mode: 70 | [BITS 32] 71 | 72 | ; Enter 64-bit long mode. 73 | 74 | ; Enable PAE 75 | mov eax, cr4 76 | or eax, (1<<5) 77 | mov cr4, eax 78 | 79 | ; Load the page map 80 | mov eax, [0xff8] 81 | mov cr3, eax 82 | 83 | ; Enter long mode. 84 | mov eax, 0x80000001 85 | xor ecx,ecx 86 | cpuid 87 | xor eax, eax 88 | test edx, (1<<20) 89 | mov esi, (1<<11) 90 | cmovnz eax, esi ; If bit 20 is set 91 | mov ecx, 0xC0000080 92 | or eax, (1 << 8)|(1<<10) 93 | xor edx,edx 94 | wrmsr 95 | 96 | ; Enable paging. 97 | mov eax, 0x80010001 98 | mov cr0, eax 99 | 100 | mov esp, 0xFC8 101 | call .jmp 102 | .jmp: 103 | pop edi ; The address of .set_cs needs to be in a register that won't be modified by a) cpuid b) the rest of the code. 104 | add edi, 8 105 | db 0x6A, 0x08, 0x57, 0xCB ; push 0x08; push edi; retfd 106 | 107 | .set_cs: 108 | mov ax, 0x10 109 | mov ds, ax 110 | mov es, ax 111 | mov ss, ax 112 | mov fs, ax 113 | mov gs, ax 114 | 115 | .done: 116 | [BITS 64] 117 | mov al, [0xFB0] 118 | test al,al 119 | jnz .call_procInit 120 | 121 | lgdt [GDT_Ptr] 122 | 123 | ; Set "trampoline_has_gdt" to true 124 | mov qword [0xFB0], 1 125 | 126 | push 0x8 127 | push rdi 128 | retfq 129 | 130 | .call_procInit: 131 | ; Set "trampoline_has_gdt" to false for the next AP. 132 | mov qword [0xFB0], 0 133 | 134 | mov rdi, [0xFD8] 135 | mov rsp, [rdi] 136 | add rsp, 0x2000 137 | jmp [0xFA8] 138 | 139 | .abort: 140 | cli 141 | hlt 142 | jmp .abort 143 | 144 | align 4096 145 | .end: 146 | 147 | _etrampoline: 148 | align 1 149 | segment .text 150 | loadGDT: 151 | lgdt [rdi] 152 | 153 | mov ax, 0x10 154 | mov ds, ax 155 | mov es, ax 156 | mov fs, ax 157 | mov gs, ax 158 | mov ss, ax 159 | 160 | mov ax, 0x28 161 | ltr ax 162 | xor ax,ax 163 | lldt ax 164 | 165 | pop rax 166 | push 0x8 167 | push rax 168 | retfq -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/sse.asm: -------------------------------------------------------------------------------- 1 | ; arch/x86_64/sse.asm 2 | ; 3 | ; Copyright (c) 2023-2024 Omar Berrow 4 | 5 | [BITS 64] 6 | 7 | global _ZN4obos7initSSEEv 8 | 9 | _ZN4obos7initSSEEv: 10 | mov rax, cr4 11 | or rax, (1<<9)|(1<<10) 12 | mov cr4, rax 13 | mov rax, cr0 14 | and eax, ~(1<<2) 15 | or eax, (1<<1) 16 | mov cr0, rax 17 | ret -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/stack_canary.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/stack_canary.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | #ifdef OBOS_DEBUG 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | uintptr_t __stack_chk_guard = 0x15E4F6DABD6F8A; 15 | 16 | struct frame 17 | { 18 | frame* next; 19 | void *rip; 20 | }; 21 | extern "C" [[noreturn]] void __stack_chk_fail(void) 22 | { 23 | frame* current = (frame*)obos::getRBP(); 24 | void* where = nullptr; 25 | // Why did I go through all this JUST to get the return address 26 | { 27 | if (!current) 28 | goto skip; 29 | uint64_t attrib = 0; 30 | size_t nPages = 0; 31 | uintptr_t _current = (uintptr_t)current; 32 | nPages = 1llu + (((_current + sizeof(*current)) & ~0xfff) > (_current & ~0xfff)); 33 | obos::memory::VirtualAllocator vallocator{ nullptr }; 34 | if (!vallocator.VirtualGetProtection(current, nPages, &attrib)) 35 | goto skip; 36 | if (!(attrib & obos::memory::PROT_IS_PRESENT)) 37 | goto skip; 38 | where = current->rip; 39 | } 40 | skip: 41 | obos::logger::panic(nullptr, "Stack corruption detected at 0x%p.\n", where); 42 | } 43 | #endif -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/syscall/handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | arch/x86_64/syscall/handle.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | namespace obos 13 | { 14 | namespace syscalls 15 | { 16 | enum class ProcessHandleType 17 | { 18 | INVALID = (-1), 19 | FILE_HANDLE, 20 | DRIVE_HANDLE, 21 | THREAD_HANDLE, 22 | VALLOCATOR_HANDLE, 23 | DIRECTORY_ITERATOR_HANDLE, 24 | }; 25 | using user_handle = uint64_t; 26 | using handle = utils::pair; 27 | constexpr user_handle USER_HANDLE_MAX = UINT64_MAX; 28 | /// 29 | /// Registers a handle for a process at a certain address with a certain type. 30 | /// 31 | /// The owner of the handle. This should be a process::Process* 32 | /// The address of the object. 33 | /// The type of the object. 34 | /// The newly made handle, or UINT64_MAX on failure. 35 | user_handle ProcessRegisterHandle(void* proc, void* objectAddress, ProcessHandleType type); 36 | /// 37 | /// Frees a handle for a process. 38 | /// 39 | /// The owner of the handle. This should be a process::Process* 40 | /// The handle to release. 41 | /// The object the handle represented, or nullptr on failure. 42 | void* ProcessReleaseHandle(void* proc, user_handle handle); 43 | /// 44 | /// Checks if a handle exists or not. 45 | /// 46 | /// The owner of the handle. This should be a process::Process* 47 | /// The handle value to check. 48 | /// The type of the handle. This can be ProcessHandleType::INVALID to specify any handle type. 49 | /// true if the handle exists, and the type matches, otherwise false. 50 | bool ProcessVerifyHandle(void* proc, user_handle handle, ProcessHandleType type = ProcessHandleType::INVALID); 51 | /// 52 | /// Gets the object represented by a handle. 53 | /// 54 | /// The owner of the handle. This should be a process::Process* 55 | /// The handle value to retrieve. 56 | /// The object represented by the handle on success, or nullptr on failure. 57 | void* ProcessGetHandleObject(void* proc, user_handle handle); 58 | /// 59 | /// Gets the type of a handle. 60 | /// 61 | /// The owner of the handle. This should be a process::Process* 62 | /// The handle value to retrieve. 63 | /// The type of thehandle on success, or ProcessHandleType::INVALID on failure. 64 | ProcessHandleType ProcessGetHandleType(void* proc, user_handle handle); 65 | 66 | /// 67 | /// Syscall Number: 24 68 | /// Frees a handle. After this function is called on a handle, the handle can no longer be used for any purpose. 69 | /// You should call this function after calling Syscall*CloseHandle. 70 | /// 71 | /// uint64_t thrHandle = SyscallMakeThreadHandle(); 72 | /// SyscallCreateThread(thrHandle, 0,0,ThreadEntry,0, nullptr, false); 73 | /// // Do stuff with the handle. 74 | /// SyscallThreadCloseHandle(thrHandle); 75 | /// SyscallInvalidateHandle(thrHandle); 76 | /// 77 | /// Only here because of the syscall abi on OBOS x86-64 78 | /// The handle to free. This is a pointer because of the syscall abi on OBOS x86-64, when 'syscall'ing, you just pass a user_handle. 79 | /// Whether the handle was freed properly (true) or false on failure. 80 | bool SyscallInvalidateHandle(uint64_t syscall, user_handle* handle); 81 | } 82 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/syscall/power_management.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/syscall/power_management.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace obos 12 | { 13 | namespace syscalls 14 | { 15 | uintptr_t PMSyscallHandler(uint64_t syscall, void* args); 16 | 17 | /// 18 | /// System number: 59 19 | /// Shuts down the system, doing necessary cleanup. 20 | /// If for some reason this fails, all CPUs are stopped and the system idles. 21 | /// This syscall does not return. 22 | /// 23 | void SyscallShutdown(); 24 | /// 25 | /// System number: 60 26 | /// Reboots the system, doing necessary cleanup. 27 | /// If for some reason this fails, all CPUs are stopped and the system idles. 28 | /// This syscall does not return. 29 | /// 30 | void SyscallReboot(); 31 | } // namespace syscall 32 | 33 | } // namespace obos 34 | -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/syscall/register.h: -------------------------------------------------------------------------------- 1 | /* 2 | arch/x86_64/syscall/register.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace obos 12 | { 13 | namespace syscalls 14 | { 15 | // Zero-based. 16 | constexpr size_t g_syscallTableLimit = 0x1fff; 17 | extern uintptr_t g_syscallTable[g_syscallTableLimit + 1]; 18 | void RegisterSyscalls(); 19 | void RegisterSyscall(uint16_t n, uintptr_t func); 20 | 21 | // These next five functions are never actually defined except for the actual syscall 22 | // They're just defined for documentation purposes 23 | 24 | /// 25 | /// Syscall number: 55 26 | /// Gets the last error for the current thread. 27 | /// 28 | /// The last error 29 | uint32_t SyscallGetLastError(); 30 | /// 31 | /// Syscall number: 56 32 | /// Sets the last error for the current thread. 33 | /// 34 | /// The new error code. 35 | void SyscallSetLastError(uint32_t newError); 36 | 37 | /// 38 | /// Syscall number: 57 39 | /// Loads a kernel module. 40 | /// 41 | /// The beginning of the file. 42 | /// The size of the file. 43 | /// Whether the function succeeded (true) or not (false). 44 | bool SyscallLoadModule(const byte* data, size_t size); 45 | 46 | /// 47 | /// Syscall number: 69 48 | /// Prefer the wrgsbase/wrfsbase instructions over this when possible. 49 | /// Writes to gs/fs base. 50 | /// 51 | /// The value to write. 52 | /// Whether to write to GSBase (true) or FSBase (false)>. 53 | void wrfsgsbase(uintptr_t val, bool isGSBase); 54 | /// 55 | /// Syscall number: 70 56 | /// Prefer the rdgsbase/rdfsbase instructions over this when possible. 57 | /// Reads from gs/fs base. 58 | /// 59 | /// Whether to write to GSBase (true) or FSBase (false)>. 60 | /// The value of gs/fs base. 61 | uintptr_t rdfsgsbase(bool isGSBase); 62 | } 63 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/syscall/signals.h: -------------------------------------------------------------------------------- 1 | /* 2 | arch/x86_64/syscall/signals.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace obos 16 | { 17 | namespace syscalls 18 | { 19 | uintptr_t SignalsSyscallHandler(uint64_t syscall, void* args); 20 | 21 | /// 22 | /// Syscall Number: 57 23 | /// Registers a signal handler for the current process. 24 | /// 25 | /// The signal to register. 26 | /// The handler, or nullptr to clear the handler. 27 | /// Whether the signal was successfully registered (true) or not (false). 28 | bool SyscallRegisterSignal(process::signals signal, uintptr_t uhandler); 29 | /// 30 | /// Syscall Number: 58 31 | /// Calls a signal on a thread. 32 | /// 33 | /// A thread handle representing the thread to call the signal on. 34 | /// The signal to send. 35 | /// Whether the signal was successfully send (true) or not (false). 36 | bool SyscallCallSignal(user_handle on, process::signals sig); 37 | } 38 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/syscall/sys_signals.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | arch/x86_64/syscall/signals.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | 20 | namespace obos 21 | { 22 | namespace syscalls 23 | { 24 | uintptr_t SignalsSyscallHandler(uint64_t syscall, void* args) 25 | { 26 | switch (syscall) 27 | { 28 | case 57: 29 | { 30 | struct _par 31 | { 32 | alignas(0x10) process::signals signal; 33 | alignas(0x10) uintptr_t uhandler; 34 | } *par = (_par*)args; 35 | if (!canAccessUserMemory(par, sizeof(*par), false)) 36 | { 37 | SetLastError(OBOS_ERROR_INVALID_PARAMETER); 38 | return false; 39 | } 40 | return SyscallRegisterSignal(par->signal, par->uhandler); 41 | } 42 | case 58: 43 | { 44 | struct _par 45 | { 46 | alignas(0x10) user_handle on; 47 | alignas(0x10) process::signals sig; 48 | } *par = (_par*)args; 49 | if (!canAccessUserMemory(par, sizeof(*par), false)) 50 | { 51 | SetLastError(OBOS_ERROR_INVALID_PARAMETER); 52 | return false; 53 | } 54 | return SyscallCallSignal(par->on, par->sig); 55 | } 56 | default: 57 | break; 58 | } 59 | return 0; 60 | } 61 | 62 | bool SyscallRegisterSignal(process::signals signal, uintptr_t uhandler) 63 | { 64 | if ((uint32_t)signal > (uint32_t)process::signals::INVALID_SIGNAL) 65 | { 66 | SetLastError(OBOS_ERROR_INVALID_PARAMETER); 67 | return false; 68 | } 69 | process::Process* currentProc = (process::Process*)thread::GetCurrentCpuLocalPtr()->currentThread->owner; 70 | currentProc->signal_table[signal] = (void(*)())uhandler; 71 | return true; 72 | } 73 | bool SyscallCallSignal(user_handle on, process::signals sig) 74 | { 75 | if (!ProcessVerifyHandle(nullptr, on, ProcessHandleType::THREAD_HANDLE)) 76 | { 77 | SetLastError(OBOS_ERROR_INVALID_PARAMETER); 78 | return false; 79 | } 80 | return process::CallSignal((thread::Thread*)ProcessGetHandleObject(nullptr, on), sig); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/syscall/verify_pars.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | arch/x86_64/syscall/verify_pars.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #define getCPULocal() ((thread::cpu_local*)thread::getCurrentCpuLocalPtr()) 18 | 19 | namespace obos 20 | { 21 | namespace syscalls 22 | { 23 | bool canAccessUserMemory(const void* addr, size_t size, bool hasToWrite) 24 | { 25 | if (!addr) 26 | return false; 27 | memory::VirtualAllocator vallocator = ((process::Process*)getCPULocal()->currentThread->owner); 28 | bool checkUsermode = ((process::Process*)getCPULocal()->currentThread->owner)->isUsermode; 29 | if (checkUsermode && (uintptr_t)addr > 0xffff'8000'0000'0000) 30 | return false; 31 | size_t nPagesToCheck = ((size + 0xfff) & ~0xfff) / 4096; 32 | uintptr_t* pageFlags = (uintptr_t*)kmalloc(nPagesToCheck * sizeof(uintptr_t)); 33 | uintptr_t requiredFlags = memory::PROT_IS_PRESENT | ((uintptr_t)checkUsermode * memory::PROT_USER_MODE_ACCESS); 34 | if(!vallocator.VirtualGetProtection((void*)((uintptr_t)addr & ~0xfff), nPagesToCheck * 4096, pageFlags)) 35 | { 36 | kfree(pageFlags); 37 | return false; 38 | } 39 | for (size_t i = 0; i < nPagesToCheck; i++) 40 | { 41 | if (((pageFlags[i] & requiredFlags) != requiredFlags) || ((pageFlags[0] & memory::PROT_READ_ONLY) && hasToWrite)) 42 | { 43 | kfree(pageFlags); 44 | return false; 45 | } 46 | } 47 | kfree(pageFlags); 48 | return true; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/syscall/verify_pars.h: -------------------------------------------------------------------------------- 1 | /* 2 | arch/x86_64/syscall/verify_pars.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace obos 12 | { 13 | namespace syscalls 14 | { 15 | bool canAccessUserMemory(const void* addr, size_t size, bool hasToWrite); 16 | } 17 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/syscall/vfs/dir.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/arch/x86_64/syscall/vfs/dir.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace obos 14 | { 15 | namespace syscalls 16 | { 17 | uintptr_t DirectorySyscallHandler(uint64_t syscall, void* args); 18 | 19 | /// 20 | /// Syscall number: 61 21 | /// Makes a directory iterator. 22 | /// 23 | /// The handle, or USER_HANDLE_MAX on failure. 24 | user_handle SyscallMakeDirectoryIterator(); 25 | 26 | /// 27 | /// Syscall number: 66 28 | /// Opens a directory iterator at 'path'. 29 | /// 30 | /// The handle to open. 31 | /// The path of the directory to iterate over. 32 | /// Whether the handle was successfully opened (true) or not (false). 33 | bool SyscallDirectoryIteratorOpen(user_handle hnd, const char* path); 34 | 35 | /// 36 | /// Syscall number: 62 37 | /// Makes the directory iterator's position increase by one. 38 | /// 39 | /// The iterator to modify. 40 | /// Whether the function succeeded (true) or not (false). 41 | bool SyscallDirectoryIteratorNext(user_handle hnd); 42 | /// 43 | /// Syscall number: 63 44 | /// Makes the directory iterator's position decrease by one. 45 | /// 46 | /// The iterator to modify. 47 | /// Whether the function succeeded (true) or not (false). 48 | bool SyscallDirectoryIteratorPrevious(user_handle hnd); 49 | /// 50 | /// Syscall number: 64 51 | /// Gets the current file path of the directory iterator. 52 | /// 53 | /// The handle to query. 54 | /// [out] The buffer to store the path in. This can be nullptr. 55 | /// [in,out] A pointer to the size of the path, and a pointer to the actual size of the path. This must not be nullptr if path is not nullptr. 56 | /// Whether the function succeeded (true) or not (false). 57 | bool SyscallDirectoryIteratorGet(user_handle hnd, char* path, size_t* size); 58 | /// 59 | /// Syscall number: 65 60 | /// Queries whether the directory iterator has any more entries left to iterator, as if you queried EOF on it. 61 | /// 62 | /// The handle to query. 63 | /// [out,opt] Whether the function succeeded (true) or not (false). 64 | /// Whether the directory iterator reached past the last entry (true) or not (false). This returns false if the function fails, always check *status. 65 | bool SyscallDirectoryIteratorEnd(user_handle hnd, bool* status); 66 | 67 | /// 68 | /// Syscall number: 67 69 | /// Closes a directory handle. 70 | /// 71 | /// The handle to close. 72 | /// Whether the handle was successfully closed (true) or not (false). 73 | bool SyscallDirectoryIteratorClose(user_handle hnd); 74 | 75 | /// 76 | /// Syscall number: 68 77 | /// Gets the path of the parent directory of a directory iterator. 78 | /// In case anyone is wondering why I (Omar Berrow) decided to not add a direct syscall to get the parent of a path, it was because I was too lazy to do that. 79 | /// 80 | /// The handle to query. 81 | /// [out] The buffer to store the path in. This can be nullptr. 82 | /// [in,out] A pointer to the size of the path, and a pointer to the actual size of the path. This must not be nullptr if path is not nullptr. 83 | /// Whether the function succeeded (true) or not (false). 84 | bool SyscallDirectoryIteratorGetParent(user_handle hnd, char* path, size_t* size); 85 | } 86 | } -------------------------------------------------------------------------------- /src/oboskrnl/arch/x86_64/syscall/vmm.h: -------------------------------------------------------------------------------- 1 | /* 2 | arch/x86_64/syscall/vmm.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace obos 16 | { 17 | namespace syscalls 18 | { 19 | uintptr_t VMMSyscallHandler(uint64_t syscall, void* args); 20 | 21 | /// 22 | /// Syscall Number: 39 23 | /// Creates a virtual allocator with 'owner' as the process to allocate as. 24 | /// 25 | /// The process to allocate as. 26 | user_handle SyscallCreateVirtualAllocator(process::Process* owner); 27 | 28 | /// 29 | /// Syscall Number: 40 30 | /// Allocates nPages at base. 31 | /// 32 | /// The base address to allocate at. 33 | /// The amount of bytes (rounded to the nearest page size) to allocate at base. 34 | /// The initial protection flags. 35 | /// "base" if base isn't nullptr. If base is nullptr, the function finds a base address. 36 | void* SyscallVirtualAlloc(user_handle hnd, void* base, size_t size, uintptr_t flags); 37 | /// 38 | /// Syscall Number: 41 39 | /// Free nPages pages at base. 40 | /// 41 | /// The base address to free. 42 | /// The amount of bytes (rounded to the nearest page size) to free. 43 | /// false on failure, otherwise true. If this function fails, use GetLastError for extra error information. 44 | bool SyscallVirtualFree(user_handle hnd, void* base, size_t size); 45 | /// 46 | /// Syscall Number: 42 47 | /// Sets the protection for the pages at base. 48 | /// 49 | /// The base address to set the protection for. 50 | /// The amount of bytes (rounded to the nearest page size) to set the protection for. 51 | /// The new protection flags 52 | /// false on failure, otherwise true. If this function fails, use GetLastError for extra error information. 53 | bool SyscallVirtualProtect(user_handle hnd, void* base, size_t size, uintptr_t flags); 54 | /// 55 | /// Syscall Number: 43 56 | /// Gets the protection for base. 57 | /// 58 | /// The base address to get the protection for. 59 | /// The amount of bytes (rounded to the nearest page size) to get the protection for. 60 | /// A pointer to a buffer of the size "sizeof(PageProtectionFlags) * sizeToPageCount(size)" to store the protection in. 61 | /// false on failure, otherwise true. If this function fails, use GetLastError for extra error information. 62 | bool SyscallVirtualGetProtection(user_handle hnd, void* base, size_t size, uintptr_t* flags); 63 | 64 | /// 65 | /// Syscall Number: 44 66 | /// Copies a buffer from this program to the other process. 67 | /// 68 | /// The remote destination's address. 69 | /// The local source's address. 70 | /// The size of the buffer. 71 | /// remoteDest on success, or nullptr. 72 | void* SyscallVirtualMemcpy(user_handle hnd, void* remoteDest, const void* localSrc, size_t size); 73 | } 74 | } -------------------------------------------------------------------------------- /src/oboskrnl/atomic.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/atomic.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace obos 12 | { 13 | void atomic_set(bool* val); 14 | void atomic_clear(bool* val); 15 | bool atomic_test(const bool* val); 16 | 17 | void atomic_inc(uint64_t& val); 18 | void atomic_dec(uint64_t& val); 19 | bool atomic_cmpxchg(bool* dest, bool val, bool src); 20 | } -------------------------------------------------------------------------------- /src/oboskrnl/boot/cfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/boot/cfg.h 3 | 4 | Copyright (c) 2023,2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | // Utility to parse the kernel config file. 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace obos 17 | { 18 | struct Element 19 | { 20 | Element() = default; 21 | enum 22 | { 23 | ELEMENT_INVALID, 24 | ELEMENT_STRING, 25 | ELEMENT_ARRAY, 26 | ELEMENT_INTEGER, 27 | ELEMENT_BOOLEAN, 28 | } type = ELEMENT_INVALID; 29 | utils::String string{}; 30 | utils::Vector array{}; 31 | uintptr_t integer = 0; 32 | bool boolean = false; 33 | Element(const Element& other) 34 | { 35 | type = other.type; 36 | switch (other.type) 37 | { 38 | case ELEMENT_ARRAY: 39 | array = other.array; 40 | break; 41 | case ELEMENT_STRING: 42 | string = other.string; 43 | break; 44 | case ELEMENT_BOOLEAN: 45 | boolean = other.boolean; 46 | break; 47 | case ELEMENT_INTEGER: 48 | integer = other.integer; 49 | break; 50 | default: 51 | break; 52 | } 53 | return; 54 | } 55 | Element& operator=(const Element& other) 56 | { 57 | type = other.type; 58 | switch (other.type) 59 | { 60 | case ELEMENT_ARRAY: 61 | array = other.array; 62 | break; 63 | case ELEMENT_STRING: 64 | string = other.string; 65 | break; 66 | case ELEMENT_BOOLEAN: 67 | boolean = other.boolean; 68 | break; 69 | case ELEMENT_INTEGER: 70 | integer = other.integer; 71 | break; 72 | default: 73 | break; 74 | } 75 | return *this; 76 | } 77 | Element& operator=(Element&&) = delete; 78 | Element(Element&&) = delete; 79 | ~Element(){} 80 | }; 81 | class Parser final 82 | { 83 | public: 84 | Parser() = default; 85 | 86 | Parser(const Parser&) = delete; 87 | Parser& operator=(const Parser&) = delete; 88 | Parser(Parser&&) = delete; 89 | Parser& operator=(Parser&&) = delete; 90 | 91 | bool Parse(const char* data, size_t size, utils::Vector& errorMessages); 92 | 93 | const Element* GetElement(const char* key); 94 | const auto& GetMap() { return m_elements; } 95 | 96 | ~Parser() {} 97 | private: 98 | static bool equals(const char* const& key1, const char* const& key2) 99 | { return utils::strcmp(key1, key2); } 100 | static size_t hasher(const char* const& key) 101 | { 102 | const byte* _key = (byte*)key; 103 | 104 | size_t h = 0, g = 0; 105 | 106 | while (*_key) 107 | { 108 | h = (h << 4) + *_key++; 109 | if ((g = h & 0xf0000000)) 110 | h ^= g >> 24; 111 | h &= ~g; 112 | } 113 | return h; 114 | } 115 | utils::Hashmap m_elements; 116 | }; 117 | } -------------------------------------------------------------------------------- /src/oboskrnl/driverInterface/input_device.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/driverInterface/register_drive.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | namespace obos 19 | { 20 | namespace driverInterface 21 | { 22 | struct InputDevice 23 | { 24 | driverIdentity* driver = nullptr; 25 | utils::Vector data; 26 | uint32_t id = 0; 27 | vfs::HandleList fileHandlesReferencing; 28 | InputDevice *next = nullptr, *prev = nullptr; 29 | 30 | void* operator new(size_t) 31 | { 32 | return ImplSlabAllocate(ObjectTypes::InputDevice); 33 | } 34 | void operator delete(void* ptr) 35 | { 36 | ImplSlabFree(ObjectTypes::InputDevice, ptr); 37 | } 38 | void* operator new[](size_t sz) 39 | { 40 | return ImplSlabAllocate(ObjectTypes::InputDevice, sz / sizeof(InputDevice)); 41 | } 42 | void operator delete[](void* ptr, size_t sz) 43 | { 44 | ImplSlabFree(ObjectTypes::InputDevice, ptr, sz / sizeof(InputDevice)); 45 | } 46 | [[nodiscard]] void* operator new(size_t, void* ptr) noexcept { return ptr; } 47 | [[nodiscard]] void* operator new[](size_t, void* ptr) noexcept { return ptr; } 48 | void operator delete(void*, void*) noexcept {} 49 | void operator delete[](void*, void*) noexcept {} 50 | }; 51 | struct InputDeviceList 52 | { 53 | InputDevice *head = nullptr, *tail = nullptr; 54 | size_t nNodes = 0; 55 | }; 56 | extern InputDeviceList g_inputDevices; 57 | } 58 | } -------------------------------------------------------------------------------- /src/oboskrnl/driverInterface/load.h: -------------------------------------------------------------------------------- 1 | /* 2 | driverInterface/load.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace obos 16 | { 17 | namespace driverInterface 18 | { 19 | extern utils::Hashmap g_driverInterfaces; 20 | void ScanAndLoadModules(const char* root); 21 | // Returns the driver header, this header must be in an offset from file to file+size. 22 | struct driverHeader* CheckModule(const byte* file, size_t size); 23 | bool LoadModule(const byte* file, size_t size, thread::ThreadHandle** mainThread); 24 | } 25 | } -------------------------------------------------------------------------------- /src/oboskrnl/driverInterface/register.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/driverInterface/register_drive.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | namespace obos 13 | { 14 | namespace driverInterface 15 | { 16 | enum class DeviceType 17 | { 18 | Drive, 19 | UserInput 20 | }; 21 | /// 22 | /// Registers a device in the kernel. 23 | /// 24 | /// The type of the device. 25 | /// The device id, or 0xffffffff on failure. 26 | OBOS_EXPORT uint32_t RegisterDevice(DeviceType type); 27 | /// 28 | /// Unregisters a device in the kernel. 29 | /// 30 | /// The device to unregister. This must be obtained through RegisterDevice. 31 | /// The device type. This cannot be 0xffffffff. 32 | OBOS_EXPORT void UnregisterDevice(uint32_t id, DeviceType type); 33 | /// 34 | /// Writes a byte to the input device's buffer. 35 | /// This function does not SetLastError on failure. 36 | /// 37 | /// The device's id. 38 | /// The character to write. 39 | /// Whether the function succeeded (true) or not (false). 40 | OBOS_EXPORT bool WriteByteToInputDeviceBuffer(uint32_t id, uint16_t exChar); 41 | void* GetUserInputDevice(uint32_t id); 42 | } 43 | } -------------------------------------------------------------------------------- /src/oboskrnl/driverInterface/x86_64/enumerate_pci.h: -------------------------------------------------------------------------------- 1 | /* 2 | drivers/x86_64/common/enumerate_pci.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #define PCI_GetRegisterOffset(reg, offset) ((uint8_t)(reg * 4 + offset)) 13 | 14 | namespace obos 15 | { 16 | namespace driverInterface 17 | { 18 | OBOS_EXPORT uint8_t pciReadByteRegister(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset); 19 | OBOS_EXPORT uint16_t pciReadWordRegister(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset); 20 | OBOS_EXPORT uint32_t pciReadDwordRegister(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset); 21 | OBOS_EXPORT void pciWriteByteRegister(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint8_t data); 22 | OBOS_EXPORT void pciWriteWordRegister(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint16_t data); 23 | OBOS_EXPORT void pciWriteDwordRegister(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint32_t data); 24 | OBOS_EXPORT void enumerateBus( 25 | uint8_t bus, 26 | bool(*callback)( 27 | void* userData, uint8_t currentSlot, uint8_t currentFunction, uint8_t currentBus, uint8_t classCode, 28 | uint8_t subclass, 29 | uint8_t progIF), 30 | void* callbackUserdata); 31 | OBOS_EXPORT bool enumerateBus(uint8_t bus, uint8_t expectedClassCode, uint8_t expectedSubclass, uint8_t exceptedProgIF, uint8_t* slot, uint8_t* function); 32 | OBOS_EXPORT bool enumeratePci(uint8_t expectedClassCode, uint8_t expectedSubclass, uint8_t exceptedProgIF, uint8_t* slot, uint8_t* function, uint8_t* bus); 33 | } 34 | } -------------------------------------------------------------------------------- /src/oboskrnl/error.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/error.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #define getCPULocal() ((thread::cpu_local*)thread::getCurrentCpuLocalPtr()) 18 | 19 | namespace obos 20 | { 21 | void SetLastError(uint32_t err) 22 | { 23 | if (!getCPULocal()) 24 | return; 25 | if (!getCPULocal()->currentThread) 26 | return; 27 | getCPULocal()->currentThread->lastError = err; 28 | } 29 | uint32_t GetLastError() 30 | { 31 | return getCPULocal()->currentThread->lastError; 32 | } 33 | } -------------------------------------------------------------------------------- /src/oboskrnl/export.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef __INTELLISENSE__ 4 | # define OBOS_WEAK __attribute__((weak)) 5 | #else 6 | # define OBOS_WEAK 7 | #endif 8 | #ifdef OBOS_DRIVER 9 | # ifndef __INTELLISENSE__ 10 | # define OBOS_EXPORT __attribute__((weak)) 11 | # else 12 | # define OBOS_EXPORT 13 | # endif 14 | #elif defined(OBOS_KERNEL) 15 | # define OBOS_EXPORT 16 | #else 17 | # define OBOS_EXPORT 18 | #endif -------------------------------------------------------------------------------- /src/oboskrnl/int.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | typedef uint8_t byte; 7 | #ifdef __cplusplus 8 | template 9 | using ptr = T*; 10 | #endif 11 | #ifdef __INTELLISENSE__ 12 | // It doesn't matter what the type actually is for intellisense. 13 | // This is only so intellisense gets out of my way. 14 | using __uint128_t = uint64_t; 15 | #endif -------------------------------------------------------------------------------- /src/oboskrnl/klog.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/klog.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #ifdef OBOS_DEBUG 14 | #define OBOS_ASSERTP(expr, msg, ...) if (!(expr)) { obos::logger::panic(nullptr, "Function %s, File %s, Line %d: Assertion failed, \"%s\". " msg "\n", __func__, __FILE__, __LINE__, #expr __VA_ARGS__); } 15 | #define OBOS_ASSERT(expr, msg, ...) if (!(expr)) { obos::logger::error("Function %s, File %s, Line %d: Assertion failed, \"%s\". " msg "\n", __func__, __FILE__, __LINE__, #expr __VA_ARGS__); } 16 | #else 17 | #define OBOS_ASSERTP(expr, msg, ...) 18 | #define OBOS_ASSERT(expr, msg, ...) 19 | #endif 20 | 21 | namespace obos 22 | { 23 | namespace logger 24 | { 25 | enum 26 | { 27 | GREY = 0xD3D3D3, 28 | GREEN = 0x03D12B, 29 | BLUE = 0x566F84, 30 | YELLOW = 0xffcc00, 31 | ERROR_RED = 0xcc3300, 32 | PANIC_RED = 0xac1616, 33 | }; 34 | 35 | OBOS_EXPORT size_t printf(const char* format, ...); 36 | OBOS_EXPORT size_t vprintf(const char* format, va_list list); 37 | OBOS_EXPORT size_t vsprintf(char* dest, const char* format, va_list list); 38 | OBOS_EXPORT size_t sprintf(char* dest, const char* format, ...); 39 | 40 | constexpr const char* DEBUG_PREFIX_MESSAGE = "[Debug] "; 41 | constexpr const char* LOG_PREFIX_MESSAGE = "[Log] "; 42 | constexpr const char* INFO_PREFIX_MESSAGE = "[Log] "; 43 | constexpr const char* WARNING_PREFIX_MESSAGE = "[Warning] "; 44 | constexpr const char* ERROR_PREFIX_MESSAGE = "[Error] "; 45 | 46 | OBOS_EXPORT size_t debug(const char* format, ...); 47 | OBOS_EXPORT size_t log(const char* format, ...); 48 | OBOS_EXPORT size_t info(const char* format, ...); 49 | OBOS_EXPORT size_t warning(const char* format, ...); 50 | OBOS_EXPORT size_t error(const char* format, ...); 51 | OBOS_EXPORT [[noreturn]] void panic(void* stackTraceParameter, const char* format, ...); 52 | OBOS_EXPORT [[noreturn]] void panicVariadic(void* stackTraceParameter, const char* format, va_list list); 53 | 54 | OBOS_EXPORT void stackTrace(void* stackTraceParameter); 55 | void dumpAddr(uint32_t* addr); 56 | } 57 | } -------------------------------------------------------------------------------- /src/oboskrnl/memory_manipulation.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/memory_manipulation.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace obos 14 | { 15 | namespace utils 16 | { 17 | OBOS_EXPORT uint32_t* dwMemcpy(uint32_t* dest, const uint32_t* src, size_t countDwords); 18 | OBOS_EXPORT uint32_t* dwMemset(uint32_t* dest, uint32_t src, size_t countDwords); 19 | OBOS_EXPORT void* memzero(void* block, size_t size); 20 | OBOS_EXPORT void* memcpy(void* dest, const void* src, size_t size); 21 | OBOS_EXPORT bool memcmp(const void* blk1, const void* blk2, size_t size); 22 | OBOS_EXPORT bool memcmp(const void* blk1, uint32_t val, size_t size); 23 | OBOS_EXPORT // Returns one less than the actual index of the character 24 | OBOS_EXPORT size_t strCountToChar(const char* string, char ch, bool stopAtZero = true); 25 | OBOS_EXPORT size_t strlen(const char* string); 26 | OBOS_EXPORT bool strcmp(const char* str1, const char* str2); 27 | } 28 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/arch.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/multitasking/arch.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | // This file defines all platform-specific functions/structures that a port of the kernel to get the scheduler to work. 10 | 11 | #include 12 | #include 13 | 14 | #if defined(__x86_64__) || defined(_WIN64) 15 | #include 16 | #endif 17 | 18 | extern "C" void idleTask(); 19 | 20 | namespace obos 21 | { 22 | #ifndef ALLOCATORS_VMM_VMM_H_INCLUDED 23 | namespace memory 24 | { 25 | class VirtualAllocator; 26 | } 27 | #endif 28 | namespace thread 29 | { 30 | void switchToThreadImpl(taskSwitchInfo* info, struct Thread* thread); 31 | bool callBlockCallbackOnThread(taskSwitchInfo* info, bool(*callback)(void* thread, void* userdata), void* par1, void* par2); 32 | void setupThreadContext(taskSwitchInfo* info, void* stackInfo, uintptr_t entry, uintptr_t userdata, size_t stackSize, memory::VirtualAllocator* vallocator, void* asProc); 33 | void freeThreadStackInfo(void* stackInfo, memory::VirtualAllocator* vallocator); 34 | void setupTimerInterrupt(); 35 | 36 | OBOS_EXPORT uintptr_t stopTimer(); 37 | OBOS_EXPORT void startTimer(uintptr_t); 38 | 39 | OBOS_EXPORT void callScheduler(bool allCores); 40 | 41 | void* getCurrentCpuLocalPtr(); 42 | // For any kernel/driver developers, this does nothing but send the other cores to a trampoline. 43 | // It DOES NOT undo the action of StopCPUs() 44 | bool StartCPUs(); 45 | OBOS_EXPORT void StopCPUs(bool includingSelf); 46 | 47 | bool inSchedulerFunction(struct Thread* thr); 48 | } 49 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/cpu_local.h: -------------------------------------------------------------------------------- 1 | /* 2 | multitasking/cpu_local.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace obos 16 | { 17 | namespace thread 18 | { 19 | struct cpu_local 20 | { 21 | Thread::StackInfo startup_stack{}; 22 | volatile Thread* currentThread = nullptr; 23 | volatile bool schedulerLock = false; 24 | uint32_t cpuId = 0; 25 | bool initialized = false; 26 | Thread::StackInfo temp_stack{}; 27 | cpu_local_arch arch_specific{}; 28 | bool isBSP = false; 29 | Thread* idleThread = nullptr; 30 | }; 31 | extern cpu_local* g_cpuInfo; 32 | extern size_t g_nCPUs; 33 | OBOS_EXPORT cpu_local* GetCurrentCpuLocalPtr(); 34 | } 35 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/locks/mutex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | multitasking/locks/mutex.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | 19 | extern obos::locks::Mutex g_allocatorMutex; 20 | 21 | #ifdef __INTELLISENSE__ 22 | template 23 | bool __atomic_compare_exchange_n(type* ptr, type* expected, type desired, bool weak, int success_memorder, int failure_memorder); 24 | #endif 25 | 26 | namespace obos 27 | { 28 | namespace thread 29 | { 30 | extern locks::Mutex g_coreGlobalSchedulerLock; 31 | } 32 | namespace locks 33 | { 34 | bool Mutex::Lock(uint64_t timeout, bool block) 35 | { 36 | if (!block && Locked()) 37 | { 38 | if (this != &thread::g_coreGlobalSchedulerLock) 39 | SetLastError(OBOS_ERROR_MUTEX_LOCKED); 40 | return false; 41 | } 42 | // Compare m_locked with zero, and if it is zero, then set it to true and return true, otherwise return false and keep m_locked intact. 43 | uint64_t wakeupTime = thread::g_timerTicks + timeout; 44 | if (timeout == 0) 45 | wakeupTime = 0xffffffffffffffff /* UINT64_MAX */; 46 | const bool expected = false; 47 | if (m_locked) 48 | { 49 | if (m_canUseMultitasking && thread::g_initialized) 50 | { 51 | thread::Thread* currentThread = (thread::Thread*)thread::GetCurrentCpuLocalPtr()->currentThread; 52 | currentThread->blockCallback.callback = [](thread::Thread* thr, void* udata)->bool 53 | { 54 | Mutex* _this = (Mutex*)udata; 55 | return _this->m_locked || _this->m_wake || thread::g_timerTicks < thr->wakeUpTime; 56 | }; 57 | currentThread->blockCallback.userdata = this; 58 | currentThread->wakeUpTime = wakeupTime; 59 | currentThread->status = thread::THREAD_STATUS_CAN_RUN | thread::THREAD_STATUS_BLOCKED; 60 | thread::callScheduler(false); 61 | } 62 | else 63 | { 64 | while (m_locked && !m_wake && thread::g_timerTicks < wakeupTime); 65 | } 66 | } 67 | while ((__atomic_compare_exchange_n(&m_locked, (bool*)&expected, true, false, 0, 0) || m_wake) || thread::g_timerTicks >= wakeupTime); 68 | if (thread::g_timerTicks >= wakeupTime) 69 | { 70 | SetLastError(OBOS_ERROR_TIMEOUT); 71 | return false; 72 | } 73 | if (thread::g_initialized && m_canUseMultitasking) 74 | m_ownerThread = (thread::Thread*)thread::GetCurrentCpuLocalPtr()->currentThread; 75 | return true; 76 | } 77 | bool Mutex::Unlock() 78 | { 79 | if (thread::g_initialized && m_canUseMultitasking) 80 | { 81 | if (thread::GetCurrentCpuLocalPtr()->currentThread != m_ownerThread) 82 | { 83 | SetLastError(OBOS_ERROR_ACCESS_DENIED); 84 | return false; 85 | } 86 | } 87 | atomic_clear(&m_locked); 88 | m_ownerThread = nullptr; 89 | return true; 90 | } 91 | bool Mutex::Locked() const 92 | { 93 | return atomic_test(&m_locked); 94 | } 95 | Mutex::~Mutex() 96 | { 97 | atomic_set(&m_wake); 98 | thread::callScheduler(false); 99 | m_ownerThread = nullptr; 100 | atomic_clear(&m_locked); 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/locks/mutex.h: -------------------------------------------------------------------------------- 1 | /* 2 | multitasking/locks/mutex.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace obos 15 | { 16 | #ifndef MULTIASKING_THREAD_H_INCLUDED 17 | namespace thread 18 | { 19 | struct Thread; 20 | } 21 | #endif 22 | namespace locks 23 | { 24 | class Mutex final 25 | { 26 | public: 27 | OBOS_EXPORT Mutex() : m_canUseMultitasking{ true }, m_initialized{ true } {}; 28 | OBOS_EXPORT Mutex(bool canUseMultitasking) : m_canUseMultitasking{ canUseMultitasking }, m_initialized{ true } {}; 29 | 30 | /// 31 | /// Locks the mutex. 32 | /// 33 | /// How long to block for, only effective if blockWithScheduler == true. 34 | /// Whether to block if the lock is locked, or to abort. 35 | /// Whether the mutex could be locked, otherwise false. If the function returned false, use GetLastError. 36 | OBOS_EXPORT bool Lock(uint64_t timeout = 0, bool block = true); 37 | /// 38 | /// Unlocks the mutex. 39 | /// 40 | /// Whether the mutex could be unlocked, otherwise false. If the function returned false, use GetLastError. 41 | OBOS_EXPORT bool Unlock(); 42 | 43 | /// 44 | /// Returns whether the mutex is locked. 45 | /// 46 | /// Whether the mutex is locked.. 47 | OBOS_EXPORT bool Locked() const; 48 | 49 | OBOS_EXPORT bool IsInitialized() const { return m_initialized; } 50 | 51 | OBOS_EXPORT void CanUseMultitasking(bool val) { m_canUseMultitasking = val; }; 52 | OBOS_EXPORT bool CanUseMultitasking() const { return m_canUseMultitasking; }; 53 | 54 | OBOS_EXPORT ~Mutex(); 55 | 56 | [[nodiscard]] void* operator new(size_t ) 57 | { 58 | return ImplSlabAllocate(ObjectTypes::Mutex); 59 | } 60 | void operator delete(void* ptr) 61 | { 62 | ImplSlabFree(ObjectTypes::Mutex, ptr); 63 | } 64 | void* operator new[](size_t sz) 65 | { 66 | return ImplSlabAllocate(ObjectTypes::Mutex, sz / sizeof(Mutex)); 67 | } 68 | void operator delete[](void* ptr, size_t sz) 69 | { 70 | ImplSlabFree(ObjectTypes::Mutex, ptr, sz / sizeof(Mutex)); 71 | } 72 | [[nodiscard]] void* operator new(size_t, void* ptr) noexcept { return ptr; } 73 | [[nodiscard]] void* operator new[](size_t, void* ptr) noexcept { return ptr; } 74 | void operator delete(void*, void*) noexcept {} 75 | void operator delete[](void*, void*) noexcept {} 76 | private: 77 | bool m_wake; 78 | bool m_locked; 79 | bool m_canUseMultitasking = true; 80 | bool m_initialized; 81 | thread::Thread* m_ownerThread; 82 | }; 83 | 84 | struct SafeMutex final 85 | { 86 | public: 87 | SafeMutex() = delete; 88 | SafeMutex(Mutex* obj) 89 | :m_obj{obj} 90 | {} 91 | SafeMutex(const SafeMutex&) = default; 92 | SafeMutex& operator=(const SafeMutex&) = default; 93 | SafeMutex(SafeMutex&&) = default; 94 | SafeMutex& operator=(SafeMutex&&) = default; 95 | 96 | bool Lock(uint64_t timeout = 0, bool block = true) 97 | { 98 | if (!m_obj) 99 | return false; 100 | return m_obj->Lock(timeout, block); 101 | } 102 | bool Unlock() 103 | { 104 | if (!m_obj) 105 | return false; 106 | return m_obj->Unlock(); 107 | } 108 | 109 | bool Locked() const 110 | { 111 | if (!m_obj) 112 | return false; 113 | return m_obj->Locked(); 114 | } 115 | 116 | Mutex* Get() const 117 | { 118 | return m_obj; 119 | } 120 | 121 | ~SafeMutex() 122 | { 123 | Unlock(); 124 | } 125 | private: 126 | Mutex* m_obj = nullptr; 127 | }; 128 | } 129 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/process/arch.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/process/arch.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | #if defined(__x86_64__) || defined(_WIN64) 14 | #include 15 | #endif 16 | 17 | namespace obos 18 | { 19 | namespace process 20 | { 21 | void setupContextInfo(procContextInfo* info); 22 | // Don't free the process' virtual address space, as that's done with virtual allocator in TerminateProcess. 23 | void freeProcessContext(procContextInfo* info); 24 | void switchToProcessContext(procContextInfo* info); 25 | 26 | // Makes the thread be at "function" with the current cpu's temporary stack, and passes par1 and par2 to the function. 27 | [[noreturn]] void putThreadAtFunctionWithCPUTempStack(thread::Thread* thread, void* function, void* par1, void* par2); 28 | } 29 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/process/process.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/process/process.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #define MULTIASKING_PROCESS_PROCESS_H_INCLUDED 22 | 23 | namespace obos 24 | { 25 | namespace process 26 | { 27 | enum 28 | { 29 | PROCESS_MAGIC_NUMBER = 0xCA44C071 30 | }; 31 | struct Process 32 | { 33 | Process() = default; 34 | struct ProcessList 35 | { 36 | Process *head, *tail; 37 | size_t size; 38 | }; 39 | uint32_t pid; 40 | uint32_t exitCode = 0; 41 | thread::Thread::ThreadList threads; 42 | uint32_t magicNumber = PROCESS_MAGIC_NUMBER; 43 | Process* parent; 44 | ProcessList children; 45 | Console* console; 46 | bool isUsermode; 47 | procContextInfo context; 48 | Process* prev; 49 | Process* next; 50 | Process* prev_child; 51 | Process* next_child; 52 | memory::VirtualAllocator vallocator{ this }; 53 | void(*signal_table[SIGMAX])(); 54 | void* operator new(size_t ) 55 | { 56 | return ImplSlabAllocate(ObjectTypes::Process); 57 | } 58 | void operator delete(void* ptr) 59 | { 60 | ImplSlabFree(ObjectTypes::Process, ptr); 61 | } 62 | void* operator new[](size_t sz) 63 | { 64 | return ImplSlabAllocate(ObjectTypes::Process, sz / sizeof(Process)); 65 | } 66 | void operator delete[](void* ptr, size_t sz) 67 | { 68 | ImplSlabFree(ObjectTypes::Process, ptr, sz / sizeof(Process)); 69 | } 70 | [[nodiscard]] void* operator new(size_t, void* ptr) noexcept { return ptr; } 71 | [[nodiscard]] void* operator new[](size_t, void* ptr) noexcept { return ptr; } 72 | void operator delete(void*, void*) noexcept {} 73 | void operator delete[](void*, void*) noexcept {} 74 | }; 75 | extern Process::ProcessList g_processes; 76 | Process* CreateProcess(bool isUsermode); 77 | // If process is the current thread's process, this function will not return. 78 | bool TerminateProcess(Process* process, bool isCurrentProcess = false); 79 | bool GracefullyTerminateProcess(Process* process); 80 | } 81 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/process/signals.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/multitasking/process/signals.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace obos 12 | { 13 | namespace process 14 | { 15 | // See documentation/signals.md for documentation on these signals. 16 | enum signals 17 | { 18 | SIGPF, 19 | SIGPM, 20 | SIGOF, 21 | SIGME, 22 | SIGDG, 23 | SIGTIME, 24 | SIGTERM, 25 | SIGINT, 26 | SIGUDOC, 27 | SIGUEXC, 28 | 29 | SIGMAX = SIGUEXC, 30 | INVALID_SIGNAL, 31 | }; 32 | 33 | bool CallSignal(thread::Thread* on, signals sig); 34 | bool CallSignalOrTerminate(thread::Thread* on, signals sig); 35 | } 36 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/process/x86_64/loader/elf.h: -------------------------------------------------------------------------------- 1 | /* 2 | multitasking/process/x86_64/loader/elf.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace obos 14 | { 15 | namespace process 16 | { 17 | namespace loader 18 | { 19 | /// 20 | /// Loads the elf file at 'startAddress' 21 | /// 22 | /// The file's data. 23 | /// The file size. 24 | /// A reference to a variable to store the entry point in. 25 | /// A reference to a variable to store the base address in. 26 | /// Whether to allocate and copy any of the program header data. 27 | /// An error code. 28 | uint32_t LoadElfFile(const byte* startAddress, size_t size, uintptr_t& entry, uintptr_t& baseAddress, memory::VirtualAllocator& allocator, bool lazyLoad = false); 29 | uint32_t CheckElfFile(const byte* startAddress, size_t size, bool setLastError = false); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/process/x86_64/procInfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/process/x86_64/procInfo.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | namespace obos 31 | { 32 | extern void SetIST(void* rsp); 33 | extern void SetTSSStack(void* rsp); 34 | namespace memory 35 | { 36 | extern uintptr_t s_pageDirectoryPhys; 37 | } 38 | namespace process 39 | { 40 | void setupContextInfo(procContextInfo* info) 41 | { 42 | uintptr_t flags = saveFlagsAndCLI(); 43 | info->cr3 = (void*)memory::allocatePhysicalPage(); 44 | uintptr_t* newPageMap = memory::mapPageTable((uintptr_t*)info->cr3); 45 | utils::memzero(newPageMap, 4096); 46 | uintptr_t* pageMap = memory::mapPageTable((uintptr_t*)memory::getCurrentPageMap()); 47 | for (size_t pml4I = memory::PageMap::addressToIndex(0xffff'8000'0000'0000, 3); pml4I < 512; pml4I++) 48 | newPageMap[pml4I] = pageMap[pml4I]; 49 | restorePreviousInterruptStatus(flags); 50 | } 51 | void freeProcessContext(procContextInfo* info) 52 | { 53 | //memory::freePhysicalPage((uintptr_t)info->cr3); 54 | for (auto iter = info->handleTable.begin(); iter; iter++) 55 | { 56 | auto &hnd_val = *(*iter).value; 57 | switch (hnd_val.second) 58 | { 59 | case obos::syscalls::ProcessHandleType::FILE_HANDLE: 60 | delete (vfs::FileHandle*)hnd_val.first; 61 | break; 62 | case obos::syscalls::ProcessHandleType::DRIVE_HANDLE: 63 | delete (vfs::DriveHandle*)hnd_val.first; 64 | break; 65 | case obos::syscalls::ProcessHandleType::THREAD_HANDLE: 66 | delete (thread::ThreadHandle*)hnd_val.first; 67 | break; 68 | case obos::syscalls::ProcessHandleType::VALLOCATOR_HANDLE: 69 | delete (memory::VirtualAllocator*)hnd_val.first; 70 | break; 71 | case obos::syscalls::ProcessHandleType::DIRECTORY_ITERATOR_HANDLE: 72 | delete (vfs::DirectoryIterator*)hnd_val.first; 73 | break; 74 | default: 75 | break; 76 | } 77 | 78 | } 79 | info->handleTable.erase(); 80 | } 81 | void switchToProcessContext(procContextInfo* info) 82 | { 83 | memory::PageMap* cr3 = (memory::PageMap*)info->cr3; 84 | thread::cpu_local* _info = thread::GetCurrentCpuLocalPtr(); 85 | SetIST((byte*)_info->temp_stack.addr + _info->temp_stack.size); 86 | SetTSSStack((byte*)_info->temp_stack.addr + _info->temp_stack.size); 87 | cr3->switchToThis(); // Warning: May page fault because of the stack being unmapped in the other process' context. 88 | } 89 | 90 | void putThreadAtFunctionWithCPUTempStack(thread::Thread *thread, void *function, void *par1, void *par2) 91 | { 92 | auto cpu_local = thread::GetCurrentCpuLocalPtr(); 93 | uintptr_t rsp = (uintptr_t)cpu_local->temp_stack.addr + cpu_local->temp_stack.size; 94 | thread->context.frame.rip = (uintptr_t)function; 95 | thread->context.frame.rdi = (uintptr_t)par1; 96 | thread->context.frame.rsi = (uintptr_t)par2; 97 | thread->context.frame.rsp = rsp; 98 | thread->context.frame.cs = 0x08; 99 | thread->context.frame.ss = 0x10; 100 | thread->context.frame.ds = 0x10; 101 | thread->context.frame.rflags = getEflags(); 102 | thread::switchToThreadImpl(&thread->context, thread); 103 | // Should never get hit, as switchToThreadImpl on x86_64 is [[noreturn]]. 104 | while(1); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/process/x86_64/procInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/process/x86_64/procInfo.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace obos 16 | { 17 | namespace process 18 | { 19 | struct procContextInfo 20 | { 21 | void* cr3; 22 | // Controls ownership of 'handleTable' and 'nextHandleValue'. 23 | locks::Mutex handleTableLock; 24 | utils::Hashmap handleTable; 25 | syscalls::user_handle nextHandleValue; 26 | struct virtuallyMappedRegionNode 27 | { 28 | void* base; 29 | void* addr; 30 | void* dirent; 31 | size_t off, size; 32 | // Whether dirent is a DirectoryEntry* (true) or a PartitionEntry* (false). 33 | // The former option is used for memory mapped files. 34 | // The latter option is used for swap space. 35 | bool isDirent; 36 | }; 37 | static bool vmapEquals(void* const &_left, void* const &_right) 38 | { 39 | uintptr_t left = (uintptr_t)_left, 40 | right = (uintptr_t)_right; 41 | return (left & ~0xfff) == (right & ~0xfff); 42 | } 43 | utils::Hashmap memoryMappedFiles; 44 | }; 45 | } 46 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/scheduler.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/multitasking/scheduler.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace obos 13 | { 14 | namespace thread 15 | { 16 | extern Thread::ThreadList g_priorityLists[4]; 17 | extern bool g_initialized; 18 | extern OBOS_EXPORT uint64_t g_schedulerFrequency; 19 | extern OBOS_EXPORT uint64_t g_timerTicks; 20 | extern uint32_t g_nextTid; 21 | void InitializeScheduler(); 22 | } 23 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/multitasking/thread.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #define MULTIASKING_THREAD_H_INCLUDED 15 | 16 | #if defined(_GNUC_) 17 | #define OBOS_ALIGN(n) __attribute__((aligned(n)) 18 | #else 19 | #define OBOS_ALIGN(n) 20 | #endif 21 | 22 | namespace obos 23 | { 24 | namespace thread 25 | { 26 | enum thrStatus 27 | { 28 | THREAD_STATUS_DEAD = 0x01, 29 | THREAD_STATUS_CAN_RUN = 0x02, 30 | THREAD_STATUS_BLOCKED = 0x04, 31 | THREAD_STATUS_PAUSED = 0x08, 32 | THREAD_STATUS_CLEAR_TIME_SLICE_INDEX = 0x10, 33 | THREAD_STATUS_RUNNING = 0x20, 34 | }; 35 | enum thrFlags 36 | { 37 | THREAD_FLAGS_IN_SIGNAL = 0x01, 38 | THREAD_FLAGS_SINGLE_STEPPING = 0x02, 39 | THREAD_FLAGS_CALLING_BLOCK_CALLBACK = 0x04, 40 | THREAD_FLAGS_IS_EXITING_PROCESS = 0x08, 41 | }; 42 | enum thrPriority 43 | { 44 | THREAD_PRIORITY_IDLE = 1, 45 | THREAD_PRIORITY_LOW = 2, 46 | THREAD_PRIORITY_NORMAL = 4, 47 | THREAD_PRIORITY_HIGH = 8, 48 | }; 49 | struct Thread 50 | { 51 | struct ThreadList 52 | { 53 | Thread* head; 54 | Thread* tail; 55 | size_t size; 56 | ThreadList* nextThreadList; 57 | ThreadList* prevThreadList; 58 | size_t iterations; // How many times the scheduler has run the list since the last iterations clear. 59 | bool lock; 60 | }; 61 | uint32_t tid; 62 | uint32_t status; 63 | uint32_t priority; 64 | uint32_t timeSliceIndex; 65 | uint32_t exitCode; 66 | uint64_t lastTimePreempted; 67 | uint64_t wakeUpTime; 68 | uint32_t lastError; 69 | uint32_t references; 70 | struct 71 | { 72 | bool(*callback)(Thread* _this, void* userData); 73 | void* userdata; 74 | } blockCallback; 75 | struct StackInfo 76 | { 77 | void* addr; 78 | size_t size; 79 | } stackInfo; 80 | void* owner; // a Process* 81 | Thread* next_run; // The next in the priority list. 82 | Thread* prev_run; // The previous in the priority list. 83 | Thread* next_list; // The next in the process thread list. 84 | Thread* prev_list; // The previous in the process thread list. 85 | ThreadList* priorityList; // A pointer to the priority list. 86 | ThreadList* threadList; // A pointer to the process' thread list. 87 | taskSwitchInfo context; 88 | // If a bit is set, the cpu corresponding to that bit number can run the thread. 89 | // This limits the kernel to 128 cores. 90 | __uint128_t affinity, ogAffinity; 91 | uint32_t flags; 92 | void* driverIdentity = nullptr; 93 | void* operator new(size_t) 94 | { 95 | return ImplSlabAllocate(ObjectTypes::Thread); 96 | } 97 | void operator delete(void* ptr) 98 | { 99 | ImplSlabFree(ObjectTypes::Thread, ptr); 100 | } 101 | void* operator new[](size_t sz) 102 | { 103 | return ImplSlabAllocate(ObjectTypes::Thread, sz / sizeof(Thread)); 104 | } 105 | void operator delete[](void* ptr, size_t sz) 106 | { 107 | ImplSlabFree(ObjectTypes::Thread, ptr, sz / sizeof(Thread)); 108 | } 109 | [[nodiscard]] void* operator new(size_t, void* ptr) noexcept { return ptr; } 110 | [[nodiscard]] void* operator new[](size_t, void* ptr) noexcept { return ptr; } 111 | void operator delete(void*, void*) noexcept {} 112 | void operator delete[](void*, void*) noexcept {} 113 | } OBOS_ALIGN(4); 114 | }; 115 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/x86_64/arch_structs.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/multitasking/x86_64/taskSwitchInfo.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace obos 14 | { 15 | namespace thread 16 | { 17 | struct taskSwitchInfo 18 | { 19 | void* cr3; 20 | void* tssStackBottom; 21 | interrupt_frame frame; 22 | alignas(0x10) uint8_t fpuState[512]; 23 | void* syscallStackBottom; 24 | uintptr_t fsbase, gsbase; 25 | }; 26 | struct cpu_local_arch 27 | { 28 | struct tssEntry 29 | { 30 | uint32_t resv1; 31 | uint64_t rsp0; 32 | uint64_t rsp1; 33 | uint64_t rsp2; 34 | uint64_t resv2; 35 | uint64_t ist0; 36 | uint8_t unused1[0x36]; 37 | uint16_t iopb; 38 | } __attribute__((packed)); 39 | uint64_t gdt[7]; 40 | tssEntry tss; 41 | struct gdtptr 42 | { 43 | uint16_t limit; 44 | uint64_t base; 45 | } __attribute__((packed)); 46 | gdtptr gdtPtr; 47 | uintptr_t mapPageTableBase; 48 | }; 49 | } 50 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/x86_64/calibrate_timer.asm: -------------------------------------------------------------------------------- 1 | ; oboskrnl/multitasking/x86_64/calibrate_timer.asm 2 | ; 3 | ; Copyright (c) 2023-2024 Omar Berrow 4 | 5 | [BITS 64] 6 | 7 | global calibrateTimer 8 | extern _ZN4obos15g_localAPICAddrE 9 | extern _ZN4obos10g_HPETAddrE 10 | ; extern _ZN4obos24RegisterInterruptHandlerEhPFvPNS_15interrupt_frameEE 11 | extern _ZN4obos6thread13configureHPETEm 12 | 13 | segment .bss 14 | 15 | segment .text 16 | 17 | calibrateTimer: 18 | push rbp 19 | mov rbp, rsp 20 | push rbx 21 | push r15 22 | push r14 23 | 24 | mov r15, [_ZN4obos15g_localAPICAddrE] 25 | mov r14, [_ZN4obos10g_HPETAddrE] 26 | 27 | xor rax,rax 28 | xor rcx,rcx 29 | cpuid 30 | test rax, 0x15 31 | jnz .noCpuid21 32 | 33 | .hasCpuid21: 34 | xor rcx, rcx 35 | cpuid 36 | mov rax, rcx 37 | xor rdx,rdx 38 | div rdi 39 | jmp .finish 40 | 41 | .noCpuid21: 42 | pushfq 43 | cli 44 | 45 | mov dword [r15+0x3E0], 13 ; divisorConfig 46 | 47 | call _ZN4obos6thread13configureHPETEm 48 | 49 | mov dword [r15+0x380], 0xffffffff ; initialCount 50 | add r14, 0xf0 ; mainCounterValue 51 | .loop: 52 | mov r11, [r14] 53 | cmp r11, rax 54 | jng .loop 55 | mov r11d, [r15+0x390] ; currentCount 56 | mov rax, 0xffffffff 57 | sub rax, r11 58 | mov dword [r15+0x380], 0 ; initialCount 59 | 60 | popfq 61 | 62 | .finish: 63 | pop r14 64 | pop r15 65 | pop rbx 66 | leave 67 | ret -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/x86_64/calibrate_timer_old.asm: -------------------------------------------------------------------------------- 1 | ; oboskrnl/multitasking/x86_64/calibrate_timer.asm 2 | ; 3 | ; Copyright (c) 2023-2024 Omar Berrow 4 | 5 | [BITS 64] 6 | 7 | global calibrateTimer 8 | extern _ZN4obos15g_localAPICAddrE 9 | extern _ZN4obos24RegisterInterruptHandlerEhPFvPNS_15interrupt_frameEE 10 | 11 | segment .bss 12 | 13 | currentCount: 14 | resd 1 15 | 16 | segment .text 17 | 18 | pitInterrupt: 19 | mov r15, [_ZN4obos15g_localAPICAddrE] 20 | mov edx, dword [r15+0x390] ; currentCount 21 | mov dword [r15+0x380], 0 ; initialCount 22 | mov [currentCount], edx 23 | mov al, 0x20 24 | out 0x20, al 25 | mov al, 0xff 26 | out 0x21, al 27 | out 0xA1, al 28 | ret 29 | 30 | ; getPITCount: 31 | ; push rbp 32 | ; mov rbp, rsp 33 | ; pop rbx 34 | ; 35 | ; mov al, 0b1110010 36 | ; mov dx, 0x43 37 | ; out dx,al 38 | ; 39 | ; xor rbx,rbx 40 | ; 41 | ; in al, 0x40 42 | ; mov bl, al 43 | ; in al, 0x40 44 | ; mov bh, al 45 | ; mov rax, rbx 46 | ; 47 | ; pop rbx 48 | ; leave 49 | ; ret 50 | 51 | calibrateTimer: 52 | push rbp 53 | mov rbp, rsp 54 | push rbx 55 | push r15 56 | 57 | mov r15, [_ZN4obos15g_localAPICAddrE] 58 | 59 | xor rax,rax 60 | xor rcx,rcx 61 | cpuid 62 | test rax, 0x15 63 | jnz .noCpuid21 64 | 65 | .hasCpuid21: 66 | xor rcx, rcx 67 | cpuid 68 | mov rax, rcx 69 | xor rdx,rdx 70 | div rdi 71 | jmp .finish 72 | 73 | .noCpuid21: 74 | pushfq 75 | cli 76 | 77 | ; mov dword [r15+0xb0], 0 ; EOI 78 | ; mov dword [r15+0x3E0], 13 ; divisorConfig 79 | ; 80 | ; mov al, 0x30 81 | ; out 0x43, al 82 | ; mov rax, 1193182 83 | ; xor rdx,rdx 84 | ; div rdi 85 | ; push rdi 86 | ; mov rdi, rax 87 | ; mov al, dl 88 | ; out 0x40, al 89 | ; mov al, dh 90 | ; out 0x40, al 91 | ; pop rdi 92 | ; 93 | ; push rdi 94 | ; mov rdi, 0x20 95 | ; mov rsi, pitInterrupt 96 | ; call _ZN4obos24RegisterInterruptHandlerEhPFvPNS_15interrupt_frameEE 97 | ; pop rdi 98 | ; 99 | ; .retry: 100 | ; 101 | ; mov al, 0xfe 102 | ; out 0x21, al 103 | ; mov al, 0xff 104 | ; out 0xA1, al 105 | ; 106 | ; mov dword [r15+0x380], 0xffffffff ; initialCount 107 | ; 108 | ; ; It's pretty hard to wait for the interrupt when interrupts are disabled... 109 | ; sti 110 | ; ; Wait for the interrupt. 111 | ; hlt 112 | ; cli 113 | ; 114 | ; ; pitInterrupt disables the pic 115 | ; ; mov al, 0xff 116 | ; ; out 0x21, al 117 | ; ; out 0xA1, al 118 | ; 119 | ; mov edx, dword [currentCount] ; currentCount 120 | ; test edx, 0xffffffff 121 | ; je .retry 122 | ; mov rax, 0xffffffff 123 | ; sub rax, rdx 124 | 125 | 126 | 127 | popfq 128 | 129 | .finish: 130 | pop r15 131 | pop rbx 132 | leave 133 | ret -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/x86_64/setupFrameInfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/multitasking/x86_64/setupFrameInfo.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include 24 | 25 | #define BIT(n) (1<isUsermode : false; 44 | 45 | info->frame.cs = isUsermodeProgram ? 0x23 : 0x08; 46 | info->frame.ss = isUsermodeProgram ? 0x1b : 0x10; 47 | info->frame.ds = info->frame.ss; 48 | 49 | info->frame.rip = entry; 50 | info->frame.rdi = userdata; 51 | info->frame.rbp = 0; 52 | info->fsbase = 0; 53 | info->gsbase = isUsermodeProgram ? 0 : rdmsr(0xC0000101 /* GS.Base */); 54 | if (entry != (uintptr_t)kmain_common) 55 | { 56 | uintptr_t stackProtFlags = memory::PROT_NO_COW_ON_ALLOCATE; 57 | if (isUsermodeProgram) 58 | stackProtFlags |= memory::PROT_USER_MODE_ACCESS; 59 | info->frame.rsp = ((uintptr_t)vallocator->VirtualAlloc(nullptr, stackSize, stackProtFlags)) + (stackSize - 8); 60 | } 61 | else 62 | { 63 | info->frame.rsp = ((uintptr_t)vallocator->VirtualAlloc((void*)0xFFFFFFFF90000000, stackSize, memory::PROT_NO_COW_ON_ALLOCATE)) + (stackSize - 8); 64 | // Find the initrd driver. 65 | byte* procExecutable = nullptr; 66 | size_t procExecutableSize = 0; 67 | for (size_t i = 0; i < module_request.response->module_count; i++) 68 | { 69 | if (utils::strcmp(module_request.response->modules[i]->path, "/obos/initrdDriver")) 70 | { 71 | procExecutable = (byte*)module_request.response->modules[i]->address; 72 | procExecutableSize = module_request.response->modules[i]->size; 73 | break; 74 | } 75 | } 76 | info->frame.rdi = (uintptr_t)utils::memcpy(new byte[procExecutableSize + 1], procExecutable, procExecutableSize); 77 | info->frame.rsi = (uintptr_t)procExecutableSize; 78 | } 79 | info->frame.rflags.setBit(x86_64_flags::RFLAGS_INTERRUPT_ENABLE | x86_64_flags::RFLAGS_CPUID); 80 | asm volatile("fninit; fxsave (%0)" : : "r"(info->fpuState) : "memory"); 81 | 82 | Thread::StackInfo* stackInfo = (Thread::StackInfo*)_stackInfo; 83 | 84 | stackInfo->size = stackSize; 85 | stackInfo->addr = reinterpret_cast(info->frame.rsp - (stackSize - 8)); 86 | 87 | if(isUsermodeProgram) 88 | info->frame.rflags.setBit(x86_64_flags::RFLAGS_IOPL_3); 89 | 90 | info->cr3 = _proc ? _proc->context.cr3 : memory::getCurrentPageMap(); 91 | info->tssStackBottom = vallocator->VirtualAlloc(nullptr, 0x4000, memory::PROT_NO_COW_ON_ALLOCATE); 92 | if (isUsermodeProgram) 93 | info->syscallStackBottom = vallocator->VirtualAlloc(nullptr, 0x4000, memory::PROT_NO_COW_ON_ALLOCATE); // Do not set user mode, or you'll page fault (SMAP). 94 | } 95 | void freeThreadStackInfo(void* _stackInfo, memory::VirtualAllocator* vallocator) 96 | { 97 | Thread::StackInfo* stackInfo = (Thread::StackInfo*)_stackInfo; 98 | vallocator->VirtualFree(stackInfo->addr, stackInfo->size); 99 | stackInfo->addr = nullptr; 100 | stackInfo->size = 0; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /src/oboskrnl/multitasking/x86_64/taskSwitchImpl.asm: -------------------------------------------------------------------------------- 1 | ; oboskrnl/multitasking/x86_64/taskSwitchImpl.asm 2 | ; 3 | ; Copyright (c) 2023-2024 Omar Berrow 4 | 5 | [BITS 64] 6 | 7 | segment .bss 8 | 9 | segment .text 10 | 11 | %macro popaq 0 12 | pop rbp 13 | add rsp, 8 14 | pop r15 15 | pop r14 16 | pop r13 17 | pop r12 18 | pop r11 19 | pop r10 20 | pop r9 21 | pop r8 22 | pop rdi 23 | pop rsi 24 | add rsp, 8 25 | pop rbx 26 | pop rdx 27 | pop rcx 28 | pop rax 29 | %endmacro 30 | 31 | extern _ZN4obos11SetTSSStackEPv 32 | extern _ZN4obos6SetISTEPv 33 | extern _ZN4obos7SendEOIEv 34 | extern _ZN4obos5rdmsrEj 35 | 36 | global _ZN4obos6thread18switchToThreadImplEPNS0_14taskSwitchInfoEPNS0_6ThreadE 37 | global _ZN4obos6thread25callBlockCallbackOnThreadEPNS0_14taskSwitchInfoEPFbPvS3_ES3_S3_ 38 | global idleTask 39 | global _callScheduler 40 | 41 | segment .sched_text 42 | _ZN4obos6thread18switchToThreadImplEPNS0_14taskSwitchInfoEPNS0_6ThreadE: 43 | ; rsp = GetCurrentCpuLocalPtr()->temp_stack.addr + GetCurrentCpuLocalPtr()->temp_stack.size 44 | ; This code is commented because _callScheduler switches to the cpu temporary stack, so another switch would be unneccessary. 45 | ; push rdi 46 | ; mov rdi, 0xC0000101 47 | ; call _ZN4obos5rdmsrEj 48 | ; pop rdi 49 | ; add rax, 0x28 50 | ; mov rsp, [rax] 51 | ; add rsp, qword [rax+8] 52 | 53 | call _ZN4obos7SendEOIEv 54 | 55 | cli 56 | 57 | ; FSBase 58 | mov eax, [rsi+0x378] 59 | mov edx, [rsi+0x37c] 60 | mov ecx, 0xC0000100 61 | wrmsr 62 | 63 | cmp qword [rdi+0x138], 0x10 64 | jne .not_kernel_mode 65 | cmp qword [rdi+0x120], 0x8 66 | jne .not_kernel_mode 67 | ; GSBase 68 | mov eax, [rsi+0x380] 69 | mov edx, [rsi+0x384] 70 | mov ecx, 0xC0000101 71 | wrmsr 72 | .not_kernel_mode: 73 | 74 | mov rax, [rdi] 75 | mov cr3, rax 76 | push rdi 77 | mov rdi, [rdi+8] 78 | add rdi, 4096*4 79 | mov rbx, rdi 80 | call _ZN4obos11SetTSSStackEPv 81 | mov rdi, rbx 82 | call _ZN4obos6SetISTEPv 83 | pop rdi 84 | add rdi, 16 85 | 86 | ; Restore all registers in the interrupt frame 87 | ; mov rax, [rdi] 88 | ; mov ss, ax 89 | 90 | add rdi, 8 91 | 92 | mov rsp, rdi 93 | popaq 94 | 95 | add rsp, 16 96 | 97 | fxrstor [rsp+0x30] 98 | 99 | iretq 100 | _ZN4obos6thread25callBlockCallbackOnThreadEPNS0_14taskSwitchInfoEPFbPvS3_ES3_S3_: 101 | push rbp 102 | mov rbp, rsp 103 | 104 | ; rsp = context->tssStackBottom + 0x4000 105 | mov rsp, [rdi+8] 106 | add rsp, 0x4000 107 | 108 | mov r10, cr3 109 | 110 | mov rax, [rdi] 111 | mov cr3, rax 112 | 113 | push r10 114 | 115 | mov r8, rsi 116 | 117 | mov rdi, rdx 118 | mov rsi, rcx 119 | call r8 120 | 121 | pop r11 122 | mov cr3, r11 123 | 124 | mov rsp, rbp 125 | pop rbp 126 | ret 127 | extern _ZN4obos6thread8scheduleEv 128 | _callScheduler: 129 | push rbp 130 | mov rbp, rsp 131 | 132 | ; Load the temporary stack. 133 | mov rdi, 0xC0000101 134 | call _ZN4obos5rdmsrEj 135 | add rax, 0x28 136 | mov rsp, [rax] 137 | add rsp, qword [rax+8] 138 | call _ZN4obos6thread8scheduleEv 139 | 140 | mov rsp, rbp 141 | pop rbp 142 | ret 143 | segment .text 144 | global _ZN4obos6thread21getCurrentCpuLocalPtrEv 145 | _ZN4obos6thread21getCurrentCpuLocalPtrEv: 146 | mov rcx, 0xC0000101 147 | rdmsr 148 | shl rdx, 32 149 | or rax, rdx 150 | ret 151 | idleTask: 152 | sti 153 | hlt 154 | jmp idleTask -------------------------------------------------------------------------------- /src/oboskrnl/new: -------------------------------------------------------------------------------- 1 | /* 2 | new 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | [[nodiscard]] void* operator new(size_t, void* ptr) noexcept; 12 | [[nodiscard]] void* operator new[](size_t, void* ptr) noexcept; 13 | void operator delete(void*, void*) noexcept; 14 | void operator delete[](void*, void*) noexcept; -------------------------------------------------------------------------------- /src/oboskrnl/utils/pair.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/pair.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | namespace obos 10 | { 11 | namespace utils 12 | { 13 | template 14 | struct pair 15 | { 16 | T1 first; 17 | T2 second; 18 | bool operator==(const pair& other) const 19 | { 20 | return 21 | first == other.first && 22 | second == other.second; 23 | } 24 | }; 25 | 26 | } 27 | } -------------------------------------------------------------------------------- /src/oboskrnl/utils/stack.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/utils/stack.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace obos 14 | { 15 | namespace utils 16 | { 17 | // These stack classes are FIFO (first in, first out) 18 | 19 | // Recommended for bigger objects. 20 | template 21 | class ListStack 22 | { 23 | public: 24 | ListStack() = default; 25 | 26 | void push(const T& obj) 27 | { 28 | StackNode* newNode = new StackNode{ obj }; 29 | newNode->next = m_head; 30 | m_head = newNode; 31 | m_nNodes++; 32 | } 33 | void pop() 34 | { 35 | if (!m_head) 36 | return; 37 | m_nNodes--; 38 | auto next = m_head->next; 39 | delete m_head; 40 | m_head = next; 41 | } 42 | T& get() 43 | { 44 | if (!m_head) 45 | return *(T*)nullptr; 46 | return m_head->data; 47 | } 48 | 49 | void erase() 50 | { 51 | while (m_head) 52 | { 53 | m_nNodes--; 54 | auto next = m_head->next; 55 | delete m_head; 56 | m_head = next; 57 | } 58 | } 59 | 60 | ~ListStack() 61 | { 62 | erase(); 63 | } 64 | private: 65 | struct StackNode 66 | { 67 | StackNode() = delete; 68 | StackNode(const T& obj) 69 | : data{obj} {} 70 | T data; 71 | StackNode *next; 72 | }; 73 | StackNode *m_head = nullptr; 74 | size_t m_nNodes = 0; 75 | }; 76 | // Recommended for smaller objects. 77 | template 78 | class ArrayStack 79 | { 80 | public: 81 | ArrayStack() = default; 82 | 83 | void push(const T& obj) 84 | { 85 | m_data = (T*)krealloc(m_data, m_szData++); 86 | m_currentOffset = m_szData; 87 | new (&m_data[m_currentOffset]) T{ obj }; 88 | } 89 | void pop() 90 | { 91 | if (!m_szData) 92 | return; 93 | ::operator delete(m_data, m_data + m_currentOffset); 94 | m_data = (T*)krealloc(m_data, m_szData--); 95 | m_currentOffset = m_szData; 96 | } 97 | T& get() 98 | { 99 | return m_data[m_currentOffset]; 100 | } 101 | 102 | void erase() 103 | { 104 | if (!m_szData) 105 | return; 106 | while (m_currentOffset--) 107 | ::operator delete(m_data, m_data + m_currentOffset); 108 | kfree(m_data); 109 | m_szData = 0; 110 | } 111 | 112 | ~ArrayStack() 113 | { 114 | erase(); 115 | } 116 | private: 117 | T* m_data; 118 | size_t m_currentOffset = 0; 119 | size_t m_szData = 0; 120 | }; 121 | } 122 | } -------------------------------------------------------------------------------- /src/oboskrnl/utils/string.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/string.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | namespace obos 14 | { 15 | namespace utils 16 | { 17 | String::String() 18 | { 19 | m_len = 0; 20 | m_str = new char[m_len + 1]; 21 | } 22 | String::String(const char* str) 23 | { 24 | initialize(str); 25 | } 26 | String::String(const char* str, size_t len) 27 | { 28 | initialize(str, len); 29 | } 30 | 31 | String& String::operator=(const char* str) 32 | { 33 | initialize(str); 34 | return *this; 35 | } 36 | 37 | String::String(const String& other) 38 | { 39 | if (!other.m_len) 40 | return; 41 | initialize(other.m_str, other.m_len); 42 | } 43 | String& String::operator=(const String& other) 44 | { 45 | initialize(other.m_str, other.m_len); 46 | return *this; 47 | } 48 | String::String(String&& other) 49 | { 50 | initialize(other.m_str, other.m_len); 51 | delete[] other.m_str; 52 | other.m_str = nullptr; 53 | other.m_len = 0; 54 | } 55 | String& String::operator=(String&& other) 56 | { 57 | initialize(other.m_str, other.m_len); 58 | delete[] other.m_str; 59 | other.m_str = nullptr; 60 | other.m_len = 0; 61 | return *this; 62 | } 63 | 64 | void String::initialize(const char* str) 65 | { 66 | initialize(str, strlen(str)); 67 | } 68 | void String::initialize(const char* str, size_t len) 69 | { 70 | if (m_str) 71 | { 72 | delete[] m_str; 73 | m_str = nullptr; 74 | m_len = 0; 75 | } 76 | m_len = len; 77 | m_str = (char*)utils::memcpy(new char[m_len + 1], str, m_len); 78 | } 79 | 80 | void String::push_back(char ch) 81 | { 82 | m_str = (char*)krealloc(m_str, ++m_len); 83 | m_str[m_len - 1] = ch; 84 | m_str[m_len] = 0; 85 | } 86 | void String::pop_back() 87 | { 88 | if (!m_len) 89 | return; 90 | m_str = (char*)krealloc(m_str, --m_len); 91 | } 92 | 93 | char& String::front() const 94 | { 95 | if (!m_len) 96 | return *(char*)nullptr; 97 | return m_str[0]; 98 | } 99 | char& String::back() const 100 | { 101 | if (!m_len) 102 | return *(char*)nullptr; 103 | return m_str[m_len - 1]; 104 | } 105 | char &String::at(size_t i) const 106 | { 107 | if (i >= m_len) 108 | return *(char*)nullptr; 109 | return m_str[i]; 110 | } 111 | void String::append(const char* str) 112 | { 113 | append(str, strlen(str)); 114 | } 115 | void String::append(const char* str, size_t len) 116 | { 117 | m_str = (char*)krealloc(m_str, m_len + len); 118 | utils::memcpy(m_str + m_len, str, len); 119 | m_len += len; 120 | } 121 | size_t String::resize(size_t newSize) 122 | { 123 | if (!newSize) 124 | { 125 | kfree(m_str); 126 | m_str = nullptr; 127 | } 128 | else 129 | { 130 | m_str = (char*)krealloc(m_str, newSize); 131 | } 132 | size_t ret = m_len; 133 | m_len = newSize; 134 | return ret; 135 | } 136 | void String::erase() 137 | { 138 | resize(0); 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /src/oboskrnl/utils/string.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/string.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | namespace obos 13 | { 14 | namespace utils 15 | { 16 | class String final 17 | { 18 | public: 19 | OBOS_EXPORT String(); 20 | OBOS_EXPORT String(const char* str); 21 | OBOS_EXPORT String(const char* str, size_t len); 22 | 23 | OBOS_EXPORT String& operator=(const char* str); 24 | 25 | OBOS_EXPORT String(const String& other); 26 | OBOS_EXPORT String& operator=(const String& other); 27 | OBOS_EXPORT String(String&& other); 28 | OBOS_EXPORT String& operator=(String&& other); 29 | 30 | OBOS_EXPORT void initialize(const char* str); 31 | OBOS_EXPORT void initialize(const char* str, size_t len); 32 | 33 | OBOS_EXPORT void push_back(char ch); 34 | OBOS_EXPORT void pop_back(); 35 | 36 | OBOS_EXPORT char& front() const; 37 | OBOS_EXPORT char& back() const; 38 | 39 | OBOS_EXPORT char& at(size_t i) const; 40 | OBOS_EXPORT char& operator[](size_t i) const { return at(i); } 41 | 42 | OBOS_EXPORT void append(const char* str); 43 | OBOS_EXPORT void append(const char* str, size_t len); 44 | 45 | OBOS_EXPORT char* data() const { return m_str; } 46 | 47 | OBOS_EXPORT size_t length() const { return m_len; } 48 | OBOS_EXPORT size_t resize(size_t newSize); 49 | 50 | OBOS_EXPORT void erase(); 51 | 52 | ~String() 53 | { 54 | delete[] m_str; 55 | m_len = 0; 56 | } 57 | private: 58 | char* m_str = nullptr; 59 | size_t m_len = 0; 60 | }; 61 | } 62 | } -------------------------------------------------------------------------------- /src/oboskrnl/vfs/devManip/driveHandle.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/vfs/devManip/driveHandle.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace obos 15 | { 16 | namespace vfs 17 | { 18 | class DriveHandle 19 | { 20 | public: 21 | enum OpenOptions 22 | { 23 | OPTIONS_DEFAULT = 0, 24 | OPTIONS_READ_ONLY = 1, 25 | }; 26 | enum Flags 27 | { 28 | FLAGS_CAN_WRITE = 1, 29 | FLAGS_CLOSED = 2, 30 | }; 31 | public: 32 | OBOS_EXPORT DriveHandle() = default; 33 | 34 | // Path format: Dd[Pp]:/ 35 | // With 'd' being the drive id, and 'p' being the partition id (optional). 36 | // Everything after the initial path is ignored. 37 | // Examples: 38 | // To open drive 0, raw: D0:/ 39 | // To open drive 0, partition 1, D0P1:/ 40 | OBOS_EXPORT bool OpenDrive(const char* path, OpenOptions options = OPTIONS_DEFAULT); 41 | 42 | OBOS_EXPORT bool ReadSectors(void* buff, size_t* nSectorsRead, uoff_t lbaOffset, size_t nSectors) const; 43 | OBOS_EXPORT bool WriteSectors(const void* buff, size_t* nSectorsWritten, uoff_t lbaOffset, size_t nSectors); 44 | 45 | OBOS_EXPORT uint32_t GetDriveId() const; 46 | OBOS_EXPORT uint32_t GetPartitionId() const; 47 | 48 | OBOS_EXPORT bool QueryInfo(size_t* nSectors, size_t* bytesPerSector, size_t* nPartitions) const; 49 | OBOS_EXPORT bool QueryPartitionInfo(size_t* nSectors, uint64_t* lbaOffset, const char** filesystemName) const; 50 | 51 | OBOS_EXPORT bool Close(); 52 | 53 | bool IsPartitionHandle() const { return m_driveNode != m_node; } 54 | 55 | // Do not use these next two functions unless you know what you're doing. 56 | 57 | void* GetNode() const { return m_node; } 58 | void* GetDriveNode() const { return m_driveNode; } 59 | 60 | OBOS_EXPORT ~DriveHandle() { if (m_node && !(m_flags & FLAGS_CLOSED)) Close(); } 61 | private: 62 | void* m_node = nullptr; 63 | void* m_handleNode = nullptr; 64 | void* m_driveNode = nullptr; 65 | void* m_driveHandleNode = nullptr; 66 | Flags m_flags = FLAGS_CLOSED; 67 | }; 68 | } 69 | } -------------------------------------------------------------------------------- /src/oboskrnl/vfs/devManip/driveIterator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/vfs/devManip/driveIterator.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | namespace obos 15 | { 16 | namespace vfs 17 | { 18 | DriveIterator::DriveIterator() 19 | { 20 | m_currentNode = g_drives.head; 21 | } 22 | 23 | const char* DriveIterator::operator*() 24 | { 25 | if (!m_currentNode) 26 | return nullptr; 27 | DriveEntry* entry = (DriveEntry*)m_currentNode; 28 | uint32_t driveId = entry->driveId; 29 | size_t szPath = logger::sprintf(nullptr, "D%d:/", driveId); 30 | char* path = new char[szPath + 1]; 31 | utils::memzero(path, szPath + 1); 32 | logger::sprintf(path, "D%d:/", driveId); 33 | return path; 34 | } 35 | const char* DriveIterator::operator++() 36 | { 37 | m_currentNode = ((DriveEntry*)m_currentNode)->next; 38 | return operator*(); 39 | } 40 | const char* DriveIterator::operator++(int) 41 | { 42 | auto ret = operator*(); 43 | m_currentNode = ((DriveEntry*)m_currentNode)->next; 44 | return ret; 45 | } 46 | const char* DriveIterator::operator--() 47 | { 48 | m_currentNode = ((DriveEntry*)m_currentNode)->prev; 49 | return operator*(); 50 | } 51 | const char* DriveIterator::operator--(int) 52 | { 53 | auto ret = operator*(); 54 | m_currentNode = ((DriveEntry*)m_currentNode)->prev; 55 | return ret; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/oboskrnl/vfs/devManip/driveIterator.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/vfs/devManip/driveIterator.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | namespace obos 13 | { 14 | namespace vfs 15 | { 16 | class DriveIterator final 17 | { 18 | public: 19 | OBOS_EXPORT DriveIterator(); 20 | 21 | // These functions return the path of the next/current element. The lifetime of the path is controlled by the user. 22 | // Allocated with the kernel's new. 23 | 24 | OBOS_EXPORT const char* operator*(); 25 | OBOS_EXPORT const char* operator++(); 26 | OBOS_EXPORT const char* operator++(int); 27 | OBOS_EXPORT const char* operator--(); 28 | OBOS_EXPORT const char* operator--(int); 29 | 30 | OBOS_EXPORT operator bool() { return m_currentNode; } 31 | 32 | ~DriveIterator() {} 33 | private: 34 | void* m_currentNode = nullptr; 35 | }; 36 | } 37 | } -------------------------------------------------------------------------------- /src/oboskrnl/vfs/devManip/memcpy.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/vfs/devManip/memcpy.h 3 | 4 | Copyright (c) 2023 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | // This function contains a memcpy variant that uses vector instructions that are architecture-specific, 10 | // but is optional to support. 11 | 12 | #include 13 | #include 14 | 15 | namespace obos 16 | { 17 | namespace vfs 18 | { 19 | // If 64 byte vectorized instructions aren't supported on the platform, then you can use smaller 20 | // chunks. 21 | // Any states must be saved, as this could be used in syscalls, and the usermode process might 22 | // expect those states to be preserved. 23 | OBOS_WEAK void *_VectorizedMemcpy64B(void* dest, const void* src, size_t nBlocks); 24 | } 25 | } -------------------------------------------------------------------------------- /src/oboskrnl/vfs/devManip/sectorStore.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024 Omar Berrow 3 | 4 | oboskrnl/vfs/devManip/sectorStore.h 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | // Contains a class to store drive sectors that uses the VMM instead of the kernel heap to allocate memory. 14 | // This will help prevent immense heap fragmentation. 15 | 16 | namespace obos 17 | { 18 | namespace utils 19 | { 20 | class SectorStorage 21 | { 22 | public: 23 | SectorStorage() = default; 24 | SectorStorage(size_t size) 25 | { 26 | if (!size) 27 | return; 28 | m_ptr = (byte*)m_valloc.VirtualAlloc(nullptr, size, 0); 29 | m_realSize = size; 30 | const size_t pageSize = m_valloc.GetPageSize(); 31 | m_size = size / pageSize * pageSize + ((size % pageSize) != 0); 32 | } 33 | 34 | // This pointer should not be stored, as it's subject to relocation. 35 | // If you end up storing it, after every resize, update that pointer. 36 | byte* data() const { return m_ptr; } 37 | void resize(size_t size) 38 | { 39 | if (!size) 40 | { 41 | free(); 42 | return; 43 | } 44 | const size_t pageSize = m_valloc.GetPageSize(); 45 | size_t oldSize = m_size; 46 | size = m_size = size / pageSize * pageSize + ((size % pageSize) != 0); 47 | m_realSize = size; 48 | if (size == oldSize) 49 | return; 50 | if (size < oldSize) 51 | { 52 | // Truncuate the block. 53 | m_valloc.VirtualFree(m_ptr + size, oldSize - size); 54 | return; 55 | } 56 | // Grow the block. 57 | // Find out if there's more space after the block. 58 | const size_t nPages = size / pageSize + ((size % pageSize) != 0); 59 | uintptr_t* flags = new uintptr_t[nPages]; 60 | m_valloc.VirtualGetProtection(m_ptr + oldSize, oldSize - size, flags); 61 | size_t i = 0; 62 | for (; i < nPages && !(flags[i] & memory::PROT_IS_PRESENT); i++); 63 | if (flags[i] & memory::PROT_IS_PRESENT) 64 | { 65 | // If so, allocate the pages after m_ptr 66 | m_valloc.VirtualAlloc(m_ptr + oldSize, oldSize - size, 0); 67 | return; 68 | } 69 | // If not, relocate m_ptr. 70 | _ImplRelocatePtr(oldSize); 71 | } 72 | 73 | void free() 74 | { 75 | if (m_ptr) 76 | m_valloc.VirtualFree(m_ptr, m_size); 77 | m_ptr = nullptr; 78 | m_size = 0; 79 | m_realSize = 0; 80 | } 81 | size_t length() const { return m_realSize; } 82 | size_t length_pageSizeAligned() const { return m_size; } 83 | 84 | ~SectorStorage() 85 | { 86 | free(); 87 | } 88 | private: 89 | void _ImplRelocatePtr(size_t oldSize) 90 | { 91 | void* newPtr = m_valloc.VirtualAlloc(nullptr, m_size, 0); 92 | utils::memcpy(newPtr, m_ptr, m_size); 93 | m_valloc.VirtualFree(m_ptr, oldSize); 94 | m_ptr = (byte*)newPtr; 95 | } 96 | byte* m_ptr = nullptr; 97 | size_t m_size = 0; 98 | size_t m_realSize = 0; 99 | memory::VirtualAllocator m_valloc{ nullptr }; 100 | }; 101 | } 102 | } -------------------------------------------------------------------------------- /src/oboskrnl/vfs/fileManip/directoryIterator.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/vfs/fileManip/directoryIterator.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace obos 12 | { 13 | namespace vfs 14 | { 15 | class DirectoryIterator final 16 | { 17 | public: 18 | DirectoryIterator() = default; 19 | 20 | bool OpenAt(const char* directory); 21 | 22 | // These functions return the path of the next/current element. The lifetime of the path is controlled by the user. 23 | // Allocated with the kernel's new. 24 | 25 | const char* operator*(); 26 | const char* operator++(); 27 | const char* operator++(int); 28 | const char* operator--(); 29 | const char* operator--(int); 30 | 31 | operator bool() { return m_currentNode; } 32 | 33 | bool Close(); 34 | 35 | ~DirectoryIterator() 36 | { 37 | if (m_currentNode && m_directoryNode) 38 | Close(); 39 | } 40 | 41 | // This can be a mount point, or a directory entry. Beware! 42 | void* GetDirectoryNode() const { return m_directoryNode; } 43 | // This should only ever be a directory entry. 44 | void* GetCurrentNode() const { return m_currentNode; } 45 | private: 46 | void* m_directoryNode = nullptr; 47 | void* m_currentNode = nullptr; 48 | }; 49 | } 50 | } -------------------------------------------------------------------------------- /src/oboskrnl/vfs/mount/mount.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/vfs/mount/mount.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace obos 15 | { 16 | namespace vfs 17 | { 18 | extern utils::Vector g_mountPoints; 19 | /// 20 | /// Mounts a partition. You can mount a partition multiple times. 21 | /// 22 | /// The place to store the mount id where the partition was mounted. If this is 0xffffffff, the function will choose a mount point. 23 | /// The drive that contains the partition id to mount. 24 | /// The partition id to mount. 25 | /// Whether the initrd should be mounted at point or not. 26 | /// If an existing mount point is found, and this parameter is true, "point" will be set to the mount point, and the function will fail. 27 | /// 28 | /// Whether the function succeeded (true) or not (false) 29 | bool mount(uint32_t& point, uint32_t driveId, uint32_t partitionId, bool isInitrd = false, bool failIfPartitionHasMountPoint = false); 30 | /// 31 | /// Unmounts the mount point. This will invalidate any file handles. 32 | /// 33 | /// The mount point to unmount. 34 | /// Whether the function succeeded (true) or not (false) 35 | bool unmount(uint32_t point); 36 | 37 | /// 38 | /// Gets the partition id for the mount point. 39 | /// 40 | /// The mount point to query. 41 | /// UINT64_MAX on failure, otherwise the top 32-bits are the drive id, and the bottom 32-bits are the partition id 42 | uint64_t getPartitionIDForMountPoint(uint32_t mountPoint); 43 | 44 | /// 45 | /// Gets the mount points for a partition id. 46 | /// 47 | /// The drive that the partition is on. 48 | /// The partition id to find. 49 | /// A pointer to an array allocated by the function containing all the mount points that use partition id. 50 | void getMountPointsForPartitionID(uint32_t driveId, uint32_t partitionId, uint32_t** oMountPoints); 51 | } 52 | } -------------------------------------------------------------------------------- /src/oboskrnl/vfs/off_t.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/vfs/off_t.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace obos 12 | { 13 | namespace vfs 14 | { 15 | typedef int64_t off_t; 16 | typedef uint64_t uoff_t; 17 | } 18 | } -------------------------------------------------------------------------------- /src/oboskrnl/x86_64-utils/asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | oboskrnl/x86_64-utils/asm.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | namespace obos 13 | { 14 | OBOS_EXPORT void outb(uint16_t port, uint8_t data); 15 | OBOS_EXPORT void outw(uint16_t port, uint16_t data); 16 | OBOS_EXPORT void outd(uint16_t port, uint32_t data); 17 | OBOS_EXPORT uint8_t inb(uint16_t port); 18 | OBOS_EXPORT uint16_t inw(uint16_t port); 19 | OBOS_EXPORT uint32_t ind(uint16_t port); 20 | 21 | OBOS_EXPORT void cli(); 22 | OBOS_EXPORT void sti(); 23 | OBOS_EXPORT void hlt(); 24 | OBOS_EXPORT void setAC(); 25 | OBOS_EXPORT void clearAC(); 26 | 27 | OBOS_EXPORT void pause(); 28 | 29 | OBOS_EXPORT uintptr_t saveFlagsAndCLI(); 30 | OBOS_EXPORT void restorePreviousInterruptStatus(uintptr_t flags); 31 | 32 | OBOS_EXPORT void* getCR2(); 33 | OBOS_EXPORT uintptr_t getCR0(); 34 | OBOS_EXPORT uintptr_t getCR4(); 35 | OBOS_EXPORT void setCR4(uintptr_t val); 36 | OBOS_EXPORT uintptr_t getCR8(); 37 | OBOS_EXPORT void setCR8(uintptr_t _cr8); 38 | OBOS_EXPORT uintptr_t getEFER(); 39 | OBOS_EXPORT void invlpg(uintptr_t addr); 40 | 41 | OBOS_EXPORT uint64_t rdmsr(uint32_t addr); 42 | OBOS_EXPORT void wrmsr(uint32_t addr, uint64_t val); 43 | 44 | OBOS_EXPORT void __cpuid__(uint64_t initialEax, uint64_t initialEcx, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx); 45 | 46 | OBOS_EXPORT uint64_t rdtsc(); 47 | 48 | OBOS_EXPORT // If *val1 == nullptr, val1 = val2. 49 | OBOS_EXPORT void set_if_zero(uint64_t* val1, uint64_t val2); 50 | 51 | OBOS_EXPORT [[noreturn]] void haltCPU(); // cli(); while(1) hlt(); 52 | OBOS_EXPORT [[noreturn]] void infiniteHLT(); // sti(); while(1) hlt(); 53 | 54 | OBOS_EXPORT void int1(); 55 | OBOS_EXPORT void int3(); 56 | 57 | OBOS_EXPORT uint64_t bswap64(uint64_t val); 58 | OBOS_EXPORT uint32_t bswap32(uint32_t val); 59 | 60 | OBOS_EXPORT uint64_t getDR0(void); 61 | OBOS_EXPORT uint64_t getDR1(void); 62 | OBOS_EXPORT uint64_t getDR2(void); 63 | OBOS_EXPORT uint64_t getDR3(void); 64 | OBOS_EXPORT uint64_t getDR6(void); 65 | OBOS_EXPORT uint64_t getDR7(void); 66 | 67 | OBOS_EXPORT uint64_t getEflags(void); 68 | 69 | OBOS_EXPORT void setDR0(uint64_t val); 70 | OBOS_EXPORT void setDR1(uint64_t val); 71 | OBOS_EXPORT void setDR2(uint64_t val); 72 | OBOS_EXPORT void setDR3(uint64_t val); 73 | OBOS_EXPORT void setDR6(uint64_t val); 74 | OBOS_EXPORT void setDR7(uint64_t val); 75 | 76 | OBOS_EXPORT void *getRBP(); 77 | 78 | OBOS_EXPORT uint8_t bsf(uint32_t bitfield); 79 | OBOS_EXPORT uint8_t bsf(uint64_t bitfield); 80 | OBOS_EXPORT uint8_t bsf(__uint128_t bitfield); 81 | OBOS_EXPORT uint8_t bsr(uint32_t bitfield); 82 | OBOS_EXPORT uint8_t bsr(uint64_t bitfield); 83 | OBOS_EXPORT uint8_t bsr(__uint128_t bitfield); 84 | } -------------------------------------------------------------------------------- /src/oboskrnl/x86_64-utils/memory_manipulation.asm: -------------------------------------------------------------------------------- 1 | [BITS 64] 2 | 3 | global _ZN4obos5utils6strlenEPKc 4 | global _ZN4obos5utils14strCountToCharEPKccb 5 | global _ZN4obos5utils7memzeroEPvm 6 | global _ZN4obos5utils8dwMemcpyEPjPKjm 7 | global _ZN4obos5utils8dwMemsetEPjjm 8 | global _ZN4obos5utils6memcmpEPKvS2_m 9 | global _ZN4obos5utils6memcmpEPKvjm 10 | global _ZN4obos5utils6memcpyEPvPKvm 11 | global _ZN4obos3vfs20_VectorizedMemcpy64BEPvPKvm 12 | 13 | _ZN4obos5utils8dwMemcpyEPjPKjm: 14 | push rbp 15 | mov rbp, rsp 16 | 17 | xor rax, rax 18 | 19 | mov rax, rdi 20 | 21 | mov rcx, rdx 22 | rep movsd 23 | 24 | leave 25 | ret 26 | _ZN4obos5utils8dwMemsetEPjjm: 27 | push rdi 28 | mov rcx, rdx 29 | mov eax, esi 30 | rep stosd 31 | pop rax 32 | ret 33 | 34 | _ZN4obos5utils6memcpyEPvPKvm: 35 | push rbp 36 | mov rbp, rsp 37 | 38 | xor rax, rax 39 | 40 | mov rax, rdi 41 | 42 | mov rcx, rdx 43 | rep movsb 44 | 45 | leave 46 | ret 47 | 48 | _ZN4obos5utils7memzeroEPvm: 49 | push rbp 50 | mov rbp, rsp 51 | 52 | mov rcx, rsi 53 | 54 | push rdi 55 | 56 | xor rax,rax 57 | rep stosb 58 | 59 | .finish: 60 | 61 | pop rax 62 | 63 | leave 64 | ret 65 | 66 | _ZN4obos5utils6memcmpEPKvS2_m: 67 | push rbp 68 | mov rbp, rsp 69 | 70 | mov rcx, rdx 71 | test rcx,rcx 72 | jz .finish 73 | 74 | .loop: 75 | mov r8b, [rdi] 76 | mov r9b, [rsi] 77 | sub r8b, r9b 78 | jne .finish 79 | 80 | inc rdi 81 | inc rsi 82 | loop .loop 83 | 84 | .finish: 85 | 86 | test rcx, rcx 87 | setz al 88 | 89 | leave 90 | ret 91 | 92 | _ZN4obos5utils6memcmpEPKvjm: 93 | push rbp 94 | mov rbp, rsp 95 | 96 | mov rcx, rdx 97 | test rcx, rcx 98 | jz .finish 99 | 100 | .loop: 101 | mov r8b, byte [rdi] 102 | sub r8b, sil 103 | jne .finish 104 | 105 | inc rdi 106 | loop .loop 107 | 108 | .finish: 109 | 110 | test rcx,rcx 111 | setz al 112 | 113 | leave 114 | ret 115 | 116 | _ZN4obos5utils14strCountToCharEPKccb: 117 | push rbp 118 | mov rbp, rsp 119 | 120 | xor rax,rax 121 | 122 | not dl 123 | and dl, 0x1 124 | 125 | .loop: 126 | mov cl, [rdi+rax] 127 | inc rax 128 | 129 | cmp cl, dl 130 | jz .finished 131 | cmp cl,sil 132 | jne .loop 133 | .finished: 134 | 135 | dec rax 136 | 137 | leave 138 | ret 139 | 140 | _ZN4obos5utils6strlenEPKc: 141 | xor sil, sil 142 | xor dl, dl 143 | call _ZN4obos5utils14strCountToCharEPKccb 144 | ret 145 | _ZN4obos3vfs20_VectorizedMemcpy64BEPvPKvm: 146 | push rbp 147 | mov rbp, rsp 148 | 149 | push rdi 150 | 151 | mov rax, rdx 152 | xor rdx,rdx 153 | mov rcx, 64 154 | mul rcx 155 | mov rcx, rax 156 | rep movsb 157 | 158 | pop rdi 159 | 160 | mov rsp, rbp 161 | pop rbp 162 | ret -------------------------------------------------------------------------------- /src/programs/x86-64/common/syscall.asm: -------------------------------------------------------------------------------- 1 | ; This file is released to the public domain. 2 | ; Example syscall code for oboskrnl on x86-64 3 | ; Compile with nasm. 4 | 5 | [BITS 64] 6 | 7 | ; uintptr_t syscall(uint64_t syscall, void* args); 8 | global syscall 9 | 10 | extern main 11 | 12 | syscall: 13 | push rbp 14 | mov rbp, rsp 15 | push rbx 16 | push r12 17 | push r13 18 | push r14 19 | push r15 20 | 21 | mov rax, rdi 22 | mov rdi, rsi 23 | syscall 24 | 25 | pop r15 26 | pop r14 27 | pop r13 28 | pop r12 29 | pop rbx 30 | leave 31 | ret -------------------------------------------------------------------------------- /src/programs/x86-64/init/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # sample_programs/x86-64/testProgram/CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | add_executable(init "../common/syscall.asm" "main.cpp" "liballoc.cpp" "liballoc.h" "syscall.h" "stb_sprintf.h" "logger.h" "logger.cpp") 6 | 7 | target_compile_options(init 8 | PRIVATE $<$:-fno-stack-protector -fno-stack-check -fno-lto> 9 | PRIVATE $<$:-fno-use-cxa-atexit> 10 | PRIVATE $<$:-fno-rtti> 11 | PRIVATE $<$:-nostdlib> 12 | PRIVATE $<$:-fno-exceptions> 13 | PRIVATE $<$:-ffreestanding> 14 | PRIVATE $<$:-Wall> 15 | PRIVATE $<$:-Wextra> 16 | PRIVATE "${DEBUG_SYMBOLS_OPT}" 17 | ) 18 | set_property (TARGET init PROPERTY CXX_STANDARD 20) 19 | 20 | set_target_properties(init PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") 21 | 22 | target_link_options(init 23 | PRIVATE "-ffreestanding" 24 | PRIVATE "-nostdlib" 25 | ) 26 | 27 | add_dependencies(init oboskrnl) -------------------------------------------------------------------------------- /src/programs/x86-64/init/liballoc.h: -------------------------------------------------------------------------------- 1 | /* 2 | init/liballoc.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #ifdef __cplusplus 13 | extern "C" 14 | { 15 | #endif 16 | 17 | void* malloc(size_t amount); 18 | void* calloc(size_t nobj, size_t szObj); 19 | void* realloc(void* ptr, size_t newSize); 20 | void free(void* ptr); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | -------------------------------------------------------------------------------- /src/programs/x86-64/init/logger.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | programs/x86_64/init/logger.cpp 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #define STB_SPRINTF_MIN 1 12 | #define STB_SPRINTF_IMPLEMENTATION 13 | #include "stb_sprintf.h" 14 | 15 | #include "syscall.h" 16 | 17 | static char* consoleOutputCallback(const char* buf, void*, int len) 18 | { 19 | char ch[2] = {}; 20 | for (size_t i = 0; i < (size_t)len; i++) 21 | { 22 | ch[0] = buf[i]; 23 | ConsoleOutput(ch); 24 | } 25 | return (char*)buf; 26 | } 27 | size_t printf(const char* format, ...) 28 | { 29 | va_list list; 30 | va_start(list, format); 31 | char ch = 0; 32 | size_t ret = stbsp_vsprintfcb(consoleOutputCallback, nullptr, &ch, format, list); 33 | va_end(list); 34 | return ret; 35 | } 36 | size_t vprintf(const char* format, va_list list) 37 | { 38 | char ch = 0; 39 | return stbsp_vsprintfcb(consoleOutputCallback, nullptr, &ch, format, list); 40 | } -------------------------------------------------------------------------------- /src/programs/x86-64/init/logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | programs/x86_64/init/logger.h 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | size_t printf(const char* format, ...); 12 | size_t vprintf(const char* format, va_list list); -------------------------------------------------------------------------------- /src/programs/x86-64/init/new: -------------------------------------------------------------------------------- 1 | /* 2 | new 3 | 4 | Copyright (c) 2023-2024 Omar Berrow 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | [[nodiscard]] void* operator new(size_t, void* ptr) noexcept; 13 | [[nodiscard]] void* operator new[](size_t, void* ptr) noexcept; 14 | void operator delete(void*, void*) noexcept; 15 | void operator delete[](void*, void*) noexcept; -------------------------------------------------------------------------------- /src/programs/x86-64/testProgram/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # sample_programs/x86-64/testProgram/CMakeLists.txt 2 | 3 | # Copyright (c) 2023-2024 Omar Berrow 4 | 5 | add_executable(test_program "../common/syscall.asm" "main.cpp") 6 | 7 | target_compile_options(test_program 8 | PRIVATE $<$:-fno-stack-protector -fno-stack-check -fno-lto> 9 | PRIVATE $<$:-fno-use-cxa-atexit> 10 | PRIVATE $<$:-fno-rtti> 11 | PRIVATE $<$:-nostdlib> 12 | PRIVATE $<$:-fno-exceptions> 13 | PRIVATE $<$:-ffreestanding> 14 | PRIVATE $<$:-Wall> 15 | PRIVATE $<$:-Wextra> 16 | PRIVATE "${DEBUG_SYMBOLS_OPT}" 17 | ) 18 | set_property (TARGET test_program PROPERTY CXX_STANDARD 20) 19 | 20 | set_target_properties(test_program PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}") 21 | 22 | target_link_options(test_program 23 | PRIVATE "-ffreestanding" 24 | PRIVATE "-nostdlib" 25 | ) 26 | 27 | add_dependencies(test_program oboskrnl) -------------------------------------------------------------------------------- /src/scripts-toolchains/x86_64/linker.ld: -------------------------------------------------------------------------------- 1 | /* From https://github.com/limine-bootloader/limine-barebones */ 2 | 3 | OUTPUT_FORMAT(elf64-x86-64) 4 | OUTPUT_ARCH(i386:x86-64) 5 | 6 | ENTRY(_ZN4obos10arch_kmainEv) 7 | 8 | PHDRS 9 | { 10 | text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ 11 | rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ 12 | data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ 13 | dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */ 14 | } 15 | 16 | SECTIONS 17 | { 18 | . = 0xffffffff80000000; 19 | 20 | .text : { 21 | *(.text .text.*) 22 | _sched_text_start = .; 23 | *(.sched_text) 24 | _sched_text_end = .; 25 | } :text 26 | 27 | . += CONSTANT(MAXPAGESIZE); 28 | 29 | .rodata : { 30 | *(.rodata .rodata.*) 31 | } :rodata 32 | 33 | . += CONSTANT(MAXPAGESIZE); 34 | 35 | .data : { 36 | *(.data .data.*) 37 | } :data 38 | 39 | .dynamic : { 40 | *(.dynamic) 41 | } :data :dynamic 42 | 43 | .bss : { 44 | *(.bss .bss.*) 45 | *(COMMON) 46 | } :data 47 | 48 | /DISCARD/ : { 49 | *(.eh_frame) 50 | *(.note .note.*) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/scripts-toolchains/x86_64/toolchain.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME "Generic") 2 | set(CMAKE_SYSTEM_PROCESSOR "x86-64") 3 | 4 | find_program(HAS_CROSS_COMPILER "x86_64-elf-g++") 5 | if (NOT HAS_CROSS_COMPILER) 6 | message(FATAL_ERROR "No x86_64-elf cross compiler in the PATH!") 7 | endif() 8 | 9 | set(CMAKE_C_COMPILER "x86_64-elf-gcc") 10 | set(CMAKE_CXX_COMPILER "x86_64-elf-g++") 11 | set(CMAKE_ASM-ATT_COMPILER "x86_64-elf-gcc") 12 | set(CMAKE_ASM_NASM_COMPILER "nasm") 13 | set(CMAKE_C_COMPILER_WORKS true) 14 | set(CMAKE_CXX_COMPILER_WORKS true) 15 | set(CMAKE_ASM-ATT_COMPILER_WORKS true) 16 | set(CMAKE_ASM_NASM_COMPILER_WORKS true) 17 | 18 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 19 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 20 | 21 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 22 | 23 | set(CMAKE_ASM_NASM_OBJECT_FORMAT "elf64") 24 | 25 | execute_process(COMMAND x86_64-elf-gcc --print-file-name=libgcc.a OUTPUT_VARIABLE LIBGCC) 26 | 27 | string(STRIP "${LIBGCC}" LIBGCC) 28 | 29 | find_program(HAS_x86_64_elf_objcopy "x86_64-elf-objcopy") 30 | find_program(HAS_x86_64_elf_nm "x86_64-elf-nm") 31 | if (HAS_x86_64_elf_objcopy) 32 | set(OBJCOPY "x86_64-elf-objcopy") 33 | else() 34 | set(OBJCOPY "objcopy") 35 | endif() 36 | if (HAS_x86_64_elf_nm) 37 | set(NM "x86_64-elf-nm") 38 | else() 39 | set(NM "nm") 40 | endif() 41 | set(TARGET_COMPILE_OPTIONS_CPP -mno-red-zone -fno-omit-frame-pointer -mgeneral-regs-only -mcmodel=kernel) 42 | set(TARGET_DRIVER_COMPILE_OPTIONS_CPP -mno-red-zone -fno-omit-frame-pointer) 43 | set(TARGET_COMPILE_OPTIONS_C ${TARGET_COMPILE_OPTIONS_CPP}) 44 | set(TARGET_DRIVER_COMPILE_OPTIONS_C ${TARGET_DRIVER_COMPILE_OPTIONS_CPP}) 45 | set(TARGET_LINKER_OPTIONS -mcmodel=kernel) 46 | 47 | set (LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/src/scripts-toolchains/x86_64/linker.ld") 48 | set (oboskrnl_platformSpecificSources 49 | "boot/x86_64/kmain_arch.cpp" "x86_64-utils/memory_manipulation.asm" "x86_64-utils/asm.asm" "arch/x86_64/gdt.cpp" 50 | "arch/x86_64/gdt.asm" "arch/x86_64/idt.cpp" "arch/x86_64/idt.asm" "arch/x86_64/int_handlers.asm" 51 | "arch/x86_64/memory_manager/physical/allocatePhys.cpp" "arch/x86_64/irq/irq.cpp" "arch/x86_64/exception_handlers.cpp" "arch/x86_64/trace.cpp" 52 | "arch/x86_64/memory_manager/virtual/initialize.cpp" "arch/x86_64/memory_manager/virtual/allocate.cpp" "arch/x86_64/irq/timer.cpp" "multitasking/x86_64/taskSwitchImpl.asm" 53 | "multitasking/x86_64/setupFrameInfo.cpp" "multitasking/x86_64/scheduler_bootstrapper.cpp" "multitasking/process/x86_64/procInfo.cpp" "multitasking/process/x86_64/loader/elf.cpp" 54 | "driverInterface/x86_64/load.cpp" "multitasking/x86_64/calibrate_timer.asm" "arch/x86_64/stack_canary.cpp" "arch/x86_64/fpu.asm" 55 | "arch/x86_64/syscall/register.cpp" "arch/x86_64/sse.asm" "arch/x86_64/smp_start.cpp" "arch/x86_64/smp_trampoline.asm" 56 | "arch/x86_64/gdbstub/communicate.cpp" "arch/x86_64/gdbstub/stub.cpp" "arch/x86_64/signals.cpp" "driverInterface/x86_64/scan.cpp" 57 | "driverInterface/x86_64/enumerate_pci.cpp" "arch/x86_64/syscall/handle.cpp" "arch/x86_64/syscall/thread.cpp" "arch/x86_64/syscall/verify_pars.cpp" 58 | "arch/x86_64/syscall/vfs/file.cpp" "arch/x86_64/syscall/sconsole.cpp" "arch/x86_64/syscall/syscall_vmm.cpp" "arch/x86_64/syscall/vfs/disk.cpp" 59 | "arch/x86_64/syscall/sys_signals.cpp" "arch/x86_64/syscall/power_management.cpp" "arch/x86_64/syscall/vfs/dir.cpp" "arch/x86_64/memory_manager/virtual/internal.cpp" 60 | "arch/x86_64/memory_manager/virtual/mapFile.cpp" 61 | ) 62 | 63 | set (OBOS_ARCHITECTURE "x86_64") --------------------------------------------------------------------------------