From 2c51e4432ff3ba3c2223a1925ae640225c3b24fa Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 6 Aug 2023 04:53:14 +0300 Subject: [PATCH] Update kernel --- .vscode/c_boilerplates.code-snippets | 14 +- .vscode/c_cpp_properties.json | 3 + .vscode/launch.json | 78 +- .../amd64/Bootstrap/Multiboot/2/Multiboot.cpp | 4 +- .../DifferentiatedSystemDescriptionTable.cpp | 4 +- .../amd64/Memory/VirtualMemoryManager.cpp | 670 +-- Architecture/amd64/SystemCalls.cpp | 10 +- .../amd64/cpu/GlobalDescriptorTable.cpp | 432 +- Architecture/amd64/cpu/gdt.hpp | 432 +- .../i386/Memory/VirtualMemoryManager.cpp | 10 +- .../i386/cpu/GlobalDescriptorTable.cpp | 423 +- Architecture/i386/cpu/gdt.hpp | 330 +- Core/CPU.cpp | 23 +- Core/Crash/CrashHandler.cpp | 1955 ++++----- Core/Crash/Screens/Details.cpp | 10 +- Core/Crash/Screens/Main.cpp | 2 +- Core/Crash/Screens/Tasks.cpp | 20 +- Core/Crash/UserHandler.cpp | 6 +- Core/Debugger.cpp | 270 +- Core/Disk.cpp | 2 +- Core/Driver/Driver.cpp | 37 +- Core/Driver/DriverBinding/BindInput.cpp | 3 + Core/Driver/DriverBinding/BindInterrupt.cpp | 2 +- Core/Driver/DriverBinding/BindPCI.cpp | 2 +- Core/Driver/DriverBinding/BindProcess.cpp | 3 + Core/InterruptsManager.cpp | 328 +- Core/Lock.cpp | 306 +- .../Memory/HeapAllocators/Xalloc/XallocV1.cpp | 14 +- Core/Memory/Memory.cpp | 1349 +++--- Core/Memory/MemoryManager.cpp | 470 +- Core/Memory/PhysicalMemoryManager.cpp | 778 ++-- Core/Memory/ReserveEssentials.cpp | 97 +- Core/Memory/SmartHeap.cpp | 15 + Core/Power.cpp | 153 +- Core/Symbols.cpp | 398 +- Core/Time/HighPrecisionEventTimer.cpp | 51 +- Core/Time/TimeStampCounter.cpp | 12 +- Core/Time/Timer.cpp | 42 +- Core/UndefinedBehaviorSanitization.c | 112 +- ...iversalAsynchronousReceiverTransmitter.cpp | 216 +- Core/Video/Display.cpp | 703 +-- Core/Video/Font.cpp | 12 +- DAPI.hpp | 60 +- Execute/BinaryParse.cpp | 171 - Execute/Elf/ElfBaseLoad.cpp | 187 - Execute/Elf/ElfInterpreter.cpp | 155 - Execute/Elf/ElfLoader.cpp | 480 -- Execute/Elf/ElfParse.cpp | 340 -- Execute/Elf/ElfSharedObjects.cpp | 159 - Execute/Spawn.cpp | 99 - ExecutionLayer/BinaryParse.cpp | 115 + ExecutionLayer/Elf/ElfLoader.cpp | 791 ++++ ExecutionLayer/Elf/ElfParse.cpp | 203 + {Execute => ExecutionLayer}/Elf/ElfRel.cpp | 17 +- .../Elf/ParseFunctions/ELFGetDynamicTag.cpp | 22 +- .../Elf/ParseFunctions/ELFGetSections.cpp | 22 +- .../Elf/ParseFunctions/ELFGetSymbolType.cpp | 22 +- ExecutionLayer/Spawn.cpp | 161 + FileSystem/FS/ustar.cpp | 12 +- FileSystem/FileDescriptor.cpp | 434 ++ FileSystem/FileNode.cpp | 197 + FileSystem/Filesystem.cpp | 1270 +++--- FileSystem/Kernel_IO.cpp | 157 + GUI/GUITools.cpp | 218 - GUI/GraphicalUserInterface.cpp | 667 --- GUI/Icons.cpp | 253 -- GUI/WidgetEvents.cpp | 159 - GUI/Widgets.cpp | 141 - GUI/Window.cpp | 82 - GUI/WindowEvents.cpp | 137 - Kernel.cpp | 85 +- KernelConfig.cpp | 426 +- KernelShell/Commands/cat.cpp | 55 + KernelShell/Commands/cd.cpp | 46 + .../Commands/echo.cpp | 9 +- .../Commands/exit.cpp | 30 +- .../Commands/kill.cpp | 33 +- KernelShell/Commands/killall.cpp | 37 + KernelShell/Commands/ls.cpp | 57 + KernelShell/Commands/lsof.cpp | 35 + KernelShell/Commands/lspci.cpp | 41 + KernelShell/Commands/mem.cpp | 64 + KernelShell/Commands/ps.cpp | 33 + KernelShell/Commands/reboot.cpp | 32 + KernelShell/Commands/shutdown.cpp | 32 + KernelShell/Commands/top.cpp | 46 + KernelShell/Commands/uname.cpp | 65 + KernelShell/Commands/uptime.cpp | 51 + KernelShell/Commands/whoami.cpp | 29 + KernelShell/Shell.cpp | 422 ++ Tests/TestSyscalls.c => KernelShell/cmds.hpp | 51 +- KernelThread.cpp | 263 +- LICENSE | 10 +- Library/Bitmap.cpp | 44 +- Library/Convert.cpp | 109 +- Library/libstdc++/cxxabi.cpp | 44 +- Library/libstdc++/pbase_type_info.cpp | 3 + Library/libstdc++/pointer_type_info.cpp | 3 + Library/std/errno.cpp | 10 +- Library/std/mutex.cpp | 81 + Library/std/typeinfo.cpp | 5 + Makefile | 20 +- .../AHCI/AdvancedHostControllerInterface.cpp | 2 +- Modules/ATA/AdvancedTechnologyAttachment.cpp | 2 +- Modules/AdvancedMicroDevices/PCNET.cpp | 2 +- Modules/AudioCodec97/AudioCodec97.cpp | 2 +- ...iverLoader.cpp => BuiltinModuleLoader.cpp} | 26 + Modules/Intel/Gigabit.cpp | 8 +- Modules/PersonalSystem2/Keyboard.cpp | 107 + Modules/PersonalSystem2/Mouse.cpp | 33 +- Modules/PersonalSystem2/keyboard.hpp | 237 + Modules/Realtek/RTL8139.cpp | 2 +- Modules/VMware/Mouse.cpp | 20 +- Modules/drv.hpp | 1 + Network/AddressResolutionProtocol.cpp | 399 +- Network/Ethernet.cpp | 216 +- Network/InternetProtocol.cpp | 8 +- Network/NetworkController.cpp | 33 +- Recovery/RecoveryMain.cpp | 371 -- SystemCalls/Linux.cpp | 2458 ----------- SystemCalls/Linux/Linux.cpp | 857 ++++ SystemCalls/Linux/linux_syscalls.hpp | 381 ++ SystemCalls/Native.cpp | 617 ++- SystemCalls/Syscalls.cpp | 12 +- Tasking/InterProcessCommunication.cpp | 14 +- Tasking/Process.cpp | 220 + Tasking/Scheduler.cpp | 93 +- Tasking/Security.cpp | 149 - Tasking/Task.cpp | 1074 ++--- Tasking/Thread.cpp | 460 ++ Tests/CPUID.cpp | 240 +- Tests/Marco.cpp | 10 + Tests/MemoryAllocation.cpp | 332 +- Tests/MemoryOperations.cpp | 193 +- Tests/RandomNumberGenerator.cpp | 70 +- Tests/String.cpp | 198 +- Tests/TypeSize.cpp | 162 +- Tests/std.cpp | 49 +- Tests/t.h | 2 +- Virtualization/IsVirtualizedEnvironment.cpp | 203 + include/bitmap.hpp | 11 +- include/cpu.hpp | 1566 +++---- include/cpu/x86/cpuid_amd.hpp | 3854 +++++++++-------- include/cpu/x86/cpuid_intel.hpp | 2520 +++++------ include/elf.h | 41 +- include/exec.hpp | 139 +- include/filesystem.hpp | 536 ++- include/gui.hpp | 414 -- include/io.h | 348 +- include/kconfig.hpp | 7 + include/kshell.hpp | 2 +- include/lock.hpp | 181 +- include/memory.hpp | 1677 +++---- include/power.hpp | 1 - include/stb/image.h | 6 + include/symbols.hpp | 42 +- include/task.hpp | 420 +- include/time.hpp | 28 +- include/types.h | 33 +- include/vm.hpp | 36 + include_std/algorithm | 65 + include_std/assert.h | 48 +- include_std/atomic | 649 ++- include_std/cstddef | 4 +- include_std/errno.h | 515 ++- include_std/float.h | 30 + include_std/functional | 30 + include_std/mutex | 66 + include_std/std.hpp | 4 +- include_std/std/atomic.hpp | 521 --- include_std/std/smart_ptr.hpp | 19 +- include_std/std/string.hpp | 142 +- include_std/std/unordered_map.hpp | 180 +- include_std/std/vector.hpp | 286 -- include_std/stdarg.h | 2 - include_std/{string.hpp => string} | 0 include_std/type_trails | 45 + include_std/utility | 29 + include_std/vector | 286 +- kernel.h | 2 - syscalls.h | 497 ++- 181 files changed, 21873 insertions(+), 21475 deletions(-) create mode 100644 Core/Memory/SmartHeap.cpp delete mode 100644 Execute/BinaryParse.cpp delete mode 100644 Execute/Elf/ElfBaseLoad.cpp delete mode 100644 Execute/Elf/ElfInterpreter.cpp delete mode 100644 Execute/Elf/ElfLoader.cpp delete mode 100644 Execute/Elf/ElfParse.cpp delete mode 100644 Execute/Elf/ElfSharedObjects.cpp delete mode 100644 Execute/Spawn.cpp create mode 100644 ExecutionLayer/BinaryParse.cpp create mode 100644 ExecutionLayer/Elf/ElfLoader.cpp create mode 100644 ExecutionLayer/Elf/ElfParse.cpp rename {Execute => ExecutionLayer}/Elf/ElfRel.cpp (87%) rename {Execute => ExecutionLayer}/Elf/ParseFunctions/ELFGetDynamicTag.cpp (72%) rename {Execute => ExecutionLayer}/Elf/ParseFunctions/ELFGetSections.cpp (68%) rename {Execute => ExecutionLayer}/Elf/ParseFunctions/ELFGetSymbolType.cpp (66%) create mode 100644 ExecutionLayer/Spawn.cpp create mode 100644 FileSystem/FileDescriptor.cpp create mode 100644 FileSystem/FileNode.cpp create mode 100644 FileSystem/Kernel_IO.cpp delete mode 100644 GUI/GUITools.cpp delete mode 100644 GUI/GraphicalUserInterface.cpp delete mode 100644 GUI/Icons.cpp delete mode 100644 GUI/WidgetEvents.cpp delete mode 100644 GUI/Widgets.cpp delete mode 100644 GUI/Window.cpp delete mode 100644 GUI/WindowEvents.cpp create mode 100644 KernelShell/Commands/cat.cpp create mode 100644 KernelShell/Commands/cd.cpp rename KernelShell.cpp => KernelShell/Commands/echo.cpp (86%) rename include/recovery.hpp => KernelShell/Commands/exit.cpp (63%) rename GUI/icons.hpp => KernelShell/Commands/kill.cpp (60%) create mode 100644 KernelShell/Commands/killall.cpp create mode 100644 KernelShell/Commands/ls.cpp create mode 100644 KernelShell/Commands/lsof.cpp create mode 100644 KernelShell/Commands/lspci.cpp create mode 100644 KernelShell/Commands/mem.cpp create mode 100644 KernelShell/Commands/ps.cpp create mode 100644 KernelShell/Commands/reboot.cpp create mode 100644 KernelShell/Commands/shutdown.cpp create mode 100644 KernelShell/Commands/top.cpp create mode 100644 KernelShell/Commands/uname.cpp create mode 100644 KernelShell/Commands/uptime.cpp create mode 100644 KernelShell/Commands/whoami.cpp create mode 100644 KernelShell/Shell.cpp rename Tests/TestSyscalls.c => KernelShell/cmds.hpp (50%) create mode 100644 Library/std/mutex.cpp rename Modules/{BuiltinDriverLoader.cpp => BuiltinModuleLoader.cpp} (91%) create mode 100644 Modules/PersonalSystem2/Keyboard.cpp create mode 100644 Modules/PersonalSystem2/keyboard.hpp delete mode 100644 Recovery/RecoveryMain.cpp delete mode 100644 SystemCalls/Linux.cpp create mode 100644 SystemCalls/Linux/Linux.cpp create mode 100644 SystemCalls/Linux/linux_syscalls.hpp create mode 100644 Tasking/Process.cpp delete mode 100644 Tasking/Security.cpp create mode 100644 Tasking/Thread.cpp create mode 100644 Virtualization/IsVirtualizedEnvironment.cpp delete mode 100644 include/gui.hpp create mode 100644 include/vm.hpp create mode 100644 include_std/algorithm create mode 100644 include_std/float.h create mode 100644 include_std/functional create mode 100644 include_std/mutex delete mode 100644 include_std/std/atomic.hpp delete mode 100644 include_std/std/vector.hpp rename include_std/{string.hpp => string} (100%) create mode 100644 include_std/type_trails create mode 100644 include_std/utility diff --git a/.vscode/c_boilerplates.code-snippets b/.vscode/c_boilerplates.code-snippets index c91ee46..8ea597c 100644 --- a/.vscode/c_boilerplates.code-snippets +++ b/.vscode/c_boilerplates.code-snippets @@ -42,6 +42,18 @@ ], "description": "Create kernel documentation brief." }, + "For Iteratoion": { + "prefix": [ + "foritr", + ], + "body": [ + "forItr(${1:itr}, ${2:container})", + "{", + "\t$0", + "}" + ], + "description": "Create for loop with iterator." + }, "License": { "prefix": [ "license", @@ -66,4 +78,4 @@ ], "description": "Create kernel license." } -} +} \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index b72c80f..853d53e 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -11,6 +11,7 @@ "defines": [ "__debug_vscode__", "KERNEL_NAME=\"Fennix\"", + "KERNEL_ARCH=\"amd64\"", "KERNEL_VERSION=\"1.0\"", "GIT_COMMIT=\"0000000000000000000000000000000000000000\"", "GIT_COMMIT_SHORT=\"0000000\"", @@ -84,6 +85,7 @@ "defines": [ "__debug_vscode__", "KERNEL_NAME=\"Fennix\"", + "KERNEL_ARCH=\"i386\"", "KERNEL_VERSION=\"1.0\"", "GIT_COMMIT=\"0000000000000000000000000000000000000000\"", "GIT_COMMIT_SHORT=\"0000000\"", @@ -160,6 +162,7 @@ "defines": [ "__debug_vscode__", "KERNEL_NAME=\"Fennix\"", + "KERNEL_ARCH=\"aarch64\"", "KERNEL_VERSION=\"1.0\"", "GIT_COMMIT=\"0000000000000000000000000000000000000000\"", "GIT_COMMIT_SHORT=\"0000000\"", diff --git a/.vscode/launch.json b/.vscode/launch.json index a53bf41..6c8d19f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -74,8 +74,82 @@ "description": "Load /bin/init." }, { - "text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/lib/ld.so", - "description": "Load /lib/ld.so." + "text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/usr/bin/doom", + "description": "Load /usr/bin/doom." + }, + ], + }, + { + "name": "Attach to VM w/init", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/kernel.fsys", + "cwd": "${workspaceFolder}", + "args": [], + "targetArchitecture": "x64", + "MIMode": "gdb", + "miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb", + "miDebuggerArgs": "", + "externalConsole": false, + "additionalSOLibSearchPath": "${workspaceFolder}", + "customLaunchSetupCommands": [ + { + "text": "target remote localhost:1234", + "description": "Connect to QEMU remote debugger" + } + ], + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "set breakpoint pending on", + "description": "Make breakpoint pending on future shared library load." + }, + { + "text": "file ${workspaceFolder}/kernel.fsys", + "description": "Load binary." + }, + { + "text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/bin/init", + "description": "Load /bin/init." + }, + ], + }, + { + "name": "Attach to VM w/doom", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/kernel.fsys", + "cwd": "${workspaceFolder}", + "args": [], + "targetArchitecture": "x64", + "MIMode": "gdb", + "miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb", + "miDebuggerArgs": "", + "externalConsole": false, + "additionalSOLibSearchPath": "${workspaceFolder}", + "customLaunchSetupCommands": [ + { + "text": "target remote localhost:1234", + "description": "Connect to QEMU remote debugger" + } + ], + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "set breakpoint pending on", + "description": "Make breakpoint pending on future shared library load." + }, + { + "text": "file ${workspaceFolder}/kernel.fsys", + "description": "Load binary." }, { "text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/usr/bin/doom", diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp index 5ac8531..5d84c87 100644 --- a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp +++ b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include "multiboot2.h" @@ -50,7 +51,6 @@ EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info) if (tmp != (tmp | 3)) outb(0x61, tmp | 3); - int pos = 0; auto InfoAddress = Info; for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); ; @@ -220,7 +220,7 @@ EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info) mb2binfo.Kernel.Symbols.Num = elf->num; mb2binfo.Kernel.Symbols.EntSize = elf->entsize; mb2binfo.Kernel.Symbols.Shndx = elf->shndx; - mb2binfo.Kernel.Symbols.Sections = (uintptr_t)&elf->sections; + mb2binfo.Kernel.Symbols.Sections = r_cst(uintptr_t, elf->sections); break; } case MULTIBOOT_TAG_TYPE_APM: diff --git a/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp b/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp index edfeb7a..3ca6cbb 100644 --- a/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp +++ b/Architecture/amd64/DifferentiatedSystemDescriptionTable.cpp @@ -82,8 +82,8 @@ namespace ACPI { TaskManager->CreateThread(TaskManager->CreateProcess(nullptr, "Shutdown", - Tasking::TaskTrustLevel::Kernel), - (Tasking::IP)KST_Shutdown); + Tasking::TaskExecutionMode::Kernel), + Tasking::IP(KST_Shutdown)); } else KernelShutdownThread(false); diff --git a/Architecture/amd64/Memory/VirtualMemoryManager.cpp b/Architecture/amd64/Memory/VirtualMemoryManager.cpp index 4f1c808..fb00ab7 100644 --- a/Architecture/amd64/Memory/VirtualMemoryManager.cpp +++ b/Architecture/amd64/Memory/VirtualMemoryManager.cpp @@ -22,402 +22,408 @@ namespace Memory { - bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type) - { - // 0x1000 aligned - uintptr_t Address = (uintptr_t)VirtualAddress; - Address &= 0xFFFFFFFFFFFFF000; + bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type) + { + // 0x1000 aligned + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; - PageMapIndexer Index = PageMapIndexer(Address); - PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; - PageDirectoryPointerTableEntryPtr *PDPTE = nullptr; - PageDirectoryEntryPtr *PDE = nullptr; - PageTableEntryPtr *PTE = nullptr; + PageDirectoryPointerTableEntryPtr *PDPTE = nullptr; + PageDirectoryEntryPtr *PDE = nullptr; + PageTableEntryPtr *PTE = nullptr; - if ((PML4->raw & Flag) > 0) - { - PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12); - if (PDPTE) - { - if ((PDPTE->Entries[Index.PDPTEIndex].Present)) - { - if (Type == MapType::OneGB && PDPTE->Entries[Index.PDPTEIndex].PageSize) - return true; + if ((PML4->raw & Flag) > 0) + { + PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12); + if (PDPTE) + { + if ((PDPTE->Entries[Index.PDPTEIndex].Present)) + { + if (Type == MapType::OneGiB && PDPTE->Entries[Index.PDPTEIndex].PageSize) + return true; - PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); - if (PDE) - { - if (Type == MapType::TwoMB && PDE->Entries[Index.PDEIndex].PageSize) - return true; + PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); + if (PDE) + { + if (Type == MapType::TwoMiB && PDE->Entries[Index.PDEIndex].PageSize) + return true; - if ((PDE->Entries[Index.PDEIndex].Present)) - { - PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); - if (PTE) - { - if ((PTE->Entries[Index.PTEIndex].Present)) - return true; - } - } - } - } - } - } - return false; - } + if ((PDE->Entries[Index.PDEIndex].Present)) + { + PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); + if (PTE) + { + if ((PTE->Entries[Index.PTEIndex].Present)) + return true; + } + } + } + } + } + } + return false; + } - void *Virtual::GetPhysical(void *VirtualAddress) - { - // 0x1000 aligned - uintptr_t Address = (uintptr_t)VirtualAddress; - Address &= 0xFFFFFFFFFFFFF000; + void *Virtual::GetPhysical(void *VirtualAddress) + { + // 0x1000 aligned + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; - PageMapIndexer Index = PageMapIndexer(Address); - PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; - PageDirectoryPointerTableEntryPtr *PDPTE = nullptr; - PageDirectoryEntryPtr *PDE = nullptr; - PageTableEntryPtr *PTE = nullptr; + PageDirectoryPointerTableEntryPtr *PDPTE = nullptr; + PageDirectoryEntryPtr *PDE = nullptr; + PageTableEntryPtr *PTE = nullptr; - if (PML4->Present) - { - PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12); - if (PDPTE) - { - if (PDPTE->Entries[Index.PDPTEIndex].Present) - { - if (PDPTE->Entries[Index.PDPTEIndex].PageSize) - return (void *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); + if (PML4->Present) + { + PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12); + if (PDPTE) + { + if (PDPTE->Entries[Index.PDPTEIndex].Present) + { + if (PDPTE->Entries[Index.PDPTEIndex].PageSize) + return (void *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); - PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); - if (PDE) - { - if (PDE->Entries[Index.PDEIndex].Present) - { - if (PDE->Entries[Index.PDEIndex].PageSize) - return (void *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); + PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); + if (PDE) + { + if (PDE->Entries[Index.PDEIndex].Present) + { + if (PDE->Entries[Index.PDEIndex].PageSize) + return (void *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); - PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); - if (PTE) - { - if (PTE->Entries[Index.PTEIndex].Present) - return (void *)((uintptr_t)PTE->Entries[Index.PTEIndex].GetAddress() << 12); - } - } - } - } - } - } - return nullptr; - } + PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); + if (PTE) + { + if (PTE->Entries[Index.PTEIndex].Present) + return (void *)((uintptr_t)PTE->Entries[Index.PTEIndex].GetAddress() << 12); + } + } + } + } + } + } + return nullptr; + } - Virtual::MapType Virtual::GetMapType(void *VirtualAddress) - { - // 0x1000 aligned - uintptr_t Address = (uintptr_t)VirtualAddress; - Address &= 0xFFFFFFFFFFFFF000; + Virtual::MapType Virtual::GetMapType(void *VirtualAddress) + { + // 0x1000 aligned + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; - PageMapIndexer Index = PageMapIndexer(Address); - PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; - PageDirectoryPointerTableEntryPtr *PDPTE = nullptr; - PageDirectoryEntryPtr *PDE = nullptr; - PageTableEntryPtr *PTE = nullptr; + PageDirectoryPointerTableEntryPtr *PDPTE = nullptr; + PageDirectoryEntryPtr *PDE = nullptr; + PageTableEntryPtr *PTE = nullptr; - if (PML4->Present) - { - PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12); - if (PDPTE) - { - if (PDPTE->Entries[Index.PDPTEIndex].Present) - { - if (PDPTE->Entries[Index.PDPTEIndex].PageSize) - return MapType::OneGB; + if (PML4->Present) + { + PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12); + if (PDPTE) + { + if (PDPTE->Entries[Index.PDPTEIndex].Present) + { + if (PDPTE->Entries[Index.PDPTEIndex].PageSize) + return MapType::OneGiB; - PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); - if (PDE) - { - if (PDE->Entries[Index.PDEIndex].Present) - { - if (PDE->Entries[Index.PDEIndex].PageSize) - return MapType::TwoMB; + PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); + if (PDE) + { + if (PDE->Entries[Index.PDEIndex].Present) + { + if (PDE->Entries[Index.PDEIndex].PageSize) + return MapType::TwoMiB; - PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); - if (PTE) - { - if (PTE->Entries[Index.PTEIndex].Present) - return MapType::FourKB; - } - } - } - } - } - } - return MapType::NoMapType; - } + PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); + if (PTE) + { + if (PTE->Entries[Index.PTEIndex].Present) + return MapType::FourKiB; + } + } + } + } + } + } + return MapType::NoMapType; + } - PageMapLevel5 *Virtual::GetPML5(void *VirtualAddress, MapType Type) - { - stub; /* TODO */ - return nullptr; - } + PageMapLevel5 *Virtual::GetPML5(void *VirtualAddress, MapType Type) + { + UNUSED(VirtualAddress); + UNUSED(Type); + stub; /* TODO */ + return nullptr; + } - PageMapLevel4 *Virtual::GetPML4(void *VirtualAddress, MapType Type) - { - uintptr_t Address = (uintptr_t)VirtualAddress; - Address &= 0xFFFFFFFFFFFFF000; + PageMapLevel4 *Virtual::GetPML4(void *VirtualAddress, MapType Type) + { + UNUSED(Type); + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; - PageMapIndexer Index = PageMapIndexer(Address); - PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; - if (PML4->Present) - return PML4; - return nullptr; - } + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + if (PML4->Present) + return PML4; + return nullptr; + } - PageDirectoryPointerTableEntry *Virtual::GetPDPTE(void *VirtualAddress, MapType Type) - { - uintptr_t Address = (uintptr_t)VirtualAddress; - Address &= 0xFFFFFFFFFFFFF000; + PageDirectoryPointerTableEntry *Virtual::GetPDPTE(void *VirtualAddress, MapType Type) + { + UNUSED(Type); + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; - PageMapIndexer Index = PageMapIndexer(Address); - PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; - if (!PML4->Present) - return nullptr; + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + if (!PML4->Present) + return nullptr; - PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); - PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; - if (PDPTE->Present) - return PDPTE; - return nullptr; - } + PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); + PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; + if (PDPTE->Present) + return PDPTE; + return nullptr; + } - PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type) - { - uintptr_t Address = (uintptr_t)VirtualAddress; - Address &= 0xFFFFFFFFFFFFF000; + PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type) + { + UNUSED(Type); + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; - PageMapIndexer Index = PageMapIndexer(Address); - PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; - if (!PML4->Present) - return nullptr; + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + if (!PML4->Present) + return nullptr; - PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); - PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; - if (!PDPTE->Present) - return nullptr; + PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); + PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; + if (!PDPTE->Present) + return nullptr; - PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12); - PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; - if (PDE->Present) - return PDE; - return nullptr; - } + PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12); + PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; + if (PDE->Present) + return PDE; + return nullptr; + } - PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type) - { - uintptr_t Address = (uintptr_t)VirtualAddress; - Address &= 0xFFFFFFFFFFFFF000; + PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type) + { + UNUSED(Type); + uintptr_t Address = (uintptr_t)VirtualAddress; + Address &= 0xFFFFFFFFFFFFF000; - PageMapIndexer Index = PageMapIndexer(Address); - PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; - if (!PML4->Present) - return nullptr; + PageMapIndexer Index = PageMapIndexer(Address); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + if (!PML4->Present) + return nullptr; - PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); - PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; - if (!PDPTE->Present) - return nullptr; + PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); + PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; + if (!PDPTE->Present) + return nullptr; - PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12); - PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; - if (!PDE->Present) - return nullptr; + PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12); + PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; + if (!PDE->Present) + return nullptr; - PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12); - PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex]; - if (PTE->Present) - return PTE; - return nullptr; - } + PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12); + PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex]; + if (PTE->Present) + return PTE; + return nullptr; + } - void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) - { - SmartLock(this->MemoryLock); - if (unlikely(!this->Table)) - { - error("No page table"); - return; - } + void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) + { + SmartLock(this->MemoryLock); + if (unlikely(!this->Table)) + { + error("No page table"); + return; + } - Flags |= PTFlag::P; + Flags |= PTFlag::P; - PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress); - // Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only - uint64_t DirectoryFlags = Flags & 0x3F; + PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress); + // Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only + uint64_t DirectoryFlags = Flags & 0x3F; - PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; - PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr; - if (!PML4->Present) - { - PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageDirectoryPointerTableEntryPtr) + 1)); - memset(PDPTEPtr, 0, sizeof(PageDirectoryPointerTableEntryPtr)); - PML4->Present = true; - PML4->SetAddress((uintptr_t)PDPTEPtr >> 12); - } - else - PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)(PML4->GetAddress() << 12); - PML4->raw |= DirectoryFlags; + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr; + if (!PML4->Present) + { + PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageDirectoryPointerTableEntryPtr) + 1)); + memset(PDPTEPtr, 0, sizeof(PageDirectoryPointerTableEntryPtr)); + PML4->Present = true; + PML4->SetAddress((uintptr_t)PDPTEPtr >> 12); + } + else + PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)(PML4->GetAddress() << 12); + PML4->raw |= DirectoryFlags; - PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; - if (Type == MapType::OneGB) - { - PDPTE->raw |= Flags; - PDPTE->PageSize = true; - PDPTE->SetAddress((uintptr_t)PhysicalAddress >> 12); - debug("Mapped 1GB page at %p to %p", VirtualAddress, PhysicalAddress); - return; - } + PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; + if (Type == MapType::OneGiB) + { + PDPTE->raw |= Flags; + PDPTE->PageSize = true; + PDPTE->SetAddress((uintptr_t)PhysicalAddress >> 12); + debug("Mapped 1GB page at %p to %p", VirtualAddress, PhysicalAddress); + return; + } - PageDirectoryEntryPtr *PDEPtr = nullptr; - if (!PDPTE->Present) - { - PDEPtr = (PageDirectoryEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageDirectoryEntryPtr) + 1)); - memset(PDEPtr, 0, sizeof(PageDirectoryEntryPtr)); - PDPTE->Present = true; - PDPTE->SetAddress((uintptr_t)PDEPtr >> 12); - } - else - PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12); - PDPTE->raw |= DirectoryFlags; + PageDirectoryEntryPtr *PDEPtr = nullptr; + if (!PDPTE->Present) + { + PDEPtr = (PageDirectoryEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageDirectoryEntryPtr) + 1)); + memset(PDEPtr, 0, sizeof(PageDirectoryEntryPtr)); + PDPTE->Present = true; + PDPTE->SetAddress((uintptr_t)PDEPtr >> 12); + } + else + PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12); + PDPTE->raw |= DirectoryFlags; - PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; - if (Type == MapType::TwoMB) - { - PDE->raw |= Flags; - PDE->PageSize = true; - PDE->SetAddress((uintptr_t)PhysicalAddress >> 12); - debug("Mapped 2MB page at %p to %p", VirtualAddress, PhysicalAddress); - return; - } + PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; + if (Type == MapType::TwoMiB) + { + PDE->raw |= Flags; + PDE->PageSize = true; + PDE->SetAddress((uintptr_t)PhysicalAddress >> 12); + debug("Mapped 2MB page at %p to %p", VirtualAddress, PhysicalAddress); + return; + } - PageTableEntryPtr *PTEPtr = nullptr; - if (!PDE->Present) - { - PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageTableEntryPtr) + 1)); - memset(PTEPtr, 0, sizeof(PageTableEntryPtr)); - PDE->Present = true; - PDE->SetAddress((uintptr_t)PTEPtr >> 12); - } - else - PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12); - PDE->raw |= DirectoryFlags; + PageTableEntryPtr *PTEPtr = nullptr; + if (!PDE->Present) + { + PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageTableEntryPtr) + 1)); + memset(PTEPtr, 0, sizeof(PageTableEntryPtr)); + PDE->Present = true; + PDE->SetAddress((uintptr_t)PTEPtr >> 12); + } + else + PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12); + PDE->raw |= DirectoryFlags; - PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex]; - PTE->Present = true; - PTE->raw |= Flags; - PTE->SetAddress((uintptr_t)PhysicalAddress >> 12); + PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex]; + PTE->Present = true; + PTE->raw |= Flags; + PTE->SetAddress((uintptr_t)PhysicalAddress >> 12); #if defined(a64) - CPU::x64::invlpg(VirtualAddress); + CPU::x64::invlpg(VirtualAddress); #elif defined(a32) - CPU::x32::invlpg(VirtualAddress); + CPU::x32::invlpg(VirtualAddress); #elif defined(aa64) - asmv("dsb sy"); - asmv("tlbi vae1is, %0" - : - : "r"(VirtualAddress) - : "memory"); - asmv("dsb sy"); - asmv("isb"); + asmv("dsb sy"); + asmv("tlbi vae1is, %0" + : + : "r"(VirtualAddress) + : "memory"); + asmv("dsb sy"); + asmv("isb"); #endif #ifdef DEBUG /* https://stackoverflow.com/a/3208376/9352057 */ #define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c" #define BYTE_TO_BINARY(byte) \ - (byte & 0x80 ? '1' : '0'), \ - (byte & 0x40 ? '1' : '0'), \ - (byte & 0x20 ? '1' : '0'), \ - (byte & 0x10 ? '1' : '0'), \ - (byte & 0x08 ? '1' : '0'), \ - (byte & 0x04 ? '1' : '0'), \ - (byte & 0x02 ? '1' : '0'), \ - (byte & 0x01 ? '1' : '0') + (byte & 0x80 ? '1' : '0'), \ + (byte & 0x40 ? '1' : '0'), \ + (byte & 0x20 ? '1' : '0'), \ + (byte & 0x10 ? '1' : '0'), \ + (byte & 0x08 ? '1' : '0'), \ + (byte & 0x04 ? '1' : '0'), \ + (byte & 0x02 ? '1' : '0'), \ + (byte & 0x01 ? '1' : '0') - if (!this->Check(VirtualAddress, (PTFlag)Flags, Type)) // quick workaround just to see where it fails - warn("Failed to map v:%#lx p:%#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags)); + if (!this->Check(VirtualAddress, (PTFlag)Flags, Type)) // quick workaround just to see where it fails + warn("Failed to map v:%#lx p:%#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags)); #endif - } + } - void Virtual::Unmap(void *VirtualAddress, MapType Type) - { - SmartLock(this->MemoryLock); - if (!this->Table) - { - error("No page table"); - return; - } + void Virtual::Unmap(void *VirtualAddress, MapType Type) + { + SmartLock(this->MemoryLock); + if (!this->Table) + { + error("No page table"); + return; + } - PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress); - PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; - if (!PML4->Present) - { - warn("Page %#lx not present", PML4->GetAddress()); - return; - } + PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress); + PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex]; + if (!PML4->Present) + { + warn("Page %#lx not present", PML4->GetAddress()); + return; + } - PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); - PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; - if (!PDPTE->Present) - { - warn("Page %#lx not present", PDPTE->GetAddress()); - return; - } + PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12); + PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex]; + if (!PDPTE->Present) + { + warn("Page %#lx not present", PDPTE->GetAddress()); + return; + } - if (Type == MapType::OneGB && PDPTE->PageSize) - { - PDPTE->Present = false; - return; - } + if (Type == MapType::OneGiB && PDPTE->PageSize) + { + PDPTE->Present = false; + return; + } - PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Address << 12); - PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; - if (!PDE->Present) - { - warn("Page %#lx not present", PDE->GetAddress()); - return; - } + PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Address << 12); + PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex]; + if (!PDE->Present) + { + warn("Page %#lx not present", PDE->GetAddress()); + return; + } - if (Type == MapType::TwoMB && PDE->PageSize) - { - PDE->Present = false; - return; - } + if (Type == MapType::TwoMiB && PDE->PageSize) + { + PDE->Present = false; + return; + } - PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE->Address << 12); - PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex]; - if (!PTE.Present) - { - warn("Page %#lx not present", PTE.GetAddress()); - return; - } + PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE->Address << 12); + PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex]; + if (!PTE.Present) + { + warn("Page %#lx not present", PTE.GetAddress()); + return; + } - PTE.Present = false; - PTEPtr->Entries[Index.PTEIndex] = PTE; + PTE.Present = false; + PTEPtr->Entries[Index.PTEIndex] = PTE; #if defined(a64) - CPU::x64::invlpg(VirtualAddress); + CPU::x64::invlpg(VirtualAddress); #elif defined(a32) - CPU::x32::invlpg(VirtualAddress); + CPU::x32::invlpg(VirtualAddress); #elif defined(aa64) - asmv("dsb sy"); - asmv("tlbi vae1is, %0" - : - : "r"(VirtualAddress) - : "memory"); - asmv("dsb sy"); - asmv("isb"); + asmv("dsb sy"); + asmv("tlbi vae1is, %0" + : + : "r"(VirtualAddress) + : "memory"); + asmv("dsb sy"); + asmv("isb"); #endif - } + } } diff --git a/Architecture/amd64/SystemCalls.cpp b/Architecture/amd64/SystemCalls.cpp index 1014d93..a984886 100644 --- a/Architecture/amd64/SystemCalls.cpp +++ b/Architecture/amd64/SystemCalls.cpp @@ -31,11 +31,11 @@ extern "C" void SystemCallHandlerStub(); extern "C" __naked __used __no_stack_protector __aligned(16) void SystemCallHandlerStub() { - asmv("swapgs\n"); /* Swap GS to get the TCB */ - asmv("mov %rsp, %gs:0x8\n"); /* We save the current rsp to TCB->TempStack */ - asmv("mov %gs:0x0, %rsp\n"); /* Get TCB->SystemCallStack and set it as rsp */ + asmv("swapgs\n"); /* Swap GS to get the gsTCB */ + asmv("mov %rsp, %gs:0x8\n"); /* We save the current rsp to gsTCB->TempStack */ + asmv("mov %gs:0x0, %rsp\n"); /* Get gsTCB->SystemCallStack and set it as rsp */ asmv("push $0x1b\n"); /* Push user data segment for SyscallsFrame */ - asmv("push %gs:0x8\n"); /* Push TCB->TempStack (old rsp) for SyscallsFrame */ + asmv("push %gs:0x8\n"); /* Push gsTCB->TempStack (old rsp) for SyscallsFrame */ asmv("push %r11\n"); /* Push the flags for SyscallsFrame */ asmv("push $0x23\n"); /* Push user code segment for SyscallsFrame */ asmv("push %rcx\n"); /* Push the return address for SyscallsFrame + sysretq (https://www.felixcloutier.com/x86/sysret) */ @@ -78,7 +78,7 @@ extern "C" __naked __used __no_stack_protector __aligned(16) void SystemCallHand "pop %rcx\n" "pop %rbx\n"); - /* Restore rsp from TCB->TempStack */ + /* Restore rsp from gsTCB->TempStack */ asmv("mov %gs:0x8, %rsp\n"); #ifdef DEBUG /* Easier to debug stacks */ diff --git a/Architecture/amd64/cpu/GlobalDescriptorTable.cpp b/Architecture/amd64/cpu/GlobalDescriptorTable.cpp index b3cac84..3db245f 100644 --- a/Architecture/amd64/cpu/GlobalDescriptorTable.cpp +++ b/Architecture/amd64/cpu/GlobalDescriptorTable.cpp @@ -24,249 +24,247 @@ namespace GlobalDescriptorTable { - static GlobalDescriptorTableEntries GDTEntriesTemplate = { - .Null = - { - .Limit0 = 0x0, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = {.Raw = 0x0}, - // .Limit1 = 0x0, - .Flags = {.Raw = 0x0}, - .BaseHigh = 0x0, - }, + static GlobalDescriptorTableEntries GDTEntriesTemplate = { + .Null = { + .Limit0 = 0x0, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = {.Raw = 0x0}, + // .Limit1 = 0x0, + .Flags = {.Raw = 0x0}, + .BaseHigh = 0x0, + }, - .Code = - { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 1, - .S = 1, - .DPL = 0, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ + .Code = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 1, + .S = 1, + .DPL = 0, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - .AVL = 0, - .L = 1, - .DB = 0, - .G = 1, - }, - .BaseHigh = 0x0, - }, + .AVL = 0, + .L = 1, + .DB = 0, + .G = 1, + }, + .BaseHigh = 0x0, + }, - .Data = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 0, - .S = 1, - .DPL = 0, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ + .Data = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 0, + .S = 1, + .DPL = 0, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - .AVL = 0, - .L = 0, - .DB = 1, - .G = 1, - }, - .BaseHigh = 0x0, - }, + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, - .UserData = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 0, - .S = 1, - .DPL = 3, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ + .UserData = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 0, + .S = 1, + .DPL = 3, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - .AVL = 0, - .L = 0, - .DB = 1, - .G = 1, - }, - .BaseHigh = 0x0, - }, + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, - .UserCode = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 1, - .S = 1, - .DPL = 3, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ + .UserCode = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 1, + .S = 1, + .DPL = 3, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - .AVL = 0, - .L = 1, - .DB = 0, - .G = 1, - }, - .BaseHigh = 0x0, - }, + .AVL = 0, + .L = 1, + .DB = 0, + .G = 1, + }, + .BaseHigh = 0x0, + }, - .TaskStateSegment = {}, - }; + .TaskStateSegment = {}, + }; - GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16); - GlobalDescriptorTableDescriptor gdt[MAX_CPU] __aligned(16); + GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16); + GlobalDescriptorTableDescriptor gdt[MAX_CPU] __aligned(16); - TaskStateSegment tss[MAX_CPU] = { - 0, - {0, 0, 0}, - 0, - {0, 0, 0, 0, 0, 0, 0}, - 0, - 0, - 0, - }; + TaskStateSegment tss[MAX_CPU] = { + 0, + {0, 0, 0}, + 0, + {0, 0, 0, 0, 0, 0, 0}, + 0, + 0, + 0, + }; - void *CPUStackPointer[MAX_CPU]; + void *CPUStackPointer[MAX_CPU]; - SafeFunction void Init(int Core) - { - memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries)); - gdt[Core] = {.Length = sizeof(GlobalDescriptorTableEntries) - 1, .Entries = &GDTEntries[Core]}; + SafeFunction void Init(int Core) + { + memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries)); + gdt[Core] = {.Length = sizeof(GlobalDescriptorTableEntries) - 1, .Entries = &GDTEntries[Core]}; - debug("GDT: %#lx", &gdt[Core]); - debug("GDT KERNEL: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_KERNEL_CODE, - GDTEntries[Core].Code.Limit0, - GDTEntries[Core].Code.BaseLow, - GDTEntries[Core].Code.BaseMiddle, - GDTEntries[Core].Code.Access.Raw, - GDTEntries[Core].Code.Flags.Reserved, - GDTEntries[Core].Code.Flags.Raw & ~0xF, - GDTEntries[Core].Code.BaseHigh); + debug("GDT: %#lx", &gdt[Core]); + debug("GDT KERNEL: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_KERNEL_CODE, + GDTEntries[Core].Code.Limit0, + GDTEntries[Core].Code.BaseLow, + GDTEntries[Core].Code.BaseMiddle, + GDTEntries[Core].Code.Access.Raw, + GDTEntries[Core].Code.Flags.Reserved, + GDTEntries[Core].Code.Flags.Raw & ~0xF, + GDTEntries[Core].Code.BaseHigh); - debug("GDT KERNEL: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_KERNEL_DATA, - GDTEntries[Core].Data.Limit0, - GDTEntries[Core].Data.BaseLow, - GDTEntries[Core].Data.BaseMiddle, - GDTEntries[Core].Data.Access.Raw, - GDTEntries[Core].Data.Flags.Reserved, - GDTEntries[Core].Data.Flags.Raw & ~0xF, - GDTEntries[Core].Data.BaseHigh); + debug("GDT KERNEL: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_KERNEL_DATA, + GDTEntries[Core].Data.Limit0, + GDTEntries[Core].Data.BaseLow, + GDTEntries[Core].Data.BaseMiddle, + GDTEntries[Core].Data.Access.Raw, + GDTEntries[Core].Data.Flags.Reserved, + GDTEntries[Core].Data.Flags.Raw & ~0xF, + GDTEntries[Core].Data.BaseHigh); - debug("GDT USER: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_USER_CODE, - GDTEntries[Core].UserCode.Limit0, - GDTEntries[Core].UserCode.BaseLow, - GDTEntries[Core].UserCode.BaseMiddle, - GDTEntries[Core].UserCode.Access.Raw, - GDTEntries[Core].UserCode.Flags.Reserved, - GDTEntries[Core].UserCode.Flags.Raw & ~0xF, - GDTEntries[Core].UserCode.BaseHigh); + debug("GDT USER: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_USER_CODE, + GDTEntries[Core].UserCode.Limit0, + GDTEntries[Core].UserCode.BaseLow, + GDTEntries[Core].UserCode.BaseMiddle, + GDTEntries[Core].UserCode.Access.Raw, + GDTEntries[Core].UserCode.Flags.Reserved, + GDTEntries[Core].UserCode.Flags.Raw & ~0xF, + GDTEntries[Core].UserCode.BaseHigh); - debug("GDT USER: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_USER_DATA, - GDTEntries[Core].UserData.Limit0, - GDTEntries[Core].UserData.BaseLow, - GDTEntries[Core].UserData.BaseMiddle, - GDTEntries[Core].UserData.Access.Raw, - GDTEntries[Core].UserData.Flags.Reserved, - GDTEntries[Core].UserData.Flags.Raw & ~0xF, - GDTEntries[Core].UserData.BaseHigh); + debug("GDT USER: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_USER_DATA, + GDTEntries[Core].UserData.Limit0, + GDTEntries[Core].UserData.BaseLow, + GDTEntries[Core].UserData.BaseMiddle, + GDTEntries[Core].UserData.Access.Raw, + GDTEntries[Core].UserData.Flags.Reserved, + GDTEntries[Core].UserData.Flags.Raw & ~0xF, + GDTEntries[Core].UserData.BaseHigh); - CPU::x64::lgdt(&gdt[Core]); + CPU::x64::lgdt(&gdt[Core]); - asmv("movq %%rsp, %%rax\n" - "pushq $16\n" - "pushq %%rax\n" - "pushfq\n" - "pushq $8\n" - "pushq $1f\n" - "iretq\n" - "1:\n" - "movw $16, %%ax\n" - "movw %%ax, %%ds\n" - "movw %%ax, %%es\n" :: - : "memory", "rax"); + asmv("movq %%rsp, %%rax\n" + "pushq $16\n" + "pushq %%rax\n" + "pushfq\n" + "pushq $8\n" + "pushq $1f\n" + "iretq\n" + "1:\n" + "movw $16, %%ax\n" + "movw %%ax, %%ds\n" + "movw %%ax, %%es\n" :: + : "memory", "rax"); - CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); - memset(CPUStackPointer[Core], 0, STACK_SIZE); - debug("CPU %d Stack Pointer: %#lx-%#lx (%d pages)", Core, - CPUStackPointer[Core], (uintptr_t)CPUStackPointer[Core] + STACK_SIZE, - TO_PAGES(STACK_SIZE + 1)); + CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); + memset(CPUStackPointer[Core], 0, STACK_SIZE); + debug("CPU %d Stack Pointer: %#lx-%#lx (%d pages)", Core, + CPUStackPointer[Core], (uintptr_t)CPUStackPointer[Core] + STACK_SIZE, + TO_PAGES(STACK_SIZE + 1)); - uintptr_t Base = (uintptr_t)&tss[Core]; - size_t Limit = Base + sizeof(TaskStateSegment); - gdt[Core].Entries->TaskStateSegment.Limit = Limit & 0xFFFF; - gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; - gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF; - gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF; - gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); - gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; - gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF); + uintptr_t Base = (uintptr_t)&tss[Core]; + size_t Limit = Base + sizeof(TaskStateSegment); + gdt[Core].Entries->TaskStateSegment.Limit = Limit & 0xFFFF; + gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; + gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF; + gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF; + gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); + gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; + gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF); - tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment); - tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE; - tss[Core].StackPointer[1] = 0x0; - tss[Core].StackPointer[2] = 0x0; + tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment); + tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE; + tss[Core].StackPointer[1] = 0x0; + tss[Core].StackPointer[2] = 0x0; - for (size_t i = 0; i < sizeof(tss[Core].InterruptStackTable) / sizeof(tss[Core].InterruptStackTable[7]); i++) - { - void *NewStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); + for (size_t i = 0; i < sizeof(tss[Core].InterruptStackTable) / sizeof(tss[Core].InterruptStackTable[7]); i++) + { + void *NewStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); - tss[Core].InterruptStackTable[i] = (uint64_t)NewStack + STACK_SIZE; - memset((void *)(tss[Core].InterruptStackTable[i] - STACK_SIZE), 0, STACK_SIZE); - debug("IST-%d: %#lx-%#lx", i, NewStack, (uintptr_t)NewStack + STACK_SIZE); - } + tss[Core].InterruptStackTable[i] = (uint64_t)NewStack + STACK_SIZE; + memset((void *)(tss[Core].InterruptStackTable[i] - STACK_SIZE), 0, STACK_SIZE); + debug("IST-%d: %#lx-%#lx", i, NewStack, (uintptr_t)NewStack + STACK_SIZE); + } - CPU::x64::ltr(GDT_TSS); - debug("Global Descriptor Table initialized"); - } + CPU::x64::ltr(GDT_TSS); + debug("Global Descriptor Table initialized"); + } - SafeFunction void SetKernelStack(void *Stack) - { - long CPUID = GetCurrentCPU()->ID; - if (Stack != nullptr) - tss[CPUID].StackPointer[0] = (uint64_t)Stack; - else - tss[CPUID].StackPointer[0] = (uint64_t)CPUStackPointer[CPUID] + STACK_SIZE; + SafeFunction void SetKernelStack(void *Stack) + { + long CPUID = GetCurrentCPU()->ID; + if (Stack != nullptr) + tss[CPUID].StackPointer[0] = (uint64_t)Stack; + else + tss[CPUID].StackPointer[0] = (uint64_t)CPUStackPointer[CPUID] + STACK_SIZE; - /* - FIXME: There's a bug in kernel which if - we won't update "tss[CPUID].StackPointer[0]" - with the current stack pointer, the kernel - will crash. - */ - asmv("mov %%rsp, %0" - : "=r"(tss[CPUID].StackPointer[0])); - } + /* + FIXME: There's a bug in kernel which if + we won't update "tss[CPUID].StackPointer[0]" + with the current stack pointer, the kernel + will crash. + */ + asmv("mov %%rsp, %0" + : "=r"(tss[CPUID].StackPointer[0])); + } - void *GetKernelStack() { return (void *)tss[GetCurrentCPU()->ID].StackPointer[0]; } + void *GetKernelStack() { return (void *)tss[GetCurrentCPU()->ID].StackPointer[0]; } } diff --git a/Architecture/amd64/cpu/gdt.hpp b/Architecture/amd64/cpu/gdt.hpp index 84b0e8b..771075f 100644 --- a/Architecture/amd64/cpu/gdt.hpp +++ b/Architecture/amd64/cpu/gdt.hpp @@ -22,197 +22,299 @@ namespace GlobalDescriptorTable { - struct TaskStateSegmentEntry - { - /* LOW */ - uint16_t Limit; - uint16_t BaseLow; - uint8_t BaseMiddle; - union GlobalDescriptorTableAccess - { - struct - { - /** @brief Access bit. - * @note The CPU sets this bit to 1 when the segment is accessed. - */ - uint8_t A : 1; + struct TaskStateSegmentEntry + { + /* LOW */ + uint16_t Limit; + uint16_t BaseLow; + uint8_t BaseMiddle; + union GlobalDescriptorTableAccess + { + struct + { + /** + * Access bit. + * + * @note The CPU sets this bit to 1 when the segment + * is accessed. + */ + uint8_t A : 1; - /** @brief Readable bit for code segments, writable bit for data segments. - * @details For code segments, this bit must be 1 for the segment to be readable. - * @details For data segments, this bit must be 1 for the segment to be writable. - */ - uint8_t RW : 1; + /** + * Readable bit for code segments, writable bit for data + * segments. + * + * Code Segment: + * This bit must be 1 for the segment to be readable. + * + * Data Segment: + * This bit must be 1 for the segment to be writable. + */ + uint8_t RW : 1; - /** @brief Direction bit for data segments, conforming bit for code segments. - * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). - * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. - */ - uint8_t DC : 1; + /** + * Direction bit for data segments, conforming bit for + * code segments. + * + * Code Segment: + * This bit must be 1 for code in the segment to be + * able to be executed from an equal or lower privilege + * level. + * + * Data Segment: + * This bit must be 1 for the segment to grow up (higher + * addresses). + */ + uint8_t DC : 1; - /** @brief Executable bit. - * @details This bit must be 1 for code-segment descriptors. - * @details This bit must be 0 for data-segment and system descriptors. - */ - uint8_t E : 1; + /** + * Executable bit. + * + * This bit must be 1 for code-segment descriptors. + * + * This bit must be 0 for data-segment and system + * descriptors. + */ + uint8_t E : 1; - /** @brief Descriptor type. - * @details This bit must be 0 for system descriptors. - * @details This bit must be 1 for code or data segment descriptor. - */ - uint8_t S : 1; + /** + * Descriptor type. + * + * This bit must be 0 for system descriptors. + * + * This bit must be 1 for code or data segment + * descriptor. + */ + uint8_t S : 1; - /** @brief Descriptor privilege level. - * @details This field determines the privilege level of the segment. - * @details 0 = kernel mode, 3 = user mode. - */ - uint8_t DPL : 2; + /** + * Descriptor privilege level. + * + * This field determines the privilege level of the + * segment. + * + * 0 = kernel mode + * 3 = user mode + */ + uint8_t DPL : 2; - /** @brief Present bit. - * @details This bit must be 1 for all valid descriptors. - */ - uint8_t P : 1; - } __packed; - uint8_t Raw : 8; - } Access; - uint8_t Granularity; - uint8_t BaseHigh; - /* HIGH */ - uint32_t BaseUpper; - uint32_t Reserved; - } __packed; + /** + * Present bit. + * + * This bit must be 1 for all valid descriptors. + */ + uint8_t P : 1; + } __packed; + uint8_t Raw : 8; + } Access; + uint8_t Granularity; + uint8_t BaseHigh; + /* HIGH */ + uint32_t BaseUpper; + uint32_t Reserved; + } __packed; - struct TaskStateSegment - { - uint32_t Reserved0 __aligned(16); - uint64_t StackPointer[3]; - uint64_t Reserved1; - uint64_t InterruptStackTable[7]; - uint64_t Reserved2; - uint16_t Reserved3; - uint16_t IOMapBaseAddressOffset; - } __packed; + struct TaskStateSegment + { + uint32_t Reserved0 __aligned(16); + uint64_t StackPointer[3]; + uint64_t Reserved1; + uint64_t InterruptStackTable[7]; + uint64_t Reserved2; + uint16_t Reserved3; + uint16_t IOMapBaseAddressOffset; + } __packed; - struct GlobalDescriptorTableEntry - { - /** @brief Limit 0:15 */ - uint16_t Limit0 : 16; + struct GlobalDescriptorTableEntry + { + /** + * Limit 0:15 + */ + uint16_t Limit0 : 16; - /** @brief Low Base 0:15 */ - uint16_t BaseLow : 16; + /** + * Low Base 0:15 + */ + uint16_t BaseLow : 16; - /** @brief Middle Base 16:23 */ - uint8_t BaseMiddle : 8; + /** + * Middle Base 16:23 + */ + uint8_t BaseMiddle : 8; - /** @brief Access */ - union GlobalDescriptorTableAccess - { - struct - { - /** @brief Access bit. - * @note The CPU sets this bit to 1 when the segment is accessed. - */ - uint8_t A : 1; + /** + * Access + */ + union GlobalDescriptorTableAccess + { + struct + { + /** + * Access bit. + * + * @note The CPU sets this bit to 1 when the segment + * is accessed. + */ + uint8_t A : 1; - /** @brief Readable bit for code segments, writable bit for data segments. - * @details For code segments, this bit must be 1 for the segment to be readable. - * @details For data segments, this bit must be 1 for the segment to be writable. - */ - uint8_t RW : 1; + /** + * Readable bit for code segments, writable bit for + * data segments. + * + * Code Segment: + * This bit must be 1 for the segment to be readable. + * + * Data Segment: + * This bit must be 1 for the segment to be writable. + */ + uint8_t RW : 1; - /** @brief Direction bit for data segments, conforming bit for code segments. - * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). - * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. - */ - uint8_t DC : 1; + /** + * Direction bit for data segments, conforming bit for + * code segments. + * + * Code Segment: + * This bit must be 1 for code in the segment to be able + * to be executed from an equal or lower privilege level. + * + * Data Segment: + * This bit must be 1 for the segment to grow up (higher + * addresses). + */ + uint8_t DC : 1; - /** @brief Executable bit. - * @details This bit must be 1 for code-segment descriptors. - * @details This bit must be 0 for data-segment and system descriptors. - */ - uint8_t E : 1; + /** + * Executable bit. + * + * This bit must be 1 for code-segment descriptors. + * + * This bit must be 0 for data-segment and + * system descriptors. + */ + uint8_t E : 1; - /** @brief Descriptor type. - * @details This bit must be 0 for system descriptors. - * @details This bit must be 1 for code or data segment descriptor. - */ - uint8_t S : 1; + /** + * Descriptor type. + * + * This bit must be 0 for system descriptors. + * + * This bit must be 1 for code or data segment + * descriptor. + */ + uint8_t S : 1; - /** @brief Descriptor privilege level. - * @details This field determines the privilege level of the segment. - * @details 0 = kernel mode, 3 = user mode. - */ - uint8_t DPL : 2; + /** + * Descriptor privilege level. + * + * This field determines the privilege level of the + * segment. + * + * 0 = kernel mode + * 3 = user mode + */ + uint8_t DPL : 2; - /** @brief Present bit. - * @details This bit must be 1 for all valid descriptors. - */ - uint8_t P : 1; - } __packed; - uint8_t Raw : 8; - } Access; + /** + * Present bit. + * + * This bit must be 1 for all valid descriptors. + */ + uint8_t P : 1; + } __packed; + uint8_t Raw : 8; + } Access; - // /** @brief Limit 16:19 */ - // uint16_t Limit1 : 4; + // /** Limit 16:19 */ - /** @brief Flags */ - union GlobalDescriptorTableFlags - { - struct - { - uint8_t Reserved : 4; /* FIXME: Without this, the kernel crashes. */ - /** @brief Available bit. - * @details This bit is available for use by system software. - */ - uint8_t AVL : 1; + // uint16_t Limit1 : 4; - /** @brief Long mode. - * @details If the long mode bit is clear, the segment is in 32-bit protected mode. - * @details If the long mode bit is set, the segment is in 64-bit long mode. - */ - uint8_t L : 1; + /** + * Flags + */ + union GlobalDescriptorTableFlags + { + struct + { + /* FIXME: Without this, the kernel crashes. */ + uint8_t Reserved : 4; - /** @brief Size flag. - * @details If the size bit is clear, the segment is in 16-bit protected mode. - * @details If the size bit is set, the segment is in 32-bit protected mode. - */ - uint8_t DB : 1; + /** + * Available bit. + * + * This bit is available for use by system software. + */ + uint8_t AVL : 1; - /** @brief Granularity bit. - * @details If the granularity bit is clear, the segment limit is in 1 B blocks. - * @details If the granularity bit is set, the segment limit is in 4 KiB blocks. - */ - uint8_t G : 1; - } __packed; - uint8_t Raw : 8; - } Flags; + /** + * Long mode. + * + * If the long mode bit is clear, the segment is in + * 32-bit protected mode. + * + * If the long mode bit is set, the segment is in + * 64-bit long mode. + */ + uint8_t L : 1; - /** @brief High Base 24:31 */ - uint8_t BaseHigh : 8; - } __packed; + /** + * Size flag. + * + * If the size bit is clear, the segment is in + * 16-bit protected mode. + * + * If the size bit is set, the segment is in + * 32-bit protected mode. + */ + uint8_t DB : 1; - struct GlobalDescriptorTableEntries - { - GlobalDescriptorTableEntry Null; - GlobalDescriptorTableEntry Code; - GlobalDescriptorTableEntry Data; - GlobalDescriptorTableEntry UserData; - GlobalDescriptorTableEntry UserCode; - TaskStateSegmentEntry TaskStateSegment; - } __packed; + /** + * Granularity bit. + * + * If the granularity bit is clear, the segment limit + * is in 1 B blocks. + * + * If the granularity bit is set, the segment limit is + * in 4 KiB blocks. + */ + uint8_t G : 1; + } __packed; + uint8_t Raw : 8; + } Flags; - struct GlobalDescriptorTableDescriptor - { - /** @brief GDT entries length */ - uint16_t Length; - /** @brief GDT entries address */ - GlobalDescriptorTableEntries *Entries; - } __packed; + /** + * High Base 24:31 + */ + uint8_t BaseHigh : 8; + } __packed; - extern void *CPUStackPointer[]; - extern TaskStateSegment tss[]; - void Init(int Core); - void SetKernelStack(void *Stack); - void *GetKernelStack(); + struct GlobalDescriptorTableEntries + { + GlobalDescriptorTableEntry Null; + GlobalDescriptorTableEntry Code; + GlobalDescriptorTableEntry Data; + GlobalDescriptorTableEntry UserData; + GlobalDescriptorTableEntry UserCode; + TaskStateSegmentEntry TaskStateSegment; + } __packed; + + struct GlobalDescriptorTableDescriptor + { + /** + * GDT entries length + */ + uint16_t Length; + + /** + * GDT entries address + */ + GlobalDescriptorTableEntries *Entries; + } __packed; + + extern void *CPUStackPointer[]; + extern TaskStateSegment tss[]; + void Init(int Core); + void SetKernelStack(void *Stack); + void *GetKernelStack(); } #define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code) diff --git a/Architecture/i386/Memory/VirtualMemoryManager.cpp b/Architecture/i386/Memory/VirtualMemoryManager.cpp index 6008767..7480c75 100644 --- a/Architecture/i386/Memory/VirtualMemoryManager.cpp +++ b/Architecture/i386/Memory/VirtualMemoryManager.cpp @@ -34,7 +34,7 @@ namespace Memory if ((PDE->raw & Flag) > 0) { - if (Type == MapType::FourMB && PDE->PageSize) + if (Type == MapType::FourMiB && PDE->PageSize) return true; PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12); @@ -86,13 +86,13 @@ namespace Memory if (PDE->Present) { if (PDE->PageSize) - return MapType::FourMB; + return MapType::FourMiB; PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12); if (PTE) { if (PTE->Entries[Index.PTEIndex].Present) - return MapType::FourKB; + return MapType::FourKiB; } } return MapType::NoMapType; @@ -143,7 +143,7 @@ namespace Memory uint64_t DirectoryFlags = Flags & 0x3F; PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; - if (Type == MapType::FourMB) + if (Type == MapType::FourMiB) { PDE->raw |= (uintptr_t)Flags; PDE->PageSize = true; @@ -218,7 +218,7 @@ namespace Memory return; } - if (Type == MapType::FourMB && PDE->PageSize) + if (Type == MapType::FourMiB && PDE->PageSize) { PDE->Present = false; return; diff --git a/Architecture/i386/cpu/GlobalDescriptorTable.cpp b/Architecture/i386/cpu/GlobalDescriptorTable.cpp index c1a4a86..4795f88 100644 --- a/Architecture/i386/cpu/GlobalDescriptorTable.cpp +++ b/Architecture/i386/cpu/GlobalDescriptorTable.cpp @@ -24,249 +24,236 @@ namespace GlobalDescriptorTable { - static GlobalDescriptorTableEntries GDTEntriesTemplate = { - .Null = - { - .Limit0 = 0x0, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = {.Raw = 0x0}, - // .Limit1 = 0x0, - .Flags = {.Raw = 0x0}, - .BaseHigh = 0x0, - }, + static GlobalDescriptorTableEntries GDTEntriesTemplate = { + .Null = + { + .Limit0 = 0x0, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = {.Raw = 0x0}, + // .Limit1 = 0x0, + .Flags = {.Raw = 0x0}, + .BaseHigh = 0x0, + }, - .Code = - { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 1, - .S = 1, - .DPL = 0, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ + .Code = + { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 1, + .S = 1, + .DPL = 0, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - .AVL = 0, - .L = 0, - .DB = 1, - .G = 1, - }, - .BaseHigh = 0x0, - }, + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, - .Data = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 0, - .S = 1, - .DPL = 0, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ + .Data = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 0, + .S = 1, + .DPL = 0, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - .AVL = 0, - .L = 0, - .DB = 1, - .G = 1, - }, - .BaseHigh = 0x0, - }, + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, - .UserData = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 0, - .S = 1, - .DPL = 3, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ + .UserData = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 0, + .S = 1, + .DPL = 3, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - .AVL = 0, - .L = 0, - .DB = 1, - .G = 1, - }, - .BaseHigh = 0x0, - }, + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, - .UserCode = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 1, - .S = 1, - .DPL = 3, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ + .UserCode = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 1, + .S = 1, + .DPL = 3, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - .AVL = 0, - .L = 0, - .DB = 1, - .G = 1, - }, - .BaseHigh = 0x0, - }, + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, - .TaskStateSegment = {}, - }; + .TaskStateSegment = {}, + }; - GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16); - GlobalDescriptorTableDescriptor gdt[MAX_CPU] __aligned(16); + GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16); + GlobalDescriptorTableDescriptor gdt[MAX_CPU] __aligned(16); - TaskStateSegment tss[MAX_CPU] = { - 0, - {0, 0, 0}, - 0, - {0, 0, 0, 0, 0, 0, 0}, - 0, - 0, - 0, - }; + TaskStateSegment tss[MAX_CPU] = { + 0, + {0, 0, 0}, + 0, + {0, 0, 0, 0, 0, 0, 0}, + 0, + 0, + 0, + }; - void *CPUStackPointer[MAX_CPU]; + void *CPUStackPointer[MAX_CPU]; - SafeFunction void Init(int Core) - { - memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries)); - gdt[Core] = {.Length = sizeof(GlobalDescriptorTableEntries) - 1, .Entries = &GDTEntries[Core]}; + SafeFunction void Init(int Core) + { + memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries)); + gdt[Core] = {.Length = sizeof(GlobalDescriptorTableEntries) - 1, .Entries = &GDTEntries[Core]}; - debug("GDT: %#lx", &gdt[Core]); - debug("GDT KERNEL: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_KERNEL_CODE, - GDTEntries[Core].Code.Limit0, - GDTEntries[Core].Code.BaseLow, - GDTEntries[Core].Code.BaseMiddle, - GDTEntries[Core].Code.Access.Raw, - GDTEntries[Core].Code.Flags.Reserved, - GDTEntries[Core].Code.Flags.Raw & ~0xF, - GDTEntries[Core].Code.BaseHigh); + debug("GDT: %#lx", &gdt[Core]); + debug("GDT KERNEL: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_KERNEL_CODE, + GDTEntries[Core].Code.Limit0, + GDTEntries[Core].Code.BaseLow, + GDTEntries[Core].Code.BaseMiddle, + GDTEntries[Core].Code.Access.Raw, + GDTEntries[Core].Code.Flags.Reserved, + GDTEntries[Core].Code.Flags.Raw & ~0xF, + GDTEntries[Core].Code.BaseHigh); - debug("GDT KERNEL: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_KERNEL_DATA, - GDTEntries[Core].Data.Limit0, - GDTEntries[Core].Data.BaseLow, - GDTEntries[Core].Data.BaseMiddle, - GDTEntries[Core].Data.Access.Raw, - GDTEntries[Core].Data.Flags.Reserved, - GDTEntries[Core].Data.Flags.Raw & ~0xF, - GDTEntries[Core].Data.BaseHigh); + debug("GDT KERNEL: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_KERNEL_DATA, + GDTEntries[Core].Data.Limit0, + GDTEntries[Core].Data.BaseLow, + GDTEntries[Core].Data.BaseMiddle, + GDTEntries[Core].Data.Access.Raw, + GDTEntries[Core].Data.Flags.Reserved, + GDTEntries[Core].Data.Flags.Raw & ~0xF, + GDTEntries[Core].Data.BaseHigh); - debug("GDT USER: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_USER_CODE, - GDTEntries[Core].UserCode.Limit0, - GDTEntries[Core].UserCode.BaseLow, - GDTEntries[Core].UserCode.BaseMiddle, - GDTEntries[Core].UserCode.Access.Raw, - GDTEntries[Core].UserCode.Flags.Reserved, - GDTEntries[Core].UserCode.Flags.Raw & ~0xF, - GDTEntries[Core].UserCode.BaseHigh); + debug("GDT USER: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_USER_CODE, + GDTEntries[Core].UserCode.Limit0, + GDTEntries[Core].UserCode.BaseLow, + GDTEntries[Core].UserCode.BaseMiddle, + GDTEntries[Core].UserCode.Access.Raw, + GDTEntries[Core].UserCode.Flags.Reserved, + GDTEntries[Core].UserCode.Flags.Raw & ~0xF, + GDTEntries[Core].UserCode.BaseHigh); - debug("GDT USER: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_USER_DATA, - GDTEntries[Core].UserData.Limit0, - GDTEntries[Core].UserData.BaseLow, - GDTEntries[Core].UserData.BaseMiddle, - GDTEntries[Core].UserData.Access.Raw, - GDTEntries[Core].UserData.Flags.Reserved, - GDTEntries[Core].UserData.Flags.Raw & ~0xF, - GDTEntries[Core].UserData.BaseHigh); + debug("GDT USER: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_USER_DATA, + GDTEntries[Core].UserData.Limit0, + GDTEntries[Core].UserData.BaseLow, + GDTEntries[Core].UserData.BaseMiddle, + GDTEntries[Core].UserData.Access.Raw, + GDTEntries[Core].UserData.Flags.Reserved, + GDTEntries[Core].UserData.Flags.Raw & ~0xF, + GDTEntries[Core].UserData.BaseHigh); - CPU::x32::lgdt(&gdt[Core]); + CPU::x32::lgdt(&gdt[Core]); - asmv("mov %%esp, %%eax\n" - "push $16\n" - "push %%eax\n" - "pushf\n" - "push $8\n" - "push $1f\n" - "iret\n" - "1:\n" - "movw $16, %%ax\n" - "movw %%ax, %%ds\n" - "movw %%ax, %%es\n" :: - : "memory", "eax"); + asmv("mov %%esp, %%eax\n" + "push $16\n" + "push %%eax\n" + "pushf\n" + "push $8\n" + "push $1f\n" + "iret\n" + "1:\n" + "movw $16, %%ax\n" + "movw %%ax, %%ds\n" + "movw %%ax, %%es\n" :: + : "memory", "eax"); - CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); - memset(CPUStackPointer[Core], 0, STACK_SIZE); - debug("CPU %d Stack Pointer: %#lx-%#lx (%d pages)", Core, - CPUStackPointer[Core], (uintptr_t)CPUStackPointer[Core] + STACK_SIZE, - TO_PAGES(STACK_SIZE + 1)); + CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); + memset(CPUStackPointer[Core], 0, STACK_SIZE); + debug("CPU %d Stack Pointer: %#lx-%#lx (%d pages)", Core, + CPUStackPointer[Core], (uintptr_t)CPUStackPointer[Core] + STACK_SIZE, + TO_PAGES(STACK_SIZE + 1)); - uintptr_t Base = (uintptr_t)&tss[Core]; - size_t Limit = Base + sizeof(TaskStateSegment); - gdt[Core].Entries->TaskStateSegment.Limit = Limit & 0xFFFF; - gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; - gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF; - gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF; - gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); - gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; - gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF); + uintptr_t Base = (uintptr_t)&tss[Core]; + size_t Limit = Base + sizeof(TaskStateSegment); + gdt[Core].Entries->TaskStateSegment.Limit = Limit & 0xFFFF; + gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; + gdt[Core].Entries->TaskStateSegment.BaseMiddle = uint8_t((Base >> 16) & 0xFF); + gdt[Core].Entries->TaskStateSegment.BaseHigh = uint8_t((Base >> 24) & 0xFF); + gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); + gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; + gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF); - tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment); - tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE; - tss[Core].StackPointer[1] = 0x0; - tss[Core].StackPointer[2] = 0x0; + tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment); + tss[Core].StackPointer[0] = (uint32_t)CPUStackPointer[Core] + STACK_SIZE; + tss[Core].StackPointer[1] = 0x0; + tss[Core].StackPointer[2] = 0x0; - for (size_t i = 0; i < sizeof(tss[Core].InterruptStackTable) / sizeof(tss[Core].InterruptStackTable[7]); i++) - { - void *NewStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); + for (size_t i = 0; i < sizeof(tss[Core].InterruptStackTable) / sizeof(tss[Core].InterruptStackTable[7]); i++) + { + void *NewStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); - tss[Core].InterruptStackTable[i] = (uint64_t)NewStack + STACK_SIZE; - memset((void *)(tss[Core].InterruptStackTable[i] - STACK_SIZE), 0, STACK_SIZE); - debug("IST-%d: %#lx-%#lx", i, NewStack, (uintptr_t)NewStack + STACK_SIZE); - } + tss[Core].InterruptStackTable[i] = (uint32_t)NewStack + STACK_SIZE; + memset((void *)(tss[Core].InterruptStackTable[i] - STACK_SIZE), 0, STACK_SIZE); + debug("IST-%d: %#lx-%#lx", i, NewStack, (uintptr_t)NewStack + STACK_SIZE); + } - CPU::x32::ltr(GDT_TSS); - debug("Global Descriptor Table initialized"); - } + CPU::x32::ltr(GDT_TSS); + debug("Global Descriptor Table initialized"); + } - SafeFunction void SetKernelStack(void *Stack) - { - long CPUID = GetCurrentCPU()->ID; - if (Stack != nullptr) - tss[CPUID].StackPointer[0] = (uint64_t)Stack; - else - tss[CPUID].StackPointer[0] = (uint64_t)CPUStackPointer[CPUID] + STACK_SIZE; + SafeFunction void SetKernelStack(void *Stack) + { + long CPUID = GetCurrentCPU()->ID; + } - /* - FIXME: There's a bug in kernel which if - we won't update "tss[CPUID].StackPointer[0]" - with the current stack pointer, the kernel - will crash. - */ - asmv("mov %%esp, %0" - : "=r"(tss[CPUID].StackPointer[0])); - } - - void *GetKernelStack() { return (void *)tss[GetCurrentCPU()->ID].StackPointer[0]; } + void *GetKernelStack() { return (void *)nullptr; } } diff --git a/Architecture/i386/cpu/gdt.hpp b/Architecture/i386/cpu/gdt.hpp index 84b0e8b..43ed227 100644 --- a/Architecture/i386/cpu/gdt.hpp +++ b/Architecture/i386/cpu/gdt.hpp @@ -22,197 +22,197 @@ namespace GlobalDescriptorTable { - struct TaskStateSegmentEntry - { - /* LOW */ - uint16_t Limit; - uint16_t BaseLow; - uint8_t BaseMiddle; - union GlobalDescriptorTableAccess - { - struct - { - /** @brief Access bit. - * @note The CPU sets this bit to 1 when the segment is accessed. - */ - uint8_t A : 1; + struct TaskStateSegmentEntry + { + /* LOW */ + uint16_t Limit; + uint16_t BaseLow; + uint8_t BaseMiddle; + union GlobalDescriptorTableAccess + { + struct + { + /** @brief Access bit. + * @note The CPU sets this bit to 1 when the segment is accessed. + */ + uint8_t A : 1; - /** @brief Readable bit for code segments, writable bit for data segments. - * @details For code segments, this bit must be 1 for the segment to be readable. - * @details For data segments, this bit must be 1 for the segment to be writable. - */ - uint8_t RW : 1; + /** @brief Readable bit for code segments, writable bit for data segments. + * @details For code segments, this bit must be 1 for the segment to be readable. + * @details For data segments, this bit must be 1 for the segment to be writable. + */ + uint8_t RW : 1; - /** @brief Direction bit for data segments, conforming bit for code segments. - * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). - * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. - */ - uint8_t DC : 1; + /** @brief Direction bit for data segments, conforming bit for code segments. + * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). + * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. + */ + uint8_t DC : 1; - /** @brief Executable bit. - * @details This bit must be 1 for code-segment descriptors. - * @details This bit must be 0 for data-segment and system descriptors. - */ - uint8_t E : 1; + /** @brief Executable bit. + * @details This bit must be 1 for code-segment descriptors. + * @details This bit must be 0 for data-segment and system descriptors. + */ + uint8_t E : 1; - /** @brief Descriptor type. - * @details This bit must be 0 for system descriptors. - * @details This bit must be 1 for code or data segment descriptor. - */ - uint8_t S : 1; + /** @brief Descriptor type. + * @details This bit must be 0 for system descriptors. + * @details This bit must be 1 for code or data segment descriptor. + */ + uint8_t S : 1; - /** @brief Descriptor privilege level. - * @details This field determines the privilege level of the segment. - * @details 0 = kernel mode, 3 = user mode. - */ - uint8_t DPL : 2; + /** @brief Descriptor privilege level. + * @details This field determines the privilege level of the segment. + * @details 0 = kernel mode, 3 = user mode. + */ + uint8_t DPL : 2; - /** @brief Present bit. - * @details This bit must be 1 for all valid descriptors. - */ - uint8_t P : 1; - } __packed; - uint8_t Raw : 8; - } Access; - uint8_t Granularity; - uint8_t BaseHigh; - /* HIGH */ - uint32_t BaseUpper; - uint32_t Reserved; - } __packed; + /** @brief Present bit. + * @details This bit must be 1 for all valid descriptors. + */ + uint8_t P : 1; + } __packed; + uint8_t Raw : 8; + } Access; + uint8_t Granularity; + uint8_t BaseHigh; + /* HIGH */ + uint32_t BaseUpper; + uint32_t Reserved; + } __packed; - struct TaskStateSegment - { - uint32_t Reserved0 __aligned(16); - uint64_t StackPointer[3]; - uint64_t Reserved1; - uint64_t InterruptStackTable[7]; - uint64_t Reserved2; - uint16_t Reserved3; - uint16_t IOMapBaseAddressOffset; - } __packed; + struct TaskStateSegment + { + uint32_t Reserved0 __aligned(16); + uint64_t StackPointer[3]; + uint64_t Reserved1; + uint64_t InterruptStackTable[7]; + uint64_t Reserved2; + uint16_t Reserved3; + uint16_t IOMapBaseAddressOffset; + } __packed; - struct GlobalDescriptorTableEntry - { - /** @brief Limit 0:15 */ - uint16_t Limit0 : 16; + struct GlobalDescriptorTableEntry + { + /** @brief Limit 0:15 */ + uint16_t Limit0 : 16; - /** @brief Low Base 0:15 */ - uint16_t BaseLow : 16; + /** @brief Low Base 0:15 */ + uint16_t BaseLow : 16; - /** @brief Middle Base 16:23 */ - uint8_t BaseMiddle : 8; + /** @brief Middle Base 16:23 */ + uint8_t BaseMiddle : 8; - /** @brief Access */ - union GlobalDescriptorTableAccess - { - struct - { - /** @brief Access bit. - * @note The CPU sets this bit to 1 when the segment is accessed. - */ - uint8_t A : 1; + /** @brief Access */ + union GlobalDescriptorTableAccess + { + struct + { + /** @brief Access bit. + * @note The CPU sets this bit to 1 when the segment is accessed. + */ + uint8_t A : 1; - /** @brief Readable bit for code segments, writable bit for data segments. - * @details For code segments, this bit must be 1 for the segment to be readable. - * @details For data segments, this bit must be 1 for the segment to be writable. - */ - uint8_t RW : 1; + /** @brief Readable bit for code segments, writable bit for data segments. + * @details For code segments, this bit must be 1 for the segment to be readable. + * @details For data segments, this bit must be 1 for the segment to be writable. + */ + uint8_t RW : 1; - /** @brief Direction bit for data segments, conforming bit for code segments. - * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). - * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. - */ - uint8_t DC : 1; + /** @brief Direction bit for data segments, conforming bit for code segments. + * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). + * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. + */ + uint8_t DC : 1; - /** @brief Executable bit. - * @details This bit must be 1 for code-segment descriptors. - * @details This bit must be 0 for data-segment and system descriptors. - */ - uint8_t E : 1; + /** @brief Executable bit. + * @details This bit must be 1 for code-segment descriptors. + * @details This bit must be 0 for data-segment and system descriptors. + */ + uint8_t E : 1; - /** @brief Descriptor type. - * @details This bit must be 0 for system descriptors. - * @details This bit must be 1 for code or data segment descriptor. - */ - uint8_t S : 1; + /** @brief Descriptor type. + * @details This bit must be 0 for system descriptors. + * @details This bit must be 1 for code or data segment descriptor. + */ + uint8_t S : 1; - /** @brief Descriptor privilege level. - * @details This field determines the privilege level of the segment. - * @details 0 = kernel mode, 3 = user mode. - */ - uint8_t DPL : 2; + /** @brief Descriptor privilege level. + * @details This field determines the privilege level of the segment. + * @details 0 = kernel mode, 3 = user mode. + */ + uint8_t DPL : 2; - /** @brief Present bit. - * @details This bit must be 1 for all valid descriptors. - */ - uint8_t P : 1; - } __packed; - uint8_t Raw : 8; - } Access; + /** @brief Present bit. + * @details This bit must be 1 for all valid descriptors. + */ + uint8_t P : 1; + } __packed; + uint8_t Raw : 8; + } Access; - // /** @brief Limit 16:19 */ - // uint16_t Limit1 : 4; + // /** @brief Limit 16:19 */ + // uint16_t Limit1 : 4; - /** @brief Flags */ - union GlobalDescriptorTableFlags - { - struct - { - uint8_t Reserved : 4; /* FIXME: Without this, the kernel crashes. */ - /** @brief Available bit. - * @details This bit is available for use by system software. - */ - uint8_t AVL : 1; + /** @brief Flags */ + union GlobalDescriptorTableFlags + { + struct + { + uint8_t Reserved : 4; /* FIXME: Without this, the kernel crashes. */ + /** @brief Available bit. + * @details This bit is available for use by system software. + */ + uint8_t AVL : 1; - /** @brief Long mode. - * @details If the long mode bit is clear, the segment is in 32-bit protected mode. - * @details If the long mode bit is set, the segment is in 64-bit long mode. - */ - uint8_t L : 1; + /** @brief Long mode. + * @details If the long mode bit is clear, the segment is in 32-bit protected mode. + * @details If the long mode bit is set, the segment is in 64-bit long mode. + */ + uint8_t L : 1; - /** @brief Size flag. - * @details If the size bit is clear, the segment is in 16-bit protected mode. - * @details If the size bit is set, the segment is in 32-bit protected mode. - */ - uint8_t DB : 1; + /** @brief Size flag. + * @details If the size bit is clear, the segment is in 16-bit protected mode. + * @details If the size bit is set, the segment is in 32-bit protected mode. + */ + uint8_t DB : 1; - /** @brief Granularity bit. - * @details If the granularity bit is clear, the segment limit is in 1 B blocks. - * @details If the granularity bit is set, the segment limit is in 4 KiB blocks. - */ - uint8_t G : 1; - } __packed; - uint8_t Raw : 8; - } Flags; + /** @brief Granularity bit. + * @details If the granularity bit is clear, the segment limit is in 1 B blocks. + * @details If the granularity bit is set, the segment limit is in 4 KiB blocks. + */ + uint8_t G : 1; + } __packed; + uint8_t Raw : 8; + } Flags; - /** @brief High Base 24:31 */ - uint8_t BaseHigh : 8; - } __packed; + /** @brief High Base 24:31 */ + uint8_t BaseHigh : 8; + } __packed; - struct GlobalDescriptorTableEntries - { - GlobalDescriptorTableEntry Null; - GlobalDescriptorTableEntry Code; - GlobalDescriptorTableEntry Data; - GlobalDescriptorTableEntry UserData; - GlobalDescriptorTableEntry UserCode; - TaskStateSegmentEntry TaskStateSegment; - } __packed; + struct GlobalDescriptorTableEntries + { + GlobalDescriptorTableEntry Null; + GlobalDescriptorTableEntry Code; + GlobalDescriptorTableEntry Data; + GlobalDescriptorTableEntry UserData; + GlobalDescriptorTableEntry UserCode; + TaskStateSegmentEntry TaskStateSegment; + } __packed; - struct GlobalDescriptorTableDescriptor - { - /** @brief GDT entries length */ - uint16_t Length; - /** @brief GDT entries address */ - GlobalDescriptorTableEntries *Entries; - } __packed; + struct GlobalDescriptorTableDescriptor + { + /** @brief GDT entries length */ + uint16_t Length; + /** @brief GDT entries address */ + GlobalDescriptorTableEntries *Entries; + } __packed; - extern void *CPUStackPointer[]; - extern TaskStateSegment tss[]; - void Init(int Core); - void SetKernelStack(void *Stack); - void *GetKernelStack(); + extern void *CPUStackPointer[]; + extern TaskStateSegment tss[]; + void Init(int Core); + void SetKernelStack(void *Stack); + void *GetKernelStack(); } #define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code) diff --git a/Core/CPU.cpp b/Core/CPU.cpp index 51881a4..3702222 100644 --- a/Core/CPU.cpp +++ b/Core/CPU.cpp @@ -28,7 +28,7 @@ namespace CPU { static bool SSEEnabled = false; - char *Vendor() + const char *Vendor() { static char Vendor[13] = {0}; if (Vendor[0] != 0) @@ -52,7 +52,7 @@ namespace CPU return Vendor; } - char *Name() + const char *Name() { static char Name[49] = {0}; if (Name[0] != 0) @@ -98,7 +98,7 @@ namespace CPU return Name; } - char *Hypervisor() + const char *Hypervisor() { static char Hypervisor[13] = {0}; if (Hypervisor[0] != 0) @@ -255,8 +255,7 @@ namespace CPU bool SSEEnableAfter = false; /* Not sure if my code is not working properly or something else is the issue. */ - if ((strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0 && - strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) && + if ((strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) && SSESupport) { debug("Enabling SSE support..."); @@ -438,16 +437,16 @@ namespace CPU #endif } - uintptr_t Counter() + uint64_t Counter() { // TODO: Get the counter from the x2APIC or any other timer that is available. (TSC is not available on all CPUs) - uintptr_t Counter; -#if defined(a64) + uint64_t Counter; +#if defined(a86) + uint32_t eax, edx; asmv("rdtsc" - : "=A"(Counter)); -#elif defined(a32) - asmv("rdtsc" - : "=A"(Counter)); + : "=a"(eax), + "=d"(edx)); + Counter = ((uint64_t)eax) | (((uint64_t)edx) << 32); #elif defined(aa64) asmv("mrs %0, cntvct_el0" : "=r"(Counter)); diff --git a/Core/Crash/CrashHandler.cpp b/Core/Crash/CrashHandler.cpp index 21dd10c..9314779 100644 --- a/Core/Crash/CrashHandler.cpp +++ b/Core/Crash/CrashHandler.cpp @@ -46,1083 +46,1086 @@ NewLock(UserInputLock); namespace CrashHandler { - uintptr_t PageFaultAddress = 0; - void *EHIntFrames[INT_FRAMES_MAX]; - static bool ExceptionOccurred = false; - int SBIdx = 255; + uintptr_t PageFaultAddress = 0; + void *EHIntFrames[INT_FRAMES_MAX]; + static bool ExceptionOccurred = false; + int SBIdx = 255; - SafeFunction void printfWrapper(char c, void *unused) - { - Display->Print(c, SBIdx, true); - UNUSED(unused); - } + SafeFunction void printfWrapper(char c, void *unused) + { + Display->Print(c, SBIdx, true); + UNUSED(unused); + } - SafeFunction void EHPrint(const char *Format, ...) - { - va_list args; - va_start(args, Format); - vfctprintf(printfWrapper, NULL, Format, args); - va_end(args); - } + SafeFunction void EHPrint(const char *Format, ...) + { + va_list args; + va_start(args, Format); + vfctprintf(printfWrapper, NULL, Format, args); + va_end(args); + } - SafeFunction void EHDumpData(void *Address, unsigned long Length) - { - EHPrint("-------------------------------------------------------------------------\n"); - Display->SetBuffer(SBIdx); - unsigned char *AddressChar = (unsigned char *)Address; - unsigned char Buffer[17]; - unsigned long Iterate; - for (Iterate = 0; Iterate < Length; Iterate++) - { - if ((Iterate % 16) == 0) - { - if (Iterate != 0) - EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer); - EHPrint(" \e9E9E9E%04x\eAABBCC ", Iterate); - Display->SetBuffer(SBIdx); - } - EHPrint(" \e4287f5%02x\eAABBCC", AddressChar[Iterate]); - if ((AddressChar[Iterate] < 0x20) || (AddressChar[Iterate] > 0x7e)) - Buffer[Iterate % 16] = '.'; - else - Buffer[Iterate % 16] = AddressChar[Iterate]; - Buffer[(Iterate % 16) + 1] = '\0'; - } + SafeFunction void EHDumpData(void *Address, unsigned long Length) + { + EHPrint("-------------------------------------------------------------------------\n"); + Display->SetBuffer(SBIdx); + unsigned char *AddressChar = (unsigned char *)Address; + unsigned char Buffer[17]; + unsigned long Iterate; + for (Iterate = 0; Iterate < Length; Iterate++) + { + if ((Iterate % 16) == 0) + { + if (Iterate != 0) + EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer); + EHPrint(" \e9E9E9E%04x\eAABBCC ", Iterate); + Display->SetBuffer(SBIdx); + } + EHPrint(" \e4287f5%02x\eAABBCC", AddressChar[Iterate]); + if ((AddressChar[Iterate] < 0x20) || (AddressChar[Iterate] > 0x7e)) + Buffer[Iterate % 16] = '.'; + else + Buffer[Iterate % 16] = AddressChar[Iterate]; + Buffer[(Iterate % 16) + 1] = '\0'; + } - while ((Iterate % 16) != 0) - { - EHPrint(" "); - Display->SetBuffer(SBIdx); - Iterate++; - } + while ((Iterate % 16) != 0) + { + EHPrint(" "); + Display->SetBuffer(SBIdx); + Iterate++; + } - EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer); - EHPrint("-------------------------------------------------------------------------\n\n."); - Display->SetBuffer(SBIdx); - } + EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer); + EHPrint("-------------------------------------------------------------------------\n\n."); + Display->SetBuffer(SBIdx); + } - SafeFunction char *TrimWhiteSpace(char *str) - { - char *end; - while (*str == ' ') - str++; - if (*str == 0) - return str; - end = str + strlen(str) - 1; - while (end > str && *end == ' ') - end--; - *(end + 1) = 0; - return str; - } + SafeFunction char *TrimWhiteSpace(char *str) + { + char *end; + while (*str == ' ') + str++; + if (*str == 0) + return str; + end = str + strlen(str) - 1; + while (end > str && *end == ' ') + end--; + *(end + 1) = 0; + return str; + } - CRData crashdata = {}; + CRData crashdata = {}; - SafeFunction void DisplayTopOverlay() - { - Video::ScreenBuffer *sb = Display->GetBuffer(SBIdx); - Video::Font *f = Display->GetCurrentFont(); - Video::FontInfo fi = f->GetInfo(); + SafeFunction void DisplayTopOverlay() + { + Video::ScreenBuffer *sb = Display->GetBuffer(SBIdx); + Video::Font *f = Display->GetCurrentFont(); + Video::FontInfo fi = f->GetInfo(); - for (uint32_t i = 0; i < sb->Width; i++) - for (uint32_t j = 0; j < fi.Height + 8; j++) - Display->SetPixel(i, j, 0x282828, SBIdx); + for (uint32_t i = 0; i < sb->Width; i++) + for (uint32_t j = 0; j < fi.Height + 8; j++) + Display->SetPixel(i, j, 0x282828, SBIdx); - Display->SetBufferCursor(SBIdx, 8, (fi.Height + 8) / 6); - switch (SBIdx) - { - case 255: - { - EHPrint("\eAAAAAAMAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE"); - break; - } - case 254: - { - EHPrint("\e606060MAIN \eAAAAAADETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE"); - break; - } - case 253: - { - EHPrint("\e606060MAIN \e606060DETAILS \eAAAAAAFRAMES \e606060TASKS \e606060CONSOLE"); - break; - } - case 252: - { - EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \eAAAAAATASKS \e606060CONSOLE"); - break; - } - case 251: - { - EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \eAAAAAACONSOLE"); - break; - } - default: - { - EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE"); - break; - } - } - EHPrint(" \e00AAFF%ldMB / %ldMB (%ldMB Reserved)", - TO_MB(KernelAllocator.GetUsedMemory()), - TO_MB(KernelAllocator.GetTotalMemory()), - TO_MB(KernelAllocator.GetReservedMemory())); - EHPrint(" \eAA0F0F%s", CPU::Hypervisor()); - EHPrint(" \eAAF00F%s", CPU::Vendor()); - EHPrint(" \eAA00FF%s", CPU::Name()); - Display->SetBufferCursor(SBIdx, 0, fi.Height + 10); + Display->SetBufferCursor(SBIdx, 8, (fi.Height + 8) / 6); + switch (SBIdx) + { + case 255: + { + EHPrint("\eAAAAAAMAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE"); + break; + } + case 254: + { + EHPrint("\e606060MAIN \eAAAAAADETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE"); + break; + } + case 253: + { + EHPrint("\e606060MAIN \e606060DETAILS \eAAAAAAFRAMES \e606060TASKS \e606060CONSOLE"); + break; + } + case 252: + { + EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \eAAAAAATASKS \e606060CONSOLE"); + break; + } + case 251: + { + EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \eAAAAAACONSOLE"); + break; + } + default: + { + EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE"); + break; + } + } + EHPrint(" \e00AAFF%ld MiB / %ld MiB (%ld MiB Reserved)", + TO_MiB(KernelAllocator.GetUsedMemory()), + TO_MiB(KernelAllocator.GetTotalMemory()), + TO_MiB(KernelAllocator.GetReservedMemory())); + EHPrint(" \eAA0F0F%s", CPU::Hypervisor()); + EHPrint(" \eAAF00F%s", CPU::Vendor()); + EHPrint(" \eAA00FF%s", CPU::Name()); + Display->SetBufferCursor(SBIdx, 0, fi.Height + 10); - /* https://imgflip.com/i/77slbl */ - if ((Random::rand32() % 100) >= 98) - { - debug("Easter egg activated!"); - int BaseXOffset = sb->Width - 14; - int BaseYOffset = 8; - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 0, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 0, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 0, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 0, 0x21852E, SBIdx); + /* https://imgflip.com/i/77slbl */ + if ((Random::rand32() % 100) >= 98) + { + debug("Easter egg activated!"); + int BaseXOffset = sb->Width - 14; + int BaseYOffset = 8; + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 0, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 0, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 0, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 0, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 1, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 1, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 1, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 1, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 1, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 1, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 8, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 1, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 8, BaseYOffset + 1, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 2, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 2, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 2, 0xFFFFFF, SBIdx); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 2, 0x000000, SBIdx); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 2, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 2, 0xFFFFFF, SBIdx); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 2, 0x000000, SBIdx); - Display->SetPixel(BaseXOffset + 8, BaseYOffset + 2, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 2, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 2, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 2, 0xFFFFFF, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 2, 0x000000, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 2, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 2, 0xFFFFFF, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 2, 0x000000, SBIdx); + Display->SetPixel(BaseXOffset + 8, BaseYOffset + 2, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 3, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 3, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 3, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 3, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 3, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 3, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 3, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 3, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 0, BaseYOffset + 4, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 4, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 4, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 4, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 4, 0xA84832, SBIdx); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 4, 0xA84832, SBIdx); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 4, 0xA84832, SBIdx); - Display->SetPixel(BaseXOffset + 7, BaseYOffset + 4, 0xA84832, SBIdx); + Display->SetPixel(BaseXOffset + 0, BaseYOffset + 4, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 4, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 4, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 4, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 4, 0xA84832, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 4, 0xA84832, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 4, 0xA84832, SBIdx); + Display->SetPixel(BaseXOffset + 7, BaseYOffset + 4, 0xA84832, SBIdx); - Display->SetPixel(BaseXOffset + 0, BaseYOffset + 5, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 5, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 5, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 5, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 5, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 5, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 0, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 5, 0x21852E, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 5, 0x21852E, SBIdx); - Display->SetPixel(BaseXOffset + 0, BaseYOffset + 6, 0x1216FF, SBIdx); - Display->SetPixel(BaseXOffset + 1, BaseYOffset + 6, 0x1216FF, SBIdx); - Display->SetPixel(BaseXOffset + 2, BaseYOffset + 6, 0x1216FF, SBIdx); - Display->SetPixel(BaseXOffset + 3, BaseYOffset + 6, 0x1216FF, SBIdx); - Display->SetPixel(BaseXOffset + 4, BaseYOffset + 6, 0x1216FF, SBIdx); - Display->SetPixel(BaseXOffset + 5, BaseYOffset + 6, 0x1216FF, SBIdx); - Display->SetPixel(BaseXOffset + 6, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 0, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 1, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 2, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 3, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 4, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 5, BaseYOffset + 6, 0x1216FF, SBIdx); + Display->SetPixel(BaseXOffset + 6, BaseYOffset + 6, 0x1216FF, SBIdx); - Display->SetBuffer(SBIdx); - } - } + Display->SetBuffer(SBIdx); + } + } - SafeFunction void DisplayBottomOverlay() - { - Video::ScreenBuffer *sb = Display->GetBuffer(SBIdx); - Video::Font *f = Display->GetCurrentFont(); - Video::FontInfo fi = f->GetInfo(); + SafeFunction void DisplayBottomOverlay() + { + Video::ScreenBuffer *sb = Display->GetBuffer(SBIdx); + Video::Font *f = Display->GetCurrentFont(); + Video::FontInfo fi = f->GetInfo(); - for (uint32_t i = 0; i < sb->Width; i++) - for (uint32_t j = sb->Height - fi.Height - 8; j < sb->Height; j++) - Display->SetPixel(i, j, 0x282828, SBIdx); + for (uint32_t i = 0; i < sb->Width; i++) + for (uint32_t j = sb->Height - fi.Height - 8; j < sb->Height; j++) + Display->SetPixel(i, j, 0x282828, SBIdx); - Display->SetBufferCursor(SBIdx, 8, sb->Height - fi.Height - 4); - EHPrint("\eAAAAAA> \eFAFAFA"); - } + Display->SetBufferCursor(SBIdx, 8, sb->Height - fi.Height - 4); + EHPrint("\eAAAAAA> \eFAFAFA"); + } - SafeFunction void ArrowInput(uint8_t key) - { - switch (key) - { - case KEY_D_UP: - if (SBIdx < 255) - SBIdx++; - else - return; - break; - case KEY_D_LEFT: - if (SBIdx < 255) - SBIdx++; - else - return; - break; - case KEY_D_RIGHT: - if (SBIdx > 251) - SBIdx--; - else - return; - break; - case KEY_D_DOWN: - if (SBIdx > 251) - SBIdx--; - else - return; - break; - default: - break; - } - Display->ClearBuffer(SBIdx); - DisplayTopOverlay(); - EHPrint("\eFAFAFA"); + SafeFunction void ArrowInput(uint8_t key) + { + switch (key) + { + case KEY_D_UP: + if (SBIdx < 255) + SBIdx++; + else + return; + break; + case KEY_D_LEFT: + if (SBIdx < 255) + SBIdx++; + else + return; + break; + case KEY_D_RIGHT: + if (SBIdx > 251) + SBIdx--; + else + return; + break; + case KEY_D_DOWN: + if (SBIdx > 251) + SBIdx--; + else + return; + break; + default: + break; + } + Display->ClearBuffer(SBIdx); + DisplayTopOverlay(); + EHPrint("\eFAFAFA"); - switch (SBIdx) - { - case 255: - { - DisplayMainScreen(crashdata); - break; - } - case 254: - { - DisplayDetailsScreen(crashdata); - break; - } - case 253: - { - DisplayStackFrameScreen(crashdata); - break; - } - case 252: - { - DisplayTasksScreen(crashdata); - break; - } - case 251: - { - DisplayConsoleScreen(crashdata); - break; - } - default: - { - break; - } - } - DisplayBottomOverlay(); - Display->SetBuffer(SBIdx); - } + switch (SBIdx) + { + case 255: + { + DisplayMainScreen(crashdata); + break; + } + case 254: + { + DisplayDetailsScreen(crashdata); + break; + } + case 253: + { + DisplayStackFrameScreen(crashdata); + break; + } + case 252: + { + DisplayTasksScreen(crashdata); + break; + } + case 251: + { + DisplayConsoleScreen(crashdata); + break; + } + default: + { + break; + } + } + DisplayBottomOverlay(); + Display->SetBuffer(SBIdx); + } - SafeFunction void UserInput(char *Input) - { - SmartCriticalSection(UserInputLock); - Display->ClearBuffer(SBIdx); - DisplayTopOverlay(); - EHPrint("\eFAFAFA"); + SafeFunction void UserInput(char *Input) + { + SmartCriticalSection(UserInputLock); + Display->ClearBuffer(SBIdx); + DisplayTopOverlay(); + EHPrint("\eFAFAFA"); - if (strcmp(Input, "help") == 0) - { - EHPrint("Available commands are:\n"); - EHPrint("exit - Shutdown the OS.\n"); - EHPrint("reboot - Reboot the OS.\n"); - EHPrint("help - Display this help message.\n"); - EHPrint("showbuf,sb - Display the contents of a screen buffer.\n"); - EHPrint(" - A sleep timer will be enabled. This will cause the OS to sleep for an unknown amount of time.\n"); - EHPrint(" - \eFF4400WARNING: This can crash the system if a wrong buffer is selected.\eFAFAFA\n"); - EHPrint("ifr - Show interrupt frames.\n"); - EHPrint("tlb
- Print the page table entries\n"); - EHPrint("bitmap - Print the memory bitmap\n"); - EHPrint("mem - Print the memory allocation\n"); - EHPrint("cr - Print the CPU control register\n"); - EHPrint("tss - Print the CPU task state segment\n"); - EHPrint("dump
- Dump memory\n"); - EHPrint(" - \eFF4400WARNING: This can crash the system if you try to read from an unmapped page.\eFAFAFA\n"); - EHPrint("uartmemdmp - Dump the memory of a UART.\n"); - EHPrint("main - Show the main screen.\n"); - EHPrint("details - Show the details screen.\n"); - EHPrint("frames - Show the stack frame screen.\n"); - EHPrint("tasks - Show the tasks screen.\n"); - EHPrint("console - Show the console screen.\n"); - EHPrint("Also, you can use the arrow keys to navigate between the screens.\n"); - EHPrint("=========================================================================\n"); - EHPrint("Kernel Compiled at: %s %s with C++ Standard: %d\n", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD); - EHPrint("C++ Language Version (__cplusplus): %ld\n", __cplusplus); - } - else if (strcmp(Input, "exit") == 0) - { - PowerManager->Shutdown(); - EHPrint("\eFFFFFFNow it's safe to turn off your computer."); - Display->SetBuffer(SBIdx); - CPU::Stop(); - } - else if (strcmp(Input, "reboot") == 0) - { - PowerManager->Reboot(); - EHPrint("\eFFFFFFNow it's safe to reboot your computer."); - Display->SetBuffer(SBIdx); - CPU::Stop(); - } - else if (strncmp(Input, "showbuf", 7) == 0 || strncmp(Input, "sb", 2) == 0) - { - char *arg = TrimWhiteSpace(Input + 7); - int tmpidx = SBIdx; - SBIdx = atoi(arg); - Display->SetBuffer(SBIdx); + if (strcmp(Input, "help") == 0) + { + EHPrint("Available commands are:\n"); + EHPrint("exit - Shutdown the OS.\n"); + EHPrint("reboot - Reboot the OS.\n"); + EHPrint("help - Display this help message.\n"); + EHPrint("showbuf,sb - Display the contents of a screen buffer.\n"); + EHPrint(" - A sleep timer will be enabled. This will cause the OS to sleep for an unknown amount of time.\n"); + EHPrint(" - \eFF4400WARNING: This can crash the system if a wrong buffer is selected.\eFAFAFA\n"); + EHPrint("ifr - Show interrupt frames.\n"); + EHPrint("tlb
- Print the page table entries\n"); + EHPrint("bitmap - Print the memory bitmap\n"); + EHPrint("mem - Print the memory allocation\n"); + EHPrint("cr - Print the CPU control register\n"); + EHPrint("tss - Print the CPU task state segment\n"); + EHPrint("dump
- Dump memory\n"); + EHPrint(" - \eFF4400WARNING: This can crash the system if you try to read from an unmapped page.\eFAFAFA\n"); + EHPrint("uartmemdmp - Dump the memory of a UART.\n"); + EHPrint("main - Show the main screen.\n"); + EHPrint("details - Show the details screen.\n"); + EHPrint("frames - Show the stack frame screen.\n"); + EHPrint("tasks - Show the tasks screen.\n"); + EHPrint("console - Show the console screen.\n"); + EHPrint("Also, you can use the arrow keys to navigate between the screens.\n"); + EHPrint("=========================================================================\n"); + EHPrint("Kernel Compiled at: %s %s with C++ Standard: %d\n", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD); + EHPrint("C++ Language Version (__cplusplus): %ld\n", __cplusplus); + } + else if (strcmp(Input, "exit") == 0) + { + PowerManager->Shutdown(); + EHPrint("\eFFFFFFNow it's safe to turn off your computer."); + Display->SetBuffer(SBIdx); + CPU::Stop(); + } + else if (strcmp(Input, "reboot") == 0) + { + PowerManager->Reboot(); + EHPrint("\eFFFFFFNow it's safe to reboot your computer."); + Display->SetBuffer(SBIdx); + CPU::Stop(); + } + else if (strncmp(Input, "showbuf", 7) == 0 || strncmp(Input, "sb", 2) == 0) + { + char *arg = TrimWhiteSpace(Input + 7); + int tmpidx = SBIdx; + SBIdx = atoi(arg); + Display->SetBuffer(SBIdx); #if defined(a86) - for (int i = 0; i < 5000000; i++) - inb(0x80); + for (int i = 0; i < 5000000; i++) + inb(0x80); #endif // a64 || a32 - SBIdx = tmpidx; - Display->SetBuffer(SBIdx); - } - else if (strncmp(Input, "ifr", 3) == 0) - { - char *arg = TrimWhiteSpace(Input + 3); - int CountI = atoi(arg); - int TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]); + SBIdx = tmpidx; + Display->SetBuffer(SBIdx); + } + else if (strncmp(Input, "ifr", 3) == 0) + { + char *arg = TrimWhiteSpace(Input + 3); + int CountI = atoi(arg); + int TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]); - debug("Printing %ld interrupt frames.", CountI); + debug("Printing %ld interrupt frames.", CountI); - if (CountI > TotalCount) - { - EHPrint("\eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount); - Display->SetBuffer(SBIdx); - } - else - { - for (int i = 0; i < CountI; i++) - { - if (EHIntFrames[i]) - { - if (!Memory::Virtual().Check(EHIntFrames[i])) - continue; - EHPrint("\n\e2565CC%p", EHIntFrames[i]); - EHPrint("\e7925CC-"); + if (CountI > TotalCount) + { + EHPrint("\eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount); + Display->SetBuffer(SBIdx); + } + else + { + for (int i = 0; i < CountI; i++) + { + if (EHIntFrames[i]) + { + if (!Memory::Virtual().Check(EHIntFrames[i])) + continue; + EHPrint("\n\e2565CC%p", EHIntFrames[i]); + EHPrint("\e7925CC-"); #if defined(a64) - if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) + if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) #elif defined(a32) - if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) + if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) #elif defined(aa64) - if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) + if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) #endif - EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i])); - else - EHPrint("\eFF4CA9Outside Kernel"); + EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i])); + else + EHPrint("\eFF4CA9Outside Kernel"); #if defined(a86) - for (int i = 0; i < 20000; i++) - inb(0x80); + for (int i = 0; i < 20000; i++) + inb(0x80); #endif // a64 || a32 - Display->SetBuffer(SBIdx); - } - } - } - } - else if (strncmp(Input, "tlb", 3) == 0) - { - char *arg = TrimWhiteSpace(Input + 3); - uintptr_t Address = NULL; - Address = strtol(arg, NULL, 16); - debug("Converted %s to %#lx", arg, Address); - Memory::PageTable *BasePageTable = (Memory::PageTable *)Address; - if (Memory::Virtual().Check(BasePageTable)) - { - for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++) - { + Display->SetBuffer(SBIdx); + } + } + } + } + else if (strncmp(Input, "tlb", 3) == 0) + { + char *arg = TrimWhiteSpace(Input + 3); + uintptr_t Address = NULL; + Address = strtol(arg, NULL, 16); + debug("Converted %s to %#lx", arg, Address); + Memory::PageTable *BasePageTable = (Memory::PageTable *)Address; + if (Memory::Virtual().Check(BasePageTable)) + { + for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++) + { #if defined(a64) - Memory::PageMapLevel4 PML4 = BasePageTable->Entries[PMLIndex]; - EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", - PMLIndex, 0, 0, 0, - PML4.Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PML4.GetAddress() << 12); - Display->SetBuffer(SBIdx); - if (PML4.Present) - { - Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); - if (PDPTE) - { - for (int PDPTEIndex = 0; PDPTEIndex < 512; PDPTEIndex++) - { - EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", - PMLIndex, PDPTEIndex, 0, 0, - PDPTE->Entries[PDPTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDPTE->Entries[PDPTEIndex].GetAddress() << 12); - Display->SetBuffer(SBIdx); - if ((PDPTE->Entries[PDPTEIndex].Present)) - { - Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[PDPTEIndex].GetAddress() << 12); - if (PDE) - { - for (int PDEIndex = 0; PDEIndex < 512; PDEIndex++) - { - EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", - PMLIndex, PDPTEIndex, PDEIndex, 0, - PDE->Entries[PDEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PDE->Entries[PDEIndex].GetAddress() << 12); - Display->SetBuffer(SBIdx); - if ((PDE->Entries[PDEIndex].Present)) - { - Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[PDEIndex].GetAddress() << 12); - if (PTE) - { - for (int PTEIndex = 0; PTEIndex < 512; PTEIndex++) - { - EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:\e888888%#lx\n", - PMLIndex, PDPTEIndex, PDEIndex, PTEIndex, - PTE->Entries[PTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].Dirty ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].PageAttributeTable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].Global ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].ProtectionKey, - PTE->Entries[PTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", - PTE->Entries[PTEIndex].GetAddress() << 12); - Display->SetBuffer(SBIdx); - } - } - } - } - } - } - } - } - } + Memory::PageMapLevel4 PML4 = BasePageTable->Entries[PMLIndex]; + EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", + PMLIndex, 0, 0, 0, + PML4.Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PML4.ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PML4.UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PML4.WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PML4.CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PML4.Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PML4.ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PML4.GetAddress() << 12); + Display->SetBuffer(SBIdx); + if (PML4.Present) + { + Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); + if (PDPTE) + { + for (int PDPTEIndex = 0; PDPTEIndex < 512; PDPTEIndex++) + { + EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", + PMLIndex, PDPTEIndex, 0, 0, + PDPTE->Entries[PDPTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDPTE->Entries[PDPTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDPTE->Entries[PDPTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDPTE->Entries[PDPTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDPTE->Entries[PDPTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDPTE->Entries[PDPTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDPTE->Entries[PDPTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDPTE->Entries[PDPTEIndex].GetAddress() << 12); + Display->SetBuffer(SBIdx); + if ((PDPTE->Entries[PDPTEIndex].Present)) + { + Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[PDPTEIndex].GetAddress() << 12); + if (PDE) + { + for (int PDEIndex = 0; PDEIndex < 512; PDEIndex++) + { + EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", + PMLIndex, PDPTEIndex, PDEIndex, 0, + PDE->Entries[PDEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDE->Entries[PDEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDE->Entries[PDEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDE->Entries[PDEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDE->Entries[PDEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDE->Entries[PDEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDE->Entries[PDEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PDE->Entries[PDEIndex].GetAddress() << 12); + Display->SetBuffer(SBIdx); + if ((PDE->Entries[PDEIndex].Present)) + { + Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[PDEIndex].GetAddress() << 12); + if (PTE) + { + for (int PTEIndex = 0; PTEIndex < 512; PTEIndex++) + { + EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:\e888888%#lx\n", + PMLIndex, PDPTEIndex, PDEIndex, PTEIndex, + PTE->Entries[PTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].Dirty ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].PageAttributeTable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].Global ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].ProtectionKey, + PTE->Entries[PTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", + PTE->Entries[PTEIndex].GetAddress() << 12); + Display->SetBuffer(SBIdx); + } + } + } + } + } + } + } + } + } #endif - } - } - } - else if (strncmp(Input, "bitmap", 6) == 0) - { - Bitmap bm = KernelAllocator.GetPageBitmap(); + } + } + } + else if (strncmp(Input, "bitmap", 6) == 0) + { + Bitmap bm = KernelAllocator.GetPageBitmap(); - EHPrint("\n\eFAFAFA[0%%] %08ld: ", 0); - for (size_t i = 0; i < bm.Size; i++) - { - if (bm.Get(i)) - EHPrint("\eFF00001"); - else - EHPrint("\e00FF000"); - if (i % 128 == 127) - { - short Percentage = s_cst(short, (i * 100) / bm.Size); - EHPrint("\n\eFAFAFA[%03ld%%] %08ld: ", Percentage, i); - Display->SetBuffer(SBIdx); - } - } - EHPrint("\n\e22AA44--- END OF BITMAP ---\nBitmap size: %ld\n\n.", bm.Size); - Display->SetBuffer(SBIdx); - } - else if (strcmp(Input, "mem") == 0) - { - uint64_t Total = KernelAllocator.GetTotalMemory(); - uint64_t Used = KernelAllocator.GetUsedMemory(); - uint64_t Free = KernelAllocator.GetFreeMemory(); - uint64_t Reserved = KernelAllocator.GetReservedMemory(); + EHPrint("\n\eFAFAFA[0%%] %08ld: ", 0); + for (size_t i = 0; i < bm.Size; i++) + { + if (bm.Get(i)) + EHPrint("\eFF00001"); + else + EHPrint("\e00FF000"); + if (i % 128 == 127) + { + short Percentage = s_cst(short, (i * 100) / bm.Size); + EHPrint("\n\eFAFAFA[%03ld%%] %08ld: ", Percentage, i); + Display->SetBuffer(SBIdx); + } + } + EHPrint("\n\e22AA44--- END OF BITMAP ---\nBitmap size: %ld\n\n.", bm.Size); + Display->SetBuffer(SBIdx); + } + else if (strcmp(Input, "mem") == 0) + { + uint64_t Total = KernelAllocator.GetTotalMemory(); + uint64_t Used = KernelAllocator.GetUsedMemory(); + uint64_t Free = KernelAllocator.GetFreeMemory(); + uint64_t Reserved = KernelAllocator.GetReservedMemory(); - EHPrint("\e22AA44Total: %ld bytes\n\eFF0000Used: %ld bytes\n\e00FF00Free: %ld bytes\n\eFF00FFReserved: %ld bytes\n", Total, Used, Free, Reserved); - int Progress = s_cst(int, (Used * 100) / Total); - int ReservedProgress = s_cst(int, (Reserved * 100) / Total); - EHPrint("\e22AA44%3d%% \eCCCCCC[", Progress); - for (int i = 0; i < Progress; i++) - EHPrint("\eFF0000|"); - for (int i = 0; i < 100 - Progress; i++) - EHPrint("\e00FF00|"); - for (int i = 0; i < ReservedProgress; i++) - EHPrint("\eFF00FF|"); - EHPrint("\eCCCCCC]\n"); + EHPrint("\e22AA44Total: %ld bytes\n\eFF0000Used: %ld bytes\n\e00FF00Free: %ld bytes\n\eFF00FFReserved: %ld bytes\n", Total, Used, Free, Reserved); + int Progress = s_cst(int, (Used * 100) / Total); + int ReservedProgress = s_cst(int, (Reserved * 100) / Total); + EHPrint("\e22AA44%3d%% \eCCCCCC[", Progress); + for (int i = 0; i < Progress; i++) + EHPrint("\eFF0000|"); + for (int i = 0; i < 100 - Progress; i++) + EHPrint("\e00FF00|"); + for (int i = 0; i < ReservedProgress; i++) + EHPrint("\eFF00FF|"); + EHPrint("\eCCCCCC]\n"); - Display->SetBuffer(SBIdx); - } - else if (strncmp(Input, "cr", 2) == 0) - { - char *cr = TrimWhiteSpace(Input + 2); - switch (cr[0]) - { - case '0': - { + Display->SetBuffer(SBIdx); + } + else if (strncmp(Input, "cr", 2) == 0) + { + char *cr = TrimWhiteSpace(Input + 2); + switch (cr[0]) + { + case '0': + { #if defined(a64) - EHPrint("\e44AA000: %#lx\n", CPU::x64::readcr0()); + EHPrint("\e44AA000: %#lx\n", CPU::x64::readcr0()); #elif defined(a32) - EHPrint("\e44AA000: %#lx\n", CPU::x32::readcr0()); + EHPrint("\e44AA000: %#lx\n", CPU::x32::readcr0()); #endif - break; - } - case '2': - { + break; + } + case '2': + { #if defined(a64) - EHPrint("\e44AA002: %#lx\n", PageFaultAddress); + EHPrint("\e44AA002: %#lx\n", PageFaultAddress); #elif defined(a32) - EHPrint("\e44AA002: %#lx\n", CPU::x32::readcr2()); + EHPrint("\e44AA002: %#lx\n", CPU::x32::readcr2()); #endif - break; - } - case '3': - { + break; + } + case '3': + { #if defined(a64) - EHPrint("\e44AA003: %#lx\n", CPU::x64::readcr3()); + EHPrint("\e44AA003: %#lx\n", CPU::x64::readcr3()); #elif defined(a32) - EHPrint("\e44AA003: %#lx\n", CPU::x32::readcr3()); + EHPrint("\e44AA003: %#lx\n", CPU::x32::readcr3()); #endif - break; - } - case '4': - { + break; + } + case '4': + { #if defined(a64) - EHPrint("\e44AA004: %#lx\n", CPU::x64::readcr4()); + EHPrint("\e44AA004: %#lx\n", CPU::x64::readcr4()); #elif defined(a32) - EHPrint("\e44AA004: %#lx\n", CPU::x32::readcr4()); + EHPrint("\e44AA004: %#lx\n", CPU::x32::readcr4()); #endif - break; - } - case '8': - { + break; + } + case '8': + { #if defined(a64) - EHPrint("\e44AA008: %#lx\n", CPU::x64::readcr8()); + EHPrint("\e44AA008: %#lx\n", CPU::x64::readcr8()); #elif defined(a32) - EHPrint("\e44AA008: %#lx\n", CPU::x32::readcr8()); + EHPrint("\e44AA008: %#lx\n", CPU::x32::readcr8()); #endif - break; - } - default: - EHPrint("\eFF0000Invalid CR\n"); - break; - } - } - else if (strncmp(Input, "tss", 3) == 0) - { - char *arg = TrimWhiteSpace(Input + 3); - int TSSIndex = atoi(arg); - if (TSSIndex > SMP::CPUCores) - { - EHPrint("\eFF0000Invalid TSS index\n"); - } - else - { + break; + } + default: + EHPrint("\eFF0000Invalid CR\n"); + break; + } + } + else if (strncmp(Input, "tss", 3) == 0) + { + char *arg = TrimWhiteSpace(Input + 3); + int TSSIndex = atoi(arg); + if (TSSIndex > SMP::CPUCores) + { + EHPrint("\eFF0000Invalid TSS index\n"); + } + else + { #if defined(a86) - GlobalDescriptorTable::TaskStateSegment tss = GlobalDescriptorTable::tss[TSSIndex]; - EHPrint("\eFAFAFAStack Pointer 0: \eAABB22%#lx\n", tss.StackPointer[0]); - EHPrint("\eFAFAFAStack Pointer 1: \eAABB22%#lx\n", tss.StackPointer[1]); - EHPrint("\eFAFAFAStack Pointer 2: \eAABB22%#lx\n", tss.StackPointer[2]); + GlobalDescriptorTable::TaskStateSegment tss = GlobalDescriptorTable::tss[TSSIndex]; + EHPrint("\eFAFAFAStack Pointer 0: \eAABB22%#lx\n", tss.StackPointer[0]); + EHPrint("\eFAFAFAStack Pointer 1: \eAABB22%#lx\n", tss.StackPointer[1]); + EHPrint("\eFAFAFAStack Pointer 2: \eAABB22%#lx\n", tss.StackPointer[2]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[0]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[1]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[2]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[3]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[4]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[5]); - EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[6]); + EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[0]); + EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[1]); + EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[2]); + EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[3]); + EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[4]); + EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[5]); + EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[6]); - EHPrint("\eFAFAFAI/O Map Base Address Offset: \eAABB22%#lx\n", tss.IOMapBaseAddressOffset); + EHPrint("\eFAFAFAI/O Map Base Address Offset: \eAABB22%#lx\n", tss.IOMapBaseAddressOffset); - EHPrint("\eFAFAFAReserved 0: \eAABB22%#lx\n", tss.Reserved0); - EHPrint("\eFAFAFAReserved 1: \eAABB22%#lx\n", tss.Reserved1); - EHPrint("\eFAFAFAReserved 2: \eAABB22%#lx\n", tss.Reserved2); + EHPrint("\eFAFAFAReserved 0: \eAABB22%#lx\n", tss.Reserved0); + EHPrint("\eFAFAFAReserved 1: \eAABB22%#lx\n", tss.Reserved1); + EHPrint("\eFAFAFAReserved 2: \eAABB22%#lx\n", tss.Reserved2); #elif defined(aa64) - EHPrint("\eFF0000AArch64 does not have TSS\n"); + EHPrint("\eFF0000AArch64 does not have TSS\n"); #endif - } - } - else if (strncmp(Input, "dump", 4) == 0) - { - char *arg = TrimWhiteSpace(Input + 4); - char *addr = strtok(arg, " "); - char *len = strtok(NULL, " "); - if (addr == NULL || len == NULL) - { - EHPrint("\eFF0000Invalid arguments\n"); - } - else - { - uint64_t Address = strtoul(addr, NULL, 16); - size_t Length = strtoul(len, NULL, 10); - debug("Dumping %ld bytes from %#lx\n", Length, Address); - EHDumpData((void *)Address, (unsigned long)Length); - } - } - else if (strncmp(Input, "uartmemdmp", 10) == 0) - { - char *arg = TrimWhiteSpace(Input + 10); - char *cPort = strtok(arg, " "); - char *cBoolSkip = strtok(NULL, " "); - UniversalAsynchronousReceiverTransmitter::SerialPorts port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1; - switch (cPort[0]) - { - case '1': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1; - break; - case '2': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM2; - break; - case '3': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM3; - break; - case '4': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM4; - break; - case '5': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM5; - break; - case '6': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM6; - break; - case '7': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM7; - break; - case '8': - port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM8; - break; - default: - EHPrint("\eFF0000Invalid port! Defaulting to 1.\n"); - break; - } - EHPrint("\eF8F8F8Dumping memory to UART port %c (%#lx) and %s inaccessible pages.\n", cPort[0], port, cBoolSkip[0] == '1' ? "skipping" : "zeroing"); - Display->SetBuffer(SBIdx); - uint64_t TotalMemLength = KernelAllocator.GetTotalMemory(); - uint64_t ProgressLength = TotalMemLength; - UniversalAsynchronousReceiverTransmitter::UART uart(port); - Memory::Virtual vmm; - uint8_t *Address = reinterpret_cast(0x0); - int Progress = 0; - for (size_t i = 0; i < TotalMemLength; i++) - { - if (vmm.Check(Address)) - uart.Write(*Address); - else if (cBoolSkip[0] == '0') - uart.Write((uint8_t)0); - else - ProgressLength--; - Address++; + } + } + else if (strncmp(Input, "dump", 4) == 0) + { + char *arg = TrimWhiteSpace(Input + 4); + char *addr = strtok(arg, " "); + char *len = strtok(NULL, " "); + if (addr == NULL || len == NULL) + { + EHPrint("\eFF0000Invalid arguments\n"); + } + else + { + uint64_t Address = strtoul(addr, NULL, 16); + size_t Length = strtoul(len, NULL, 10); + debug("Dumping %ld bytes from %#lx\n", Length, Address); + EHDumpData((void *)Address, (unsigned long)Length); + } + } + else if (strncmp(Input, "uartmemdmp", 10) == 0) + { + char *arg = TrimWhiteSpace(Input + 10); + char *cPort = strtok(arg, " "); + char *cBoolSkip = strtok(NULL, " "); + UniversalAsynchronousReceiverTransmitter::SerialPorts port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1; + switch (cPort[0]) + { + case '1': + port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1; + break; + case '2': + port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM2; + break; + case '3': + port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM3; + break; + case '4': + port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM4; + break; + case '5': + port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM5; + break; + case '6': + port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM6; + break; + case '7': + port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM7; + break; + case '8': + port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM8; + break; + default: + EHPrint("\eFF0000Invalid port! Defaulting to 1.\n"); + break; + } + EHPrint("\eF8F8F8Dumping memory to UART port %c (%#lx) and %s inaccessible pages.\n", cPort[0], port, cBoolSkip[0] == '1' ? "skipping" : "zeroing"); + Display->SetBuffer(SBIdx); + uint64_t TotalMemLength = KernelAllocator.GetTotalMemory(); + uint64_t ProgressLength = TotalMemLength; + UniversalAsynchronousReceiverTransmitter::UART uart(port); + Memory::Virtual vmm; + uint8_t *Address = reinterpret_cast(0x0); + int Progress = 0; + for (size_t i = 0; i < TotalMemLength; i++) + { + if (vmm.Check(Address)) + uart.Write(*Address); + else if (cBoolSkip[0] == '0') + uart.Write((uint8_t)0); + else + ProgressLength--; + Address++; - if (unlikely(i % 0x1000 == 0)) - { - int NewProgress = (int)((i * 100) / ProgressLength); - if (unlikely(NewProgress != Progress)) - { - Progress = NewProgress; - EHPrint("\n%d%%\n", Progress); - Display->SetBuffer(SBIdx); - } - Display->Print('.', SBIdx); - if (unlikely(i % 0x500 == 0)) - Display->SetBuffer(SBIdx); - } - } - EHPrint("\nDone.\n"); - } - else if (strcmp(Input, "main") == 0) - { - SBIdx = 255; - DisplayTopOverlay(); - DisplayMainScreen(crashdata); - Display->SetBuffer(SBIdx); - } - else if (strcmp(Input, "details") == 0) - { - SBIdx = 254; - DisplayTopOverlay(); - DisplayDetailsScreen(crashdata); - Display->SetBuffer(SBIdx); - } - else if (strcmp(Input, "frames") == 0) - { - SBIdx = 253; - DisplayTopOverlay(); - DisplayStackFrameScreen(crashdata); - Display->SetBuffer(SBIdx); - } - else if (strcmp(Input, "tasks") == 0) - { - SBIdx = 252; - DisplayTopOverlay(); - DisplayTasksScreen(crashdata); - Display->SetBuffer(SBIdx); - } - else if (strcmp(Input, "console") == 0) - { - SBIdx = 251; - DisplayTopOverlay(); - DisplayConsoleScreen(crashdata); - Display->SetBuffer(SBIdx); - } - else if (strlen(Input) > 0) - EHPrint("Unknown command: %s", Input); + if (unlikely(i % 0x1000 == 0)) + { + int NewProgress = (int)((i * 100) / ProgressLength); + if (unlikely(NewProgress != Progress)) + { + Progress = NewProgress; + EHPrint("\n%d%%\n", Progress); + Display->SetBuffer(SBIdx); + } + Display->Print('.', SBIdx); + if (unlikely(i % 0x500 == 0)) + Display->SetBuffer(SBIdx); + } + } + EHPrint("\nDone.\n"); + } + else if (strcmp(Input, "main") == 0) + { + SBIdx = 255; + DisplayTopOverlay(); + DisplayMainScreen(crashdata); + Display->SetBuffer(SBIdx); + } + else if (strcmp(Input, "details") == 0) + { + SBIdx = 254; + DisplayTopOverlay(); + DisplayDetailsScreen(crashdata); + Display->SetBuffer(SBIdx); + } + else if (strcmp(Input, "frames") == 0) + { + SBIdx = 253; + DisplayTopOverlay(); + DisplayStackFrameScreen(crashdata); + Display->SetBuffer(SBIdx); + } + else if (strcmp(Input, "tasks") == 0) + { + SBIdx = 252; + DisplayTopOverlay(); + DisplayTasksScreen(crashdata); + Display->SetBuffer(SBIdx); + } + else if (strcmp(Input, "console") == 0) + { + SBIdx = 251; + DisplayTopOverlay(); + DisplayConsoleScreen(crashdata); + Display->SetBuffer(SBIdx); + } + else if (strlen(Input) > 0) + EHPrint("Unknown command: %s", Input); - DisplayBottomOverlay(); - Display->SetBuffer(SBIdx); - } + DisplayBottomOverlay(); + Display->SetBuffer(SBIdx); + } - SafeFunction void StopAllCores() - { + SafeFunction void StopAllCores() + { #if defined(a86) - /* FIXME: Can't send IPIs to other cores - * because it causes another exception on - * the other cores. - * - * Also it makes every core to stay at 100% usage for some reason. - */ + /* FIXME: Can't send IPIs to other cores + * because it causes another exception on + * the other cores. + * + * Also it makes every core to stay at 100% usage for some reason. + */ - // if (SMP::CPUCores > 1) - // { - // for (int i = 1; i < SMP::CPUCores; i++) - // { - // APIC::InterruptCommandRegisterLow icr; - // icr.Vector = CPU::x86::IRQ29; - // icr.Level = APIC::APICLevel::Assert; - // ((APIC::APIC *)Interrupts::apic[i])->IPI(i, icr); - // __sync; - // } - // } - // APIC::InterruptCommandRegisterLow icr; - // icr.Vector = CPU::x86::IRQ29; - // icr.Level = APIC::APICLevel::Assert; - // icr.DestinationShorthand = APIC::APICDestinationShorthand::AllExcludingSelf; - // ((APIC::APIC *)Interrupts::apic[0])->IPI(0, icr); - // CPU::Interrupts(CPU::Enable); - __sync; - CPU::Interrupts(CPU::Disable); - // } + // if (SMP::CPUCores > 1) + // { + // for (int i = 1; i < SMP::CPUCores; i++) + // { + // APIC::InterruptCommandRegisterLow icr; + // icr.Vector = CPU::x86::IRQ29; + // icr.Level = APIC::APICLevel::Assert; + // ((APIC::APIC *)Interrupts::apic[i])->IPI(i, icr); + // __sync; + // } + // } + // APIC::InterruptCommandRegisterLow icr; + // icr.Vector = CPU::x86::IRQ29; + // icr.Level = APIC::APICLevel::Assert; + // icr.DestinationShorthand = APIC::APICDestinationShorthand::AllExcludingSelf; + // ((APIC::APIC *)Interrupts::apic[0])->IPI(0, icr); + // CPU::Interrupts(CPU::Enable); + __sync; + CPU::Interrupts(CPU::Disable); + // } #elif defined(aa64) #endif - } + } - SafeFunction void Handle(void *Data) - { - // TODO: SUPPORT SMP - CPU::Interrupts(CPU::Disable); - CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data; - SBIdx = 255; + SafeFunction void Handle(void *Data) + { + // TODO: SUPPORT SMP + CPU::Interrupts(CPU::Disable); + CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data; + SBIdx = 255; #if defined(a64) - debug("-----------------------------------------------------------------------------------"); - error("Exception: %#llx", Frame->InterruptNumber); - for (size_t i = 0; i < INT_FRAMES_MAX; i++) - EHIntFrames[i] = Interrupts::InterruptFrames[i]; - PageFaultAddress = CPU::x64::readcr2().PFLA; + debug("-----------------------------------------------------------------------------------"); + error("Exception: %#llx", Frame->InterruptNumber); + for (size_t i = 0; i < INT_FRAMES_MAX; i++) + EHIntFrames[i] = Interrupts::InterruptFrames[i]; + PageFaultAddress = CPU::x64::readcr2().PFLA; - if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA) - { - if (PageFaultAddress) - { - debug("Exception in kernel mode (ip: %#lx cr2: %#lx (%s))", - Frame->rip, PageFaultAddress, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol"); - } - else - { - debug("Exception in kernel mode (ip: %#lx (%s))", - Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol"); - } + if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA) + { + if (PageFaultAddress) + { + debug("Exception in kernel mode (ip: %#lx cr2: %#lx (%s))", + Frame->rip, PageFaultAddress, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol"); + } + else + { + debug("Exception in kernel mode (ip: %#lx (%s))", + Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol"); + } - CPUData *data = GetCurrentCPU(); - if (data) - { - if (data->CurrentThread) - { - if (!data->CurrentThread->Security.IsCritical) - { - fixme("Exception in non-critical thread (kernel mode)"); - } - } - } + CPUData *data = GetCurrentCPU(); + if (data) + { + if (data->CurrentThread) + { + if (!data->CurrentThread->Security.IsCritical) + { + fixme("Exception in non-critical thread (kernel mode)"); + } + } + } - if (TaskManager) - TaskManager->Panic(); - ForceUnlock = true; - Display->CreateBuffer(0, 0, SBIdx); - StopAllCores(); - } - else - { - if (PageFaultAddress) - { - debug("Exception in user mode (ip: %#lx cr2: %#lx (%s))", - Frame->rip, PageFaultAddress, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol"); - } - else - { - debug("Exception in user mode (ip: %#lx (%s))", - Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol"); - } - CPUData *data = GetCurrentCPU(); - if (!data) - { - ForceUnlock = true; - Display->CreateBuffer(0, 0, SBIdx); - StopAllCores(); - EHPrint("\eFF0000Cannot get CPU data! This results in a kernel crash!"); - error("Cannot get CPU data! This results in a kernel crash!"); - error("This should never happen!"); - } - else - { - debug("CPU %ld data is valid", data->ID); - if (data->CurrentThread->Security.IsCritical) - { - debug("Critical thread \"%s\"(%d) died", data->CurrentThread->Name, data->CurrentThread->ID); - if (TaskManager) - TaskManager->Panic(); - ForceUnlock = true; - Display->CreateBuffer(0, 0, SBIdx); - StopAllCores(); - } - else - { - debug("Current thread is valid %#lx", data->CurrentThread); - UserModeExceptionHandler(Frame); - return; - } - } - } + if (TaskManager) + TaskManager->Panic(); + ForceUnlock = true; + Display->CreateBuffer(0, 0, SBIdx); + StopAllCores(); + } + else + { + if (PageFaultAddress) + { + debug("Exception in user mode (ip: %#lx cr2: %#lx (%s))", + Frame->rip, PageFaultAddress, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol"); + } + else + { + debug("Exception in user mode (ip: %#lx (%s))", + Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol"); + } + CPUData *data = GetCurrentCPU(); + if (!data) + { + ForceUnlock = true; + Display->CreateBuffer(0, 0, SBIdx); + StopAllCores(); + EHPrint("\eFF0000Cannot get CPU data! This results in a kernel crash!"); + error("Cannot get CPU data! This results in a kernel crash!"); + error("This should never happen!"); + } + else + { + debug("CPU %ld data is valid", data->ID); + if (data->CurrentThread->Security.IsCritical) + { + debug("Critical thread \"%s\"(%d) died", + data->CurrentThread->Name, + data->CurrentThread->ID); + if (TaskManager) + TaskManager->Panic(); + ForceUnlock = true; + Display->CreateBuffer(0, 0, SBIdx); + StopAllCores(); + } + else + { + debug("Current thread is valid %#lx", + data->CurrentThread.load()); + UserModeExceptionHandler(Frame); + return; + } + } + } - if (ExceptionOccurred) - { - SBIdx = 255; - Display->ClearBuffer(SBIdx); - Display->SetBufferCursor(SBIdx, 0, 0); + if (ExceptionOccurred) + { + SBIdx = 255; + Display->ClearBuffer(SBIdx); + Display->SetBufferCursor(SBIdx, 0, 0); - CPU::x64::CR0 cr0 = CPU::x64::readcr0(); - CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; - CPU::x64::CR3 cr3 = CPU::x64::readcr3(); - CPU::x64::CR4 cr4 = CPU::x64::readcr4(); - CPU::x64::CR8 cr8 = CPU::x64::readcr8(); - CPU::x64::EFER efer; - efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER); - uintptr_t ds; - asmv("mov %%ds, %0" - : "=r"(ds)); + CPU::x64::CR0 cr0 = CPU::x64::readcr0(); + CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; + CPU::x64::CR3 cr3 = CPU::x64::readcr3(); + CPU::x64::CR4 cr4 = CPU::x64::readcr4(); + CPU::x64::CR8 cr8 = CPU::x64::readcr8(); + CPU::x64::EFER efer; + efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER); + uintptr_t ds; + asmv("mov %%ds, %0" + : "=r"(ds)); - EHPrint("\eFF2525FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n", - CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), - Frame->ss, Frame->cs, ds); - EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11); - EHPrint("R12=%#llx R13=%#llx R14=%#llx R15=%#llx\n", Frame->r12, Frame->r13, Frame->r14, Frame->r15); - EHPrint("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx\n", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); - EHPrint("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx\n", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); - EHPrint("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw); - EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw); - EHPrint("CR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n R0:%#x R1:%#x R2:%#x\n", - cr0.PE ? "True " : "False", cr0.MP ? "True " : "False", cr0.EM ? "True " : "False", cr0.TS ? "True " : "False", - cr0.ET ? "True " : "False", cr0.NE ? "True " : "False", cr0.WP ? "True " : "False", cr0.AM ? "True " : "False", - cr0.NW ? "True " : "False", cr0.CD ? "True " : "False", cr0.PG ? "True " : "False", - cr0.Reserved0, cr0.Reserved1, cr0.Reserved2); - EHPrint("CR2: PFLA: %#llx\n", - cr2.PFLA); - EHPrint("CR3: PWT:%s PCD:%s PDBR:%#llx\n", - cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR); - EHPrint("CR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n R0:%#x R1:%#x R2:%#x\n", - cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False", - cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False", - cr4.PCE ? "True " : "False", cr4.UMIP ? "True " : "False", cr4.OSFXSR ? "True " : "False", cr4.OSXMMEXCPT ? "True " : "False", - cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False", - cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False", - cr4.Reserved0, cr4.Reserved1, cr4.Reserved2); - EHPrint("CR8: TPL:%d\n", cr8.TPL); - EHPrint("RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n", - Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False", - Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False", - Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False", - Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False", - Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne, - Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); - EHPrint("EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n R0:%#x R1:%#x R2:%#x\n", - efer.SCE ? "True " : "False", efer.LME ? "True " : "False", efer.LMA ? "True " : "False", efer.NXE ? "True " : "False", - efer.SVME ? "True " : "False", efer.LMSLE ? "True " : "False", efer.FFXSR ? "True " : "False", efer.TCE ? "True " : "False", - efer.Reserved0, efer.Reserved1, efer.Reserved2); + EHPrint("\eFF2525FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n", + CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), + Frame->ss, Frame->cs, ds); + EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11); + EHPrint("R12=%#llx R13=%#llx R14=%#llx R15=%#llx\n", Frame->r12, Frame->r13, Frame->r14, Frame->r15); + EHPrint("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx\n", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); + EHPrint("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx\n", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); + EHPrint("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw); + EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw); + EHPrint("CR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n R0:%#x R1:%#x R2:%#x\n", + cr0.PE ? "True " : "False", cr0.MP ? "True " : "False", cr0.EM ? "True " : "False", cr0.TS ? "True " : "False", + cr0.ET ? "True " : "False", cr0.NE ? "True " : "False", cr0.WP ? "True " : "False", cr0.AM ? "True " : "False", + cr0.NW ? "True " : "False", cr0.CD ? "True " : "False", cr0.PG ? "True " : "False", + cr0.Reserved0, cr0.Reserved1, cr0.Reserved2); + EHPrint("CR2: PFLA: %#llx\n", + cr2.PFLA); + EHPrint("CR3: PWT:%s PCD:%s PDBR:%#llx\n", + cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR); + EHPrint("CR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n R0:%#x R1:%#x R2:%#x\n", + cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False", + cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False", + cr4.PCE ? "True " : "False", cr4.UMIP ? "True " : "False", cr4.OSFXSR ? "True " : "False", cr4.OSXMMEXCPT ? "True " : "False", + cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False", + cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False", + cr4.Reserved0, cr4.Reserved1, cr4.Reserved2); + EHPrint("CR8: TPL:%d\n", cr8.TPL); + EHPrint("RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n", + Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False", + Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False", + Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False", + Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False", + Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne, + Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); + EHPrint("EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n R0:%#x R1:%#x R2:%#x\n", + efer.SCE ? "True " : "False", efer.LME ? "True " : "False", efer.LMA ? "True " : "False", efer.NXE ? "True " : "False", + efer.SVME ? "True " : "False", efer.LMSLE ? "True " : "False", efer.FFXSR ? "True " : "False", efer.TCE ? "True " : "False", + efer.Reserved0, efer.Reserved1, efer.Reserved2); - EHPrint("\nException occurred while handling exception! HALTED!"); - Display->SetBuffer(SBIdx); - Interrupts::RemoveAll(); - CPU::Stop(); - } + EHPrint("\nException occurred while handling exception! HALTED!"); + Display->SetBuffer(SBIdx); + Interrupts::RemoveAll(); + CPU::Stop(); + } - ExceptionOccurred = true; + ExceptionOccurred = true; - if (DriverManager) - DriverManager->Panic(); + if (DriverManager) + DriverManager->Panic(); - debug("Reading control registers..."); - crashdata.Frame = Frame; - crashdata.cr0 = CPU::x64::readcr0(); - crashdata.cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; - crashdata.cr3 = CPU::x64::readcr3(); - crashdata.cr4 = CPU::x64::readcr4(); - crashdata.cr8 = CPU::x64::readcr8(); - crashdata.efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER); - uintptr_t ds; - asmv("mov %%ds, %0" - : "=r"(ds)); + debug("Reading control registers..."); + crashdata.Frame = Frame; + crashdata.cr0 = CPU::x64::readcr0(); + crashdata.cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; + crashdata.cr3 = CPU::x64::readcr3(); + crashdata.cr4 = CPU::x64::readcr4(); + crashdata.cr8 = CPU::x64::readcr8(); + crashdata.efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER); + uintptr_t ds; + asmv("mov %%ds, %0" + : "=r"(ds)); - // Get debug registers - asmv("movq %%dr0, %0" - : "=r"(crashdata.dr0)); - asmv("movq %%dr1, %0" - : "=r"(crashdata.dr1)); - asmv("movq %%dr2, %0" - : "=r"(crashdata.dr2)); - asmv("movq %%dr3, %0" - : "=r"(crashdata.dr3)); - asmv("movq %%dr6, %0" - : "=r"(crashdata.dr6.raw)); - asmv("movq %%dr7, %0" - : "=r"(crashdata.dr7.raw)); + // Get debug registers + asmv("movq %%dr0, %0" + : "=r"(crashdata.dr0)); + asmv("movq %%dr1, %0" + : "=r"(crashdata.dr1)); + asmv("movq %%dr2, %0" + : "=r"(crashdata.dr2)); + asmv("movq %%dr3, %0" + : "=r"(crashdata.dr3)); + asmv("movq %%dr6, %0" + : "=r"(crashdata.dr6.raw)); + asmv("movq %%dr7, %0" + : "=r"(crashdata.dr7.raw)); - CPUData *cpudata = GetCurrentCPU(); + CPUData *cpudata = GetCurrentCPU(); - if (cpudata == nullptr) - { - EHPrint("\eFFA500Invalid CPU data!\n"); - for (long i = 0; i < MAX_CPU; i++) - { - cpudata = GetCPU(i); - if (cpudata != nullptr) - break; - if (i == MAX_CPU - 1) - { - EHPrint("\eFF0000No CPU data found!\n"); - cpudata = nullptr; - } - } - debug("CPU ptr %#lx", cpudata); - } + if (cpudata == nullptr) + { + EHPrint("\eFFA500Invalid CPU data!\n"); + for (long i = 0; i < MAX_CPU; i++) + { + cpudata = GetCPU(i); + if (cpudata != nullptr) + break; + if (i == MAX_CPU - 1) + { + EHPrint("\eFF0000No CPU data found!\n"); + cpudata = nullptr; + } + } + debug("CPU ptr %#lx", cpudata); + } - if (cpudata != nullptr) - { - crashdata.ID = cpudata->ID; - crashdata.CPUData = cpudata; - error("Technical Informations on CPU %lld:", cpudata->ID); - } + if (cpudata != nullptr) + { + crashdata.ID = cpudata->ID; + crashdata.CPUData = cpudata; + error("Technical Informations on CPU %lld:", cpudata->ID); + } - if (TaskManager && cpudata != nullptr) - { - crashdata.Process = cpudata->CurrentProcess.load(); - crashdata.Thread = cpudata->CurrentThread.load(); + if (TaskManager && cpudata != nullptr) + { + crashdata.Process = cpudata->CurrentProcess.load(); + crashdata.Thread = cpudata->CurrentThread.load(); - error("Current Process: %s(%ld)", - cpudata->CurrentProcess->Name, - cpudata->CurrentProcess->ID); - error("Current Thread: %s(%ld)", - cpudata->CurrentThread->Name, - cpudata->CurrentThread->ID); - } + error("Current Process: %s(%ld)", + cpudata->CurrentProcess->Name, + cpudata->CurrentProcess->ID); + error("Current Thread: %s(%ld)", + cpudata->CurrentThread->Name, + cpudata->CurrentThread->ID); + } - { - error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx", - CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), - Frame->ss, Frame->cs, ds); - error("R8=%#llx R9=%#llx R10=%#llx R11=%#llx", Frame->r8, Frame->r9, Frame->r10, Frame->r11); - error("R12=%#llx R13=%#llx R14=%#llx R15=%#llx", Frame->r12, Frame->r13, Frame->r14, Frame->r15); - error("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); - error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); - error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, crashdata.efer.raw); - error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", crashdata.cr0.raw, crashdata.cr2.raw, crashdata.cr3.raw, crashdata.cr4.raw, crashdata.cr8.raw); - error("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx", crashdata.dr0, crashdata.dr1, crashdata.dr2, crashdata.dr3, crashdata.dr6.raw, crashdata.dr7.raw); + { + error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx", + CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE), + Frame->ss, Frame->cs, ds); + error("R8=%#llx R9=%#llx R10=%#llx R11=%#llx", Frame->r8, Frame->r9, Frame->r10, Frame->r11); + error("R12=%#llx R13=%#llx R14=%#llx R15=%#llx", Frame->r12, Frame->r13, Frame->r14, Frame->r15); + error("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx); + error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp); + error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, crashdata.efer.raw); + error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", crashdata.cr0.raw, crashdata.cr2.raw, crashdata.cr3.raw, crashdata.cr4.raw, crashdata.cr8.raw); + error("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx", crashdata.dr0, crashdata.dr1, crashdata.dr2, crashdata.dr3, crashdata.dr6.raw, crashdata.dr7.raw); - error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x", - crashdata.cr0.PE ? "True " : "False", crashdata.cr0.MP ? "True " : "False", crashdata.cr0.EM ? "True " : "False", crashdata.cr0.TS ? "True " : "False", - crashdata.cr0.ET ? "True " : "False", crashdata.cr0.NE ? "True " : "False", crashdata.cr0.WP ? "True " : "False", crashdata.cr0.AM ? "True " : "False", - crashdata.cr0.NW ? "True " : "False", crashdata.cr0.CD ? "True " : "False", crashdata.cr0.PG ? "True " : "False", - crashdata.cr0.Reserved0, crashdata.cr0.Reserved1, crashdata.cr0.Reserved2); + error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x", + crashdata.cr0.PE ? "True " : "False", crashdata.cr0.MP ? "True " : "False", crashdata.cr0.EM ? "True " : "False", crashdata.cr0.TS ? "True " : "False", + crashdata.cr0.ET ? "True " : "False", crashdata.cr0.NE ? "True " : "False", crashdata.cr0.WP ? "True " : "False", crashdata.cr0.AM ? "True " : "False", + crashdata.cr0.NW ? "True " : "False", crashdata.cr0.CD ? "True " : "False", crashdata.cr0.PG ? "True " : "False", + crashdata.cr0.Reserved0, crashdata.cr0.Reserved1, crashdata.cr0.Reserved2); - error("CR2: PFLA: %#llx", - crashdata.cr2.PFLA); + error("CR2: PFLA: %#llx", + crashdata.cr2.PFLA); - error("CR3: PWT:%s PCD:%s PDBR:%#llx", - crashdata.cr3.PWT ? "True " : "False", crashdata.cr3.PCD ? "True " : "False", crashdata.cr3.PDBR); + error("CR3: PWT:%s PCD:%s PDBR:%#llx", + crashdata.cr3.PWT ? "True " : "False", crashdata.cr3.PCD ? "True " : "False", crashdata.cr3.PDBR); - error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x R2:%#x", - crashdata.cr4.VME ? "True " : "False", crashdata.cr4.PVI ? "True " : "False", crashdata.cr4.TSD ? "True " : "False", crashdata.cr4.DE ? "True " : "False", - crashdata.cr4.PSE ? "True " : "False", crashdata.cr4.PAE ? "True " : "False", crashdata.cr4.MCE ? "True " : "False", crashdata.cr4.PGE ? "True " : "False", - crashdata.cr4.PCE ? "True " : "False", crashdata.cr4.UMIP ? "True " : "False", crashdata.cr4.OSFXSR ? "True " : "False", crashdata.cr4.OSXMMEXCPT ? "True " : "False", - crashdata.cr4.LA57 ? "True " : "False", crashdata.cr4.VMXE ? "True " : "False", crashdata.cr4.SMXE ? "True " : "False", crashdata.cr4.PCIDE ? "True " : "False", - crashdata.cr4.OSXSAVE ? "True " : "False", crashdata.cr4.SMEP ? "True " : "False", crashdata.cr4.SMAP ? "True " : "False", crashdata.cr4.PKE ? "True " : "False", - crashdata.cr4.Reserved0, crashdata.cr4.Reserved1, crashdata.cr4.Reserved2); + error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x R2:%#x", + crashdata.cr4.VME ? "True " : "False", crashdata.cr4.PVI ? "True " : "False", crashdata.cr4.TSD ? "True " : "False", crashdata.cr4.DE ? "True " : "False", + crashdata.cr4.PSE ? "True " : "False", crashdata.cr4.PAE ? "True " : "False", crashdata.cr4.MCE ? "True " : "False", crashdata.cr4.PGE ? "True " : "False", + crashdata.cr4.PCE ? "True " : "False", crashdata.cr4.UMIP ? "True " : "False", crashdata.cr4.OSFXSR ? "True " : "False", crashdata.cr4.OSXMMEXCPT ? "True " : "False", + crashdata.cr4.LA57 ? "True " : "False", crashdata.cr4.VMXE ? "True " : "False", crashdata.cr4.SMXE ? "True " : "False", crashdata.cr4.PCIDE ? "True " : "False", + crashdata.cr4.OSXSAVE ? "True " : "False", crashdata.cr4.SMEP ? "True " : "False", crashdata.cr4.SMAP ? "True " : "False", crashdata.cr4.PKE ? "True " : "False", + crashdata.cr4.Reserved0, crashdata.cr4.Reserved1, crashdata.cr4.Reserved2); - error("CR8: TPL:%d", crashdata.cr8.TPL); + error("CR8: TPL:%d", crashdata.cr8.TPL); - error("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x", - Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False", - Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False", - Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False", - Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False", - Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne, - Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); + error("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x", + Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False", + Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False", + Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False", + Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False", + Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne, + Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); - error("DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s", - crashdata.dr6.B0 ? "True " : "False", crashdata.dr6.B1 ? "True " : "False", crashdata.dr6.B2 ? "True " : "False", crashdata.dr6.B3 ? "True " : "False", - crashdata.dr6.BD ? "True " : "False", crashdata.dr6.BS ? "True " : "False", crashdata.dr6.BT ? "True " : "False"); + error("DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s", + crashdata.dr6.B0 ? "True " : "False", crashdata.dr6.B1 ? "True " : "False", crashdata.dr6.B2 ? "True " : "False", crashdata.dr6.B3 ? "True " : "False", + crashdata.dr6.BD ? "True " : "False", crashdata.dr6.BS ? "True " : "False", crashdata.dr6.BT ? "True " : "False"); - error("DR7: L0:%s G0:%s L1:%s G1:%s L2:%s G2:%s L3:%s G3:%s LE:%s GE:%s GD:%s R/W0:%s LEN0:%s R/W1:%s LEN1:%s R/W2:%s LEN2:%s R/W3:%s LEN3:%s", - crashdata.dr7.L0 ? "True " : "False", crashdata.dr7.G0 ? "True " : "False", crashdata.dr7.L1 ? "True " : "False", crashdata.dr7.G1 ? "True " : "False", - crashdata.dr7.L2 ? "True " : "False", crashdata.dr7.G2 ? "True " : "False", crashdata.dr7.L3 ? "True " : "False", crashdata.dr7.G3 ? "True " : "False", - crashdata.dr7.LE ? "True " : "False", crashdata.dr7.GE ? "True " : "False", crashdata.dr7.GD ? "True " : "False", crashdata.dr7.RW0 ? "True " : "False", - crashdata.dr7.LEN0 ? "True " : "False", crashdata.dr7.RW1 ? "True " : "False", crashdata.dr7.LEN1 ? "True " : "False", crashdata.dr7.RW2 ? "True " : "False", - crashdata.dr7.LEN2 ? "True " : "False", crashdata.dr7.RW3 ? "True " : "False", crashdata.dr7.LEN3 ? "True " : "False"); + error("DR7: L0:%s G0:%s L1:%s G1:%s L2:%s G2:%s L3:%s G3:%s LE:%s GE:%s GD:%s R/W0:%s LEN0:%s R/W1:%s LEN1:%s R/W2:%s LEN2:%s R/W3:%s LEN3:%s", + crashdata.dr7.L0 ? "True " : "False", crashdata.dr7.G0 ? "True " : "False", crashdata.dr7.L1 ? "True " : "False", crashdata.dr7.G1 ? "True " : "False", + crashdata.dr7.L2 ? "True " : "False", crashdata.dr7.G2 ? "True " : "False", crashdata.dr7.L3 ? "True " : "False", crashdata.dr7.G3 ? "True " : "False", + crashdata.dr7.LE ? "True " : "False", crashdata.dr7.GE ? "True " : "False", crashdata.dr7.GD ? "True " : "False", crashdata.dr7.RW0 ? "True " : "False", + crashdata.dr7.LEN0 ? "True " : "False", crashdata.dr7.RW1 ? "True " : "False", crashdata.dr7.LEN1 ? "True " : "False", crashdata.dr7.RW2 ? "True " : "False", + crashdata.dr7.LEN2 ? "True " : "False", crashdata.dr7.RW3 ? "True " : "False", crashdata.dr7.LEN3 ? "True " : "False"); - error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x", - crashdata.efer.SCE ? "True " : "False", crashdata.efer.LME ? "True " : "False", crashdata.efer.LMA ? "True " : "False", crashdata.efer.NXE ? "True " : "False", - crashdata.efer.SVME ? "True " : "False", crashdata.efer.LMSLE ? "True " : "False", crashdata.efer.FFXSR ? "True " : "False", crashdata.efer.TCE ? "True " : "False", - crashdata.efer.Reserved0, crashdata.efer.Reserved1, crashdata.efer.Reserved2); - } - goto CrashEnd; + error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x", + crashdata.efer.SCE ? "True " : "False", crashdata.efer.LME ? "True " : "False", crashdata.efer.LMA ? "True " : "False", crashdata.efer.NXE ? "True " : "False", + crashdata.efer.SVME ? "True " : "False", crashdata.efer.LMSLE ? "True " : "False", crashdata.efer.FFXSR ? "True " : "False", crashdata.efer.TCE ? "True " : "False", + crashdata.efer.Reserved0, crashdata.efer.Reserved1, crashdata.efer.Reserved2); + } + goto CrashEnd; #elif defined(a32) - goto CrashEnd; + goto CrashEnd; #elif defined(aa64) - goto CrashEnd; + goto CrashEnd; #endif - CrashEnd: - if (Config.InterruptsOnCrash) - { - // 255 // Main - Display->CreateBuffer(0, 0, 254); // Details - Display->CreateBuffer(0, 0, 253); // Frames - Display->CreateBuffer(0, 0, 252); // Tasks - Display->CreateBuffer(0, 0, 251); // Console - Display->CreateBuffer(0, 0, 250); // Empty + CrashEnd: + if (Config.InterruptsOnCrash) + { + // 255 // Main + Display->CreateBuffer(0, 0, 254); // Details + Display->CreateBuffer(0, 0, 253); // Frames + Display->CreateBuffer(0, 0, 252); // Tasks + Display->CreateBuffer(0, 0, 251); // Console + Display->CreateBuffer(0, 0, 250); // Empty - DisplayTopOverlay(); - DisplayMainScreen(crashdata); - DisplayBottomOverlay(); - Display->SetBuffer(255); - debug("Interrupts are enabled, waiting for user input"); - CPU::Interrupts(CPU::Enable); - HookKeyboard(); - } - else - { - /* - TODO: Stuff that should be done when IOC is disabled. - */ - Display->SetBuffer(255); - } + DisplayTopOverlay(); + DisplayMainScreen(crashdata); + DisplayBottomOverlay(); + Display->SetBuffer(255); + debug("Interrupts are enabled, waiting for user input"); + CPU::Interrupts(CPU::Enable); + HookKeyboard(); + } + else + { + /* + TODO: Stuff that should be done when IOC is disabled. + */ + Display->SetBuffer(255); + } - CPU::Halt(true); - } + CPU::Halt(true); + } } diff --git a/Core/Crash/Screens/Details.cpp b/Core/Crash/Screens/Details.cpp index 97c2803..2b938f6 100644 --- a/Core/Crash/Screens/Details.cpp +++ b/Core/Crash/Screens/Details.cpp @@ -52,9 +52,11 @@ namespace CrashHandler if (cpu) { EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu); - EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", cpu->Stack, cpu->ID, cpu->ErrorCode); + EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", + cpu->Stack, cpu->ID, cpu->ErrorCode); EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false"); - EHPrint("Current Process: %#lx, Current Thread: %#lx\n", cpu->CurrentProcess, cpu->CurrentThread); + EHPrint("Current Process: %#lx, Current Thread: %#lx\n", + cpu->CurrentProcess.load(), cpu->CurrentThread.load()); EHPrint("Arch Specific Data: %#lx\n", cpu->Data); EHPrint("Checksum: 0x%X\n", cpu->Checksum); } @@ -128,11 +130,11 @@ namespace CrashHandler #endif #if defined(a86) - EHPrint("\eA0A0A0DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s\n", + EHPrint("\eA0A0A0DR6: B0:%s B1:%s B2:%s B3:%s\n BD:%s BS:%s BT:%s\n", data.dr6.B0 ? "True " : "False", data.dr6.B1 ? "True " : "False", data.dr6.B2 ? "True " : "False", data.dr6.B3 ? "True " : "False", data.dr6.BD ? "True " : "False", data.dr6.BS ? "True " : "False", data.dr6.BT ? "True " : "False"); - EHPrint("\eA0F0F0DR7: L0:%s G0:%s L1:%s G1:%s\n L2:%s G2:%s L3:%s G3:%s\n LE:%s GE:%s GD:%s\n R/W0:%s LEN0:%s R/W1:%s LEN1:%s\n R/W2:%s LEN2:%s R/W3:%s LEN3:%s\n", + EHPrint("\eA0F0F0DR7: L0:%s G0:%s L1:%s G1:%s\n L2:%s G2:%s L3:%s G3:%s\n LE:%s GE:%s GD:%s\n R/W0:%s LEN0:%s R/W1:%s LEN1:%s\n R/W2:%s LEN2:%s R/W3:%s LEN3:%s\n", data.dr7.L0 ? "True " : "False", data.dr7.G0 ? "True " : "False", data.dr7.L1 ? "True " : "False", data.dr7.G1 ? "True " : "False", data.dr7.L2 ? "True " : "False", data.dr7.G2 ? "True " : "False", data.dr7.L3 ? "True " : "False", data.dr7.G3 ? "True " : "False", data.dr7.LE ? "True " : "False", data.dr7.GE ? "True " : "False", data.dr7.GD ? "True " : "False", data.dr7.RW0 ? "True " : "False", diff --git a/Core/Crash/Screens/Main.cpp b/Core/Crash/Screens/Main.cpp index 437324f..a03f951 100644 --- a/Core/Crash/Screens/Main.cpp +++ b/Core/Crash/Screens/Main.cpp @@ -311,7 +311,7 @@ namespace CrashHandler case CPU::x86::PageFault: { EHPrint("Exception: Page Fault\n"); - EHPrint("The processor attempted to access a page that is not present.\n"); + EHPrint("The processor attempted to access a page that is not present/accessible.\n"); CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; #if defined(a64) diff --git a/Core/Crash/Screens/Tasks.cpp b/Core/Crash/Screens/Tasks.cpp index 97d8c4f..c2f64f7 100644 --- a/Core/Crash/Screens/Tasks.cpp +++ b/Core/Crash/Screens/Tasks.cpp @@ -41,8 +41,8 @@ namespace CrashHandler "AAFF00", // Ready "00AA00", // Running "FFAA00", // Sleeping - "FFAA00", // Waiting - "FF0088", // Stopped + "FFAA00", // Blocked + "FF0088", // Zombie "FF0000", // Terminated }; @@ -51,8 +51,8 @@ namespace CrashHandler "Ready", // Ready "Running", // Running "Sleeping", // Sleeping - "Waiting", // Waiting - "Stopped", // Stopped + "Blocked", // Blocked + "Zombie", // Zombie "Terminated", // Terminated }; @@ -62,9 +62,11 @@ namespace CrashHandler if (data.Thread) #if defined(a64) - EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip); + EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", + data.Thread->Name, data.Thread->ID, data.Frame->rip); #elif defined(a32) - EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->eip); + EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", + data.Thread->Name, data.Thread->ID, data.Frame->eip); #elif defined(aa64) #endif @@ -72,12 +74,14 @@ namespace CrashHandler foreach (auto Process in Plist) { EHPrint("\e%s-> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA PT:\e00AAAA%#lx\n", - StatusColor[Process->Status], Process->Name, Process->ID, StatusString[Process->Status], + StatusColor[Process->Status.load()], Process->Name, + Process->ID, StatusString[Process->Status.load()], Process->PageTable); foreach (auto Thread in Process->Threads) EHPrint("\e%s -> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA Stack:\e00AAAA%#lx\n", - StatusColor[Thread->Status], Thread->Name, Thread->ID, StatusString[Thread->Status], + StatusColor[Thread->Status.load()], Thread->Name, + Thread->ID, StatusString[Thread->Status.load()], Thread->Stack); } } diff --git a/Core/Crash/UserHandler.cpp b/Core/Crash/UserHandler.cpp index 6792b84..a777e25 100644 --- a/Core/Crash/UserHandler.cpp +++ b/Core/Crash/UserHandler.cpp @@ -47,7 +47,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) CriticalSection cs; debug("Interrupts? %s.", cs.IsInterruptsEnabled() ? "Yes" : "No"); fixme("Handling user mode exception"); - TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Stopped; + thisThread->Status = Tasking::TaskStatus::Zombie; CPUData *CurCPU = GetCurrentCPU(); { @@ -354,7 +354,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) if (CurCPU->CurrentThread->Stack->Expand(CrashHandler::PageFaultAddress)) { debug("Stack expanded"); - TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready; + thisThread->Status = Tasking::TaskStatus::Ready; return; } break; @@ -389,7 +389,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) } } - TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated; + thisThread->Status = Tasking::TaskStatus::Terminated; __sync; error("End of report."); CPU::Interrupts(CPU::Enable); diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 9545caa..3af8ffe 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -27,170 +27,170 @@ using namespace UniversalAsynchronousReceiverTransmitter; static inline NIF void uart_wrapper(char c, void *unused) { - UART(COM1).Write(c); - UNUSED(unused); + UART(COM1).Write(c); + UNUSED(unused); } static inline NIF bool WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, va_list args) { - const char *DbgLvlString; - switch (Level) - { - case DebugLevelError: - DbgLvlString = "ERROR"; - break; - case DebugLevelWarning: - DbgLvlString = "WARN "; - break; - case DebugLevelInfo: - DbgLvlString = "INFO "; - break; - case DebugLevelDebug: - DbgLvlString = "DEBUG"; - break; - case DebugLevelTrace: - DbgLvlString = "TRACE"; - break; - case DebugLevelFixme: - DbgLvlString = "FIXME"; - break; - case DebugLevelStub: - fctprintf(uart_wrapper, nullptr, "STUB | %s>%s() is stub\n", File, Function); - return false; - case DebugLevelFunction: - fctprintf(uart_wrapper, nullptr, "FUNC | %s>%s( ", File, Function); - vfctprintf(uart_wrapper, nullptr, Format, args); - fctprintf(uart_wrapper, nullptr, " )\n"); - return false; - case DebugLevelUbsan: - { - DbgLvlString = "UBSAN"; - fctprintf(uart_wrapper, nullptr, "%s| ", DbgLvlString); - return true; - } - default: - DbgLvlString = "UNKNW"; - break; - } - fctprintf(uart_wrapper, nullptr, "%s| %s>%s:%d: ", DbgLvlString, File, Function, Line); - return true; + const char *DbgLvlString; + switch (Level) + { + case DebugLevelError: + DbgLvlString = "ERROR"; + break; + case DebugLevelWarning: + DbgLvlString = "WARN "; + break; + case DebugLevelInfo: + DbgLvlString = "INFO "; + break; + case DebugLevelDebug: + DbgLvlString = "DEBUG"; + break; + case DebugLevelTrace: + DbgLvlString = "TRACE"; + break; + case DebugLevelFixme: + DbgLvlString = "FIXME"; + break; + case DebugLevelStub: + fctprintf(uart_wrapper, nullptr, "STUB | %s>%s() is stub\n", File, Function); + return false; + case DebugLevelFunction: + fctprintf(uart_wrapper, nullptr, "FUNC | %s>%s( ", File, Function); + vfctprintf(uart_wrapper, nullptr, Format, args); + fctprintf(uart_wrapper, nullptr, " )\n"); + return false; + case DebugLevelUbsan: + { + DbgLvlString = "UBSAN"; + fctprintf(uart_wrapper, nullptr, "%s| ", DbgLvlString); + return true; + } + default: + DbgLvlString = "UNKNW"; + break; + } + fctprintf(uart_wrapper, nullptr, "%s| %s>%s:%d: ", DbgLvlString, File, Function, Line); + return true; } namespace SysDbg { - NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) - { - va_list args; - va_start(args, Format); - if (!WritePrefix(Level, File, Line, Function, Format, args)) - { - va_end(args); - return; - } - vfctprintf(uart_wrapper, nullptr, Format, args); - va_end(args); - } + NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) + { + va_list args; + va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } + vfctprintf(uart_wrapper, nullptr, Format, args); + va_end(args); + } - NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) - { - va_list args; - va_start(args, Format); - if (!WritePrefix(Level, File, Line, Function, Format, args)) - { - va_end(args); - return; - } - vfctprintf(uart_wrapper, nullptr, Format, args); - va_end(args); - uart_wrapper('\n', nullptr); - } + NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) + { + va_list args; + va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } + vfctprintf(uart_wrapper, nullptr, Format, args); + va_end(args); + uart_wrapper('\n', nullptr); + } - NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) - { - SmartTimeoutLock(DebuggerLock, 1000); - va_list args; - va_start(args, Format); - if (!WritePrefix(Level, File, Line, Function, Format, args)) - { - va_end(args); - return; - } - vfctprintf(uart_wrapper, nullptr, Format, args); - va_end(args); - } + NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) + { + SmartTimeoutLock(DebuggerLock, 1000); + va_list args; + va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } + vfctprintf(uart_wrapper, nullptr, Format, args); + va_end(args); + } - NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) - { - SmartTimeoutLock(DebuggerLock, 1000); - va_list args; - va_start(args, Format); - if (!WritePrefix(Level, File, Line, Function, Format, args)) - { - va_end(args); - return; - } - vfctprintf(uart_wrapper, nullptr, Format, args); - va_end(args); - uart_wrapper('\n', nullptr); - } + NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) + { + SmartTimeoutLock(DebuggerLock, 1000); + va_list args; + va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } + vfctprintf(uart_wrapper, nullptr, Format, args); + va_end(args); + uart_wrapper('\n', nullptr); + } } // C compatibility extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { - va_list args; - va_start(args, Format); - if (!WritePrefix(Level, File, Line, Function, Format, args)) - { - va_end(args); - return; - } - vfctprintf(uart_wrapper, nullptr, Format, args); - va_end(args); + va_list args; + va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } + vfctprintf(uart_wrapper, nullptr, Format, args); + va_end(args); } // C compatibility extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { - va_list args; - va_start(args, Format); - if (!WritePrefix(Level, File, Line, Function, Format, args)) - { - va_end(args); - return; - } - vfctprintf(uart_wrapper, nullptr, Format, args); - va_end(args); - uart_wrapper('\n', nullptr); + va_list args; + va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } + vfctprintf(uart_wrapper, nullptr, Format, args); + va_end(args); + uart_wrapper('\n', nullptr); } // C compatibility extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { - SmartTimeoutLock(DebuggerLock, 1000); - va_list args; - va_start(args, Format); - if (!WritePrefix(Level, File, Line, Function, Format, args)) - { - va_end(args); - return; - } - vfctprintf(uart_wrapper, nullptr, Format, args); - va_end(args); + SmartTimeoutLock(DebuggerLock, 1000); + va_list args; + va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } + vfctprintf(uart_wrapper, nullptr, Format, args); + va_end(args); } // C compatibility extern "C" NIF void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) { - SmartTimeoutLock(DebuggerLock, 1000); - va_list args; - va_start(args, Format); - if (!WritePrefix(Level, File, Line, Function, Format, args)) - { - va_end(args); - return; - } - vfctprintf(uart_wrapper, nullptr, Format, args); - va_end(args); - uart_wrapper('\n', nullptr); + SmartTimeoutLock(DebuggerLock, 1000); + va_list args; + va_start(args, Format); + if (!WritePrefix(Level, File, Line, Function, Format, args)) + { + va_end(args); + return; + } + vfctprintf(uart_wrapper, nullptr, Format, args); + va_end(args); + uart_wrapper('\n', nullptr); } diff --git a/Core/Disk.cpp b/Core/Disk.cpp index 2444b16..5aa3ddb 100644 --- a/Core/Disk.cpp +++ b/Core/Disk.cpp @@ -29,7 +29,7 @@ namespace Disk void Manager::FetchDisks(unsigned long DriverUID) { KernelCallback callback{}; - callback.Reason = FetchReason; + callback.Reason = QueryReason; DriverManager->IOCB(DriverUID, &callback); this->AvailablePorts = callback.DiskCallback.Fetch.Ports; this->BytesPerSector = callback.DiskCallback.Fetch.BytesPerSector; diff --git a/Core/Driver/Driver.cpp b/Core/Driver/Driver.cpp index fd99c57..1b560bc 100644 --- a/Core/Driver/Driver.cpp +++ b/Core/Driver/Driver.cpp @@ -83,29 +83,29 @@ namespace Driver { debug("Searching for driver %ld", DUID); - foreach (auto Drv in Drivers) + forItr(Drv, Drivers) { - if (Drv.DriverUID != DUID) + if (Drv->DriverUID != DUID) continue; KernelCallback callback{}; callback.Reason = StopReason; - debug("Stopping & unloading driver %ld [%#lx]", Drv.DriverUID, Drv.Address); - this->IOCB(Drv.DriverUID, &callback); + debug("Stopping & unloading driver %ld [%#lx]", Drv->DriverUID, Drv->Address); + this->IOCB(Drv->DriverUID, &callback); - for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++) + for (size_t j = 0; j < sizeof(Drv->InterruptHook) / sizeof(Drv->InterruptHook[0]); j++) { - if (!Drv.InterruptHook[j]) + if (!Drv->InterruptHook[j]) continue; - debug("Interrupt hook %#lx", Drv.InterruptHook[j]); - delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr; + debug("Interrupt hook %#lx", Drv->InterruptHook[j]); + delete Drv->InterruptHook[j], Drv->InterruptHook[j] = nullptr; } - if (Drv.MemTrk) - delete Drv.MemTrk, Drv.MemTrk = nullptr; + if (Drv->MemTrk) + delete Drv->MemTrk, Drv->MemTrk = nullptr; - Drivers.remove(Drv); + Drivers.erase(Drv); return true; } return false; @@ -157,7 +157,7 @@ namespace Driver return DriverCode::OK; } - DriverCode Driver::LoadDriver(uintptr_t DriverAddress, uintptr_t Size) + DriverCode Driver::LoadDriver(uintptr_t DriverAddress, size_t Size) { Fex *DrvHdr = (Fex *)DriverAddress; if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0') @@ -201,22 +201,23 @@ namespace Driver StartAHCI(); StartVMwareMouse(); StartPS2Mouse(); + StartPS2Keyboard(); StartATA(); StartAC97(); StartRTL8139(); StartPCNET(); StartGigabit(); - VirtualFileSystem::File DriverDirectory = vfs->Open(Config.DriverDirectory); - if (!DriverDirectory.IsOK()) + RefNode *DriverDirectory = vfs->Open(Config.DriverDirectory); + if (!DriverDirectory) { - KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status); - vfs->Close(DriverDirectory); + KPrint("\eE85230Failed to open %s: %d)", + Config.DriverDirectory, errno); return; } debug("Loading drivers from %s", Config.DriverDirectory); - foreach (auto DrvFile in DriverDirectory.GetChildren()) + foreach (auto DrvFile in DriverDirectory->GetNode()->Children) { if (DrvFile->Flags != VirtualFileSystem::NodeFlags::FILE) continue; @@ -241,7 +242,7 @@ namespace Driver } } } - vfs->Close(DriverDirectory); + delete DriverDirectory; } Driver::Driver() {} diff --git a/Core/Driver/DriverBinding/BindInput.cpp b/Core/Driver/DriverBinding/BindInput.cpp index 0ac2fe0..98fe0c9 100644 --- a/Core/Driver/DriverBinding/BindInput.cpp +++ b/Core/Driver/DriverBinding/BindInput.cpp @@ -34,6 +34,9 @@ namespace Driver DriverCode Driver::DriverLoadBindInput(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn) { stub; + UNUSED(DriverAddress); + UNUSED(Size); + UNUSED(IsBuiltIn); return DriverCode::NOT_IMPLEMENTED; } } diff --git a/Core/Driver/DriverBinding/BindInterrupt.cpp b/Core/Driver/DriverBinding/BindInterrupt.cpp index d14bd91..09cfdcf 100644 --- a/Core/Driver/DriverBinding/BindInterrupt.cpp +++ b/Core/Driver/DriverBinding/BindInterrupt.cpp @@ -33,7 +33,7 @@ namespace Driver { DriverCode Driver::DriverLoadBindInterrupt(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn) { - Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory); + Memory::MemMgr *mem = new Memory::MemMgr(nullptr, thisProcess->memDirectory); BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress; Fex *fex = nullptr; diff --git a/Core/Driver/DriverBinding/BindPCI.cpp b/Core/Driver/DriverBinding/BindPCI.cpp index 792ad44..9311aab 100644 --- a/Core/Driver/DriverBinding/BindPCI.cpp +++ b/Core/Driver/DriverBinding/BindPCI.cpp @@ -61,7 +61,7 @@ namespace Driver debug("[%ld] VendorID: %#x; DeviceID: %#x", devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID); - Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory); + Memory::MemMgr *mem = new Memory::MemMgr(nullptr, thisProcess->memDirectory); BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress; Fex *fex = nullptr; diff --git a/Core/Driver/DriverBinding/BindProcess.cpp b/Core/Driver/DriverBinding/BindProcess.cpp index e461415..188ef73 100644 --- a/Core/Driver/DriverBinding/BindProcess.cpp +++ b/Core/Driver/DriverBinding/BindProcess.cpp @@ -34,6 +34,9 @@ namespace Driver DriverCode Driver::DriverLoadBindProcess(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn) { stub; + UNUSED(DriverAddress); + UNUSED(Size); + UNUSED(IsBuiltIn); return DriverCode::NOT_IMPLEMENTED; } } diff --git a/Core/InterruptsManager.cpp b/Core/InterruptsManager.cpp index b679a89..77467f1 100644 --- a/Core/InterruptsManager.cpp +++ b/Core/InterruptsManager.cpp @@ -40,209 +40,213 @@ extern "C" SafeFunction void ExceptionHandler(void *Data) { CrashHandler::Handle namespace Interrupts { - struct Event - { - int ID; - void *Data; - }; - std::vector RegisteredEvents; + struct Event + { + int ID; + void *Data; + }; + std::vector RegisteredEvents; #if defined(a64) - /* APIC::APIC */ void *apic[MAX_CPU]; - /* APIC::Timer */ void *apicTimer[MAX_CPU]; + /* APIC::APIC */ void *apic[MAX_CPU]; + /* APIC::Timer */ void *apicTimer[MAX_CPU]; #elif defined(a32) - /* APIC::APIC */ void *apic[MAX_CPU]; + /* APIC::APIC */ void *apic[MAX_CPU]; #elif defined(aa64) #endif - void *InterruptFrames[INT_FRAMES_MAX]; + void *InterruptFrames[INT_FRAMES_MAX]; - void Initialize(int Core) - { + void Initialize(int Core) + { #if defined(a64) - GlobalDescriptorTable::Init(Core); - InterruptDescriptorTable::Init(Core); - CPUData *CoreData = GetCPU(Core); - CoreData->Checksum = CPU_DATA_CHECKSUM; - CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, (uint64_t)CoreData); - CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); - CoreData->ID = Core; - CoreData->IsActive = true; - CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE; - if (CoreData->Checksum != CPU_DATA_CHECKSUM) - { - KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM); - CPU::Stop(); - } - debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE); - InitializeSystemCalls(); + GlobalDescriptorTable::Init(Core); + InterruptDescriptorTable::Init(Core); + CPUData *CoreData = GetCPU(Core); + CoreData->Checksum = CPU_DATA_CHECKSUM; + CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, (uint64_t)CoreData); + CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); + CoreData->ID = Core; + CoreData->IsActive = true; + CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE; + if (CoreData->Checksum != CPU_DATA_CHECKSUM) + { + KPrint("CPU %d checksum mismatch! %x != %x", + Core, CoreData->Checksum, CPU_DATA_CHECKSUM); + CPU::Stop(); + } + debug("Stack for core %d is %#lx (Address: %#lx)", + Core, CoreData->Stack, CoreData->Stack - STACK_SIZE); + InitializeSystemCalls(); #elif defined(a32) - GlobalDescriptorTable::Init(Core); - InterruptDescriptorTable::Init(Core); - CPUData *CoreData = GetCPU(Core); - CoreData->Checksum = CPU_DATA_CHECKSUM; - CPU::x32::wrmsr(CPU::x32::MSR_GS_BASE, (uint64_t)CoreData); - CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); - CoreData->ID = Core; - CoreData->IsActive = true; - CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE; - if (CoreData->Checksum != CPU_DATA_CHECKSUM) - { - KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM); - CPU::Stop(); - } - debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE); + GlobalDescriptorTable::Init(Core); + InterruptDescriptorTable::Init(Core); + CPUData *CoreData = GetCPU(Core); + CoreData->Checksum = CPU_DATA_CHECKSUM; + CPU::x32::wrmsr(CPU::x32::MSR_GS_BASE, (uint64_t)CoreData); + CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); + CoreData->ID = Core; + CoreData->IsActive = true; + CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE; + if (CoreData->Checksum != CPU_DATA_CHECKSUM) + { + KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM); + CPU::Stop(); + } + debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE); #elif defined(aa64) - warn("aarch64 is not supported yet"); + warn("aarch64 is not supported yet"); #endif - } + } - void Enable(int Core) - { + void Enable(int Core) + { #if defined(a64) - if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr) - { - // TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores. - apic[Core] = new APIC::APIC(Core); - if (Core == Config.IOAPICInterruptCore) // Redirect IRQs to the specified core. - ((APIC::APIC *)apic[Core])->RedirectIRQs(Core); - } - else - { - error("LAPIC not found"); - // TODO: PIC - } + if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr) + { + // TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores. + apic[Core] = new APIC::APIC(Core); + if (Core == Config.IOAPICInterruptCore) // Redirect IRQs to the specified core. + ((APIC::APIC *)apic[Core])->RedirectIRQs(Core); + } + else + { + error("LAPIC not found"); + // TODO: PIC + } #elif defined(a32) - warn("i386 is not supported yet"); + warn("i386 is not supported yet"); #elif defined(aa64) - warn("aarch64 is not supported yet"); + warn("aarch64 is not supported yet"); #endif - } + } - void InitializeTimer(int Core) - { - // TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores. + void InitializeTimer(int Core) + { + // TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores. #if defined(a64) - if (apic[Core] != nullptr) - apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]); - else - { - fixme("apic not found"); - } + if (apic[Core] != nullptr) + apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]); + else + { + fixme("apic not found"); + } #elif defined(a32) - warn("i386 is not supported yet"); + warn("i386 is not supported yet"); #elif defined(aa64) - warn("aarch64 is not supported yet"); + warn("aarch64 is not supported yet"); #endif - } + } - SafeFunction void RemoveAll() - { - RegisteredEvents.clear(); - } + SafeFunction void RemoveAll() + { + RegisteredEvents.clear(); + } - extern "C" SafeFunction void MainInterruptHandler(void *Data) - { + extern "C" SafeFunction void MainInterruptHandler(void *Data) + { #if defined(a64) - CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data; - // debug("IRQ%ld", Frame->InterruptNumber - 32); + CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data; + // debug("IRQ%ld", Frame->InterruptNumber - 32); - memmove(InterruptFrames + 1, InterruptFrames, sizeof(InterruptFrames) - sizeof(InterruptFrames[0])); - InterruptFrames[0] = (void *)Frame->rip; + memmove(InterruptFrames + 1, InterruptFrames, sizeof(InterruptFrames) - sizeof(InterruptFrames[0])); + InterruptFrames[0] = (void *)Frame->rip; - CPUData *CoreData = GetCurrentCPU(); - int Core = 0; - if (likely(CoreData != nullptr)) - Core = CoreData->ID; + CPUData *CoreData = GetCurrentCPU(); + int Core = 0; + if (likely(CoreData != nullptr)) + Core = CoreData->ID; - /* If this is false, we have a big problem. */ - if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && Frame->InterruptNumber > CPU::x86::ISR0)) - { - /* Halt core interrupt */ - if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ29)) - CPU::Stop(); + /* If this is false, we have a big problem. */ + if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && Frame->InterruptNumber > CPU::x86::ISR0)) + { + /* Halt core interrupt */ + if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ29)) + CPU::Stop(); - bool InterruptHandled = false; - foreach (auto ev in RegisteredEvents) - { + bool InterruptHandled = false; + foreach (auto ev in RegisteredEvents) + { #if defined(a86) - if ((ev.ID + CPU::x86::IRQ0) == static_cast(Frame->InterruptNumber)) + if ((ev.ID + CPU::x86::IRQ0) == s_cst(int, Frame->InterruptNumber)) #elif defined(aa64) - if (ev.ID == static_cast(Frame->InterruptNumber)) + if (ev.ID == s_cst(int, Frame->InterruptNumber)) #endif - { - ((Handler *)ev.Data)->OnInterruptReceived(Frame); - InterruptHandled = true; - } - } + { + Handler *hnd = (Handler *)ev.Data; + hnd->OnInterruptReceived(Frame); + InterruptHandled = true; + } + } - if (!InterruptHandled) - { - error("IRQ%ld is unhandled on CPU %d.", Frame->InterruptNumber - 32, Core); - if (Frame->InterruptNumber == CPU::x86::IRQ1) - { - uint8_t scancode = inb(0x60); - warn("IRQ1 is the keyboard interrupt. Scancode: %#x", scancode); - } - } + if (!InterruptHandled) + { + error("IRQ%ld is unhandled on CPU %d.", Frame->InterruptNumber - 32, Core); + if (Frame->InterruptNumber == CPU::x86::IRQ1) + { + uint8_t scancode = inb(0x60); + warn("IRQ1 is the keyboard interrupt. Scancode: %#x", scancode); + } + } - if (likely(apic[Core])) - { - ((APIC::APIC *)Interrupts::apic[Core])->EOI(); - // TODO: Handle PIC too - return; - } - // TODO: PIC - } + if (likely(apic[Core])) + { + ((APIC::APIC *)Interrupts::apic[Core])->EOI(); + // TODO: Handle PIC too + return; + } + // TODO: PIC + } #elif defined(a32) - void *Frame = Data; + void *Frame = Data; #elif defined(aa64) - CPU::aarch64::TrapFrame *Frame = (CPU::aarch64::TrapFrame *)Data; + CPU::aarch64::TrapFrame *Frame = (CPU::aarch64::TrapFrame *)Data; #endif - error("HALT HALT HALT HALT HALT HALT HALT HALT HALT"); - CPU::Stop(); - } + error("HALT HALT HALT HALT HALT HALT HALT HALT HALT"); + CPU::Stop(); + } - Handler::Handler(int InterruptNumber) - { - foreach (auto ev in RegisteredEvents) - { - if (ev.ID == InterruptNumber) - { - warn("IRQ%d is already registered.", InterruptNumber); - } - } + Handler::Handler(int InterruptNumber) + { + foreach (auto ev in RegisteredEvents) + { + if (ev.ID == InterruptNumber) + { + warn("IRQ%d is already registered.", InterruptNumber); + } + } - debug("Registering interrupt handler for IRQ%d.", InterruptNumber); - this->InterruptNumber = InterruptNumber; - RegisteredEvents.push_back({InterruptNumber, this}); - } + debug("Registering interrupt handler for IRQ%d.", InterruptNumber); + this->InterruptNumber = InterruptNumber; + RegisteredEvents.push_back({InterruptNumber, this}); + } - Handler::~Handler() - { - debug("Unregistering interrupt handler for IRQ%d.", this->InterruptNumber); - for (size_t i = 0; i < RegisteredEvents.size(); i++) - { - if (RegisteredEvents[i].ID == this->InterruptNumber) - { - RegisteredEvents.remove(i); - return; - } - } - warn("Event %d not found.", this->InterruptNumber); - } + Handler::~Handler() + { + debug("Unregistering interrupt handler for IRQ%d.", this->InterruptNumber); + + forItr(itr, RegisteredEvents) + { + if (itr->ID == this->InterruptNumber) + { + RegisteredEvents.erase(itr); + return; + } + } + warn("Event %d not found.", this->InterruptNumber); + } #if defined(a64) - void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame) - { - trace("Unhandled interrupt IRQ%d", Frame->InterruptNumber - 32); + void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame) + { + trace("Unhandled interrupt IRQ%d", Frame->InterruptNumber - 32); #elif defined(a32) - void Handler::OnInterruptReceived(CPU::x32::TrapFrame *Frame) - { - trace("Unhandled interrupt received"); + void Handler::OnInterruptReceived(CPU::x32::TrapFrame *Frame) + { + trace("Unhandled interrupt received"); #elif defined(aa64) - void Handler::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame) - { - trace("Unhandled interrupt received"); + void Handler::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame) + { + trace("Unhandled interrupt received"); #endif - } + } } diff --git a/Core/Lock.cpp b/Core/Lock.cpp index 248c713..3a5cc11 100644 --- a/Core/Lock.cpp +++ b/Core/Lock.cpp @@ -27,52 +27,67 @@ #endif #ifdef PRINT_BACKTRACE +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wframe-address" void PrintStacktrace(LockClass::SpinLockData *Lock) { - if (KernelSymbolTable) - { - struct StackFrame - { - uintptr_t BasePointer; - uintptr_t ReturnAddress; - }; + if (KernelSymbolTable) + { + struct StackFrame + { + uintptr_t BasePointer; + uintptr_t ReturnAddress; + }; - char DbgAttempt[1024] = "\0"; - char DbgHolder[1024] = "\0"; + // char DbgAttempt[1024] = "\0"; + // char DbgHolder[1024] = "\0"; - StackFrame *FrameAttempt = (StackFrame *)Lock->StackPointerAttempt.load(); - StackFrame *FrameHolder = (StackFrame *)Lock->StackPointerHolder.load(); + std::string DbgAttempt = "\0"; + std::string DbgHolder = "\0"; - while (Memory::Virtual().Check(FrameAttempt)) - { - sprintf(DbgAttempt + strlen(DbgAttempt), "%s<-", KernelSymbolTable->GetSymbolFromAddress(FrameAttempt->ReturnAddress)); - FrameAttempt = (StackFrame *)FrameAttempt->BasePointer; - } + StackFrame *FrameAttempt = (StackFrame *)Lock->StackPointerAttempt.load(); + StackFrame *FrameHolder = (StackFrame *)Lock->StackPointerHolder.load(); - while (Memory::Virtual().Check(FrameHolder)) - { - sprintf(DbgHolder + strlen(DbgHolder), "%s<-", KernelSymbolTable->GetSymbolFromAddress(FrameHolder->ReturnAddress)); - FrameHolder = (StackFrame *)FrameHolder->BasePointer; - } + while (Memory::Virtual().Check(FrameAttempt)) + { + DbgAttempt.concat(KernelSymbolTable->GetSymbolFromAddress(FrameAttempt->ReturnAddress)); + DbgAttempt.concat("<-"); + FrameAttempt = (StackFrame *)FrameAttempt->BasePointer; + } + debug("Attempt: %s", DbgAttempt.c_str()); - debug("Attempt: %s", DbgAttempt); - debug("Holder: %s", DbgHolder); + while (Memory::Virtual().Check(FrameHolder)) + { + DbgHolder.concat(KernelSymbolTable->GetSymbolFromAddress(FrameHolder->ReturnAddress)); + DbgHolder.concat("<-"); + FrameHolder = (StackFrame *)FrameHolder->BasePointer; + } - // debug("\t\t%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s", - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)), - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(1)), - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(2)), - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(3)), - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(4)), - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(5)), - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(6)), - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(7)), - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(8)), - // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(9))); - } + debug("Holder: %s", DbgHolder.c_str()); + + // debug("\t\t%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s", + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)), + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(1)), + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(2)), + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(3)), + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(4)), + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(5)), + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(6)), + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(7)), + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(8)), + // KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(9))); + } } +#pragma GCC diagnostic pop +#endif + +#ifdef DEBUG +#define DEADLOCK_TIMEOUT 0x100000 +#define DEADLOCK_TIMEOUT_DEBUGGER 0x1000 +#else +#define DEADLOCK_TIMEOUT 0x10000000 +#define DEADLOCK_TIMEOUT_DEBUGGER 0x100000 #endif bool ForceUnlock = false; @@ -80,161 +95,168 @@ std::atomic_size_t LocksCount = 0; size_t GetLocksCount() { return LocksCount.load(); } -void LockClass::DeadLock(SpinLockData Lock) +void LockClass::Yield() { - if (ForceUnlock) - { - warn("Unlocking lock '%s' which it was held by '%s'...", Lock.AttemptingToGet, Lock.CurrentHolder); - this->DeadLocks = 0; - this->Unlock(); - return; - } + if (CPU::Interrupts(CPU::Check) && + TaskManager && + !TaskManager->IsPanic()) + { + TaskManager->Yield(); + } - CPUData *CoreData = GetCurrentCPU(); - long CCore = 0xdead; - if (CoreData != nullptr) - CCore = CoreData->ID; + CPU::Pause(); +} - warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. (%ld times happened)", - Lock.AttemptingToGet, Lock.CurrentHolder, - Lock.Count, Lock.Count > 1 ? "locks" : "lock", - CPU::Interrupts(CPU::Check) ? "enabled" : "disabled", - CCore, Lock.Core, this->DeadLocks); +void LockClass::DeadLock(SpinLockData &Lock) +{ + if (ForceUnlock) + { + warn("Unlocking lock '%s' which it was held by '%s'...", + Lock.AttemptingToGet, Lock.CurrentHolder); + this->DeadLocks = 0; + this->Unlock(); + return; + } + + CPUData *CoreData = GetCurrentCPU(); + long CCore = 0xdead; + if (CoreData != nullptr) + CCore = CoreData->ID; + + warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. (%ld times happened)", + Lock.AttemptingToGet, Lock.CurrentHolder, + Lock.Count, Lock.Count > 1 ? "locks" : "lock", + CPU::Interrupts(CPU::Check) ? "enabled" : "disabled", + CCore, Lock.Core, this->DeadLocks); #ifdef PRINT_BACKTRACE - PrintStacktrace(&Lock); + PrintStacktrace(&Lock); #endif - // TODO: Print on screen too. + // TODO: Print on screen too. - this->DeadLocks++; + this->DeadLocks++; - if (Config.UnlockDeadLock && this->DeadLocks.load() > 10) - { - warn("Unlocking lock '%s' to prevent deadlock. (this is enabled in the kernel config)", Lock.AttemptingToGet); - this->DeadLocks = 0; - this->Unlock(); - } + if (Config.UnlockDeadLock && this->DeadLocks.load() > 10) + { + warn("Unlocking lock '%s' to prevent deadlock. (this is enabled in the kernel config)", Lock.AttemptingToGet); + this->DeadLocks = 0; + this->Unlock(); + } - if (TaskManager && !TaskManager->IsPanic()) - TaskManager->Schedule(); + this->Yield(); } int LockClass::Lock(const char *FunctionName) { - LockData.AttemptingToGet = FunctionName; - LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0); + LockData.AttemptingToGet = FunctionName; + LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0); Retry: - int i = 0; - while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000)) - { - /* FIXME */ - // if (TaskManager && !TaskManager->IsPanic()) - // TaskManager->Schedule(); - // else - CPU::Pause(); - } + int i = 0; + while (IsLocked.exchange(true, std::memory_order_acquire) && + ++i < (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT)) + { + this->Yield(); + } - if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000)) - { - DeadLock(LockData); - goto Retry; - } + if (i >= (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT)) + { + DeadLock(LockData); + goto Retry; + } - LockData.Count++; - LockData.CurrentHolder = FunctionName; - LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0); + LockData.Count++; + LockData.CurrentHolder = FunctionName; + LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0); - CPUData *CoreData = GetCurrentCPU(); - if (CoreData != nullptr) - LockData.Core = CoreData->ID; + CPUData *CoreData = GetCurrentCPU(); + if (CoreData != nullptr) + LockData.Core = CoreData->ID; - LocksCount++; + LocksCount++; - __sync; - return 0; + __sync; + return 0; } int LockClass::Unlock() { - __sync; + __sync; - IsLocked.store(false, std::memory_order_release); - LockData.Count--; - LocksCount--; + IsLocked.store(false, std::memory_order_release); + LockData.Count--; + LocksCount--; - return 0; + return 0; } -void LockClass::TimeoutDeadLock(SpinLockData Lock, uint64_t Timeout) +void LockClass::TimeoutDeadLock(SpinLockData &Lock, uint64_t Timeout) { - CPUData *CoreData = GetCurrentCPU(); - long CCore = 0xdead; + CPUData *CoreData = GetCurrentCPU(); + long CCore = 0xdead; - if (CoreData != nullptr) - CCore = CoreData->ID; + if (CoreData != nullptr) + CCore = CoreData->ID; - uint64_t Counter = TimeManager->GetCounter(); + uint64_t Counter = TimeManager->GetCounter(); - warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. Timeout in %ld (%ld ticks remaining).", - Lock.AttemptingToGet, Lock.CurrentHolder, - Lock.Count, Lock.Count > 1 ? "locks" : "lock", - CPU::Interrupts(CPU::Check) ? "enabled" : "disabled", - CCore, Lock.Core, Timeout, Timeout - Counter); + warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. Timeout in %ld (%ld ticks remaining).", + Lock.AttemptingToGet, Lock.CurrentHolder, + Lock.Count, Lock.Count > 1 ? "locks" : "lock", + CPU::Interrupts(CPU::Check) ? "enabled" : "disabled", + CCore, Lock.Core, Timeout, Timeout - Counter); #ifdef PRINT_BACKTRACE - PrintStacktrace(&Lock); + PrintStacktrace(&Lock); #endif - if (Timeout < Counter) - { - warn("Unlocking lock '%s' because of timeout. (%ld < %ld)", Lock.AttemptingToGet, Timeout, Counter); - this->Unlock(); - } + if (Timeout < Counter) + { + warn("Unlocking lock '%s' because of timeout. (%ld < %ld)", + Lock.AttemptingToGet, Timeout, Counter); + this->Unlock(); + } - if (TaskManager && !TaskManager->IsPanic()) - TaskManager->Schedule(); + this->Yield(); } int LockClass::TimeoutLock(const char *FunctionName, uint64_t Timeout) { - if (!TimeManager) - return Lock(FunctionName); + if (!TimeManager) + return Lock(FunctionName); - LockData.AttemptingToGet = FunctionName; - LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0); + LockData.AttemptingToGet = FunctionName; + LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0); - std::atomic_uint64_t Target = 0; + std::atomic_uint64_t Target = 0; Retry: - int i = 0; - while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000)) - { - /* FIXME */ - // if (TaskManager && !TaskManager->IsPanic()) - // TaskManager->Schedule(); - // else - CPU::Pause(); - } + int i = 0; + while (IsLocked.exchange(true, std::memory_order_acquire) && + ++i < (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT)) + { + this->Yield(); + } - if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000)) - { - if (Target.load() == 0) - Target.store(TimeManager->CalculateTarget(Timeout, Time::Units::Milliseconds)); - TimeoutDeadLock(LockData, Target.load()); - goto Retry; - } + if (i >= (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT)) + { + if (Target.load() == 0) + Target.store(TimeManager->CalculateTarget(Timeout, + Time::Units::Milliseconds)); + TimeoutDeadLock(LockData, Target.load()); + goto Retry; + } - LockData.Count++; - LockData.CurrentHolder = FunctionName; - LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0); + LockData.Count++; + LockData.CurrentHolder = FunctionName; + LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0); - CPUData *CoreData = GetCurrentCPU(); - if (CoreData != nullptr) - LockData.Core = CoreData->ID; + CPUData *CoreData = GetCurrentCPU(); + if (CoreData != nullptr) + LockData.Core = CoreData->ID; - LocksCount++; + LocksCount++; - __sync; - return 0; + __sync; + return 0; } diff --git a/Core/Memory/HeapAllocators/Xalloc/XallocV1.cpp b/Core/Memory/HeapAllocators/Xalloc/XallocV1.cpp index 12f3837..46f8d22 100644 --- a/Core/Memory/HeapAllocators/Xalloc/XallocV1.cpp +++ b/Core/Memory/HeapAllocators/Xalloc/XallocV1.cpp @@ -22,7 +22,7 @@ Xalloc_def; #define XALLOC_CONCAT(x, y) x##y #define XStoP(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE) #define XPtoS(d) ((d)*PAGE_SIZE) -#define Xalloc_BlockChecksum 0xA110C +#define Xalloc_BlockSanityKey 0xA110C extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages); extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages); @@ -55,7 +55,7 @@ namespace Xalloc public: void *Address = nullptr; - int Checksum = Xalloc_BlockChecksum; + int Sanity = Xalloc_BlockSanityKey; Xsize_t Size = 0; Block *Next = nullptr; Block *Last = nullptr; @@ -63,7 +63,7 @@ namespace Xalloc bool Check() { - if (this->Checksum != Xalloc_BlockChecksum) + if (this->Sanity != Xalloc_BlockSanityKey) return false; return true; } @@ -168,8 +168,8 @@ namespace Xalloc { if (!CurrentBlock->Check()) { - Xalloc_err("Block %#lx has an invalid checksum! (%#x != %#x)", - (Xuint64_t)CurrentBlock, CurrentBlock->Checksum, Xalloc_BlockChecksum); + Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)", + (Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey); while (Xalloc_StopOnFail) ; } @@ -210,8 +210,8 @@ namespace Xalloc { if (!CurrentBlock->Check()) { - Xalloc_err("Block %#lx has an invalid checksum! (%#x != %#x)", - (Xuint64_t)CurrentBlock, CurrentBlock->Checksum, Xalloc_BlockChecksum); + Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)", + (Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey); while (Xalloc_StopOnFail) ; } diff --git a/Core/Memory/Memory.cpp b/Core/Memory/Memory.cpp index ff04f17..15771c4 100644 --- a/Core/Memory/Memory.cpp +++ b/Core/Memory/Memory.cpp @@ -33,8 +33,8 @@ #ifdef DEBUG_ALLOCATIONS #define memdbg(m, ...) \ - debug(m, ##__VA_ARGS__); \ - __sync + debug(m, ##__VA_ARGS__); \ + __sync #else #define memdbg(m, ...) #endif @@ -51,236 +51,238 @@ PageTable *KernelPageTable = nullptr; bool Page1GBSupport = false; bool PSESupport = false; -static MemoryAllocatorType AllocatorType = MemoryAllocatorType::Pages; +MemoryAllocatorType AllocatorType = MemoryAllocatorType::Pages; Xalloc::V1 *XallocV1Allocator = nullptr; #ifdef DEBUG NIF void tracepagetable(PageTable *pt) { - for (int i = 0; i < 512; i++) - { + for (int i = 0; i < 512; i++) + { #if defined(a64) - if (pt->Entries[i].Present) - debug("Entry %03d: %x %x %x %x %x %x %x %p-%#llx", i, - pt->Entries[i].Present, pt->Entries[i].ReadWrite, - pt->Entries[i].UserSupervisor, pt->Entries[i].WriteThrough, - pt->Entries[i].CacheDisable, pt->Entries[i].Accessed, - pt->Entries[i].ExecuteDisable, pt->Entries[i].Address << 12, - pt->Entries[i]); + if (pt->Entries[i].Present) + debug("Entry %03d: %x %x %x %x %x %x %x %p-%#llx", i, + pt->Entries[i].Present, pt->Entries[i].ReadWrite, + pt->Entries[i].UserSupervisor, pt->Entries[i].WriteThrough, + pt->Entries[i].CacheDisable, pt->Entries[i].Accessed, + pt->Entries[i].ExecuteDisable, pt->Entries[i].Address << 12, + pt->Entries[i]); #elif defined(a32) #elif defined(aa64) #endif - } + } } #endif NIF void MapFromZero(PageTable *PT) { - debug("Mapping from 0x0 to %#llx", bInfo.Memory.Size); - Virtual va = Virtual(PT); - size_t MemSize = bInfo.Memory.Size; + debug("Mapping from 0x0 to %#llx", bInfo.Memory.Size); + Virtual va = Virtual(PT); + size_t MemSize = bInfo.Memory.Size; - if (Page1GBSupport && PSESupport) - { - /* Map the first 100MB of memory as 4KB pages */ + if (Page1GBSupport && PSESupport) + { + /* Map the first 100MB of memory as 4KB pages */ - // uintptr_t Physical4KBSectionStart = 0x10000000; - // va.Map((void *)0, - // (void *)0, - // Physical4KBSectionStart, - // PTFlag::RW); + // uintptr_t Physical4KBSectionStart = 0x10000000; + // va.Map((void *)0, + // (void *)0, + // Physical4KBSectionStart, + // PTFlag::RW); - // va.Map((void *)Physical4KBSectionStart, - // (void *)Physical4KBSectionStart, - // MemSize - Physical4KBSectionStart, - // PTFlag::RW, - // Virtual::MapType::OneGB); + // va.Map((void *)Physical4KBSectionStart, + // (void *)Physical4KBSectionStart, + // MemSize - Physical4KBSectionStart, + // PTFlag::RW, + // Virtual::MapType::OneGiB); - va.Map((void *)0, (void *)0, MemSize, PTFlag::RW); - } - else - va.Map((void *)0, (void *)0, MemSize, PTFlag::RW); + va.Map((void *)0, (void *)0, MemSize, PTFlag::RW); + } + else + va.Map((void *)0, (void *)0, MemSize, PTFlag::RW); - va.Unmap((void *)0); + va.Unmap((void *)0); } NIF void MapFramebuffer(PageTable *PT) { - debug("Mapping Framebuffer"); - Virtual va = Virtual(PT); - int itrfb = 0; - while (1) - { - if (!bInfo.Framebuffer[itrfb].BaseAddress) - break; + debug("Mapping Framebuffer"); + Virtual va = Virtual(PT); + int itrfb = 0; + while (1) + { + if (!bInfo.Framebuffer[itrfb].BaseAddress) + break; - va.OptimizedMap((void *)bInfo.Framebuffer[itrfb].BaseAddress, - (void *)bInfo.Framebuffer[itrfb].BaseAddress, - (size_t)(bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height), - PTFlag::RW | PTFlag::US | PTFlag::G); - itrfb++; + va.OptimizedMap((void *)bInfo.Framebuffer[itrfb].BaseAddress, + (void *)bInfo.Framebuffer[itrfb].BaseAddress, + (size_t)(bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height), + PTFlag::RW | PTFlag::US | PTFlag::G); + itrfb++; #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r", - bInfo.Framebuffer[itrfb].BaseAddress, - (bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height) + PAGE_SIZE); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r", + bInfo.Framebuffer[itrfb].BaseAddress, + (bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height) + PAGE_SIZE); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif - } + } } NIF void MapKernel(PageTable *PT) { - debug("Mapping Kernel"); + debug("Mapping Kernel"); - /* RWX */ - uintptr_t BootstrapStart = (uintptr_t)&_bootstrap_start; - uintptr_t BootstrapEnd = (uintptr_t)&_bootstrap_end; + /* RWX */ + uintptr_t BootstrapStart = (uintptr_t)&_bootstrap_start; + uintptr_t BootstrapEnd = (uintptr_t)&_bootstrap_end; - /* RX */ - uintptr_t KernelTextStart = (uintptr_t)&_kernel_text_start; - uintptr_t KernelTextEnd = (uintptr_t)&_kernel_text_end; + /* RX */ + uintptr_t KernelTextStart = (uintptr_t)&_kernel_text_start; + uintptr_t KernelTextEnd = (uintptr_t)&_kernel_text_end; - /* RW */ - uintptr_t KernelDataStart = (uintptr_t)&_kernel_data_start; - uintptr_t KernelDataEnd = (uintptr_t)&_kernel_data_end; + /* RW */ + uintptr_t KernelDataStart = (uintptr_t)&_kernel_data_start; + uintptr_t KernelDataEnd = (uintptr_t)&_kernel_data_end; - /* R */ - uintptr_t KernelRoDataStart = (uintptr_t)&_kernel_rodata_start; - uintptr_t KernelRoDataEnd = (uintptr_t)&_kernel_rodata_end; + /* R */ + uintptr_t KernelRoDataStart = (uintptr_t)&_kernel_rodata_start; + uintptr_t KernelRoDataEnd = (uintptr_t)&_kernel_rodata_end; - /* RW */ - uintptr_t KernelBssStart = (uintptr_t)&_kernel_bss_start; - uintptr_t KernelBssEnd = (uintptr_t)&_kernel_bss_end; - - uintptr_t KernelStart = (uintptr_t)&_kernel_start; - uintptr_t KernelEnd = (uintptr_t)&_kernel_end; - uintptr_t KernelFileStart = (uintptr_t)bInfo.Kernel.FileBase; - uintptr_t KernelFileEnd = KernelFileStart + bInfo.Kernel.Size; - - debug("Bootstrap: %#lx-%#lx", BootstrapStart, BootstrapEnd); - debug("Kernel text: %#lx-%#lx", KernelTextStart, KernelTextEnd); - debug("Kernel data: %#lx-%#lx", KernelDataStart, KernelDataEnd); - debug("Kernel rodata: %#lx-%#lx", KernelRoDataStart, KernelRoDataEnd); - debug("Kernel bss: %#lx-%#lx", KernelBssStart, KernelBssEnd); - debug("Kernel: %#lx-%#lx", KernelStart, KernelEnd); - debug("Kernel file: %#lx-%#lx", KernelFileStart, KernelFileEnd); - - debug("File size: %ld KB", TO_KB(bInfo.Kernel.Size)); - debug(".bootstrap size: %ld KB", TO_KB(BootstrapEnd - BootstrapStart)); - debug(".text size: %ld KB", TO_KB(KernelTextEnd - KernelTextStart)); - debug(".data size: %ld KB", TO_KB(KernelDataEnd - KernelDataStart)); - debug(".rodata size: %ld KB", TO_KB(KernelRoDataEnd - KernelRoDataStart)); - debug(".bss size: %ld KB", TO_KB(KernelBssEnd - KernelBssStart)); - - uintptr_t BaseKernelMapAddress = (uintptr_t)bInfo.Kernel.PhysicalBase; - debug("Base kernel map address: %#lx", BaseKernelMapAddress); - uintptr_t k; - Virtual va = Virtual(PT); - - /* Bootstrap section */ - if (BaseKernelMapAddress == BootstrapStart) - { - for (k = BootstrapStart; k < BootstrapEnd; k += PAGE_SIZE) - { - va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); - KernelAllocator.ReservePage((void *)BaseKernelMapAddress); - BaseKernelMapAddress += PAGE_SIZE; - } - } - else - { - trace("Ignoring bootstrap section."); - /* Bootstrap section must be mapped at 0x100000. */ - } - - /* Text section */ - for (k = KernelTextStart; k < KernelTextEnd; k += PAGE_SIZE) - { - va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); - KernelAllocator.ReservePage((void *)BaseKernelMapAddress); - BaseKernelMapAddress += PAGE_SIZE; - } - - /* Data section */ - for (k = KernelDataStart; k < KernelDataEnd; k += PAGE_SIZE) - { - va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); - KernelAllocator.ReservePage((void *)BaseKernelMapAddress); - BaseKernelMapAddress += PAGE_SIZE; - } - - /* Read only data section */ - for (k = KernelRoDataStart; k < KernelRoDataEnd; k += PAGE_SIZE) - { - va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::G); - KernelAllocator.ReservePage((void *)BaseKernelMapAddress); - BaseKernelMapAddress += PAGE_SIZE; - } - - /* Block starting symbol section */ - for (k = KernelBssStart; k < KernelBssEnd; k += PAGE_SIZE) - { - va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); - KernelAllocator.ReservePage((void *)BaseKernelMapAddress); - BaseKernelMapAddress += PAGE_SIZE; - } - - debug("Base kernel map address: %#lx", BaseKernelMapAddress); - - /* Kernel file */ - if (KernelFileStart != 0) - { - for (k = KernelFileStart; k < KernelFileEnd; k += PAGE_SIZE) - { - va.Map((void *)k, (void *)k, PTFlag::G); - KernelAllocator.ReservePage((void *)k); - } - } + /* RW */ + uintptr_t KernelBssStart = (uintptr_t)&_kernel_bss_start; + uintptr_t KernelBssEnd = (uintptr_t)&_kernel_bss_end; #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r", - bInfo.Kernel.PhysicalBase, - bInfo.Kernel.Size); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } + uintptr_t KernelStart = (uintptr_t)&_kernel_start; + uintptr_t KernelEnd = (uintptr_t)&_kernel_end; +#endif + uintptr_t KernelFileStart = (uintptr_t)bInfo.Kernel.FileBase; + uintptr_t KernelFileEnd = KernelFileStart + bInfo.Kernel.Size; - sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r", - bInfo.Kernel.VirtualBase, - bInfo.Kernel.Size); - mExtTrkLock.Unlock(); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - } + debug("Bootstrap: %#lx-%#lx", BootstrapStart, BootstrapEnd); + debug("Kernel text: %#lx-%#lx", KernelTextStart, KernelTextEnd); + debug("Kernel data: %#lx-%#lx", KernelDataStart, KernelDataEnd); + debug("Kernel rodata: %#lx-%#lx", KernelRoDataStart, KernelRoDataEnd); + debug("Kernel bss: %#lx-%#lx", KernelBssStart, KernelBssEnd); + debug("Kernel: %#lx-%#lx", KernelStart, KernelEnd); + debug("Kernel file: %#lx-%#lx", KernelFileStart, KernelFileEnd); + + debug("File size: %ld KiB", TO_KiB(bInfo.Kernel.Size)); + debug(".bootstrap size: %ld KiB", TO_KiB(BootstrapEnd - BootstrapStart)); + debug(".text size: %ld KiB", TO_KiB(KernelTextEnd - KernelTextStart)); + debug(".data size: %ld KiB", TO_KiB(KernelDataEnd - KernelDataStart)); + debug(".rodata size: %ld KiB", TO_KiB(KernelRoDataEnd - KernelRoDataStart)); + debug(".bss size: %ld KiB", TO_KiB(KernelBssEnd - KernelBssStart)); + + uintptr_t BaseKernelMapAddress = (uintptr_t)bInfo.Kernel.PhysicalBase; + debug("Base kernel map address: %#lx", BaseKernelMapAddress); + uintptr_t k; + Virtual va = Virtual(PT); + + /* Bootstrap section */ + if (BaseKernelMapAddress == BootstrapStart) + { + for (k = BootstrapStart; k < BootstrapEnd; k += PAGE_SIZE) + { + va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); + KernelAllocator.ReservePage((void *)BaseKernelMapAddress); + BaseKernelMapAddress += PAGE_SIZE; + } + } + else + { + trace("Ignoring bootstrap section."); + /* Bootstrap section must be mapped at 0x100000. */ + } + + /* Text section */ + for (k = KernelTextStart; k < KernelTextEnd; k += PAGE_SIZE) + { + va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); + KernelAllocator.ReservePage((void *)BaseKernelMapAddress); + BaseKernelMapAddress += PAGE_SIZE; + } + + /* Data section */ + for (k = KernelDataStart; k < KernelDataEnd; k += PAGE_SIZE) + { + va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); + KernelAllocator.ReservePage((void *)BaseKernelMapAddress); + BaseKernelMapAddress += PAGE_SIZE; + } + + /* Read only data section */ + for (k = KernelRoDataStart; k < KernelRoDataEnd; k += PAGE_SIZE) + { + va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::G); + KernelAllocator.ReservePage((void *)BaseKernelMapAddress); + BaseKernelMapAddress += PAGE_SIZE; + } + + /* Block starting symbol section */ + for (k = KernelBssStart; k < KernelBssEnd; k += PAGE_SIZE) + { + va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); + KernelAllocator.ReservePage((void *)BaseKernelMapAddress); + BaseKernelMapAddress += PAGE_SIZE; + } + + debug("Base kernel map address: %#lx", BaseKernelMapAddress); + + /* Kernel file */ + if (KernelFileStart != 0) + { + for (k = KernelFileStart; k < KernelFileEnd; k += PAGE_SIZE) + { + va.Map((void *)k, (void *)k, PTFlag::G); + KernelAllocator.ReservePage((void *)k); + } + } + +#ifdef DEBUG + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r", + bInfo.Kernel.PhysicalBase, + bInfo.Kernel.Size); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + + sprintf(mExtTrkLog, "Rsrv( %p %ld )\n\r", + bInfo.Kernel.VirtualBase, + bInfo.Kernel.Size); + mExtTrkLock.Unlock(); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + } #endif } @@ -288,564 +290,587 @@ NIF void InitializeMemoryManagement() { #ifdef DEBUG #ifndef a32 - for (uint64_t i = 0; i < bInfo.Memory.Entries; i++) - { - uintptr_t Base = r_cst(uintptr_t, bInfo.Memory.Entry[i].BaseAddress); - size_t Length = bInfo.Memory.Entry[i].Length; - uintptr_t End = Base + Length; - const char *Type = "Unknown"; + for (uint64_t i = 0; i < bInfo.Memory.Entries; i++) + { + uintptr_t Base = r_cst(uintptr_t, bInfo.Memory.Entry[i].BaseAddress); + size_t Length = bInfo.Memory.Entry[i].Length; + uintptr_t End = Base + Length; + const char *Type = "Unknown"; - switch (bInfo.Memory.Entry[i].Type) - { - case likely(Usable): - Type = "Usable"; - break; - case Reserved: - Type = "Reserved"; - break; - case ACPIReclaimable: - Type = "ACPI Reclaimable"; - break; - case ACPINVS: - Type = "ACPI NVS"; - break; - case BadMemory: - Type = "Bad Memory"; - break; - case BootloaderReclaimable: - Type = "Bootloader Reclaimable"; - break; - case KernelAndModules: - Type = "Kernel and Modules"; - break; - case Framebuffer: - Type = "Framebuffer"; - break; - default: - break; - } + switch (bInfo.Memory.Entry[i].Type) + { + case likely(Usable): + Type = "Usable"; + break; + case Reserved: + Type = "Reserved"; + break; + case ACPIReclaimable: + Type = "ACPI Reclaimable"; + break; + case ACPINVS: + Type = "ACPI NVS"; + break; + case BadMemory: + Type = "Bad Memory"; + break; + case BootloaderReclaimable: + Type = "Bootloader Reclaimable"; + break; + case KernelAndModules: + Type = "Kernel and Modules"; + break; + case Framebuffer: + Type = "Framebuffer"; + break; + default: + break; + } - debug("%ld: %p-%p %s", - i, - Base, - End, - Type); - } + debug("%ld: %p-%p %s", + i, + Base, + End, + Type); + } #endif // a32 #endif // DEBUG - trace("Initializing Physical Memory Manager"); - // KernelAllocator = Physical(); <- Already called in the constructor - KernelAllocator.Init(); - debug("Memory Info: %lldMB / %lldMB (%lldMB reserved)", - TO_MB(KernelAllocator.GetUsedMemory()), - TO_MB(KernelAllocator.GetTotalMemory()), - TO_MB(KernelAllocator.GetReservedMemory())); + trace("Initializing Physical Memory Manager"); + // KernelAllocator = Physical(); <- Already called in the constructor + KernelAllocator.Init(); + debug("Memory Info:\n\n%lld MiB / %lld MiB (%lld MiB reserved)\n", + TO_MiB(KernelAllocator.GetUsedMemory()), + TO_MiB(KernelAllocator.GetTotalMemory()), + TO_MiB(KernelAllocator.GetReservedMemory())); - /* -- Debugging -- - size_t bmap_size = KernelAllocator.GetPageBitmap().Size; - for (size_t i = 0; i < bmap_size; i++) - { - bool idx = KernelAllocator.GetPageBitmap().Get(i); - if (idx == true) - debug("Page %04d: %#lx", i, i * PAGE_SIZE); - } + /* -- Debugging -- + size_t bmap_size = KernelAllocator.GetPageBitmap().Size; + for (size_t i = 0; i < bmap_size; i++) + { + bool idx = KernelAllocator.GetPageBitmap().Get(i); + if (idx == true) + debug("Page %04d: %#lx", i, i * PAGE_SIZE); + } - inf_loop debug("Alloc.: %#lx", KernelAllocator.RequestPage()); - */ + inf_loop debug("Alloc.: %#lx", KernelAllocator.RequestPage()); + */ - trace("Initializing Virtual Memory Manager"); - KernelPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE + 1)); - memset(KernelPageTable, 0, PAGE_SIZE); + trace("Initializing Virtual Memory Manager"); + KernelPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE + 1)); + memset(KernelPageTable, 0, PAGE_SIZE); - if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) - { - CPU::x86::AMD::CPUID0x80000001 cpuid; - cpuid.Get(); - PSESupport = cpuid.EDX.PSE; - Page1GBSupport = cpuid.EDX.Page1GB; - } - else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) - { - CPU::x86::Intel::CPUID0x00000001 cpuid; - cpuid.Get(); - PSESupport = cpuid.EDX.PSE; - } + if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) + { + CPU::x86::AMD::CPUID0x80000001 cpuid; + cpuid.Get(); + PSESupport = cpuid.EDX.PSE; + Page1GBSupport = cpuid.EDX.Page1GB; + } + else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) + { + CPU::x86::Intel::CPUID0x00000001 cpuid; + cpuid.Get(); + PSESupport = cpuid.EDX.PSE; + } - if (PSESupport) - { + if (PSESupport) + { #if defined(a64) - CPU::x64::CR4 cr4 = CPU::x64::readcr4(); - cr4.PSE = 1; - CPU::x64::writecr4(cr4); + CPU::x64::CR4 cr4 = CPU::x64::readcr4(); + cr4.PSE = 1; + CPU::x64::writecr4(cr4); #elif defined(a32) - CPU::x32::CR4 cr4 = CPU::x32::readcr4(); - cr4.PSE = 1; - CPU::x32::writecr4(cr4); + CPU::x32::CR4 cr4 = CPU::x32::readcr4(); + cr4.PSE = 1; + CPU::x32::writecr4(cr4); #elif defined(aa64) #endif - trace("PSE Support Enabled"); - } + trace("PSE Support Enabled"); + } #ifdef DEBUG - if (Page1GBSupport) - debug("1GB Page Support Enabled"); + if (Page1GBSupport) + debug("1GB Page Support Enabled"); #endif - MapFromZero(KernelPageTable); - MapFramebuffer(KernelPageTable); - MapKernel(KernelPageTable); + MapFromZero(KernelPageTable); + MapFramebuffer(KernelPageTable); + MapKernel(KernelPageTable); - trace("Applying new page table from address %#lx", KernelPageTable); + trace("Applying new page table from address %#lx", KernelPageTable); #ifdef DEBUG - tracepagetable(KernelPageTable); + tracepagetable(KernelPageTable); #endif - CPU::PageTable(KernelPageTable); - debug("Page table updated."); - if (strstr(bInfo.Kernel.CommandLine, "xallocv1")) - { - XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false); - AllocatorType = MemoryAllocatorType::XallocV1; - trace("XallocV1 Allocator initialized (%p)", XallocV1Allocator); - } - else if (strstr(bInfo.Kernel.CommandLine, "liballoc11")) - { - AllocatorType = MemoryAllocatorType::liballoc11; - } + CPU::PageTable(KernelPageTable); + debug("Page table updated."); + + /* FIXME: Read kernel config */ + XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false); + AllocatorType = MemoryAllocatorType::XallocV1; + trace("XallocV1 Allocator initialized (%p)", XallocV1Allocator); } void *malloc(size_t Size) { -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("malloc(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Size > 0); - void *ret = nullptr; - switch (AllocatorType) - { - case MemoryAllocatorType::Pages: - { - ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); - memset(ret, 0, Size); - break; - } - case MemoryAllocatorType::XallocV1: - { - ret = XallocV1Allocator->malloc(Size); - break; - } - case MemoryAllocatorType::liballoc11: - { - ret = PREFIX(malloc)(Size); - memset(ret, 0, Size); - break; - } - default: - { - error("Unknown allocator type %d", AllocatorType); - CPU::Stop(); - } - } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "malloc( %ld )=%p~%p\n\r", - Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); #endif - return ret; + memdbg("malloc(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + void *ret = nullptr; + switch (AllocatorType) + { + case MemoryAllocatorType::Pages: + { + ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); + memset(ret, 0, Size); + break; + } + case MemoryAllocatorType::XallocV1: + { + ret = XallocV1Allocator->malloc(Size); + break; + } + case MemoryAllocatorType::liballoc11: + { + ret = PREFIX(malloc)(Size); + memset(ret, 0, Size); + break; + } + default: + { + error("Unknown allocator type %d", AllocatorType); + CPU::Stop(); + } + } +#ifdef DEBUG + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "malloc( %ld )=%p~%p\n\r", + Size, + ret, __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } +#endif + return ret; } void *calloc(size_t n, size_t Size) { -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("calloc(%d, %d)->[%s]", n, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Size > 0); - void *ret = nullptr; - switch (AllocatorType) - { - case MemoryAllocatorType::Pages: - { - ret = KernelAllocator.RequestPages(TO_PAGES(n * Size + 1)); - memset(ret, 0, n * Size); - break; - } - case MemoryAllocatorType::XallocV1: - { - ret = XallocV1Allocator->calloc(n, Size); - break; - } - case MemoryAllocatorType::liballoc11: - { - void *ret = PREFIX(calloc)(n, Size); - memset(ret, 0, Size); - return ret; - } - default: - { - error("Unknown allocator type %d", AllocatorType); - CPU::Stop(); - } - } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "calloc( %ld %ld )=%p~%p\n\r", - n, Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); #endif - return ret; + memdbg("calloc(%d, %d)->[%s]", n, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + void *ret = nullptr; + switch (AllocatorType) + { + case MemoryAllocatorType::Pages: + { + ret = KernelAllocator.RequestPages(TO_PAGES(n * Size + 1)); + memset(ret, 0, n * Size); + break; + } + case MemoryAllocatorType::XallocV1: + { + ret = XallocV1Allocator->calloc(n, Size); + break; + } + case MemoryAllocatorType::liballoc11: + { + void *ret = PREFIX(calloc)(n, Size); + memset(ret, 0, Size); + return ret; + } + default: + { + error("Unknown allocator type %d", AllocatorType); + CPU::Stop(); + } + } +#ifdef DEBUG + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "calloc( %ld %ld )=%p~%p\n\r", + n, Size, + ret, __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } +#endif + return ret; } void *realloc(void *Address, size_t Size) { -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("realloc(%#lx, %d)->[%s]", Address, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Size > 0); - void *ret = nullptr; - switch (AllocatorType) - { - case unlikely(MemoryAllocatorType::Pages): - { - ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); // WARNING: Potential memory leak - memset(ret, 0, Size); - break; - } - case MemoryAllocatorType::XallocV1: - { - ret = XallocV1Allocator->realloc(Address, Size); - break; - } - case MemoryAllocatorType::liballoc11: - { - void *ret = PREFIX(realloc)(Address, Size); - memset(ret, 0, Size); - return ret; - } - default: - { - error("Unknown allocator type %d", AllocatorType); - CPU::Stop(); - } - } -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "realloc( %p %ld )=%p~%p\n\r", - Address, Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); #endif - return ret; + memdbg("realloc(%#lx, %d)->[%s]", Address, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + void *ret = nullptr; + switch (AllocatorType) + { + case unlikely(MemoryAllocatorType::Pages): + { + ret = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); // WARNING: Potential memory leak + memset(ret, 0, Size); + break; + } + case MemoryAllocatorType::XallocV1: + { + ret = XallocV1Allocator->realloc(Address, Size); + break; + } + case MemoryAllocatorType::liballoc11: + { + void *ret = PREFIX(realloc)(Address, Size); + memset(ret, 0, Size); + return ret; + } + default: + { + error("Unknown allocator type %d", AllocatorType); + CPU::Stop(); + } + } +#ifdef DEBUG + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "realloc( %p %ld )=%p~%p\n\r", + Address, Size, + ret, __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } +#endif + return ret; } void free(void *Address) { -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("free(%#lx)->[%s]", Address, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Address != nullptr); - switch (AllocatorType) - { - case unlikely(MemoryAllocatorType::Pages): - { - KernelAllocator.FreePage(Address); // WARNING: Potential memory leak - break; - } - case MemoryAllocatorType::XallocV1: - { - XallocV1Allocator->free(Address); - break; - } - case MemoryAllocatorType::liballoc11: - { - PREFIX(free) - (Address); - break; - } - default: - { - error("Unknown allocator type %d", AllocatorType); - CPU::Stop(); - } - } +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); +#endif + memdbg("free(%#lx)->[%s]", Address, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + switch (AllocatorType) + { + case unlikely(MemoryAllocatorType::Pages): + { + KernelAllocator.FreePage(Address); // WARNING: Potential memory leak + break; + } + case MemoryAllocatorType::XallocV1: + { + XallocV1Allocator->free(Address); + break; + } + case MemoryAllocatorType::liballoc11: + { + PREFIX(free) + (Address); + break; + } + default: + { + error("Unknown allocator type %d", AllocatorType); + CPU::Stop(); + } + } #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "free( %p )~%p\n\r", - Address, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "free( %p )~%p\n\r", + Address, + __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif } void *operator new(std::size_t Size) { -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("new(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Size > 0); - void *ret = malloc(Size); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "new( %ld )=%p~%p\n\r", - Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); #endif - return ret; + memdbg("new(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + void *ret = malloc(Size); +#ifdef DEBUG + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "new( %ld )=%p~%p\n\r", + Size, + ret, __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } +#endif + return ret; } void *operator new[](std::size_t Size) { -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("new[](%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Size > 0); - void *ret = malloc(Size); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "new[]( %ld )=%p~%p\n\r", - Size, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); #endif - return ret; + memdbg("new[](%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + void *ret = malloc(Size); +#ifdef DEBUG + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "new[]( %ld )=%p~%p\n\r", + Size, + ret, __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } +#endif + return ret; } void *operator new(std::size_t Size, std::align_val_t Alignment) { -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("new(%d, %d)->[%s]", Size, Alignment, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); - fixme("operator new with alignment(%#lx) is not implemented", Alignment); + assert(Size > 0); - void *ret = malloc(Size); -#ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "new( %ld %#lx )=%p~%p\n\r", - Size, (uintptr_t)Alignment, - ret, __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); #endif - return ret; + memdbg("new(%d, %d)->[%s]", Size, Alignment, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + fixme("operator new with alignment(%#lx) is not implemented", Alignment); + + void *ret = malloc(Size); +#ifdef DEBUG + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); +#if defined(a64) || defined(aa64) + sprintf(mExtTrkLog, "new( %ld %#lx )=%p~%p\n\r", + Size, (uintptr_t)Alignment, + ret, __builtin_return_address(0)); +#elif defined(a32) + sprintf(mExtTrkLog, "new( %ld %#x )=%p~%p\n\r", + Size, (uintptr_t)Alignment, + ret, __builtin_return_address(0)); +#endif + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } +#endif + return ret; } void operator delete(void *Pointer) { -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("delete(%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Pointer != nullptr); - free(Pointer); +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); +#endif + memdbg("delete(%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + free(Pointer); #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "delete( %p )~%p\n\r", - Pointer, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "delete( %p )~%p\n\r", + Pointer, + __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif } void operator delete[](void *Pointer) { -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("delete[](%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Pointer != nullptr); - free(Pointer); +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); +#endif + memdbg("delete[](%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + free(Pointer); #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "delete[]( %p )~%p\n\r", - Pointer, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "delete[]( %p )~%p\n\r", + Pointer, + __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif } void operator delete(void *Pointer, long unsigned int Size) { - UNUSED(Size); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("delete(%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Pointer != nullptr); + assert(Size > 0); - free(Pointer); +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); +#endif + memdbg("delete(%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + free(Pointer); #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "delete( %p %ld )~%p\n\r", - Pointer, Size, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "delete( %p %ld )~%p\n\r", + Pointer, Size, + __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif } void operator delete[](void *Pointer, long unsigned int Size) { - UNUSED(Size); -#ifdef DEBUG_ALLOCATIONS_SL - SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); -#endif - memdbg("delete[](%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + assert(Pointer != nullptr); + assert(Size > 0); - free(Pointer); +#ifdef DEBUG_ALLOCATIONS_SL + SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown")); +#endif + memdbg("delete[](%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"); + + free(Pointer); #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "delete[]( %p %ld )~%p\n\r", - Pointer, Size, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "delete[]( %p %ld )~%p\n\r", + Pointer, Size, + __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif } diff --git a/Core/Memory/MemoryManager.cpp b/Core/Memory/MemoryManager.cpp index bae4f26..5e01d87 100644 --- a/Core/Memory/MemoryManager.cpp +++ b/Core/Memory/MemoryManager.cpp @@ -22,250 +22,266 @@ namespace Memory { - ReadFSFunction(MEM_Read) - { - if (!Size) - Size = node->Length; + ReadFSFunction(MEM_Read) + { + if (!Size) + Size = node->Length; - if ((size_t)node->Offset > node->Length) - return 0; + if (RefOffset > node->Length) + return 0; - if (node->Offset + Size > node->Length) - Size = node->Length - node->Offset; + if (RefOffset + (off_t)Size > node->Length) + Size = node->Length - RefOffset; - memcpy(Buffer, (uint8_t *)(node->Address + node->Offset), Size); - return Size; - } + memcpy(Buffer, (uint8_t *)(node->Address + RefOffset), Size); + return Size; + } - WriteFSFunction(MEM_Write) - { - if (!Size) - Size = node->Length; + WriteFSFunction(MEM_Write) + { + if (!Size) + Size = node->Length; - if ((size_t)node->Offset > node->Length) - return 0; + if (RefOffset > node->Length) + return 0; - if (node->Offset + Size > node->Length) - Size = node->Length - node->Offset; + if (RefOffset + (off_t)Size > node->Length) + Size = node->Length - RefOffset; - memcpy((uint8_t *)(node->Address + node->Offset), Buffer, Size); - return Size; - } + memcpy((uint8_t *)(node->Address + RefOffset), Buffer, Size); + return Size; + } - VirtualFileSystem::FileSystemOperations mem_op = { - .Name = "mem", - .Read = MEM_Read, - .Write = MEM_Write, - }; + VirtualFileSystem::FileSystemOperations mem_op = { + .Name = "mem", + .Read = MEM_Read, + .Write = MEM_Write, + }; - uint64_t MemMgr::GetAllocatedMemorySize() - { - SmartLock(MgrLock); - uint64_t Size = 0; - foreach (auto ap in AllocatedPagesList) - Size += ap.PageCount; - return FROM_PAGES(Size); - } + uint64_t MemMgr::GetAllocatedMemorySize() + { + SmartLock(MgrLock); + uint64_t Size = 0; + foreach (auto ap in AllocatedPagesList) + Size += ap.PageCount; + return FROM_PAGES(Size); + } - bool MemMgr::Add(void *Address, size_t Count) - { - SmartLock(MgrLock); - if (Address == nullptr) - { - error("Address is null!"); - return false; - } + bool MemMgr::Add(void *Address, size_t Count) + { + SmartLock(MgrLock); + if (Address == nullptr) + { + error("Address is null!"); + return false; + } - if (Count == 0) - { - error("Count is 0!"); - return false; - } + if (Count == 0) + { + error("Count is 0!"); + return false; + } - for (size_t i = 0; i < AllocatedPagesList.size(); i++) - { - if (AllocatedPagesList[i].Address == Address) - { - error("Address already exists!"); - return false; - } - else if ((uintptr_t)Address < (uintptr_t)AllocatedPagesList[i].Address) - { - if ((uintptr_t)Address + (Count * PAGE_SIZE) > (uintptr_t)AllocatedPagesList[i].Address) - { - error("Address intersects with an allocated page!"); - return false; - } - } - else - { - if ((uintptr_t)AllocatedPagesList[i].Address + (AllocatedPagesList[i].PageCount * PAGE_SIZE) > (uintptr_t)Address) - { - error("Address intersects with an allocated page!"); - return false; - } - } - } + for (size_t i = 0; i < AllocatedPagesList.size(); i++) + { + if (AllocatedPagesList[i].Address == Address) + { + error("Address already exists!"); + return false; + } + else if ((uintptr_t)Address < (uintptr_t)AllocatedPagesList[i].Address) + { + if ((uintptr_t)Address + (Count * PAGE_SIZE) > (uintptr_t)AllocatedPagesList[i].Address) + { + error("Address intersects with an allocated page!"); + return false; + } + } + else + { + if ((uintptr_t)AllocatedPagesList[i].Address + (AllocatedPagesList[i].PageCount * PAGE_SIZE) > (uintptr_t)Address) + { + error("Address intersects with an allocated page!"); + return false; + } + } + } - if (this->Directory) - { - char FileName[64]; - sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count); - VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory); - if (n) - { - n->Address = (uintptr_t)Address; - n->Length = Count * PAGE_SIZE; - n->Operator = &mem_op; - } - } - - AllocatedPagesList.push_back({Address, Count}); - return true; - } - - void *MemMgr::RequestPages(size_t Count, bool User) - { - SmartLock(MgrLock); - void *Address = KernelAllocator.RequestPages(Count); - for (size_t i = 0; i < Count; i++) - { - int Flags = Memory::PTFlag::RW; - if (User) - Flags |= Memory::PTFlag::US; - - void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE)); - - Memory::Virtual vmm = Memory::Virtual(this->Table); - vmm.Remap(AddressToMap, AddressToMap, Flags); - } - - if (this->Directory) - { - char FileName[64]; - sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count); - VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory); - if (n) // If null, error or file already exists - { - n->Address = (uintptr_t)Address; - n->Length = Count * PAGE_SIZE; - n->Operator = &mem_op; - } - } - - AllocatedPagesList.push_back({Address, Count}); - - /* For security reasons, we clear the allocated page - if it's a user page. */ - if (User) - memset(Address, 0, Count * PAGE_SIZE); - - return Address; - } - - void MemMgr::FreePages(void *Address, size_t Count) - { - SmartLock(MgrLock); - for (size_t i = 0; i < AllocatedPagesList.size(); i++) - { - if (AllocatedPagesList[i].Address == Address) - { - /** TODO: Advanced checks. Allow if the page count is less than the requested one. - * This will allow the user to free only a part of the allocated pages. - * - * But this will be in a separate function because we need to specify if we - * want to free from the start or from the end and return the new address. - */ - if (AllocatedPagesList[i].PageCount != Count) - { - error("Page count mismatch! (Allocated: %lld, Requested: %lld)", AllocatedPagesList[i].PageCount, Count); - return; - } - - KernelAllocator.FreePages(Address, Count); - - Memory::Virtual vmm = Memory::Virtual(this->Table); - for (size_t i = 0; i < Count; i++) - { - void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE)); - vmm.Remap(AddressToMap, AddressToMap, Memory::PTFlag::RW); - // vmm.Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE))); - } - - if (this->Directory) - { - char FileName[64]; - sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count); - VirtualFileSystem::FileStatus s = vfs->Delete(FileName, false, this->Directory); - if (s != VirtualFileSystem::FileStatus::OK) - error("Failed to delete file %s", FileName); - } - - AllocatedPagesList.remove(i); - return; - } - } - } - - void MemMgr::DetachAddress(void *Address) - { - SmartLock(MgrLock); - for (size_t i = 0; i < AllocatedPagesList.size(); i++) - { - if (AllocatedPagesList[i].Address == Address) - { - if (this->Directory) - { - char FileName[64]; - sprintf(FileName, "%lx-%ld", (uintptr_t)Address, AllocatedPagesList[i].PageCount); - VirtualFileSystem::FileStatus s = vfs->Delete(FileName, false, this->Directory); - if (s != VirtualFileSystem::FileStatus::OK) - error("Failed to delete file %s", FileName); - } - - AllocatedPagesList.remove(i); - return; - } - } - } - - MemMgr::MemMgr(PageTable *Table, VirtualFileSystem::Node *Directory) - { - SmartLock(MgrLock); - if (Table) - this->Table = Table; - else - { -#if defined(a64) - this->Table = (PageTable *)CPU::x64::readcr3().raw; + if (this->Directory) + { + char FileName[64]; +#if defined(a64) || defined(aa64) + sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count); #elif defined(a32) - this->Table = (PageTable *)CPU::x32::readcr3().raw; + sprintf(FileName, "%x-%ld", (uintptr_t)Address, Count); #endif - } + VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory); + if (n) + { + n->Address = (uintptr_t)Address; + n->Length = Count * PAGE_SIZE; + n->Operator = &mem_op; + } + } - this->Directory = Directory; - debug("+ %#lx", this); - } + AllocatedPagesList.push_back({Address, Count}); + return true; + } - MemMgr::~MemMgr() - { - SmartLock(MgrLock); - foreach (auto ap in AllocatedPagesList) - { - KernelAllocator.FreePages(ap.Address, ap.PageCount); - Memory::Virtual vmm = Memory::Virtual(this->Table); - for (size_t i = 0; i < ap.PageCount; i++) - vmm.Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), - (void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), - Memory::PTFlag::RW); - } + void *MemMgr::RequestPages(size_t Count, bool User) + { + SmartLock(MgrLock); + void *Address = KernelAllocator.RequestPages(Count); + for (size_t i = 0; i < Count; i++) + { + int Flags = Memory::PTFlag::RW; + if (User) + Flags |= Memory::PTFlag::US; - if (this->Directory) - { - foreach (auto Child in this->Directory->Children) - vfs->Delete(Child, true); - } + void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE)); - debug("- %#lx", this); - } + Memory::Virtual vmm = Memory::Virtual(this->Table); + vmm.Remap(AddressToMap, AddressToMap, Flags); + } + + if (this->Directory) + { + char FileName[64]; +#if defined(a64) || defined(aa64) + sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count); +#elif defined(a32) + sprintf(FileName, "%x-%ld", (uintptr_t)Address, Count); +#endif + VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory); + if (n) // If null, error or file already exists + { + n->Address = (uintptr_t)Address; + n->Length = Count * PAGE_SIZE; + n->Operator = &mem_op; + } + } + + AllocatedPagesList.push_back({Address, Count}); + + /* For security reasons, we clear the allocated page + if it's a user page. */ + if (User) + memset(Address, 0, Count * PAGE_SIZE); + + return Address; + } + + void MemMgr::FreePages(void *Address, size_t Count) + { + SmartLock(MgrLock); + forItr(itr, AllocatedPagesList) + { + if (itr->Address == Address) + { + /** TODO: Advanced checks. Allow if the page count is less than the requested one. + * This will allow the user to free only a part of the allocated pages. + * + * But this will be in a separate function because we need to specify if we + * want to free from the start or from the end and return the new address. + */ + if (itr->PageCount != Count) + { + error("Page count mismatch! (Allocated: %lld, Requested: %lld)", itr->PageCount, Count); + return; + } + + KernelAllocator.FreePages(Address, Count); + + Memory::Virtual vmm = Memory::Virtual(this->Table); + for (size_t i = 0; i < Count; i++) + { + void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE)); + vmm.Remap(AddressToMap, AddressToMap, Memory::PTFlag::RW); + // vmm.Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE))); + } + + if (this->Directory) + { + char FileName[64]; +#if defined(a64) || defined(aa64) + sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count); +#elif defined(a32) + sprintf(FileName, "%x-%ld", (uintptr_t)Address, Count); +#endif + if (!vfs->Delete(FileName, false, this->Directory)) + error("Failed to delete file %s", FileName); + } + + AllocatedPagesList.erase(itr); + return; + } + } + } + + void MemMgr::DetachAddress(void *Address) + { + SmartLock(MgrLock); + forItr(itr, AllocatedPagesList) + { + if (itr->Address == Address) + { + if (this->Directory) + { + char FileName[64]; +#if defined(a64) || defined(aa64) + sprintf(FileName, "%lx-%ld", (uintptr_t)Address, itr->PageCount); +#elif defined(a32) + sprintf(FileName, "%x-%ld", (uintptr_t)Address, itr->PageCount); +#endif + if (!vfs->Delete(FileName, false, this->Directory)) + error("Failed to delete file %s", FileName); + } + + AllocatedPagesList.erase(itr); + return; + } + } + } + + MemMgr::MemMgr(PageTable *Table, VirtualFileSystem::Node *Directory) + { + SmartLock(MgrLock); + if (Table) + this->Table = Table; + else + { +#if defined(a64) + this->Table = (PageTable *)CPU::x64::readcr3().raw; +#elif defined(a32) + this->Table = (PageTable *)CPU::x32::readcr3().raw; +#endif + } + + this->Directory = Directory; + debug("+ %#lx %s", this, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : ""); + } + + MemMgr::~MemMgr() + { + SmartLock(MgrLock); + foreach (auto ap in AllocatedPagesList) + { + KernelAllocator.FreePages(ap.Address, ap.PageCount); + Memory::Virtual vmm = Memory::Virtual(this->Table); + for (size_t i = 0; i < ap.PageCount; i++) + vmm.Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), + (void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), + Memory::PTFlag::RW); + } + + if (this->Directory) + { + foreach (auto Child in this->Directory->Children) + vfs->Delete(Child, true); + } + + debug("- %#lx %s", this, + KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : ""); + } } diff --git a/Core/Memory/PhysicalMemoryManager.cpp b/Core/Memory/PhysicalMemoryManager.cpp index 3a2cdb4..b12327e 100644 --- a/Core/Memory/PhysicalMemoryManager.cpp +++ b/Core/Memory/PhysicalMemoryManager.cpp @@ -26,467 +26,477 @@ namespace Memory { - uint64_t Physical::GetTotalMemory() - { - SmartLock(this->MemoryLock); - return this->TotalMemory; - } + uint64_t Physical::GetTotalMemory() + { + return this->TotalMemory.load(); + } - uint64_t Physical::GetFreeMemory() - { - SmartLock(this->MemoryLock); - return this->FreeMemory; - } + uint64_t Physical::GetFreeMemory() + { + return this->FreeMemory.load(); + } - uint64_t Physical::GetReservedMemory() - { - SmartLock(this->MemoryLock); - return this->ReservedMemory; - } + uint64_t Physical::GetReservedMemory() + { + return this->ReservedMemory.load(); + } - uint64_t Physical::GetUsedMemory() - { - SmartLock(this->MemoryLock); - return this->UsedMemory; - } + uint64_t Physical::GetUsedMemory() + { + return this->UsedMemory.load(); + } - bool Physical::SwapPage(void *Address) - { - fixme("%p", Address); - return false; - } + bool Physical::SwapPage(void *Address) + { + fixme("%p", Address); + return false; + } - bool Physical::SwapPages(void *Address, size_t PageCount) - { - for (size_t i = 0; i < PageCount; i++) - { - if (!this->SwapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)))) - return false; - } - return false; - } + bool Physical::SwapPages(void *Address, size_t PageCount) + { + for (size_t i = 0; i < PageCount; i++) + { + if (!this->SwapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)))) + return false; + } + return false; + } - bool Physical::UnswapPage(void *Address) - { - fixme("%p", Address); - return false; - } + bool Physical::UnswapPage(void *Address) + { + fixme("%p", Address); + return false; + } - bool Physical::UnswapPages(void *Address, size_t PageCount) - { - for (size_t i = 0; i < PageCount; i++) - { - if (!this->UnswapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)))) - return false; - } - return false; - } + bool Physical::UnswapPages(void *Address, size_t PageCount) + { + for (size_t i = 0; i < PageCount; i++) + { + if (!this->UnswapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)))) + return false; + } + return false; + } - void *Physical::RequestPage() - { - SmartLock(this->MemoryLock); + void *Physical::RequestPage() + { + SmartLock(this->MemoryLock); - for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++) - { - if (PageBitmap[PageBitmapIndex] == true) - continue; + for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++) + { + if (PageBitmap[PageBitmapIndex] == true) + continue; - this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE)); + this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE)); #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "RequestPage( )=%p~%p\n\r", - (void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "RequestPage( )=%p~%p\n\r", + (void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif - return (void *)(PageBitmapIndex * PAGE_SIZE); - } + return (void *)(PageBitmapIndex * PAGE_SIZE); + } - if (this->SwapPage((void *)(PageBitmapIndex * PAGE_SIZE))) - { - this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE)); - return (void *)(PageBitmapIndex * PAGE_SIZE); - } + if (this->SwapPage((void *)(PageBitmapIndex * PAGE_SIZE))) + { + this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE)); + return (void *)(PageBitmapIndex * PAGE_SIZE); + } - if (TaskManager && !TaskManager->IsPanic()) - { - error("Out of memory! Killing current process..."); - TaskManager->KillProcess(TaskManager->GetCurrentProcess(), Tasking::KILL_OOM); - TaskManager->Schedule(); - } + if (TaskManager && !TaskManager->IsPanic()) + { + error("Out of memory! Killing current process..."); + TaskManager->KillProcess(thisProcess, Tasking::KILL_OOM); + TaskManager->Yield(); + } - error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory)); - CPU::Stop(); - __builtin_unreachable(); - } + error("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)", + TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory)); + KPrint("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)", + TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory)); + CPU::Stop(); + __builtin_unreachable(); + } - void *Physical::RequestPages(size_t Count) - { - SmartLock(this->MemoryLock); + void *Physical::RequestPages(size_t Count) + { + SmartLock(this->MemoryLock); - for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++) - { - if (PageBitmap[PageBitmapIndex] == true) - continue; + for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++) + { + if (PageBitmap[PageBitmapIndex] == true) + continue; - for (uint64_t Index = PageBitmapIndex; Index < PageBitmap.Size * 8; Index++) - { - if (PageBitmap[Index] == true) - continue; + for (uint64_t Index = PageBitmapIndex; Index < PageBitmap.Size * 8; Index++) + { + if (PageBitmap[Index] == true) + continue; - for (size_t i = 0; i < Count; i++) - { - if (PageBitmap[Index + i] == true) - goto NextPage; - } + for (size_t i = 0; i < Count; i++) + { + if (PageBitmap[Index + i] == true) + goto NextPage; + } - this->LockPages((void *)(Index * PAGE_SIZE), Count); + this->LockPages((void *)(Index * PAGE_SIZE), Count); #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r", - Count, - (void *)(Index * PAGE_SIZE), __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r", + Count, + (void *)(Index * PAGE_SIZE), __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif - return (void *)(Index * PAGE_SIZE); + return (void *)(Index * PAGE_SIZE); - NextPage: - Index += Count; - continue; - } - } + NextPage: + Index += Count; + continue; + } + } - if (this->SwapPages((void *)(PageBitmapIndex * PAGE_SIZE), Count)) - { - this->LockPages((void *)(PageBitmapIndex * PAGE_SIZE), Count); - return (void *)(PageBitmapIndex * PAGE_SIZE); - } + if (this->SwapPages((void *)(PageBitmapIndex * PAGE_SIZE), Count)) + { + this->LockPages((void *)(PageBitmapIndex * PAGE_SIZE), Count); + return (void *)(PageBitmapIndex * PAGE_SIZE); + } - if (TaskManager && !TaskManager->IsPanic()) - { - error("Out of memory! Killing current process..."); - TaskManager->KillProcess(TaskManager->GetCurrentProcess(), Tasking::KILL_OOM); - TaskManager->Schedule(); - } + if (TaskManager && !TaskManager->IsPanic()) + { + error("Out of memory! Killing current process..."); + TaskManager->KillProcess(thisProcess, Tasking::KILL_OOM); + TaskManager->Yield(); + } - error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory)); - CPU::Halt(true); - __builtin_unreachable(); - } + error("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)", + TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory)); + KPrint("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)", + TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory)); + CPU::Halt(true); + __builtin_unreachable(); + } - void Physical::FreePage(void *Address) - { - SmartLock(this->MemoryLock); + void Physical::FreePage(void *Address) + { + SmartLock(this->MemoryLock); - if (unlikely(Address == nullptr)) - { - warn("Null pointer passed to FreePage."); - return; - } + if (unlikely(Address == nullptr)) + { + warn("Null pointer passed to FreePage."); + return; + } - size_t Index = (size_t)Address / PAGE_SIZE; + size_t Index = (size_t)Address / PAGE_SIZE; - if (unlikely(PageBitmap[Index] == false)) - { - warn("Tried to free an already free page. (%p)", Address); - return; - } + if (unlikely(PageBitmap[Index] == false)) + { + warn("Tried to free an already free page. (%p)", + Address); + return; + } - if (PageBitmap.Set(Index, false)) - { - FreeMemory += PAGE_SIZE; - UsedMemory -= PAGE_SIZE; - if (PageBitmapIndex > Index) - PageBitmapIndex = Index; - } + if (PageBitmap.Set(Index, false)) + { + FreeMemory += PAGE_SIZE; + UsedMemory -= PAGE_SIZE; + if (PageBitmapIndex > Index) + PageBitmapIndex = Index; + } #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "FreePage( %p )~%p\n\r", - Address, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "FreePage( %p )~%p\n\r", + Address, + __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif - } + } - void Physical::FreePages(void *Address, size_t Count) - { - if (unlikely(Address == nullptr || Count == 0)) - { - warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : ""); - return; - } + void Physical::FreePages(void *Address, size_t Count) + { + if (unlikely(Address == nullptr || Count == 0)) + { + warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : ""); + return; + } #ifdef DEBUG - if (EnableExternalMemoryTracer) - { - char LockTmpStr[64]; - strcpy_unsafe(LockTmpStr, __FUNCTION__); - strcat_unsafe(LockTmpStr, "_memTrk"); - mExtTrkLock.TimeoutLock(LockTmpStr, 10000); - sprintf(mExtTrkLog, "!FreePages( %p %ld )~%p\n\r", - Address, Count, - __builtin_return_address(0)); - UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); - for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) - { - if (mExtTrkLog[i] == '\r') - break; - mTrkUART.Write(mExtTrkLog[i]); - } - mExtTrkLock.Unlock(); - } + if (EnableExternalMemoryTracer) + { + char LockTmpStr[64]; + strcpy_unsafe(LockTmpStr, __FUNCTION__); + strcat_unsafe(LockTmpStr, "_memTrk"); + mExtTrkLock.TimeoutLock(LockTmpStr, 10000); + sprintf(mExtTrkLog, "!FreePages( %p %ld )~%p\n\r", + Address, Count, + __builtin_return_address(0)); + UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3); + for (short i = 0; i < MEM_TRK_MAX_SIZE; i++) + { + if (mExtTrkLog[i] == '\r') + break; + mTrkUART.Write(mExtTrkLog[i]); + } + mExtTrkLock.Unlock(); + } #endif - for (size_t t = 0; t < Count; t++) - this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE))); - } + for (size_t t = 0; t < Count; t++) + this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE))); + } - void Physical::LockPage(void *Address) - { - if (unlikely(Address == nullptr)) - warn("Trying to lock null address."); + void Physical::LockPage(void *Address) + { + if (unlikely(Address == nullptr)) + warn("Trying to lock null address."); - uintptr_t Index = (uintptr_t)Address / PAGE_SIZE; + uintptr_t Index = (uintptr_t)Address / PAGE_SIZE; - if (unlikely(PageBitmap[Index] == true)) - return; + if (unlikely(PageBitmap[Index] == true)) + return; - if (PageBitmap.Set(Index, true)) - { - FreeMemory -= PAGE_SIZE; - UsedMemory += PAGE_SIZE; - } - } + if (PageBitmap.Set(Index, true)) + { + FreeMemory -= PAGE_SIZE; + UsedMemory += PAGE_SIZE; + } + } - void Physical::LockPages(void *Address, size_t PageCount) - { - if (unlikely(Address == nullptr || PageCount == 0)) - warn("Trying to lock %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : ""); + void Physical::LockPages(void *Address, size_t PageCount) + { + if (unlikely(Address == nullptr || PageCount == 0)) + warn("Trying to lock %s%s.", + Address ? "null address" : "", + PageCount ? "0 pages" : ""); - for (size_t i = 0; i < PageCount; i++) - this->LockPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))); - } + for (size_t i = 0; i < PageCount; i++) + this->LockPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))); + } - void Physical::ReservePage(void *Address) - { - if (unlikely(Address == nullptr)) - warn("Trying to reserve null address."); + void Physical::ReservePage(void *Address) + { + if (unlikely(Address == nullptr)) + warn("Trying to reserve null address."); - uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE; + uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE; - if (unlikely(PageBitmap[Index] == true)) - return; + if (unlikely(PageBitmap[Index] == true)) + return; - if (PageBitmap.Set(Index, true)) - { - FreeMemory -= PAGE_SIZE; - ReservedMemory += PAGE_SIZE; - } - } + if (PageBitmap.Set(Index, true)) + { + FreeMemory -= PAGE_SIZE; + ReservedMemory += PAGE_SIZE; + } + } - void Physical::ReservePages(void *Address, size_t PageCount) - { - if (unlikely(Address == nullptr || PageCount == 0)) - warn("Trying to reserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : ""); + void Physical::ReservePages(void *Address, size_t PageCount) + { + if (unlikely(Address == nullptr || PageCount == 0)) + warn("Trying to reserve %s%s.", + Address ? "null address" : "", + PageCount ? "0 pages" : ""); - for (size_t t = 0; t < PageCount; t++) - { - uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE; + for (size_t t = 0; t < PageCount; t++) + { + uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE; - if (unlikely(PageBitmap[Index] == true)) - return; + if (unlikely(PageBitmap[Index] == true)) + return; - if (PageBitmap.Set(Index, true)) - { - FreeMemory -= PAGE_SIZE; - ReservedMemory += PAGE_SIZE; - } - } - } + if (PageBitmap.Set(Index, true)) + { + FreeMemory -= PAGE_SIZE; + ReservedMemory += PAGE_SIZE; + } + } + } - void Physical::UnreservePage(void *Address) - { - if (unlikely(Address == nullptr)) - warn("Trying to unreserve null address."); + void Physical::UnreservePage(void *Address) + { + if (unlikely(Address == nullptr)) + warn("Trying to unreserve null address."); - uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE; + uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE; - if (unlikely(PageBitmap[Index] == false)) - return; + if (unlikely(PageBitmap[Index] == false)) + return; - if (PageBitmap.Set(Index, false)) - { - FreeMemory += PAGE_SIZE; - ReservedMemory -= PAGE_SIZE; - if (PageBitmapIndex > Index) - PageBitmapIndex = Index; - } - } + if (PageBitmap.Set(Index, false)) + { + FreeMemory += PAGE_SIZE; + ReservedMemory -= PAGE_SIZE; + if (PageBitmapIndex > Index) + PageBitmapIndex = Index; + } + } - void Physical::UnreservePages(void *Address, size_t PageCount) - { - if (unlikely(Address == nullptr || PageCount == 0)) - warn("Trying to unreserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : ""); + void Physical::UnreservePages(void *Address, size_t PageCount) + { + if (unlikely(Address == nullptr || PageCount == 0)) + warn("Trying to unreserve %s%s.", + Address ? "null address" : "", + PageCount ? "0 pages" : ""); - for (size_t t = 0; t < PageCount; t++) - { - uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE; + for (size_t t = 0; t < PageCount; t++) + { + uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE; - if (unlikely(PageBitmap[Index] == false)) - return; + if (unlikely(PageBitmap[Index] == false)) + return; - if (PageBitmap.Set(Index, false)) - { - FreeMemory += PAGE_SIZE; - ReservedMemory -= PAGE_SIZE; - if (PageBitmapIndex > Index) - PageBitmapIndex = Index; - } - } - } + if (PageBitmap.Set(Index, false)) + { + FreeMemory += PAGE_SIZE; + ReservedMemory -= PAGE_SIZE; + if (PageBitmapIndex > Index) + PageBitmapIndex = Index; + } + } + } - void Physical::Init() - { - SmartLock(this->MemoryLock); + void Physical::Init() + { + SmartLock(this->MemoryLock); - uint64_t MemorySize = bInfo.Memory.Size; - debug("Memory size: %lld bytes (%ld pages)", MemorySize, TO_PAGES(MemorySize)); - TotalMemory = MemorySize; - FreeMemory = MemorySize; + uint64_t MemorySize = bInfo.Memory.Size; + debug("Memory size: %lld bytes (%ld pages)", + MemorySize, TO_PAGES(MemorySize)); + TotalMemory = MemorySize; + FreeMemory = MemorySize; - size_t BitmapSize = (size_t)(MemorySize / PAGE_SIZE) / 8 + 1; - uintptr_t BitmapAddress = 0x0; - size_t BitmapAddressSize = 0; + size_t BitmapSize = (size_t)(MemorySize / PAGE_SIZE) / 8 + 1; + uintptr_t BitmapAddress = 0x0; + size_t BitmapAddressSize = 0; - uintptr_t KernelStart = (uintptr_t)bInfo.Kernel.PhysicalBase; - uintptr_t KernelEnd = (uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size; + uintptr_t KernelStart = (uintptr_t)bInfo.Kernel.PhysicalBase; + uintptr_t KernelEnd = (uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size; - for (uint64_t i = 0; i < bInfo.Memory.Entries; i++) - { - if (bInfo.Memory.Entry[i].Type == Usable) - { - uintptr_t RegionAddress = (uintptr_t)bInfo.Memory.Entry[i].BaseAddress; - uintptr_t RegionSize = bInfo.Memory.Entry[i].Length; + for (uint64_t i = 0; i < bInfo.Memory.Entries; i++) + { + if (bInfo.Memory.Entry[i].Type == Usable) + { + uintptr_t RegionAddress = (uintptr_t)bInfo.Memory.Entry[i].BaseAddress; + uintptr_t RegionSize = bInfo.Memory.Entry[i].Length; - /* We don't want to use 0 as a memory address. */ - if (RegionAddress == 0x0) - continue; + /* We don't want to use the first 1MB of memory. */ + if (RegionAddress <= 0xFFFFF) + continue; - if ((BitmapSize + 0x100) > RegionSize) - { - debug("Region %p-%p (%dMB) is too small for bitmap.", - (void *)RegionAddress, - (void *)(RegionAddress + RegionSize), - TO_MB(RegionSize)); - continue; - } + if ((BitmapSize + 0x100) > RegionSize) + { + debug("Region %p-%p (%d MiB) is too small for bitmap.", + (void *)RegionAddress, + (void *)(RegionAddress + RegionSize), + TO_MiB(RegionSize)); + continue; + } - BitmapAddress = RegionAddress; - BitmapAddressSize = RegionSize; + BitmapAddress = RegionAddress; + BitmapAddressSize = RegionSize; - if (RegionAddress >= KernelStart && KernelEnd <= (RegionAddress + RegionSize)) - { - BitmapAddress = KernelEnd; - BitmapAddressSize = RegionSize - (KernelEnd - RegionAddress); - } + if (RegionAddress >= KernelStart && KernelEnd <= (RegionAddress + RegionSize)) + { + BitmapAddress = KernelEnd; + BitmapAddressSize = RegionSize - (KernelEnd - RegionAddress); + } - if ((BitmapSize + 0x100) > BitmapAddressSize) - { - debug("Region %p-%p (%dMB) is too small for bitmap.", - (void *)RegionAddress, - (void *)(RegionAddress + BitmapAddressSize), - TO_MB(BitmapAddressSize)); - continue; - } + if ((BitmapSize + 0x100) > BitmapAddressSize) + { + debug("Region %p-%p (%d MiB) is too small for bitmap.", + (void *)RegionAddress, + (void *)(RegionAddress + BitmapAddressSize), + TO_MiB(BitmapAddressSize)); + continue; + } - for (size_t i = 0; i < MAX_MODULES; i++) - { - uintptr_t ModuleStart = (uintptr_t)bInfo.Modules[i].Address; - uintptr_t ModuleEnd = (uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size; + for (size_t i = 0; i < MAX_MODULES; i++) + { + uintptr_t ModuleStart = (uintptr_t)bInfo.Modules[i].Address; + uintptr_t ModuleEnd = (uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size; - if (ModuleStart == 0x0) - break; + if (ModuleStart == 0x0) + break; - if (RegionAddress >= ModuleStart && ModuleEnd <= (RegionAddress + RegionSize)) - { - BitmapAddress = ModuleEnd; - BitmapAddressSize = RegionSize - (ModuleEnd - RegionAddress); - } - } + if (RegionAddress >= ModuleStart && ModuleEnd <= (RegionAddress + RegionSize)) + { + BitmapAddress = ModuleEnd; + BitmapAddressSize = RegionSize - (ModuleEnd - RegionAddress); + } + } - if ((BitmapSize + 0x100) > BitmapAddressSize) - { - debug("Region %p-%p (%dMB) is too small for bitmap.", - (void *)BitmapAddress, - (void *)(BitmapAddress + BitmapAddressSize), - TO_MB(BitmapAddressSize)); - continue; - } + if ((BitmapSize + 0x100) > BitmapAddressSize) + { + debug("Region %p-%p (%d MiB) is too small for bitmap.", + (void *)BitmapAddress, + (void *)(BitmapAddress + BitmapAddressSize), + TO_MiB(BitmapAddressSize)); + continue; + } - debug("Found free memory for bitmap: %p (%dMB)", - (void *)BitmapAddress, - TO_MB(BitmapAddressSize)); - break; - } - } + debug("Found free memory for bitmap: %p (%d MiB)", + (void *)BitmapAddress, + TO_MiB(BitmapAddressSize)); + break; + } + } - if (BitmapAddress == 0x0) - { - error("No free memory found!"); - CPU::Stop(); - } + if (BitmapAddress == 0x0) + { + error("No free memory found!"); + CPU::Stop(); + } - /* TODO: Read swap config and make the configure the bitmap size correctly */ - debug("Initializing Bitmap at %p-%p (%d Bytes)", - BitmapAddress, - (void *)(BitmapAddress + BitmapSize), - BitmapSize); + /* TODO: Read swap config and make the configure the bitmap size correctly */ + debug("Initializing Bitmap at %p-%p (%d Bytes)", + BitmapAddress, + (void *)(BitmapAddress + BitmapSize), + BitmapSize); - PageBitmap.Size = BitmapSize; - PageBitmap.Buffer = (uint8_t *)BitmapAddress; - for (size_t i = 0; i < BitmapSize; i++) - *(uint8_t *)(PageBitmap.Buffer + i) = 0; + PageBitmap.Size = BitmapSize; + PageBitmap.Buffer = (uint8_t *)BitmapAddress; + for (size_t i = 0; i < BitmapSize; i++) + *(uint8_t *)(PageBitmap.Buffer + i) = 0; - ReserveEssentials(); - } + ReserveEssentials(); + } - Physical::Physical() {} - Physical::~Physical() {} + Physical::Physical() {} + Physical::~Physical() {} } diff --git a/Core/Memory/ReserveEssentials.cpp b/Core/Memory/ReserveEssentials.cpp index 1041380..8aa34d7 100644 --- a/Core/Memory/ReserveEssentials.cpp +++ b/Core/Memory/ReserveEssentials.cpp @@ -18,6 +18,7 @@ #include #include +#include #ifdef DEBUG #include #endif @@ -44,7 +45,13 @@ namespace Memory for (uint64_t i = 0; i < bInfo.Memory.Entries; i++) { if (bInfo.Memory.Entry[i].Type == Usable) - this->UnreservePages(bInfo.Memory.Entry[i].BaseAddress, TO_PAGES(bInfo.Memory.Entry[i].Length)); + { + if (uintptr_t(bInfo.Memory.Entry[i].BaseAddress) <= 0xFFFFF) + continue; + + this->UnreservePages(bInfo.Memory.Entry[i].BaseAddress, + TO_PAGES(bInfo.Memory.Entry[i].Length)); + } } debug("Reserving 0x0-0xFFFFF range..."); @@ -57,18 +64,72 @@ namespace Memory */ this->ReservePages((void *)0x0, TO_PAGES(0xFFFFF)); - debug("Reserving bitmap region %#lx-%#lx...", PageBitmap.Buffer, (void *)((uintptr_t)PageBitmap.Buffer + PageBitmap.Size)); + debug("Reserving bitmap region %#lx-%#lx...", + PageBitmap.Buffer, + (void *)((uintptr_t)PageBitmap.Buffer + PageBitmap.Size)); + this->ReservePages(PageBitmap.Buffer, TO_PAGES(PageBitmap.Size)); - debug("Reserving kernel physical region %#lx-%#lx...", bInfo.Kernel.PhysicalBase, (void *)((uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size)); + debug("Reserving kernel physical region %#lx-%#lx...", + bInfo.Kernel.PhysicalBase, + (void *)((uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size)); + this->ReservePages(bInfo.Kernel.PhysicalBase, TO_PAGES(bInfo.Kernel.Size)); debug("Reserving kernel file and symbols..."); if (bInfo.Kernel.FileBase) this->ReservePages(bInfo.Kernel.FileBase, TO_PAGES(bInfo.Kernel.Size)); - if (bInfo.Kernel.Symbols.Num && bInfo.Kernel.Symbols.EntSize && bInfo.Kernel.Symbols.Shndx) - this->ReservePages((void *)bInfo.Kernel.Symbols.Sections, TO_PAGES(bInfo.Kernel.Symbols.Num * bInfo.Kernel.Symbols.EntSize)); + if (bInfo.Kernel.Symbols.Num && + bInfo.Kernel.Symbols.EntSize && + bInfo.Kernel.Symbols.Shndx) + { + char *sections = reinterpret_cast(bInfo.Kernel.Symbols.Sections); + uint8_t *StringAddress = nullptr; + + Elf_Sym *Symbols = nullptr; + +#if defined(a64) || defined(aa64) + Elf64_Xword SymbolSize = 0; + Elf64_Xword StringSize = 0; +#elif defined(a32) + Elf32_Word SymbolSize = 0; + Elf32_Word StringSize = 0; +#endif + + for (size_t i = 0; i < bInfo.Kernel.Symbols.Num; ++i) + { + Elf_Shdr *sym = (Elf_Shdr *)§ions[bInfo.Kernel.Symbols.EntSize * i]; + Elf_Shdr *str = (Elf_Shdr *)§ions[bInfo.Kernel.Symbols.EntSize * + sym->sh_link]; + + if (sym->sh_type == SHT_SYMTAB && + str->sh_type == SHT_STRTAB) + { + Symbols = (Elf_Sym *)sym->sh_addr; + StringAddress = (uint8_t *)str->sh_addr; + SymbolSize = (int)sym->sh_size; + StringSize = (int)str->sh_size; + debug("Symbol table found, %d entries", + SymbolSize / sym->sh_entsize); + break; + } + } + + if (Symbols) + { + debug("Reserving symbol table region %#lx-%#lx...", + Symbols, (void *)((uintptr_t)Symbols + SymbolSize)); + this->ReservePages(Symbols, TO_PAGES(SymbolSize)); + } + + if (StringAddress) + { + debug("Reserving string table region %#lx-%#lx...", + StringAddress, (void *)((uintptr_t)StringAddress + StringSize)); + this->ReservePages(StringAddress, TO_PAGES(StringSize)); + } + } debug("Reserving kernel modules..."); @@ -78,13 +139,17 @@ namespace Memory continue; debug("Reserving module %s (%#lx-%#lx)...", bInfo.Modules[i].CommandLine, - bInfo.Modules[i].Address, (void *)((uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size)); + bInfo.Modules[i].Address, + (void *)((uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size)); - this->ReservePages((void *)bInfo.Modules[i].Address, TO_PAGES(bInfo.Modules[i].Size)); + this->ReservePages((void *)bInfo.Modules[i].Address, + TO_PAGES(bInfo.Modules[i].Size)); } #if defined(a86) - debug("Reserving RSDT region %#lx-%#lx...", bInfo.RSDP, (void *)((uintptr_t)bInfo.RSDP + sizeof(BootInfo::RSDPInfo))); + debug("Reserving RSDT region %#lx-%#lx...", bInfo.RSDP, + (void *)((uintptr_t)bInfo.RSDP + sizeof(BootInfo::RSDPInfo))); + this->ReservePages(bInfo.RSDP, TO_PAGES(sizeof(BootInfo::RSDPInfo))); ACPI::ACPI::ACPIHeader *ACPIPtr = nullptr; @@ -115,23 +180,27 @@ namespace Memory } #endif - size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) / (XSDT ? 8 : 4)); + size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) / + (XSDT ? 8 : 4)); debug("Reserving %d ACPI tables...", TableSize); for (size_t t = 0; t < TableSize; t++) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" - // TODO: Should I be concerned about unaligned memory access? ACPI::ACPI::ACPIHeader *SDTHdr = nullptr; if (XSDT) - SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIPtr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 8))); + SDTHdr = + (ACPI::ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIPtr + + sizeof(ACPI::ACPI::ACPIHeader) + + (t * 8))); else - SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIPtr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 4))); - + SDTHdr = + (ACPI::ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIPtr + + sizeof(ACPI::ACPI::ACPIHeader) + + (t * 4))); #pragma GCC diagnostic pop - this->ReservePages(SDTHdr, TO_PAGES(SDTHdr->Length)); } diff --git a/Core/Memory/SmartHeap.cpp b/Core/Memory/SmartHeap.cpp new file mode 100644 index 0000000..48884ef --- /dev/null +++ b/Core/Memory/SmartHeap.cpp @@ -0,0 +1,15 @@ +#include + +namespace Memory +{ + SmartHeap::SmartHeap(size_t Size) + { + this->Object = kmalloc(Size); + this->ObjectSize = Size; + } + + SmartHeap::~SmartHeap() + { + kfree(this->Object); + } +} diff --git a/Core/Power.cpp b/Core/Power.cpp index c1cb86c..491d769 100644 --- a/Core/Power.cpp +++ b/Core/Power.cpp @@ -29,111 +29,102 @@ namespace Power { - void Power::Reboot() - { - if (((ACPI::ACPI *)this->acpi)->FADT) - if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported) - ((ACPI::DSDT *)this->dsdt)->Reboot(); + void Power::Reboot() + { + if (((ACPI::ACPI *)this->acpi)->FADT) + if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported) + ((ACPI::DSDT *)this->dsdt)->Reboot(); - uint8_t val = 0x02; - while (val & 0x02) - val = inb(0x64); - outb(0x64, 0xFE); + uint8_t val = 0x02; + while (val & 0x02) + val = inb(0x64); + outb(0x64, 0xFE); - warn("Executing the second attempt to reboot..."); + warn("Executing the second attempt to reboot..."); - // second attempt to reboot - // https://wiki.osdev.org/Reboot - uint8_t temp; - asmv("cli"); - do - { - temp = inb(0x64); - if (((temp) & (1 << (0))) != 0) - inb(0x60); - } while (((temp) & (1 << (1))) != 0); - outb(0x64, 0xFE); + // https://wiki.osdev.org/Reboot + /* Second attempt to reboot */ + asmv("cli"); + uint8_t temp; + do + { + temp = inb(0x64); + if (((temp) & (1 << (0))) != 0) + inb(0x60); + } while (((temp) & (1 << (1))) != 0); + outb(0x64, 0xFE); - CPU::Stop(); - } + CPU::Stop(); + } - void Power::Shutdown() - { - if (((ACPI::ACPI *)this->acpi)->FADT) - if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported) - ((ACPI::DSDT *)this->dsdt)->Shutdown(); + void Power::Shutdown() + { + if (((ACPI::ACPI *)this->acpi)->FADT) + if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported) + ((ACPI::DSDT *)this->dsdt)->Shutdown(); + /* TODO: If no ACPI, display "It is now safe to turn off your computer" */ - outl(0xB004, 0x2000); // for qemu - outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu - outl(0x4004, 0x3400); // virtual box - CPU::Stop(); - } + /* FIXME: Detect emulators and use their shutdown methods */ +#ifdef DEBUG + outl(0xB004, 0x2000); // for qemu + outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu + outl(0x4004, 0x3400); // virtual box +#endif + CPU::Stop(); + } - void Power::InitDSDT() - { - if (((ACPI::ACPI *)this->acpi)->FADT) - this->dsdt = new ACPI::DSDT((ACPI::ACPI *)acpi); - } + void Power::InitDSDT() + { + if (((ACPI::ACPI *)this->acpi)->FADT) + this->dsdt = new ACPI::DSDT((ACPI::ACPI *)acpi); + } - Power::Power() - { - this->acpi = new ACPI::ACPI; - this->madt = new ACPI::MADT(((ACPI::ACPI *)acpi)->MADT); - trace("Power manager initialized"); - } - - Power::~Power() - { - debug("Destructor called"); - } + Power::Power() + { + this->acpi = new ACPI::ACPI; + this->madt = new ACPI::MADT(((ACPI::ACPI *)acpi)->MADT); + trace("Power manager initialized"); + } } #elif defined(a32) namespace Power { - void Power::Reboot() - { - warn("Reboot not implemented for i386"); - } + void Power::Reboot() + { + warn("Reboot not implemented for i386"); + } - void Power::Shutdown() - { - warn("Shutdown not implemented for i386"); - } + void Power::Shutdown() + { + warn("Shutdown not implemented for i386"); + } - Power::Power() - { - error("Power not implemented for i386"); - } - - Power::~Power() - { - } + Power::Power() + { + error("Power not implemented for i386"); + } } #elif defined(aa64) namespace Power { - void Power::Reboot() - { - warn("Reboot not implemented for aarch64"); - } + void Power::Reboot() + { + warn("Reboot not implemented for aarch64"); + } - void Power::Shutdown() - { - warn("Shutdown not implemented for aarch64"); - } + void Power::Shutdown() + { + warn("Shutdown not implemented for aarch64"); + } - Power::Power() - { - error("Power not implemented for aarch64"); - } - - Power::~Power() - { - } + Power::Power() + { + error("Power not implemented for aarch64"); + } } #endif diff --git a/Core/Symbols.cpp b/Core/Symbols.cpp index 367855d..5586db3 100644 --- a/Core/Symbols.cpp +++ b/Core/Symbols.cpp @@ -25,220 +25,228 @@ namespace SymbolResolver { - const NIF char *Symbols::GetSymbolFromAddress(uintptr_t Address) - { - Symbols::SymbolTable Result{0, (char *)""}; - for (int64_t i = 0; i < this->TotalEntries; i++) - if (this->SymTable[i].Address <= Address && this->SymTable[i].Address > Result.Address) - Result = this->SymTable[i]; - return Result.FunctionName; - } + const NIF char *Symbols::GetSymbolFromAddress(uintptr_t Address) + { + SymbolTable Result{}; + foreach (auto tbl in this->SymTable) + { + if (tbl.Address <= Address && + tbl.Address > Result.Address) + Result = tbl; + } + // debug("Address: %#lx, Function: %s", + // Address, Result.FunctionName); + return Result.FunctionName; + } - void Symbols::AddSymbol(uintptr_t Address, const char *Name) - { - if (this->TotalEntries >= 0x10000) - { - error("Symbol table is full"); - return; - } + void Symbols::AddSymbol(uintptr_t Address, const char *Name) + { + SymbolTable tbl{}; + tbl.Address = Address; + tbl.FunctionName = (char *)Name; + this->SymTable.push_back(tbl); + this->SymbolTableExists = true; + } - this->SymTable[this->TotalEntries].Address = Address; - strcpy(this->SymTable[this->TotalEntries].FunctionName, Name); - this->TotalEntries++; - } - - __no_sanitize("alignment") void Symbols::AddBySymbolInfo(uint64_t Num, uint64_t EntSize, uint64_t Shndx, uintptr_t Sections) - { + __no_sanitize("alignment") void Symbols::AddSymbolInfoFromGRUB(uint64_t Num, + uint64_t EntSize, + __unused uint64_t Shndx, + uintptr_t Sections) + { #ifdef a32 - fixme("Function not working on 32-bit"); - return; + fixme("Function not working on 32-bit"); + return; #endif - if (this->TotalEntries >= 0x10000) - { - error("Symbol table is full"); - return; - } + char *sections = reinterpret_cast(Sections); + + Elf_Sym *Symbols = nullptr; + uint8_t *StringAddress = nullptr; #if defined(a64) || defined(aa64) - Elf64_Shdr *ElfSections = (Elf64_Shdr *)(Sections); - Elf64_Sym *ElfSymbols = nullptr; + Elf64_Xword SymbolSize = 0; + // Elf64_Xword StringSize = 0; #elif defined(a32) - Elf32_Shdr *ElfSections = (Elf32_Shdr *)(Sections); - Elf32_Sym *ElfSymbols = nullptr; + Elf32_Word SymbolSize = 0; + // Elf32_Word StringSize = 0; #endif - char *strtab = nullptr; + int64_t TotalEntries = 0; + + for (size_t i = 0; i < Num; ++i) + { + Elf_Shdr *sym = (Elf_Shdr *)§ions[EntSize * i]; + Elf_Shdr *str = (Elf_Shdr *)§ions[EntSize * sym->sh_link]; + + if (sym->sh_type == SHT_SYMTAB && + str->sh_type == SHT_STRTAB) + { + Symbols = (Elf_Sym *)sym->sh_addr; + StringAddress = (uint8_t *)str->sh_addr; + SymbolSize = (int)sym->sh_size; + // StringSize = (int)str->sh_size; + // TotalEntries = Section.sh_size / sizeof(Elf64_Sym) + TotalEntries = sym->sh_size / sym->sh_entsize; + debug("Symbol table found, %d entries", + SymbolSize / sym->sh_entsize); + UNUSED(SymbolSize); + break; + } + } + + if (Symbols != nullptr && StringAddress != nullptr) + { + int64_t Index, MinimumIndex; + for (int64_t i = 0; i < TotalEntries - 1; i++) + { + MinimumIndex = i; + for (Index = i + 1; Index < TotalEntries; Index++) + if (Symbols[Index].st_value < Symbols[MinimumIndex].st_value) + MinimumIndex = Index; + Elf_Sym tmp = Symbols[MinimumIndex]; + Symbols[MinimumIndex] = Symbols[i]; + Symbols[i] = tmp; + } + + while (Symbols[0].st_value == 0) + { + if (TotalEntries <= 0) + break; + Symbols++; + TotalEntries--; + } + + if (TotalEntries <= 0) + { + error("Symbol table is empty"); + return; + } + + debug("Symbol table loaded, %d entries (%ld KiB)", + TotalEntries, TO_KiB(TotalEntries * sizeof(SymbolTable))); + Elf_Sym *sym = nullptr; + const char *name = nullptr; + for (int64_t i = 0, g = TotalEntries; i < g; i++) + { + sym = &Symbols[i]; + name = (const char *)&StringAddress[Symbols[i].st_name]; + if (strlen(name) == 0) + continue; + SymbolTable tbl{}; + tbl.Address = sym->st_value; + tbl.FunctionName = (char *)name; + this->SymTable.push_back(tbl); + this->SymbolTableExists = true; + + // debug("Symbol %d: %#lx %s(%#lx)", + // i, tbl.Address, + // tbl.FunctionName, + // name); + } + } + } + + void Symbols::AppendSymbols(uintptr_t ImageAddress, uintptr_t BaseAddress) + { + /* FIXME: Get only the required headers instead of the whole file */ + + if (ImageAddress == 0 || Memory::Virtual().Check((void *)ImageAddress) == false) + { + error("Invalid image address %#lx", ImageAddress); + return; + } + debug("Solving symbols for address: %#llx", ImageAddress); - for (uint64_t i = 0; i < Num; i++) - switch (ElfSections[i].sh_type) - { - case SHT_SYMTAB: #if defined(a64) || defined(aa64) - ElfSymbols = (Elf64_Sym *)(Sections + ElfSections[i].sh_offset); - this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf64_Sym); + Elf64_Ehdr *Header = (Elf64_Ehdr *)ImageAddress; #elif defined(a32) - ElfSymbols = (Elf32_Sym *)(Sections + ElfSections[i].sh_offset); - this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf32_Sym); + Elf32_Ehdr *Header = (Elf32_Ehdr *)ImageAddress; #endif - if (this->TotalEntries >= 0x10000) - this->TotalEntries = 0x10000 - 1; + if (Header->e_ident[0] != 0x7F && + Header->e_ident[1] != 'E' && + Header->e_ident[2] != 'L' && + Header->e_ident[3] != 'F') + { + error("Invalid ELF header"); + return; + } - debug("Symbol table found, %d entries", this->TotalEntries); - break; - case SHT_STRTAB: - if (Shndx == i) - { - debug("String table found, %d entries", ElfSections[i].sh_size); - } - else - { - strtab = (char *)(Sections + ElfSections[i].sh_offset); - debug("String table found, %d entries", ElfSections[i].sh_size); - } - break; - default: - break; - } + Elf_Shdr *ElfSections = (Elf_Shdr *)(ImageAddress + Header->e_shoff); + Elf_Sym *ElfSymbols = nullptr; + char *strtab = nullptr; + int64_t TotalEntries = 0; - if (ElfSymbols != nullptr && strtab != nullptr) - { - int64_t Index, MinimumIndex; - for (int64_t i = 0; i < this->TotalEntries - 1; i++) - { - MinimumIndex = i; - for (Index = i + 1; Index < this->TotalEntries; Index++) - if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value) - MinimumIndex = Index; -#if defined(a64) || defined(aa64) - Elf64_Sym tmp = ElfSymbols[MinimumIndex]; -#elif defined(a32) - Elf32_Sym tmp = ElfSymbols[MinimumIndex]; -#endif - ElfSymbols[MinimumIndex] = ElfSymbols[i]; - ElfSymbols[i] = tmp; - } + for (uint16_t i = 0; i < Header->e_shnum; i++) + { + switch (ElfSections[i].sh_type) + { + case SHT_SYMTAB: + ElfSymbols = (Elf_Sym *)(ImageAddress + ElfSections[i].sh_offset); + TotalEntries = ElfSections[i].sh_size / sizeof(Elf_Sym); + debug("Symbol table found, %d entries", TotalEntries); + break; + case SHT_STRTAB: + if (Header->e_shstrndx == i) + { + debug("String table found, %d entries", ElfSections[i].sh_size); + } + else + { + strtab = (char *)(ImageAddress + ElfSections[i].sh_offset); + debug("String table found, %d entries", ElfSections[i].sh_size); + } + break; + default: + break; + } + } - while (ElfSymbols[0].st_value == 0) - { - if (this->TotalEntries <= 0) - break; - ElfSymbols++; - this->TotalEntries--; - } + if (ElfSymbols != nullptr && strtab != nullptr) + { + int64_t Index, MinimumIndex; + for (int64_t i = 0; i < TotalEntries - 1; i++) + { + MinimumIndex = i; + for (Index = i + 1; Index < TotalEntries; Index++) + if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value) + MinimumIndex = Index; + Elf_Sym tmp = ElfSymbols[MinimumIndex]; + ElfSymbols[MinimumIndex] = ElfSymbols[i]; + ElfSymbols[i] = tmp; + } - if (this->TotalEntries <= 0) - { - error("Symbol table is empty"); - return; - } + while (ElfSymbols[0].st_value == 0) + { + ElfSymbols++; + TotalEntries--; + } - trace("Symbol table loaded, %d entries (%ldKB)", this->TotalEntries, TO_KB(this->TotalEntries * sizeof(SymbolTable))); - for (int64_t i = 0, g = this->TotalEntries; i < g; i++) - { - this->SymTable[i].Address = ElfSymbols[i].st_value; - this->SymTable[i].FunctionName = &strtab[ElfSymbols[i].st_name]; + trace("Symbol table loaded, %d entries (%ld KiB)", + TotalEntries, TO_KiB(TotalEntries * sizeof(SymbolTable))); - // debug("Symbol %d: %#llx %s", i, this->SymTable[i].Address, this->SymTable[i].FunctionName); - } - } - } + /* TODO: maybe a checker for duplicated addresses? */ + Elf_Sym *sym = nullptr; + const char *name = nullptr; + for (int64_t i = 0, g = TotalEntries; i < g; i++) + { + sym = &ElfSymbols[i]; + name = &strtab[ElfSymbols[i].st_name]; + SymbolTable tbl{}; + tbl.Address = sym->st_value + BaseAddress; + tbl.FunctionName = (char *)name; + this->SymTable.push_back(tbl); + this->SymbolTableExists = true; - Symbols::Symbols(uintptr_t ImageAddress) - { - if (ImageAddress == 0 || Memory::Virtual().Check((void *)ImageAddress) == false) - { - error("Invalid image address %#lx", ImageAddress); - return; - } + // debug("Symbol %d: %#llx %s", i, + // this->SymTable[i].Address, + // this->SymTable[i].FunctionName); + } + } + } - this->Image = (void *)ImageAddress; - debug("Solving symbols for address: %#llx", ImageAddress); -#if defined(a64) || defined(aa64) - Elf64_Ehdr *Header = (Elf64_Ehdr *)ImageAddress; -#elif defined(a32) - Elf32_Ehdr *Header = (Elf32_Ehdr *)ImageAddress; -#endif - if (Header->e_ident[0] != 0x7F && - Header->e_ident[1] != 'E' && - Header->e_ident[2] != 'L' && - Header->e_ident[3] != 'F') - { - error("Invalid ELF header"); - return; - } -#if defined(a64) || defined(aa64) - Elf64_Shdr *ElfSections = (Elf64_Shdr *)(ImageAddress + Header->e_shoff); - Elf64_Sym *ElfSymbols = nullptr; -#elif defined(a32) - Elf32_Shdr *ElfSections = (Elf32_Shdr *)(ImageAddress + Header->e_shoff); - Elf32_Sym *ElfSymbols = nullptr; -#endif - char *strtab = nullptr; + Symbols::Symbols(uintptr_t ImageAddress) + { + this->Image = (void *)ImageAddress; + this->AppendSymbols(ImageAddress); + } - for (uint16_t i = 0; i < Header->e_shnum; i++) - switch (ElfSections[i].sh_type) - { - case SHT_SYMTAB: -#if defined(a64) || defined(aa64) - ElfSymbols = (Elf64_Sym *)(ImageAddress + ElfSections[i].sh_offset); - this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf64_Sym); -#elif defined(a32) - ElfSymbols = (Elf32_Sym *)(ImageAddress + ElfSections[i].sh_offset); - this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf32_Sym); -#endif - if (this->TotalEntries >= 0x10000) - this->TotalEntries = 0x10000 - 1; - - debug("Symbol table found, %d entries", this->TotalEntries); - break; - case SHT_STRTAB: - if (Header->e_shstrndx == i) - { - debug("String table found, %d entries", ElfSections[i].sh_size); - } - else - { - strtab = (char *)(ImageAddress + ElfSections[i].sh_offset); - debug("String table found, %d entries", ElfSections[i].sh_size); - } - break; - default: - break; - } - - if (ElfSymbols != nullptr && strtab != nullptr) - { - int64_t Index, MinimumIndex; - for (int64_t i = 0; i < this->TotalEntries - 1; i++) - { - MinimumIndex = i; - for (Index = i + 1; Index < this->TotalEntries; Index++) - if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value) - MinimumIndex = Index; -#if defined(a64) || defined(aa64) - Elf64_Sym tmp = ElfSymbols[MinimumIndex]; -#elif defined(a32) - Elf32_Sym tmp = ElfSymbols[MinimumIndex]; -#endif - ElfSymbols[MinimumIndex] = ElfSymbols[i]; - ElfSymbols[i] = tmp; - } - - while (ElfSymbols[0].st_value == 0) - { - ElfSymbols++; - this->TotalEntries--; - } - - trace("Symbol table loaded, %d entries (%ldKB)", this->TotalEntries, TO_KB(this->TotalEntries * sizeof(SymbolTable))); - for (int64_t i = 0, g = this->TotalEntries; i < g; i++) - { - this->SymTable[i].Address = ElfSymbols[i].st_value; - this->SymTable[i].FunctionName = &strtab[ElfSymbols[i].st_name]; - - // debug("Symbol %d: %#llx %s", i, this->SymTable[i].Address, this->SymTable[i].FunctionName); - } - } - } - - Symbols::~Symbols() {} + Symbols::~Symbols() {} } diff --git a/Core/Time/HighPrecisionEventTimer.cpp b/Core/Time/HighPrecisionEventTimer.cpp index ea1769d..9979684 100644 --- a/Core/Time/HighPrecisionEventTimer.cpp +++ b/Core/Time/HighPrecisionEventTimer.cpp @@ -32,52 +32,52 @@ namespace Time { - bool HighPrecisionEventTimer::Sleep(size_t Duration, Units Unit) - { + bool HighPrecisionEventTimer::Sleep(size_t Duration, Units Unit) + { #if defined(a64) - size_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk; + uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk; while (mminq(&((HPET *)hpet)->MainCounterValue) < Target) - CPU::Pause(); + CPU::Pause(); return true; #elif defined(a32) - size_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk; + uint64_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk; while (mminl(&((HPET *)hpet)->MainCounterValue) < Target) - CPU::Pause(); + CPU::Pause(); return true; #endif return false; - } + } - size_t HighPrecisionEventTimer::GetCounter() - { + uint64_t HighPrecisionEventTimer::GetCounter() + { #if defined(a64) return mminq(&((HPET *)hpet)->MainCounterValue); #elif defined(a32) return mminl(&((HPET *)hpet)->MainCounterValue); #endif - } + } - size_t HighPrecisionEventTimer::CalculateTarget(size_t Target, Units Unit) - { + uint64_t HighPrecisionEventTimer::CalculateTarget(uint64_t Target, Units Unit) + { #if defined(a64) return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk; #elif defined(a32) return mminl(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk; #endif - } + } - size_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation() - { + uint64_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation() + { #if defined(a86) - size_t Subtraction = this->GetCounter() - this->ClassCreationTime; + uint64_t Subtraction = this->GetCounter() - this->ClassCreationTime; if (Subtraction <= 0 || this->clk <= 0) - return 0; - return Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds)); + return 0; + return uint64_t(Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds))); #endif - } + } - HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet) - { + HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet) + { #if defined(a86) ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet; Memory::Virtual().Remap((void *)HPET_HDR->Address.Address, @@ -86,6 +86,7 @@ return false; this->hpet = (HPET *)HPET_HDR->Address.Address; trace("%s timer is at address %016p", HPET_HDR->Header.OEMID, (void *)HPET_HDR->Address.Address); clk = s_cst(uint32_t, (uint64_t)this->hpet->GeneralCapabilities >> 32); + debug("HPET clock is %u Hz", clk); #ifdef a64 mmoutq(&this->hpet->GeneralConfiguration, 0); mmoutq(&this->hpet->MainCounterValue, 0); @@ -97,9 +98,9 @@ return false; #endif ClassCreationTime = this->GetCounter(); #endif - } + } - HighPrecisionEventTimer::~HighPrecisionEventTimer() - { - } + HighPrecisionEventTimer::~HighPrecisionEventTimer() + { + } } diff --git a/Core/Time/TimeStampCounter.cpp b/Core/Time/TimeStampCounter.cpp index 4c9db28..7a26ac2 100644 --- a/Core/Time/TimeStampCounter.cpp +++ b/Core/Time/TimeStampCounter.cpp @@ -34,31 +34,31 @@ namespace Time bool TimeStampCounter::Sleep(size_t Duration, Units Unit) { #if defined(a86) - size_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk; + uint64_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk; while (this->GetCounter() < Target) CPU::Pause(); return true; #endif } - size_t TimeStampCounter::GetCounter() + uint64_t TimeStampCounter::GetCounter() { #if defined(a86) return CPU::Counter(); #endif } - size_t TimeStampCounter::CalculateTarget(size_t Target, Units Unit) + uint64_t TimeStampCounter::CalculateTarget(uint64_t Target, Units Unit) { #if defined(a86) - return this->GetCounter() + (Target * ConvertUnit(Unit)) / this->clk; + return uint64_t((this->GetCounter() + (Target * ConvertUnit(Unit))) / this->clk); #endif } - size_t TimeStampCounter::GetNanosecondsSinceClassCreation() + uint64_t TimeStampCounter::GetNanosecondsSinceClassCreation() { #if defined(a86) - return (this->GetCounter() - this->ClassCreationTime) / this->clk; + return uint64_t((this->GetCounter() - this->ClassCreationTime) / this->clk); #endif } diff --git a/Core/Time/Timer.cpp b/Core/Time/Timer.cpp index 1803949..4dc7ef6 100644 --- a/Core/Time/Timer.cpp +++ b/Core/Time/Timer.cpp @@ -61,90 +61,90 @@ namespace Time } } - size_t time::GetCounter() + uint64_t time::GetCounter() { switch (ActiveTimer) { case NONE: error("No timer is active"); - return false; + return 0; case RTC: fixme("RTC sleep not implemented"); - return false; + return 0; case PIT: fixme("PIT sleep not implemented"); - return false; + return 0; case HPET: return this->hpet->GetCounter(); case ACPI: fixme("ACPI sleep not implemented"); - return false; + return 0; case APIC: fixme("APIC sleep not implemented"); - return false; + return 0; case TSC: return this->tsc->GetCounter(); default: error("Unknown timer"); - return false; + return 0; } } - size_t time::CalculateTarget(size_t Target, Units Unit) + uint64_t time::CalculateTarget(uint64_t Target, Units Unit) { switch (ActiveTimer) { case NONE: error("No timer is active"); - return false; + return 0; case RTC: fixme("RTC sleep not implemented"); - return false; + return 0; case PIT: fixme("PIT sleep not implemented"); - return false; + return 0; case HPET: return this->hpet->CalculateTarget(Target, Unit); case ACPI: fixme("ACPI sleep not implemented"); - return false; + return 0; case APIC: fixme("APIC sleep not implemented"); - return false; + return 0; case TSC: return this->tsc->CalculateTarget(Target, Unit); default: error("Unknown timer"); - return false; + return 0; } } - size_t time::GetNanosecondsSinceClassCreation() + uint64_t time::GetNanosecondsSinceClassCreation() { switch (ActiveTimer) { case NONE: error("No timer is active"); - return false; + return 0; case RTC: fixme("RTC sleep not implemented"); - return false; + return 0; case PIT: fixme("PIT sleep not implemented"); - return false; + return 0; case HPET: return this->hpet->GetNanosecondsSinceClassCreation(); case ACPI: fixme("ACPI sleep not implemented"); - return false; + return 0; case APIC: fixme("APIC sleep not implemented"); - return false; + return 0; case TSC: return this->tsc->GetNanosecondsSinceClassCreation(); default: error("Unknown timer"); - return false; + return 0; } } diff --git a/Core/UndefinedBehaviorSanitization.c b/Core/UndefinedBehaviorSanitization.c index 83887f0..1f25fd2 100644 --- a/Core/UndefinedBehaviorSanitization.c +++ b/Core/UndefinedBehaviorSanitization.c @@ -20,6 +20,8 @@ #include #include +#ifdef DEBUG + // TODO: implement: /* __ubsan_handle_type_mismatch_v1_abort @@ -47,320 +49,320 @@ __ubsan_handle_pointer_overflow_abort __ubsan_handle_cfi_check_fail */ -extern void __asan_report_load1(void *unknown) +void __asan_report_load1(void *unknown) { ubsan("load1"); UNUSED(unknown); } -extern void __asan_report_load2(void *unknown) +void __asan_report_load2(void *unknown) { ubsan("load2"); UNUSED(unknown); } -extern void __asan_report_load4(void *unknown) +void __asan_report_load4(void *unknown) { ubsan("load4"); UNUSED(unknown); } -extern void __asan_report_load8(void *unknown) +void __asan_report_load8(void *unknown) { ubsan("load8"); UNUSED(unknown); } -extern void __asan_report_load16(void *unknown) +void __asan_report_load16(void *unknown) { ubsan("load16"); UNUSED(unknown); } -extern void __asan_report_load_n(void *unknown, uintptr_t size) +void __asan_report_load_n(void *unknown, uintptr_t size) { ubsan("loadn"); UNUSED(unknown); UNUSED(size); } -extern void __asan_report_store1(void *unknown) +void __asan_report_store1(void *unknown) { ubsan("store1"); UNUSED(unknown); } -extern void __asan_report_store2(void *unknown) +void __asan_report_store2(void *unknown) { ubsan("store2"); UNUSED(unknown); } -extern void __asan_report_store4(void *unknown) +void __asan_report_store4(void *unknown) { ubsan("store4"); UNUSED(unknown); } -extern void __asan_report_store8(void *unknown) +void __asan_report_store8(void *unknown) { ubsan("store8"); UNUSED(unknown); } -extern void __asan_report_store16(void *unknown) +void __asan_report_store16(void *unknown) { ubsan("store16"); UNUSED(unknown); } -extern void __asan_report_store_n(void *unknown, uintptr_t size) +void __asan_report_store_n(void *unknown, uintptr_t size) { ubsan("storen"); UNUSED(unknown); UNUSED(size); } -extern void __asan_report_load1_noabort(void *unknown) +void __asan_report_load1_noabort(void *unknown) { ubsan("load1"); UNUSED(unknown); } -extern void __asan_report_load2_noabort(void *unknown) +void __asan_report_load2_noabort(void *unknown) { ubsan("load2"); UNUSED(unknown); } -extern void __asan_report_load4_noabort(void *unknown) +void __asan_report_load4_noabort(void *unknown) { ubsan("load4"); UNUSED(unknown); } -extern void __asan_report_load8_noabort(void *unknown) +void __asan_report_load8_noabort(void *unknown) { ubsan("load8"); UNUSED(unknown); } -extern void __asan_report_load16_noabort(void *unknown) +void __asan_report_load16_noabort(void *unknown) { ubsan("load16"); UNUSED(unknown); } -extern void __asan_report_load_n_noabort(void *unknown, uintptr_t size) +void __asan_report_load_n_noabort(void *unknown, uintptr_t size) { ubsan("loadn"); UNUSED(unknown); UNUSED(size); } -extern void __asan_report_store1_noabort(void *unknown) +void __asan_report_store1_noabort(void *unknown) { ubsan("store1"); UNUSED(unknown); } -extern void __asan_report_store2_noabort(void *unknown) +void __asan_report_store2_noabort(void *unknown) { ubsan("store2"); UNUSED(unknown); } -extern void __asan_report_store4_noabort(void *unknown) +void __asan_report_store4_noabort(void *unknown) { ubsan("store4"); UNUSED(unknown); } -extern void __asan_report_store8_noabort(void *unknown) +void __asan_report_store8_noabort(void *unknown) { ubsan("store8"); UNUSED(unknown); } -extern void __asan_report_store16_noabort(void *unknown) +void __asan_report_store16_noabort(void *unknown) { ubsan("store16"); UNUSED(unknown); } -extern void __asan_report_store_n_noabort(void *unknown, uintptr_t size) +void __asan_report_store_n_noabort(void *unknown, uintptr_t size) { ubsan("storen"); UNUSED(unknown); UNUSED(size); } -extern void __asan_stack_malloc_0(uintptr_t size) +void __asan_stack_malloc_0(uintptr_t size) { ubsan("stack malloc 0"); UNUSED(size); } -extern void __asan_stack_malloc_1(uintptr_t size) +void __asan_stack_malloc_1(uintptr_t size) { ubsan("stack malloc 1"); UNUSED(size); } -extern void __asan_stack_malloc_2(uintptr_t size) +void __asan_stack_malloc_2(uintptr_t size) { ubsan("stack malloc 2"); UNUSED(size); } -extern void __asan_stack_malloc_3(uintptr_t size) +void __asan_stack_malloc_3(uintptr_t size) { ubsan("stack malloc 3"); UNUSED(size); } -extern void __asan_stack_malloc_4(uintptr_t size) +void __asan_stack_malloc_4(uintptr_t size) { ubsan("stack malloc 4"); UNUSED(size); } -extern void __asan_stack_malloc_5(uintptr_t size) +void __asan_stack_malloc_5(uintptr_t size) { ubsan("stack malloc 5"); UNUSED(size); } -extern void __asan_stack_malloc_6(uintptr_t size) +void __asan_stack_malloc_6(uintptr_t size) { ubsan("stack malloc 6"); UNUSED(size); } -extern void __asan_stack_malloc_7(uintptr_t size) +void __asan_stack_malloc_7(uintptr_t size) { ubsan("stack malloc 7"); UNUSED(size); } -extern void __asan_stack_malloc_8(uintptr_t size) +void __asan_stack_malloc_8(uintptr_t size) { ubsan("stack malloc 8"); UNUSED(size); } -extern void __asan_stack_malloc_9(uintptr_t size) +void __asan_stack_malloc_9(uintptr_t size) { ubsan("stack malloc 9"); UNUSED(size); } -extern void __asan_stack_free_0(void *ptr, uintptr_t size) +void __asan_stack_free_0(void *ptr, uintptr_t size) { ubsan("stack free 0"); UNUSED(ptr); UNUSED(size); } -extern void __asan_stack_free_1(void *ptr, uintptr_t size) +void __asan_stack_free_1(void *ptr, uintptr_t size) { ubsan("stack free 1"); UNUSED(ptr); UNUSED(size); } -extern void __asan_stack_free_2(void *ptr, uintptr_t size) +void __asan_stack_free_2(void *ptr, uintptr_t size) { ubsan("stack free 2"); UNUSED(ptr); UNUSED(size); } -extern void __asan_stack_free_3(void *ptr, uintptr_t size) +void __asan_stack_free_3(void *ptr, uintptr_t size) { ubsan("stack free 3"); UNUSED(ptr); UNUSED(size); } -extern void __asan_stack_free_4(void *ptr, uintptr_t size) +void __asan_stack_free_4(void *ptr, uintptr_t size) { ubsan("stack free 4"); UNUSED(ptr); UNUSED(size); } -extern void __asan_stack_free_5(void *ptr, uintptr_t size) +void __asan_stack_free_5(void *ptr, uintptr_t size) { ubsan("stack free 5"); UNUSED(ptr); UNUSED(size); } -extern void __asan_stack_free_6(void *ptr, uintptr_t size) +void __asan_stack_free_6(void *ptr, uintptr_t size) { ubsan("stack free 6"); UNUSED(ptr); UNUSED(size); } -extern void __asan_stack_free_7(void *ptr, uintptr_t size) +void __asan_stack_free_7(void *ptr, uintptr_t size) { ubsan("stack free 7"); UNUSED(ptr); UNUSED(size); } -extern void __asan_stack_free_8(void *ptr, uintptr_t size) +void __asan_stack_free_8(void *ptr, uintptr_t size) { ubsan("stack free 8"); UNUSED(ptr); UNUSED(size); } -extern void __asan_stack_free_9(void *ptr, uintptr_t size) +void __asan_stack_free_9(void *ptr, uintptr_t size) { ubsan("stack free 9"); UNUSED(ptr); UNUSED(size); } -extern void __asan_poison_stack_memory(void *addr, uintptr_t size) +void __asan_poison_stack_memory(void *addr, uintptr_t size) { ubsan("poison stack memory"); UNUSED(addr); UNUSED(size); } -extern void __asan_unpoison_stack_memory(void *addr, uintptr_t size) +void __asan_unpoison_stack_memory(void *addr, uintptr_t size) { ubsan("unpoison stack memory"); UNUSED(addr); UNUSED(size); } -extern void __asan_before_dynamic_init(const char *module_name) +void __asan_before_dynamic_init(const char *module_name) { ubsan("before dynamic init"); UNUSED(module_name); } -extern void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); } +void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); } -extern void __asan_register_globals(void *unknown, size_t size) +void __asan_register_globals(void *unknown, size_t size) { ubsan("register_globals"); UNUSED(unknown); UNUSED(size); } -extern void __asan_unregister_globals(void) { ubsan("unregister_globals"); } +void __asan_unregister_globals(void) { ubsan("unregister_globals"); } -extern void __asan_init(void) { ubsan("init"); } -extern void __asan_version_mismatch_check_v8(void) { ubsan("version_mismatch_check_v8"); } -extern void __asan_option_detect_stack_use_after_return(void) { ubsan("stack use after return"); } +void __asan_init(void) { ubsan("init"); } +void __asan_version_mismatch_check_v8(void) { ubsan("version_mismatch_check_v8"); } +void __asan_option_detect_stack_use_after_return(void) { ubsan("stack use after return"); } -extern __noreturn void __asan_handle_no_return(void) +__noreturn void __asan_handle_no_return(void) { ubsan("no_return"); while (1) @@ -511,3 +513,5 @@ void __ubsan_handle_dynamic_type_cache_miss(struct dynamic_type_cache_miss_data ubsan("Dynamic type cache miss."); UNUSED(ptr); } + +#endif diff --git a/Core/UniversalAsynchronousReceiverTransmitter.cpp b/Core/UniversalAsynchronousReceiverTransmitter.cpp index d18c73b..cdbd6b7 100644 --- a/Core/UniversalAsynchronousReceiverTransmitter.cpp +++ b/Core/UniversalAsynchronousReceiverTransmitter.cpp @@ -26,18 +26,18 @@ std::vector RegisteredEvents #if defined(a86) NIF __always_inline inline uint8_t NoProfiler_inportb(uint16_t Port) { - uint8_t Result; - asm("in %%dx, %%al" - : "=a"(Result) - : "d"(Port)); - return Result; + uint8_t Result; + asm("in %%dx, %%al" + : "=a"(Result) + : "d"(Port)); + return Result; } NIF __always_inline inline void NoProfiler_outportb(uint16_t Port, uint8_t Data) { - asmv("out %%al, %%dx" - : - : "a"(Data), "d"(Port)); + asmv("out %%al, %%dx" + : + : "a"(Data), "d"(Port)); } #endif @@ -52,123 +52,125 @@ namespace UniversalAsynchronousReceiverTransmitter #define SERIAL_RATE_38400_HI 0x00 #define SERIAL_BUFFER_EMPTY 0x20 - /* TODO: Serial Port implementation needs reword. https://wiki.osdev.org/Serial_Ports */ + /* TODO: Serial Port implementation needs reword. https://wiki.osdev.org/Serial_Ports */ - SafeFunction NIF UART::UART(SerialPorts Port) - { + SafeFunction NIF UART::UART(SerialPorts Port) + { #if defined(a86) - if (Port == COMNULL) - return; + if (Port == COMNULL) + return; - this->Port = Port; - int PortNumber = 0; + this->Port = Port; + int PortNumber = 0; - switch (Port) - { - case COM1: - PortNumber = 0; - break; - case COM2: - PortNumber = 1; - break; - case COM3: - PortNumber = 2; - break; - case COM4: - PortNumber = 3; - break; - case COM5: - PortNumber = 4; - break; - case COM6: - PortNumber = 5; - break; - case COM7: - PortNumber = 6; - break; - case COM8: - PortNumber = 7; - break; - default: - return; - } + switch (Port) + { + case COM1: + PortNumber = 0; + break; + case COM2: + PortNumber = 1; + break; + case COM3: + PortNumber = 2; + break; + case COM4: + PortNumber = 3; + break; + case COM5: + PortNumber = 4; + break; + case COM6: + PortNumber = 5; + break; + case COM7: + PortNumber = 6; + break; + case COM8: + PortNumber = 7; + break; + default: + return; + } - if (serialports[PortNumber]) - return; + if (serialports[PortNumber]) + return; - // Initialize the serial port - NoProfiler_outportb(s_cst(uint16_t, Port + 1), 0x00); // Disable all interrupts - NoProfiler_outportb(s_cst(uint16_t, Port + 3), SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor) - NoProfiler_outportb(s_cst(uint16_t, Port + 0), SERIAL_RATE_115200_LO); // Set divisor to 1 (lo byte) 115200 baud - NoProfiler_outportb(s_cst(uint16_t, Port + 1), SERIAL_RATE_115200_HI); // (hi byte) - NoProfiler_outportb(s_cst(uint16_t, Port + 3), 0x03); // 8 bits, no parity, one stop bit - NoProfiler_outportb(s_cst(uint16_t, Port + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold - NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0B); // IRQs enabled, RTS/DSR set + // Initialize the serial port + NoProfiler_outportb(s_cst(uint16_t, Port + 1), 0x00); // Disable all interrupts + NoProfiler_outportb(s_cst(uint16_t, Port + 3), SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor) + NoProfiler_outportb(s_cst(uint16_t, Port + 0), SERIAL_RATE_115200_LO); // Set divisor to 1 (lo byte) 115200 baud + NoProfiler_outportb(s_cst(uint16_t, Port + 1), SERIAL_RATE_115200_HI); // (hi byte) + NoProfiler_outportb(s_cst(uint16_t, Port + 3), 0x03); // 8 bits, no parity, one stop bit + NoProfiler_outportb(s_cst(uint16_t, Port + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold + NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0B); // IRQs enabled, RTS/DSR set - /* FIXME https://wiki.osdev.org/Serial_Ports */ - // NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0x1E); - // NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0xAE); - // Check if the serial port is faulty. - // if (NoProfiler_inportb(s_cst(uint16_t, Port + 0)) != 0xAE) - // { - // static int once = 0; - // if (!once++) - // warn("Serial port %#llx is faulty.", Port); - // // serialports[Port] = false; // ignore for now - // // return; - // } + /* FIXME https://wiki.osdev.org/Serial_Ports */ + // NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0x1E); + // NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0xAE); + // Check if the serial port is faulty. + // if (NoProfiler_inportb(s_cst(uint16_t, Port + 0)) != 0xAE) + // { + // static int once = 0; + // if (!once++) + // warn("Serial port %#llx is faulty.", Port); + // // serialports[Port] = false; // ignore for now + // // return; + // } - // Set to normal operation mode. - NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0F); - serialports[PortNumber] = true; + // Set to normal operation mode. + NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0F); + serialports[PortNumber] = true; #endif - } + } - SafeFunction NIF UART::~UART() {} + SafeFunction NIF UART::~UART() {} - SafeFunction NIF void UART::Write(uint8_t Char) - { + SafeFunction NIF void UART::Write(uint8_t Char) + { #if defined(a86) - while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & SERIAL_BUFFER_EMPTY) == 0) - ; - NoProfiler_outportb(Port, Char); + while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & SERIAL_BUFFER_EMPTY) == 0) + ; + NoProfiler_outportb(Port, Char); #endif - foreach (auto e in RegisteredEvents) - if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL) - e->OnSent(Char); - } + foreach (auto e in RegisteredEvents) + if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL) + e->OnSent(Char); + } - SafeFunction NIF uint8_t UART::Read() - { + SafeFunction NIF uint8_t UART::Read() + { #if defined(a86) - while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & 1) == 0) - ; - return NoProfiler_inportb(Port); + while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & 1) == 0) + ; + return NoProfiler_inportb(Port); #endif - foreach (auto e in RegisteredEvents) - { - if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL) - { + foreach (auto e in RegisteredEvents) + { + if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL) + { #if defined(a86) - e->OnReceived(NoProfiler_inportb(Port)); + e->OnReceived(NoProfiler_inportb(Port)); #endif - } - } - } + } + } + } - SafeFunction NIF Events::Events(SerialPorts Port) - { - this->Port = Port; - RegisteredEvents.push_back(this); - } + SafeFunction NIF Events::Events(SerialPorts Port) + { + this->Port = Port; + RegisteredEvents.push_back(this); + } - SafeFunction NIF Events::~Events() - { - for (size_t i = 0; i < RegisteredEvents.size(); i++) - if (RegisteredEvents[i] == this) - { - RegisteredEvents.remove(i); - return; - } - } + SafeFunction NIF Events::~Events() + { + forItr(itr, RegisteredEvents) + { + if (*itr == this) + { + RegisteredEvents.erase(itr); + return; + } + } + } } diff --git a/Core/Video/Display.cpp b/Core/Video/Display.cpp index 13f4f5e..39e17f7 100644 --- a/Core/Video/Display.cpp +++ b/Core/Video/Display.cpp @@ -28,418 +28,419 @@ NewLock(PrintLock); namespace Video { - Font *Display::GetCurrentFont() { return CurrentFont; } - void Display::SetCurrentFont(Font *Font) { CurrentFont = Font; } - uint16_t Display::GetBitsPerPixel() { return this->framebuffer.BitsPerPixel; } - size_t Display::GetPitch() { return this->framebuffer.Pitch; } + Font *Display::GetCurrentFont() { return CurrentFont; } + void Display::SetCurrentFont(Font *Font) { CurrentFont = Font; } + uint16_t Display::GetBitsPerPixel() { return this->framebuffer.BitsPerPixel; } + size_t Display::GetPitch() { return this->framebuffer.Pitch; } - void Display::CreateBuffer(uint32_t Width, uint32_t Height, int Index) - { - if (Width == 0 || Height == 0) - { - Width = this->framebuffer.Width; - Height = this->framebuffer.Height; - debug("Buffer %d created with default size (%d, %d)", Index, Width, Height); - } + void Display::CreateBuffer(uint32_t Width, uint32_t Height, int Index) + { + if (Width == 0 || Height == 0) + { + Width = this->framebuffer.Width; + Height = this->framebuffer.Height; + debug("Buffer %d created with default size (%d, %d)", Index, Width, Height); + } - if (this->Buffers[Index].Checksum == 0xBBFFE515A117E) - { - warn("Buffer %d already exists, skipping creation", Index); - return; - } + if (this->Buffers[Index].Checksum == 0xBBFFE515A117E) + { + warn("Buffer %d already exists, skipping creation", Index); + return; + } - size_t Size = this->framebuffer.Pitch * Height; + size_t Size = this->framebuffer.Pitch * Height; - this->Buffers[Index].Buffer = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); - memset(this->Buffers[Index].Buffer, 0, Size); + this->Buffers[Index].Buffer = KernelAllocator.RequestPages(TO_PAGES(Size + 1)); + memset(this->Buffers[Index].Buffer, 0, Size); - this->Buffers[Index].Width = Width; - this->Buffers[Index].Height = Height; - this->Buffers[Index].Size = Size; - this->Buffers[Index].Color = 0xFFFFFF; - this->Buffers[Index].CursorX = 0; - this->Buffers[Index].CursorY = 0; - this->Buffers[Index].Brightness = 100; - this->Buffers[Index].Checksum = 0xBBFFE515A117E; - debug("Buffer %d created", Index); - } + this->Buffers[Index].Width = Width; + this->Buffers[Index].Height = Height; + this->Buffers[Index].Size = Size; + this->Buffers[Index].Color = 0xFFFFFF; + this->Buffers[Index].CursorX = 0; + this->Buffers[Index].CursorY = 0; + this->Buffers[Index].Brightness = 100; + this->Buffers[Index].Checksum = 0xBBFFE515A117E; + debug("Buffer %d created", Index); + } - void Display::SetBuffer(int Index) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::SetBuffer(int Index) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - if (this->Buffers[Index].Brightness != 100) - this->SetBrightness(this->Buffers[Index].Brightness, Index); + if (this->Buffers[Index].Brightness != 100) + this->SetBrightness(this->Buffers[Index].Brightness, Index); - if (this->Buffers[Index].Brightness == 0) /* Just clear the buffer */ - memset(this->Buffers[Index].Buffer, 0, this->Buffers[Index].Size); + if (this->Buffers[Index].Brightness == 0) /* Just clear the buffer */ + memset(this->Buffers[Index].Buffer, 0, this->Buffers[Index].Size); - memcpy(this->framebuffer.BaseAddress, this->Buffers[Index].Buffer, this->Buffers[Index].Size); - } + memcpy(this->framebuffer.BaseAddress, this->Buffers[Index].Buffer, this->Buffers[Index].Size); + } - ScreenBuffer *Display::GetBuffer(int Index) { return &this->Buffers[Index]; } + ScreenBuffer *Display::GetBuffer(int Index) { return &this->Buffers[Index]; } - void Display::ClearBuffer(int Index) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::ClearBuffer(int Index) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - memset(this->Buffers[Index].Buffer, 0, this->Buffers[Index].Size); - } + memset(this->Buffers[Index].Buffer, 0, this->Buffers[Index].Size); + } - void Display::DeleteBuffer(int Index) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::DeleteBuffer(int Index) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - KernelAllocator.FreePages(this->Buffers[Index].Buffer, TO_PAGES(this->Buffers[Index].Size + 1)); - this->Buffers[Index].Buffer = nullptr; - this->Buffers[Index].Checksum = 0; - debug("Buffer %d deleted", Index); - } + KernelAllocator.FreePages(this->Buffers[Index].Buffer, TO_PAGES(this->Buffers[Index].Size + 1)); + this->Buffers[Index].Buffer = nullptr; + this->Buffers[Index].Checksum = 0; + debug("Buffer %d deleted", Index); + } - void Display::SetBrightness(int Value, int Index) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::SetBrightness(int Value, int Index) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - if (Value > 100) - Value = 100; - else if (Value < 0) - Value = 0; + if (Value > 100) + Value = 100; + else if (Value < 0) + Value = 0; - uint32_t *pixel = (uint32_t *)this->Buffers[Index].Buffer; + uint32_t *pixel = (uint32_t *)this->Buffers[Index].Buffer; - for (uint32_t y = 0; y < this->Buffers[Index].Height; y++) - { - for (uint32_t x = 0; x < this->Buffers[Index].Width; x++) - { - uint32_t color = pixel[y * this->Buffers[Index].Width + x]; + for (uint32_t y = 0; y < this->Buffers[Index].Height; y++) + { + for (uint32_t x = 0; x < this->Buffers[Index].Width; x++) + { + uint32_t color = pixel[y * this->Buffers[Index].Width + x]; - uint8_t r = color & 0xff; - uint8_t g = (color >> 8) & 0xff; - uint8_t b = (color >> 16) & 0xff; + uint8_t r = color & 0xff; + uint8_t g = (color >> 8) & 0xff; + uint8_t b = (color >> 16) & 0xff; - r = s_cst(uint8_t, (r * Value) / 100); - g = s_cst(uint8_t, (g * Value) / 100); - b = s_cst(uint8_t, (b * Value) / 100); + r = s_cst(uint8_t, (r * Value) / 100); + g = s_cst(uint8_t, (g * Value) / 100); + b = s_cst(uint8_t, (b * Value) / 100); - pixel[y * this->Buffers[Index].Width + x] = (b << 16) | (g << 8) | r; - } - } - this->Buffers[Index].Brightness = s_cst(char, Value); - } + pixel[y * this->Buffers[Index].Width + x] = (b << 16) | (g << 8) | r; + } + } + this->Buffers[Index].Brightness = s_cst(char, Value); + } - void Display::SetBufferCursor(int Index, uint32_t X, uint32_t Y) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::SetBufferCursor(int Index, uint32_t X, uint32_t Y) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - this->Buffers[Index].CursorX = X; - this->Buffers[Index].CursorY = Y; - } + this->Buffers[Index].CursorX = X; + this->Buffers[Index].CursorY = Y; + } - void Display::GetBufferCursor(int Index, uint32_t *X, uint32_t *Y) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::GetBufferCursor(int Index, uint32_t *X, uint32_t *Y) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - *X = this->Buffers[Index].CursorX; - *Y = this->Buffers[Index].CursorY; - } + *X = this->Buffers[Index].CursorX; + *Y = this->Buffers[Index].CursorY; + } - void Display::SetPixel(uint32_t X, uint32_t Y, uint32_t Color, int Index) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::SetPixel(uint32_t X, uint32_t Y, uint32_t Color, int Index) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - if (unlikely(X >= this->Buffers[Index].Width)) - X = this->Buffers[Index].Width - 1; + if (unlikely(X >= this->Buffers[Index].Width)) + X = this->Buffers[Index].Width - 1; - if (unlikely(Y >= this->Buffers[Index].Height)) - Y = this->Buffers[Index].Height - 1; + if (unlikely(Y >= this->Buffers[Index].Height)) + Y = this->Buffers[Index].Height - 1; - uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8)); - *Pixel = Color; - } + uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8)); + *Pixel = Color; + } - uint32_t Display::GetPixel(uint32_t X, uint32_t Y, int Index) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - return 0; + uint32_t Display::GetPixel(uint32_t X, uint32_t Y, int Index) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + return 0; - if (unlikely(X >= this->Buffers[Index].Width || Y >= this->Buffers[Index].Height)) - return 0; + if (unlikely(X >= this->Buffers[Index].Width || Y >= this->Buffers[Index].Height)) + return 0; - uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8)); - return *Pixel; - } + uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8)); + return *Pixel; + } - void Display::Scroll(int Index, int Lines) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::Scroll(int Index, int Lines) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - if (this->Buffers[Index].DoNotScroll) - return; + if (this->Buffers[Index].DoNotScroll) + return; - if (Lines == 0) - return; + if (Lines == 0) + return; - if (Lines > 0) - { - uint32_t LineSize = this->Buffers[Index].Width * (this->framebuffer.BitsPerPixel / 8); - uint32_t BytesToMove = LineSize * Lines * this->CurrentFont->GetInfo().Height; - size_t BytesToClear = this->Buffers[Index].Size - BytesToMove; - memmove(this->Buffers[Index].Buffer, (uint8_t *)this->Buffers[Index].Buffer + BytesToMove, BytesToClear); - memset((uint8_t *)this->Buffers[Index].Buffer + BytesToClear, 0, BytesToMove); - } - } + if (Lines > 0) + { + uint32_t LineSize = this->Buffers[Index].Width * (this->framebuffer.BitsPerPixel / 8); + uint32_t BytesToMove = LineSize * Lines * this->CurrentFont->GetInfo().Height; + size_t BytesToClear = this->Buffers[Index].Size - BytesToMove; + memmove(this->Buffers[Index].Buffer, (uint8_t *)this->Buffers[Index].Buffer + BytesToMove, BytesToClear); + memset((uint8_t *)this->Buffers[Index].Buffer + BytesToClear, 0, BytesToMove); + } + } - void Display::SetDoNotScroll(bool Value, int Index) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::SetDoNotScroll(bool Value, int Index) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - this->Buffers[Index].DoNotScroll = Value; - } + this->Buffers[Index].DoNotScroll = Value; + } #if defined(a32) - __no_sanitize("undefined") + __no_sanitize("undefined") #endif - char Display::Print(char Char, int Index, bool WriteToUART) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - return 0; + char Display::Print(char Char, int Index, bool WriteToUART) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + return 0; - // SmartLock(PrintLock); + // SmartLock(PrintLock); - if (this->ColorIteration) - { - // RRGGBB - if (Char >= '0' && Char <= '9') - this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - '0'); - else if (Char >= 'a' && Char <= 'f') - this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'a' + 10); - else if (Char >= 'A' && Char <= 'F') - this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'A' + 10); - else - this->Buffers[Index].Color = 0xFFFFFF; - if (WriteToUART) - UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char); - this->ColorPickerIteration++; - if (this->ColorPickerIteration == 6) - { - this->ColorPickerIteration = 0; - if (WriteToUART) - UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(']'); - this->ColorIteration = false; - } - return Char; - } + if (this->ColorIteration) + { + // RRGGBB + if (Char >= '0' && Char <= '9') + this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - '0'); + else if (Char >= 'a' && Char <= 'f') + this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'a' + 10); + else if (Char >= 'A' && Char <= 'F') + this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'A' + 10); + else + this->Buffers[Index].Color = 0xFFFFFF; + if (WriteToUART) + UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char); + this->ColorPickerIteration++; + if (this->ColorPickerIteration == 6) + { + this->ColorPickerIteration = 0; + if (WriteToUART) + UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(']'); + this->ColorIteration = false; + } + return Char; + } - if (WriteToUART) - UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char); + if (WriteToUART) + UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char); - switch (Char) - { - case '\e': - { - if (WriteToUART) - UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('['); - this->ColorIteration = true; - return Char; - } - case '\b': - { - switch (this->CurrentFont->GetInfo().Type) - { - case FontType::PCScreenFont1: - { - fixme("PCScreenFont1"); - break; - } - case FontType::PCScreenFont2: - { - uint32_t fonthdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width; - uint32_t fonthdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height; + switch (Char) + { + case '\e': + { + if (WriteToUART) + UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('['); + this->ColorIteration = true; + return Char; + } + case '\b': + { + switch (this->CurrentFont->GetInfo().Type) + { + case FontType::PCScreenFont1: + { + fixme("PCScreenFont1"); + break; + } + case FontType::PCScreenFont2: + { + uint32_t fonthdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width; + uint32_t fonthdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height; - for (unsigned long Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + fonthdrHeight; Y++) - for (unsigned long X = this->Buffers[Index].CursorX - fonthdrWidth; X < this->Buffers[Index].CursorX; X++) - *(uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + - (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8)) = 0; - break; - } - default: - warn("Unsupported font type"); - break; - } + for (unsigned long Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + fonthdrHeight; Y++) + for (unsigned long X = this->Buffers[Index].CursorX - fonthdrWidth; X < this->Buffers[Index].CursorX; X++) + *(uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + + (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8)) = 0; + break; + } + default: + warn("Unsupported font type"); + break; + } - if (this->Buffers[Index].CursorX > 0) - this->Buffers[Index].CursorX -= this->GetCurrentFont()->GetInfo().Width; + if (this->Buffers[Index].CursorX > 0) + this->Buffers[Index].CursorX -= this->GetCurrentFont()->GetInfo().Width; - return Char; - } - case '\t': - { - this->Buffers[Index].CursorX = (this->Buffers[Index].CursorX + 8) & ~(8 - 1); - return Char; - } - case '\r': - { - this->Buffers[Index].CursorX = 0; - return Char; - } - case '\n': - { - this->Buffers[Index].CursorX = 0; - this->Buffers[Index].CursorY += this->GetCurrentFont()->GetInfo().Height; - return Char; - } - default: - break; - } + return Char; + } + case '\t': + { + this->Buffers[Index].CursorX = (this->Buffers[Index].CursorX + 8) & ~(8 - 1); + return Char; + } + case '\r': + { + this->Buffers[Index].CursorX = 0; + return Char; + } + case '\n': + { + this->Buffers[Index].CursorX = 0; + this->Buffers[Index].CursorY += this->GetCurrentFont()->GetInfo().Height; + return Char; + } + default: + break; + } - uint32_t FontHeight = this->GetCurrentFont()->GetInfo().Height; + uint32_t FontHeight = this->GetCurrentFont()->GetInfo().Height; - if (this->Buffers[Index].CursorX + this->GetCurrentFont()->GetInfo().Width >= this->Buffers[Index].Width) - { - this->Buffers[Index].CursorX = 0; - this->Buffers[Index].CursorY += FontHeight; - } + if (this->Buffers[Index].CursorX + this->GetCurrentFont()->GetInfo().Width >= this->Buffers[Index].Width) + { + this->Buffers[Index].CursorX = 0; + this->Buffers[Index].CursorY += FontHeight; + } - if (this->Buffers[Index].CursorY + FontHeight >= this->Buffers[Index].Height) - { - if (!this->Buffers[Index].DoNotScroll) - { - this->Buffers[Index].CursorY -= FontHeight; - this->Scroll(Index, 1); - } - } + if (this->Buffers[Index].CursorY + FontHeight >= this->Buffers[Index].Height) + { + if (!this->Buffers[Index].DoNotScroll) + { + this->Buffers[Index].CursorY -= FontHeight; + this->Scroll(Index, 1); + } + } - switch (this->CurrentFont->GetInfo().Type) - { - case FontType::PCScreenFont1: - { - uint32_t *PixelPtr = (uint32_t *)this->Buffers[Index].Buffer; - char *FontPtr = (char *)this->CurrentFont->GetInfo().PSF1Font->GlyphBuffer + (Char * this->CurrentFont->GetInfo().PSF1Font->Header->charsize); - for (uint64_t Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + 16; Y++) - { - for (uint64_t X = this->Buffers[Index].CursorX; X < this->Buffers[Index].CursorX + 8; X++) - if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index].CursorX))) > 0) - *(unsigned int *)(PixelPtr + X + (Y * this->Buffers[Index].Width)) = this->Buffers[Index].Color; - FontPtr++; - } - this->Buffers[Index].CursorX += 8; + switch (this->CurrentFont->GetInfo().Type) + { + case FontType::PCScreenFont1: + { + uint32_t *PixelPtr = (uint32_t *)this->Buffers[Index].Buffer; + char *FontPtr = (char *)this->CurrentFont->GetInfo().PSF1Font->GlyphBuffer + (Char * this->CurrentFont->GetInfo().PSF1Font->Header->charsize); + for (uint64_t Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + 16; Y++) + { + for (uint64_t X = this->Buffers[Index].CursorX; X < this->Buffers[Index].CursorX + 8; X++) + if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index].CursorX))) > 0) + *(unsigned int *)(PixelPtr + X + (Y * this->Buffers[Index].Width)) = this->Buffers[Index].Color; + FontPtr++; + } + this->Buffers[Index].CursorX += 8; - break; - } - case FontType::PCScreenFont2: - { - // if (this->CurrentFont->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE - // Char = this->CurrentFont->PSF2Font->GlyphBuffer[Char]; - int BytesPerLine = (this->CurrentFont->GetInfo().PSF2Font->Header->width + 7) / 8; - char *FontAddress = (char *)this->CurrentFont->GetInfo().StartAddress; - uint32_t FontHeaderSize = this->CurrentFont->GetInfo().PSF2Font->Header->headersize; - uint32_t FontCharSize = this->CurrentFont->GetInfo().PSF2Font->Header->charsize; - uint32_t FontLength = this->CurrentFont->GetInfo().PSF2Font->Header->length; - char *FontPtr = FontAddress + FontHeaderSize + (Char > 0 && (uint32_t)Char < FontLength ? Char : 0) * FontCharSize; + break; + } + case FontType::PCScreenFont2: + { + // if (this->CurrentFont->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE + // Char = this->CurrentFont->PSF2Font->GlyphBuffer[Char]; + int BytesPerLine = (this->CurrentFont->GetInfo().PSF2Font->Header->width + 7) / 8; + char *FontAddress = (char *)this->CurrentFont->GetInfo().StartAddress; + uint32_t FontHeaderSize = this->CurrentFont->GetInfo().PSF2Font->Header->headersize; + uint32_t FontCharSize = this->CurrentFont->GetInfo().PSF2Font->Header->charsize; + uint32_t FontLength = this->CurrentFont->GetInfo().PSF2Font->Header->length; + char *FontPtr = FontAddress + FontHeaderSize + (Char > 0 && (uint32_t)Char < FontLength ? Char : 0) * FontCharSize; - uint32_t FontHdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width; - uint32_t FontHdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height; + uint32_t FontHdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width; + uint32_t FontHdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height; - for (size_t Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + FontHdrHeight; Y++) - { - for (size_t X = this->Buffers[Index].CursorX; X < this->Buffers[Index].CursorX + FontHdrWidth; X++) - { - if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index].CursorX))) > 0) - { - void *FramebufferAddress = (void *)((uintptr_t)this->Buffers[Index].Buffer + - (Y * this->Buffers[Index].Width + X) * - (this->framebuffer.BitsPerPixel / 8)); - *(uint32_t *)FramebufferAddress = this->Buffers[Index].Color; - } - } - FontPtr += BytesPerLine; - } - this->Buffers[Index].CursorX += FontHdrWidth; - break; - } - default: - warn("Unsupported font type"); - break; - } - return Char; - } + for (size_t Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + FontHdrHeight; Y++) + { + for (size_t X = this->Buffers[Index].CursorX; X < this->Buffers[Index].CursorX + FontHdrWidth; X++) + { + if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index].CursorX))) > 0) + { + void *FramebufferAddress = (void *)((uintptr_t)this->Buffers[Index].Buffer + + (Y * this->Buffers[Index].Width + X) * + (this->framebuffer.BitsPerPixel / 8)); + *(uint32_t *)FramebufferAddress = this->Buffers[Index].Color; + } + } + FontPtr += BytesPerLine; + } + this->Buffers[Index].CursorX += FontHdrWidth; + break; + } + default: + warn("Unsupported font type"); + break; + } + return Char; + } - void Display::DrawString(const char *String, uint32_t X, uint32_t Y, int Index, bool WriteToUART) - { - if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) - { - debug("Invalid buffer %d", Index); - return; - } + void Display::DrawString(const char *String, uint32_t X, uint32_t Y, int Index, bool WriteToUART) + { + if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E)) + { + debug("Invalid buffer %d", Index); + return; + } - this->Buffers[Index].CursorX = X; - this->Buffers[Index].CursorY = Y; + this->Buffers[Index].CursorX = X; + this->Buffers[Index].CursorY = Y; - for (int i = 0; String[i] != '\0'; i++) - this->Print(String[i], Index, WriteToUART); - } + for (int i = 0; String[i] != '\0'; i++) + this->Print(String[i], Index, WriteToUART); + } - Display::Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont) - { - this->framebuffer = Info; - if (LoadDefaultFont) - { - this->CurrentFont = new Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, FontType::PCScreenFont2); + Display::Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont) + { + this->framebuffer = Info; + if (LoadDefaultFont) + { + this->CurrentFont = new Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, FontType::PCScreenFont2); #ifdef DEBUG - FontInfo Info = this->CurrentFont->GetInfo(); - debug("Font loaded: %dx%d %s", - Info.Width, Info.Height, Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2"); + FontInfo Info = this->CurrentFont->GetInfo(); + debug("Font loaded: %dx%d %s", + Info.Width, Info.Height, + Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2"); #endif - } - this->CreateBuffer(Info.Width, Info.Height, 0); - } + } + this->CreateBuffer(Info.Width, Info.Height, 0); + } - Display::~Display() - { - debug("Destructor called"); - this->ClearBuffer(0); - this->SetBuffer(0); + Display::~Display() + { + debug("Destructor called"); + this->ClearBuffer(0); + this->SetBuffer(0); - for (int i = 0; i < s_cst(int, sizeof(this->Buffers) / sizeof(this->Buffers[0])); i++) - { - if (this->Buffers[i].Checksum == 0xBBFFE515A117E) - this->DeleteBuffer(i); - } - } + for (int i = 0; i < s_cst(int, sizeof(this->Buffers) / sizeof(this->Buffers[0])); i++) + { + if (this->Buffers[i].Checksum == 0xBBFFE515A117E) + this->DeleteBuffer(i); + } + } } diff --git a/Core/Video/Font.cpp b/Core/Video/Font.cpp index 20cd305..57a7c89 100644 --- a/Core/Video/Font.cpp +++ b/Core/Video/Font.cpp @@ -36,9 +36,11 @@ namespace Video PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(TO_PAGES(FontDataLength + 1)); memcpy((void *)font2, Start, FontDataLength); - Memory::Virtual().Map((void *)font2, (void *)font2, FontDataLength, Memory::PTFlag::RW); + Memory::Virtual().Map((void *)font2, (void *)font2, + FontDataLength, Memory::PTFlag::RW); - if (font2->magic[0] != PSF2_MAGIC0 || font2->magic[1] != PSF2_MAGIC1 || font2->magic[2] != PSF2_MAGIC2 || font2->magic[3] != PSF2_MAGIC3) + if (font2->magic[0] != PSF2_MAGIC0 || font2->magic[1] != PSF2_MAGIC1 || + font2->magic[2] != PSF2_MAGIC2 || font2->magic[3] != PSF2_MAGIC3) { error("Font2 magic mismatch."); KernelAllocator.FreePages((void *)font2, TO_PAGES(FontDataLength + 1)); @@ -46,7 +48,8 @@ namespace Video } this->Info.PSF2Font->Header = font2; - this->Info.PSF2Font->GlyphBuffer = reinterpret_cast(reinterpret_cast(Start) + sizeof(PSF2_HEADER)); + this->Info.PSF2Font->GlyphBuffer = + r_cst(void *, r_cst(uintptr_t, Start) + sizeof(PSF2_HEADER)); this->Info.Width = font2->width; this->Info.Height = font2->height; } @@ -59,7 +62,8 @@ namespace Video uint32_t glyphBufferSize = font1->charsize * 256; if (font1->mode == 1) // 512 glyph mode glyphBufferSize = font1->charsize * 512; - void *glyphBuffer = reinterpret_cast(reinterpret_cast(Start) + sizeof(PSF1_HEADER)); + void *glyphBuffer = + r_cst(void *, r_cst(uintptr_t, Start) + sizeof(PSF1_HEADER)); this->Info.PSF1Font->Header = font1; this->Info.PSF1Font->GlyphBuffer = glyphBuffer; UNUSED(glyphBufferSize); // TODO: Use this in the future? diff --git a/DAPI.hpp b/DAPI.hpp index f4b8c40..9ebc8e7 100644 --- a/DAPI.hpp +++ b/DAPI.hpp @@ -34,7 +34,7 @@ #define __FENNIX_DRIVER_API_H__ /** - * @brief The driver API is a set of functions that the kernel provides to the drivers. + * The driver API is a set of functions that the kernel provides to the drivers. * * - The driver is responsible for the memory management. * - The kernel will NOT free any memory allocated by the driver. On @see StopReason the driver must free all the memory it allocated and disable the hardware it uses. @@ -115,14 +115,14 @@ struct KernelAPI struct KAPIDriverTalk { - /** @brief Connects to the network manager */ + /** Connects to the network manager */ struct { void (*SendPacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size); void (*ReceivePacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size); } Network; - /** @brief Connects to the disk manager */ + /** Connects to the disk manager */ struct { struct @@ -144,24 +144,24 @@ struct KernelAPI enum CallbackReason { /** - * @brief This is used to detect memory corruption, not used. + * This is used to detect memory corruption, not used. */ UnknownReason, /** - * @brief This is called once the kernel is ready to use the driver and call @see ConfigurationReason . + * This is called once the kernel is ready to use the driver and call @see ConfigurationReason . */ AcknowledgeReason, /** - * @brief This is used after the driver is loaded and the kernel is ready to use the driver. + * This is used after the driver is loaded and the kernel is ready to use the driver. * * For PCI drivers, @see RawPtr will be the PCI device address. */ ConfigurationReason, /** - * @brief This is used when the kernel wants to stop the driver. + * This is used when the kernel wants to stop the driver. * * The memory allocated by the driver will be freed automatically. */ @@ -175,7 +175,7 @@ enum CallbackReason /* Driver callbacks for basic usage. */ /** - * @brief This is used when the kernel sends data. + * This is used when the kernel sends data. * * - Network * - Packet @@ -185,13 +185,13 @@ enum CallbackReason SendReason, /** - * @brief This is used when the kernel wants to receive data. + * This is used when the kernel wants to receive data. * Currently not used. */ ReceiveReason, /** - * @brief This is used to adjust driver settings. + * This is used to adjust driver settings. * * - Audio * - Volume @@ -200,7 +200,7 @@ enum CallbackReason AdjustReason, /** - * @brief This is used when the kernel wants to fetch information about the driver. + * This is used when the kernel wants to query information about the driver. * * - Input * - Mouse @@ -209,7 +209,19 @@ enum CallbackReason * - Keyboard * - Key */ - FetchReason, + QueryReason, + + /** + * This is used when the kernel wants to wait for an event. + * + * - Input + * - Mouse + * - Position + * - Buttons + * - Keyboard + * - Key + */ + PollWaitReason, }; union KernelCallback @@ -220,7 +232,7 @@ union KernelCallback void *RawPtr; unsigned long RawData; - /** @brief When the kernel wants to send a packet. */ + /** When the kernel wants to send a packet. */ struct { struct @@ -236,7 +248,7 @@ union KernelCallback } Fetch; } NetworkCallback; - /** @brief When the kernel wants to write to disk. */ + /** When the kernel wants to write to disk. */ struct { struct @@ -255,7 +267,7 @@ union KernelCallback } Fetch; } DiskCallback; - /** @brief When the kernel wants to get mouse position / keyboard key */ + /** When the kernel wants to get mouse position / keyboard key */ struct { struct @@ -270,6 +282,16 @@ union KernelCallback bool Middle; } Buttons; } Mouse; + + struct + { + /** + * The key. + * + * @note This is a scancode, not a character. + */ + unsigned char Key; + } Keyboard; } InputCallback; struct @@ -282,14 +304,14 @@ union KernelCallback bool _Channels; /** - * @brief Adjust the volume. + * Adjust the volume. * * 0 - 100 */ unsigned char Volume; /** - * @brief Adjust the encoding. + * Adjust the encoding. * * 0 - None, use default * @@ -330,7 +352,7 @@ union KernelCallback unsigned short Encoding; /** - * @brief Adjust the sample rate. + * Adjust the sample rate. * * 0 - 8000 Hz * 1 - 11025 Hz @@ -345,7 +367,7 @@ union KernelCallback unsigned char SampleRate; /** - * @brief Adjust the channels. + * Adjust the channels. * * 0 - Mono * 1 - Stereo diff --git a/Execute/BinaryParse.cpp b/Execute/BinaryParse.cpp deleted file mode 100644 index bfbf57d..0000000 --- a/Execute/BinaryParse.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include - -#include "../kernel.h" -#include "../Fex.hpp" - -namespace Execute -{ - BinaryType GetBinaryType(void *Image) - { - Fex *FexHdr = (Fex *)Image; - Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Image; - IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Image; - - /* Check Fex magic */ - if (FexHdr->Magic[0] == 'F' && - FexHdr->Magic[1] == 'E' && - FexHdr->Magic[2] == 'X' && - FexHdr->Magic[3] == '\0') - { - /* If the fex type is driver, we shouldn't return as Fex. */ - if (FexHdr->Type == FexFormatType::FexFormatType_Executable) - { - debug("Image - Fex"); - return BinaryType::BinTypeFex; - } - else if (FexHdr->Type == FexFormatType::FexFormatType_Driver) - { - debug("Fex Driver is not supposed to be executed."); - } - } - /* Check ELF magic. */ - else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 && - ELFHeader->e_ident[EI_MAG1] == ELFMAG1 && - ELFHeader->e_ident[EI_MAG2] == ELFMAG2 && - ELFHeader->e_ident[EI_MAG3] == ELFMAG3) - { - debug("Image - ELF"); - return BinaryType::BinTypeELF; - } - /* Every Windows executable starts with MZ header. */ - else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE) - { - IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Image) + MZHeader->e_lfanew); - IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Image) + MZHeader->e_lfanew); - - /* TODO: LE, EDOS */ - if (PEHeader->Signature == IMAGE_NT_SIGNATURE) - { - debug("Image - PE"); - return BinaryType::BinTypePE; - } - else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE) - { - debug("Image - NE"); - return BinaryType::BinTypeNE; - } - else - { - debug("Image - MZ"); - return BinaryType::BinTypeMZ; - } - } - - /* ... */ - return BinaryType::BinTypeUnknown; - } - - BinaryType GetBinaryType(char *Path) - { - BinaryType Type = BinaryType::BinTypeInvalid; - VirtualFileSystem::File ExFile = vfs->Open(Path); - - if (!ExFile.IsOK()) - { - vfs->Close(ExFile); - return Type; - } - - debug("File opened: %s", Path); - uint8_t *Buffer = new uint8_t[1024]; - vfs->Read(ExFile, Buffer, 128); - - Fex *FexHdr = (Fex *)Buffer; - Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Buffer; - IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Buffer; - - /* Check Fex header. */ - if (FexHdr->Magic[0] == 'F' && - FexHdr->Magic[1] == 'E' && - FexHdr->Magic[2] == 'X' && - FexHdr->Magic[3] == '\0') - { - /* If the fex type is driver, we shouldn't return as Fex. */ - if (FexHdr->Type == FexFormatType::FexFormatType_Executable) - { - debug("Image - Fex"); - Type = BinaryType::BinTypeFex; - goto Success; - } - else if (FexHdr->Type == FexFormatType::FexFormatType_Driver) - { - fixme("Fex Driver is not supposed to be executed."); - /* TODO: Driver installation pop-up. */ - } - } - /* Check ELF header. */ - else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 && - ELFHeader->e_ident[EI_MAG1] == ELFMAG1 && - ELFHeader->e_ident[EI_MAG2] == ELFMAG2 && - ELFHeader->e_ident[EI_MAG3] == ELFMAG3) - { - debug("Image - ELF"); - Type = BinaryType::BinTypeELF; - goto Success; - } - /* Check MZ header. */ - else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE) - { - vfs->Seek(ExFile, MZHeader->e_lfanew, SEEK_SET); - vfs->Read(ExFile, Buffer, 512); - IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Buffer) + MZHeader->e_lfanew); - IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Buffer) + MZHeader->e_lfanew); - - /* TODO: LE, EDOS */ - if (PEHeader->Signature == IMAGE_NT_SIGNATURE) - { - debug("Image - PE"); - Type = BinaryType::BinTypePE; - goto Success; - } - else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE) - { - debug("Image - NE"); - Type = BinaryType::BinTypeNE; - goto Success; - } - else - { - debug("Image - MZ"); - Type = BinaryType::BinTypeMZ; - goto Success; - } - } - - /* ... */ - Type = BinaryType::BinTypeUnknown; - Success: - delete[] Buffer; - vfs->Close(ExFile); - return Type; - } -} diff --git a/Execute/Elf/ElfBaseLoad.cpp b/Execute/Elf/ElfBaseLoad.cpp deleted file mode 100644 index ebccd4c..0000000 --- a/Execute/Elf/ElfBaseLoad.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#include "../../kernel.h" -#include "../../Fex.hpp" - -using namespace Tasking; -using VirtualFileSystem::File; -using VirtualFileSystem::FileStatus; -using VirtualFileSystem::NodeFlags; - -namespace Execute -{ - ELFBaseLoad ELFLoad(char *Path, - const char **argv, const char **envp, - TaskCompatibility Compatibility) - { - const char *BaseName; - cwk_path_get_basename(Path, &BaseName, nullptr); - TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture; - - File ExFile = vfs->Open(Path); - - if (ExFile.Status != FileStatus::OK) - { - vfs->Close(ExFile); - error("Failed to open file: %s", Path); - return {}; - } - else if (ExFile.GetFlags() != NodeFlags::FILE) - { - vfs->Close(ExFile); - error("Invalid file path: %s", Path); - return {}; - } - else if (GetBinaryType(Path) != BinaryType::BinTypeELF) - { - vfs->Close(ExFile); - error("Invalid file type: %s", Path); - return {}; - } - - size_t ExFileSize = ExFile.GetLength(); - - void *ElfFile = KernelAllocator.RequestPages(TO_PAGES(ExFileSize + 1)); - vfs->Read(ExFile, (uint8_t *)ElfFile, ExFileSize); - debug("Loaded elf %s at %#lx with the length of %ld", - Path, ElfFile, ExFileSize); - - Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)ElfFile; - - switch (ELFHeader->e_machine) - { - case EM_386: - Arch = TaskArchitecture::x32; - break; - case EM_X86_64: - Arch = TaskArchitecture::x64; - break; - case EM_ARM: - Arch = TaskArchitecture::ARM32; - break; - case EM_AARCH64: - Arch = TaskArchitecture::ARM64; - break; - default: - break; - } - - // TODO: This shouldn't be ignored - if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32) - fixme("32-bit ELF"); - else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64) - fixme("64-bit ELF"); - else - fixme("Unknown class %d", ELFHeader->e_ident[EI_CLASS]); - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - if (ELFHeader->e_ident[EI_DATA] != ELFDATA2LSB) - { - fixme("ELF32 LSB expected, got %d", ELFHeader->e_ident[EI_DATA]); - } -#else - if (ELFHeader->e_ident[EI_DATA] != ELFDATA2MSB) - { - fixme("ELF32 MSB expected, got %d", ELFHeader->e_ident[EI_DATA]); - } -#endif - - /* ------------------------------------------------------------------------------------------------------------------------------ */ - - PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), - BaseName, TaskTrustLevel::User, ElfFile); - Process->SetWorkingDirectory(vfs->GetNodeFromPath(Path)->Parent); - Process->Info.Compatibility = TaskCompatibility::Native; - Process->Info.Architecture = TaskArchitecture::x64; - - ELFBaseLoad bl; - - ELFObject *obj = new ELFObject(Path, Process); - if (!obj->IsValid()) - { - error("Failed to load ELF object"); - vfs->Close(ExFile); - TaskManager->RevertProcessCreation(Process); - return {}; - } - - bl = obj->GetBaseLoadInfo(); - - /* TODO: Keep only the necessary headers */ - Memory::Virtual vmm = Memory::Virtual(Process->PageTable); - for (size_t i = 0; i < TO_PAGES(ExFileSize); i++) - { - void *AddressToMap = (void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)); - vmm.Remap(AddressToMap, AddressToMap, Memory::RW | Memory::US); - } - - if (bl.Interpreter) - { - debug("Keeping ElfFile at %p", ElfFile); - - TCB *InterIPCThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), - (IP)ELFInterpreterIPCThread, - nullptr, - nullptr, - std::vector(), - TaskArchitecture::x64, - TaskCompatibility::Native, - true); - - std::vector *tmp_needed_libs = - new std::vector(bl.NeededLibraries); - - InterIPCThread->SYSV_ABI_Call((uintptr_t)Process, - (uintptr_t) new std::string(Path), - (uintptr_t)bl.VirtualMemoryImage, - (uintptr_t)tmp_needed_libs); - - InterIPCThread->Rename("ELF Interpreter IPC Thread"); - InterIPCThread->SetPriority(TaskPriority::Low); - InterIPCThread->Status = TaskStatus::Ready; - } - - TCB *Thread = TaskManager->CreateThread(Process, - bl.InstructionPointer, - argv, envp, bl.auxv, - Arch, - Compatibility); - - foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList()) - { - Thread->Memory->Add(p.Address, p.PageCount); - bl.TmpMem->DetachAddress(p.Address); - } - delete bl.TmpMem, bl.TmpMem = nullptr; - - bl.sd.Process = Process; - bl.sd.Thread = Thread; - bl.sd.Status = ExStatus::OK; - vfs->Close(ExFile); - return bl; - } -} diff --git a/Execute/Elf/ElfInterpreter.cpp b/Execute/Elf/ElfInterpreter.cpp deleted file mode 100644 index 0dbe4bd..0000000 --- a/Execute/Elf/ElfInterpreter.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include -#include - -#include "../../kernel.h" - -using namespace Tasking; - -namespace Execute -{ - struct InterpreterIPCDataLibrary - { - char Name[64]; - }; - - typedef struct - { - char Path[256]; - void *MemoryImage; - struct InterpreterIPCDataLibrary Libraries[64]; - } InterpreterIPCData; - - void ELFInterpreterIPCThread(PCB *TargetProcess, - std::string *TargetPath, - void *MemoryImage, - std::vector *_NeededLibraries) - { - std::vector NeededLibraries = *_NeededLibraries; - delete _NeededLibraries; - - debug("Interpreter thread started for %s", TargetPath->c_str()); - // Interpreter will create an IPC with token "LOAD". - char UniqueToken[16] = {'L', 'O', 'A', 'D', '\0'}; - InterProcessCommunication::IPCHandle *Handle = nullptr; - while (Handle == nullptr) - { - debug("Searching for IPC with token %s", UniqueToken); - Handle = TargetProcess->IPC->SearchByToken(UniqueToken); - if (Handle == nullptr) - debug("Failed"); - - TaskManager->Sleep(200); - if (Handle == nullptr) - debug("Retrying..."); - } - debug("IPC found, sending data..."); - InterpreterIPCData *TmpBuffer = new InterpreterIPCData; - strncpy(TmpBuffer->Path, TargetPath->c_str(), sizeof(TmpBuffer->Path) - 1); - TmpBuffer->MemoryImage = MemoryImage; - size_t NeededLibsSize = NeededLibraries.size(); - - for (size_t i = 0; i < NeededLibsSize; i++) - strncpy(TmpBuffer->Libraries[i].Name, NeededLibraries[i], - sizeof(TmpBuffer->Libraries[i].Name) - 1); - -#ifdef DEBUG - debug("Input:"); - debug("Path: %s", TargetPath->c_str()); - debug("MemoryImage: %p", MemoryImage); - for (size_t i = 0; i < NeededLibsSize; i++) - debug("Library: %s", NeededLibraries[i]); - - debug("Buffer:"); - debug("Path: %s", TmpBuffer->Path); - debug("MemoryImage: %p", TmpBuffer->MemoryImage); - for (size_t i = 0; i < 64; i++) - { - if (TmpBuffer->Libraries[i].Name[0] != '\0') - break; - debug("Library: %s", TmpBuffer->Libraries[i].Name); - } -#endif - - RetryIPCWrite: - InterProcessCommunication::IPCErrorCode ret = - TargetProcess->IPC->Write(Handle->ID, TmpBuffer, sizeof(InterpreterIPCData)); - debug("Write returned %d", ret); - if (ret == InterProcessCommunication::IPCErrorCode::IPCNotListening) - { - debug("IPC not listening, retrying..."); - TaskManager->Sleep(100); - goto RetryIPCWrite; - } - delete TmpBuffer; - - while (!TargetProcess->IPC->SearchByToken(UniqueToken)) - TaskManager->Schedule(); - - debug("Interpreter thread finished for %s", TargetPath->c_str()); - - for (size_t i = 0; i < NeededLibsSize; i++) - delete[] NeededLibraries[i]; - - delete TargetPath; - TEXIT(0); - } - - uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &vmm, const char *Interpreter) - { - if (GetBinaryType((char *)Interpreter) != BinaryType::BinTypeELF) - { - error("Interpreter \"%s\" is not an ELF file.", Interpreter); - return 0; - } - - /* No need to check if it's valid because - the function that calls this already checks it. */ - VirtualFileSystem::File ElfFile = vfs->Open(Interpreter); - - Elf64_Ehdr ELFHeader; - vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); - debug("Interpreter type: %#x", ELFHeader.e_type); - - uintptr_t BaseAddress; - size_t ElfPHDRsSize; - - GetBaseAndSize(ElfFile, BaseAddress, ElfPHDRsSize); - MmImage MemoryImage = ELFCreateMemoryImage(mem, vmm, ElfFile, ElfPHDRsSize); - CopyLOADSegments(ElfFile, BaseAddress, (uintptr_t)MemoryImage.Physical); - vfs->Close(ElfFile); - - bool IsPIC = ELFHeader.e_type == ET_DYN; - debug("Elf %s PIC", IsPIC ? "is" : "is not"); - - if (IsPIC) - { - debug("Interpreter entry point: %#lx (%#lx + %#lx)", - (uintptr_t)MemoryImage.Physical + ELFHeader.e_entry, - (uintptr_t)MemoryImage.Physical, ELFHeader.e_entry); - - return (uintptr_t)MemoryImage.Physical + ELFHeader.e_entry; - } - else - { - debug("Interpreter entry point: %#lx", ELFHeader.e_entry); - return ELFHeader.e_entry; - } - } -} diff --git a/Execute/Elf/ElfLoader.cpp b/Execute/Elf/ElfLoader.cpp deleted file mode 100644 index 26badcb..0000000 --- a/Execute/Elf/ElfLoader.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#include "../../kernel.h" -#include "../../Fex.hpp" - -using namespace Tasking; -using namespace VirtualFileSystem; - -namespace Execute -{ - ELFBaseLoad ELFObject::LoadExec_x86_32(File &ElfFile, PCB *TargetProcess) - { - stub; - return {}; - } - - ELFBaseLoad ELFObject::LoadExec_x86_64(File &ElfFile, PCB *TargetProcess) - { - ELFBaseLoad ELFBase{}; - - uintptr_t BaseAddress; - size_t ElfPHDRsSize; - GetBaseAndSize(ElfFile, BaseAddress, ElfPHDRsSize); - - Elf64_Ehdr ELFHeader; - vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); - uintptr_t EntryPoint = ELFHeader.e_entry; - debug("%s's entry point is %#lx", ElfFile.Name, EntryPoint); - - ELFBase.TmpMem = new Memory::MemMgr(TargetProcess->PageTable); /* This should be deleted inside BaseLoad.cpp */ - Memory::Virtual vmm(TargetProcess->PageTable); - - /* If required, MemoryImage will be at virtual address. (unless is PIC) - tl;dr this is where the code is stored. */ - MmImage MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, vmm, ElfFile, ElfPHDRsSize); - - debug("Solving symbols for %s", ElfFile.Name); - std::vector DynamicString = ELFGetSections_x86_64(ElfFile, ".dynstr"); - std::vector StringTable = ELFGetSections_x86_64(ElfFile, ".strtab"); - - if (DynamicString.size() < 1) /* TODO: check if this is required */ - DynamicString = StringTable; - - /* Calculate entry point */ - Elf64_Phdr FirstPhdr; - vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&FirstPhdr, sizeof(Elf64_Phdr)); - /* FIXME: this is not the correct way to calculate entry point */ - if (FirstPhdr.p_vaddr == 0) - { - debug("Entry point is null. Adding virtual address to entry point"); - EntryPoint += (uintptr_t)MemoryImage.Virtual; - } - - CopyLOADSegments(ElfFile, BaseAddress, (uintptr_t)MemoryImage.Physical); - - foreach (auto Tag in ELFGetDynamicTag_x86_64(ElfFile, DT_NEEDED)) - { - const char *ReqLib = new char[256]; - vfs->Seek(ElfFile, DynamicString[0].sh_offset + Tag.d_un.d_val, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)ReqLib, 256); - - debug("DT_NEEDED - %s", ReqLib); - ELFBase.NeededLibraries.push_back(ReqLib); - } - - char InterpreterPath[256] = {'\0'}; - std::vector PhdrINTERP = ELFGetSymbolType_x86_64(ElfFile, PT_INTERP); - foreach (auto Interp in PhdrINTERP) - { - const char *InterpPath = new char[256]; - vfs->Seek(ElfFile, Interp.p_offset, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)InterpPath, 256); - - memcpy((void *)InterpreterPath, InterpPath, - (strlen(InterpPath) > 256) ? 256 : strlen(InterpPath)); - debug("Interpreter: %s", InterpreterPath); - delete[] InterpPath; - - VirtualFileSystem::File InterpreterFile = vfs->Open(InterpreterPath); - if (!InterpreterFile.IsOK()) - { - warn("Failed to open interpreter file: %s", InterpreterPath); - vfs->Close(InterpreterFile); - continue; - } - else - { - if (GetBinaryType(InterpreterPath) != BinTypeELF) - { - warn("Interpreter %s is not an ELF file", InterpreterPath); - vfs->Close(InterpreterFile); - continue; - } - vfs->Close(InterpreterFile); - break; - } - } - - if (strlen(InterpreterPath) > 1) - { - EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, vmm, InterpreterPath); - ELFBase.Interpreter = true; - } - - debug("Entry Point: %#lx", EntryPoint); - - char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true); /* TODO: 4096 bytes is too much for this */ - strcpy(aux_platform, "x86_64"); - - ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)0 /* FIXME */}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage.Virtual}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader.e_phoff}}}); - - ELFBase.InstructionPointer = EntryPoint; - ELFBase.MemoryImage = MemoryImage.Physical; - ELFBase.VirtualMemoryImage = MemoryImage.Virtual; - - ELFBase.Success = true; - return ELFBase; - } - - ELFBaseLoad ELFObject::LoadDyn_x86_32(File &ElfFile, PCB *TargetProcess, bool IsLibrary) - { - stub; - return {}; - } - - ELFBaseLoad ELFObject::LoadDyn_x86_64(File &ElfFile, PCB *TargetProcess, bool IsLibrary) - { - ELFBaseLoad ELFBase{}; - - uintptr_t BaseAddress; - size_t ElfPHDRsSize; - GetBaseAndSize(ElfFile, BaseAddress, ElfPHDRsSize); - - Elf64_Ehdr ELFHeader; - vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); - uintptr_t EntryPoint = ELFHeader.e_entry; - debug("%s's entry point is %#lx", ElfFile.Name, EntryPoint); - - ELFBase.TmpMem = new Memory::MemMgr(TargetProcess->PageTable); /* This should be deleted inside BaseLoad.cpp */ - Memory::Virtual vmm(TargetProcess->PageTable); - - /* If required, MemoryImage will be at virtual address. (unless is PIC) - tl;dr this is where the code is stored. */ - MmImage MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, vmm, ElfFile, ElfPHDRsSize); - - debug("Solving symbols for %s", ElfFile.Name); - std::vector DynamicString = ELFGetSections_x86_64(ElfFile, ".dynstr"); - std::vector StringTable = ELFGetSections_x86_64(ElfFile, ".strtab"); - - if (DynamicString.size() < 1) /* TODO: check if this is required */ - DynamicString = StringTable; - - /* Calculate entry point */ - Elf64_Phdr FirstPhdr; - vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&FirstPhdr, sizeof(Elf64_Phdr)); - /* FIXME: this is not the correct way to calculate entry point */ - if (FirstPhdr.p_vaddr == 0) - { - debug("Entry point is null. Adding virtual address to entry point"); - EntryPoint += (uintptr_t)MemoryImage.Virtual; - } - - CopyLOADSegments(ElfFile, BaseAddress, (uintptr_t)MemoryImage.Physical); - - foreach (auto Tag in ELFGetDynamicTag_x86_64(ElfFile, DT_NEEDED)) - { - const char *ReqLib = new char[256]; - vfs->Seek(ElfFile, DynamicString[0].sh_offset + Tag.d_un.d_val, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)ReqLib, 256); - - debug("DT_NEEDED - %s", ReqLib); - ELFBase.NeededLibraries.push_back(ReqLib); - } - - std::vector JmpRel = ELFGetDynamicTag_x86_64(ElfFile, DT_JMPREL); - std::vector SymTab = ELFGetDynamicTag_x86_64(ElfFile, DT_SYMTAB); - std::vector StrTab = ELFGetDynamicTag_x86_64(ElfFile, DT_STRTAB); - - if (JmpRel.size() < 1) - { - debug("No DT_JMPREL"); - } - - if (SymTab.size() < 1) - { - debug("No DT_SYMTAB"); - } - - if (StrTab.size() < 1) - { - debug("No DT_STRTAB"); - } - - if (JmpRel.size() > 1 && - SymTab.size() > 1 && - StrTab.size() > 1) - { - debug("JmpRel: %#lx, SymTab: %#lx, StrTab: %#lx", JmpRel[0].d_un.d_ptr, SymTab[0].d_un.d_ptr, StrTab[0].d_un.d_ptr); - Elf64_Rela *_JmpRel = (Elf64_Rela *)((uintptr_t)MemoryImage.Physical + (JmpRel[0].d_un.d_ptr - BaseAddress)); - Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)MemoryImage.Physical + (SymTab[0].d_un.d_ptr - BaseAddress)); - - char *_DynStr = (char *)((uintptr_t)MemoryImage.Physical + (StrTab[0].d_un.d_ptr - BaseAddress)); - - Elf64_Shdr *gotSection = nullptr; - Elf64_Shdr shdr; - for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++) - { - vfs->Seek(ElfFile, ELFHeader.e_shoff + i * sizeof(Elf64_Shdr), SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&shdr, sizeof(Elf64_Shdr)); - if (shdr.sh_type == SHT_PROGBITS && - (shdr.sh_flags & SHF_WRITE) && - (shdr.sh_flags & SHF_ALLOC)) - { - gotSection = new Elf64_Shdr; - *gotSection = shdr; - break; - } - } - - if (gotSection) - { - Elf64_Xword numEntries = gotSection->sh_size / sizeof(Elf64_Addr); - for (Elf64_Xword i = 0; i < numEntries - 3; i++) - { - Elf64_Rela *Rel = _JmpRel + i; - Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset + (uintptr_t)MemoryImage.Physical); - - Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info); - debug("r_offset: %#lx RelType: %d", Rel->r_offset, RelType); - - switch (RelType) - { - case R_X86_64_NONE: - break; - case R_X86_64_JUMP_SLOT: - { - Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info); - Elf64_Sym *Sym = _SymTab + SymIndex; - - if (Sym->st_name) - { - char *SymName = _DynStr + Sym->st_name; - debug("SymName: %s", SymName); - - Elf64_Sym LibSym = ELFLookupSymbol(ElfFile, SymName); - - if (LibSym.st_value) - { - *GOTEntry = (Elf64_Addr)((uintptr_t)MemoryImage.Physical + LibSym.st_value); - debug("GOT[%ld]: %#lx + %#lx = %#lx", - i, (uintptr_t)MemoryImage.Physical, LibSym.st_value, *GOTEntry); - } - } - break; - } - default: - { - fixme("RelType %d not supported", RelType); - break; - } - } - - debug("GOT[%ld](%#lx): %#lx", i, GOTEntry, *GOTEntry); - } - - delete gotSection; - } - else - { - debug("GOT section not found"); - } - } - - /* ------------------------------------------------------------------------ */ - - foreach (auto Tag in ELFGetDynamicTag_x86_64(ElfFile, DT_NEEDED)) - { - const char *ReqLib = new char[256]; - vfs->Seek(ElfFile, DynamicString[0].sh_offset + Tag.d_un.d_val, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)ReqLib, 256); - - debug("DT_NEEDED - %s", ReqLib); - ELFBase.NeededLibraries.push_back(ReqLib); - } - - char InterpreterPath[256] = {'\0'}; - std::vector PhdrINTERP = ELFGetSymbolType_x86_64(ElfFile, PT_INTERP); - foreach (auto Interp in PhdrINTERP) - { - const char *InterpPath = new char[256]; - vfs->Seek(ElfFile, Interp.p_offset, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)InterpPath, 256); - - memcpy((void *)InterpreterPath, InterpPath, - (strlen(InterpPath) > 256) ? 256 : strlen(InterpPath)); - debug("Interpreter: %s", InterpreterPath); - delete[] InterpPath; - - VirtualFileSystem::File InterpreterFile = vfs->Open(InterpreterPath); - if (!InterpreterFile.IsOK()) - { - warn("Failed to open interpreter file: %s", InterpreterPath); - vfs->Close(InterpreterFile); - continue; - } - else - { - if (GetBinaryType(InterpreterPath) != BinTypeELF) - { - warn("Interpreter %s is not an ELF file", InterpreterPath); - vfs->Close(InterpreterFile); - continue; - } - vfs->Close(InterpreterFile); - break; - } - } - - if (strlen(InterpreterPath) > 1) - { - EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, vmm, InterpreterPath); - ELFBase.Interpreter = true; - } - else if (IsLibrary) - { - /* FIXME: Detect interpreter from current running process. */ - EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, vmm, "/lib/ld.so"); - ELFBase.Interpreter = true; - } - - debug("Entry Point: %#lx", EntryPoint); - - char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true); /* TODO: 4096 bytes is too much for this */ - strcpy(aux_platform, "x86_64"); - - ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)0 /* FIXME */}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage.Virtual}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}}); - ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader.e_phoff}}}); - - ELFBase.InstructionPointer = EntryPoint; - ELFBase.MemoryImage = MemoryImage.Physical; - ELFBase.VirtualMemoryImage = MemoryImage.Virtual; - - ELFBase.Success = true; - return ELFBase; - } - - ELFObject::ELFObject(char *AbsolutePath, - PCB *TargetProcess, - bool IsLibrary) - { - if (GetBinaryType(AbsolutePath) != BinaryType::BinTypeELF) - { - error("%s is not an ELF file or is invalid.", AbsolutePath); - return; - } - - VirtualFileSystem::File ExFile = vfs->Open(AbsolutePath); - - Elf32_Ehdr ELFHeader; - vfs->Read(ExFile, (uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr)); - - ELFBaseLoad bl; - switch (ELFHeader.e_type) - { - case ET_REL: - { - fixme("ET_REL not implemented"); - break; - } - case ET_EXEC: - { - switch (ELFHeader.e_machine) - { - case EM_386: - this->BaseLoadInfo = this->LoadExec_x86_32(ExFile, - TargetProcess); - break; - case EM_X86_64: - this->BaseLoadInfo = this->LoadExec_x86_64(ExFile, - TargetProcess); - break; - case EM_ARM: - error("ARM is not supported yet!"); - break; - case EM_AARCH64: - error("ARM64 is not supported yet!"); - break; - default: - error("Unknown architecture: %d", ELFHeader.e_machine); - break; - } - break; - } - case ET_DYN: - { - switch (ELFHeader.e_machine) - { - case EM_386: - this->BaseLoadInfo = this->LoadDyn_x86_32(ExFile, - TargetProcess, - IsLibrary); - break; - case EM_X86_64: - this->BaseLoadInfo = this->LoadDyn_x86_64(ExFile, - TargetProcess, - IsLibrary); - break; - case EM_ARM: - error("ARM is not supported yet!"); - break; - case EM_AARCH64: - error("ARM64 is not supported yet!"); - break; - default: - error("Unknown architecture: %d", ELFHeader.e_machine); - break; - } - break; - } - case ET_CORE: - { - fixme("ET_CORE not implemented"); - break; - } - case ET_NONE: - default: - { - error("Unknown ELF Type: %d", ELFHeader.e_type); - break; - } - } - - vfs->Close(ExFile); - } - - ELFObject::~ELFObject() - { - } -} diff --git a/Execute/Elf/ElfParse.cpp b/Execute/Elf/ElfParse.cpp deleted file mode 100644 index 7858ad5..0000000 --- a/Execute/Elf/ElfParse.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include - -#include "../../kernel.h" -#include "../../Fex.hpp" - -namespace Execute -{ - bool ELFIs64(void *Header) - { - Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Header; - if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64) - return true; - return false; - } - - /* Originally from https://wiki.osdev.org/ELF_Tutorial */ - - Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header) - { - return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff); - } - - Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index) - { - return &GetELFSheader(Header)[Index]; - } - - char *GetELFStringTable(Elf64_Ehdr *Header) - { - if (Header->e_shstrndx == SHN_UNDEF) - return nullptr; - return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset; - } - - char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset) - { - char *StringTable = GetELFStringTable(Header); - if (StringTable == nullptr) - return nullptr; - return StringTable + Offset; - } - - Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name) - { - Elf64_Shdr *SymbolTable = nullptr; - Elf64_Shdr *StringTable = nullptr; - - for (Elf64_Half i = 0; i < Header->e_shnum; i++) - { - Elf64_Shdr *shdr = GetELFSection(Header, i); - switch (shdr->sh_type) - { - case SHT_SYMTAB: - SymbolTable = shdr; - StringTable = GetELFSection(Header, shdr->sh_link); - break; - default: - { - break; - } - } - } - - if (SymbolTable == nullptr || StringTable == nullptr) - return nullptr; - - for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++) - { - Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym))); - char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name); - if (strcmp(String, Name) == 0) - return Symbol; - } - return nullptr; - } - - Elf64_Sym ELFLookupSymbol(VirtualFileSystem::File &ElfFile, const char *Name) - { - off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); - - Elf64_Ehdr Header; - vfs->Seek(ElfFile, 0, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&Header, sizeof(Elf64_Ehdr)); - - Elf64_Shdr SymbolTable; - Elf64_Shdr StringTable; - - for (Elf64_Half i = 0; i < Header.e_shnum; i++) - { - Elf64_Shdr shdr; - vfs->Seek(ElfFile, Header.e_shoff + (i * sizeof(Elf64_Shdr)), SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&shdr, sizeof(Elf64_Shdr)); - - switch (shdr.sh_type) - { - case SHT_SYMTAB: - SymbolTable = shdr; - vfs->Seek(ElfFile, Header.e_shoff + (shdr.sh_link * sizeof(Elf64_Shdr)), SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&StringTable, sizeof(Elf64_Shdr)); - break; - default: - { - break; - } - } - } - - if (SymbolTable.sh_name == 0 || - StringTable.sh_name == 0) - { - error("Symbol table not found."); - vfs->Seek(ElfFile, OldOffset, SEEK_SET); - return {}; - } - - for (size_t i = 0; i < (SymbolTable.sh_size / sizeof(Elf64_Sym)); i++) - { - // Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym))); - Elf64_Sym Symbol; - vfs->Seek(ElfFile, SymbolTable.sh_offset + (i * sizeof(Elf64_Sym)), SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&Symbol, sizeof(Elf64_Sym)); - - // char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name); - char String[256]; - vfs->Seek(ElfFile, StringTable.sh_offset + Symbol.st_name, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&String, 256); - - if (strcmp(String, Name) == 0) - { - vfs->Seek(ElfFile, OldOffset, SEEK_SET); - return Symbol; - } - } - error("Symbol not found."); - vfs->Seek(ElfFile, OldOffset, SEEK_SET); - return {}; - } - - uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index) - { -#if defined(a64) - if (Table == SHN_UNDEF || Index == SHN_UNDEF) - return 0; - Elf64_Shdr *SymbolTable = GetELFSection(Header, Table); - - uint64_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize; - if (Index >= STEntries) - { - error("Symbol index out of range %d-%u.", Table, Index); - return 0xdead; - } - - uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset; - Elf64_Sym *Symbol = &((Elf64_Sym *)SymbolAddress)[Index]; - - if (Symbol->st_shndx == SHN_UNDEF) - { - Elf64_Shdr *StringTable = GetELFSection(Header, SymbolTable->sh_link); - const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name; - - void *Target = (void *)ELFLookupSymbol(Header, Name)->st_value; - if (Target == nullptr) - { - if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK) - return 0; - else - { - error("Undefined external symbol \"%s\".", Name); - return 0xdead; - } - } - else - return (uintptr_t)Target; - } - else if (Symbol->st_shndx == SHN_ABS) - return Symbol->st_value; - else - { - Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx); - return (uintptr_t)Header + Symbol->st_value + Target->sh_offset; - } -#endif - } - - void CopyLOADSegments(VirtualFileSystem::File &ElfFile, uintptr_t HdrsBase, uintptr_t PhysicalBase) - { - off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); - - Elf64_Ehdr ELFHeader; - vfs->Seek(ElfFile, 0, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); - - Elf64_Phdr ProgramHeaders; - for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) - { - vfs->Seek(ElfFile, ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); - if (ProgramHeaders.p_type != PT_LOAD) - continue; - - uintptr_t SegmentDestination = (ProgramHeaders.p_vaddr - HdrsBase) + PhysicalBase; - - debug("Copying segment to %#lx (%ld file bytes, %ld mem bytes)", - SegmentDestination, - ProgramHeaders.p_filesz, ProgramHeaders.p_memsz); - - if (ProgramHeaders.p_filesz > 0) - { - vfs->Seek(ElfFile, ProgramHeaders.p_offset, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)SegmentDestination, ProgramHeaders.p_filesz); - } - - if (ProgramHeaders.p_memsz - ProgramHeaders.p_filesz > 0) - memset((void *)(SegmentDestination + ProgramHeaders.p_filesz), - 0, - ProgramHeaders.p_memsz - ProgramHeaders.p_filesz); - } - - vfs->Seek(ElfFile, OldOffset, SEEK_SET); - } - - void GetBaseAndSize(VirtualFileSystem::File &ElfFile, uintptr_t &Base, size_t &Size) - { - Base = UINTPTR_MAX; - Size = 0; - - off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); - - Elf64_Ehdr ELFHeader; - vfs->Seek(ElfFile, 0, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); - - Elf64_Phdr ProgramHeaders; - vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); - - for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) - { - Base = MIN(Base, ProgramHeaders.p_vaddr); - uintptr_t SegmentEnd = ProgramHeaders.p_vaddr - Base + ProgramHeaders.p_memsz; - Size = MAX(Size, SegmentEnd); - - vfs->Seek(ElfFile, sizeof(Elf64_Phdr), SEEK_CUR); - vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); - } - debug("Base: %#lx, Size: %#lx (%ld, %ld KB)", Base, Size, Size, TO_KB(Size)); - vfs->Seek(ElfFile, OldOffset, SEEK_SET); - } - - MmImage ELFCreateMemoryImage(Memory::MemMgr *mem, - Memory::Virtual &vmm, - VirtualFileSystem::File &ElfFile, - size_t Length) - { - off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); - - void *MemoryImage = nullptr; - Elf64_Ehdr ELFHeader; - vfs->Seek(ElfFile, 0, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); - - bool IsPIC = ELFHeader.e_type == ET_DYN; - UNUSED(IsPIC); - debug("Elf %s PIC", IsPIC ? "is" : "is not"); - - bool FirstProgramHeader = false; - uintptr_t FirstProgramHeaderVirtualAddress = 0x0; - - Elf64_Phdr ProgramHeaders; - for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) - { - vfs->Seek(ElfFile, ELFHeader.e_phoff + i * sizeof(Elf64_Phdr), SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); - if (ProgramHeaders.p_type != PT_LOAD) - continue; - - if (!FirstProgramHeader) - { - FirstProgramHeader = true; - FirstProgramHeaderVirtualAddress = ProgramHeaders.p_vaddr; - } - - if (ProgramHeaders.p_vaddr == 0) - { - debug("p_vaddr is 0, allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length); - MemoryImage = mem->RequestPages(TO_PAGES(Length), true); - debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length); - memset(MemoryImage, 0, Length); - - vfs->Seek(ElfFile, OldOffset, SEEK_SET); - return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress}; - } - } - - debug("Allocating %ld pages for image (size: %#lx)", TO_PAGES(Length), Length); - MemoryImage = mem->RequestPages(TO_PAGES(Length)); - debug("MemoryImage: %#lx-%#lx", MemoryImage, (uintptr_t)MemoryImage + Length); - memset(MemoryImage, 0, Length); - - uintptr_t FirstProgramHeaderVirtualAddressAligned = 0; - - if (FirstProgramHeaderVirtualAddress != 0) - { - FirstProgramHeaderVirtualAddressAligned = ALIGN_DOWN(FirstProgramHeaderVirtualAddress, PAGE_SIZE); - debug("Aligning address %#lx to %#lx", - FirstProgramHeaderVirtualAddress, - FirstProgramHeaderVirtualAddressAligned); - } - else - FirstProgramHeaderVirtualAddress = (uintptr_t)MemoryImage; - - for (size_t i = 0; i < TO_PAGES(Length); i++) - { - vmm.Remap((void *)((uintptr_t)FirstProgramHeaderVirtualAddressAligned + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); - debug("Remapped: %#lx -> %#lx", (uintptr_t)FirstProgramHeaderVirtualAddressAligned + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE)); - } - - vfs->Seek(ElfFile, OldOffset, SEEK_SET); - return {MemoryImage, (void *)FirstProgramHeaderVirtualAddress}; - } -} diff --git a/Execute/Elf/ElfSharedObjects.cpp b/Execute/Elf/ElfSharedObjects.cpp deleted file mode 100644 index 516d26c..0000000 --- a/Execute/Elf/ElfSharedObjects.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#ifdef DEBUG -#include -#endif - -#include "../../kernel.h" -#include "../../Fex.hpp" - -using namespace Tasking; - -NewLock(ExecuteServiceLock); - -namespace Execute -{ - Memory::MemMgr *mem = nullptr; - std::vector Libs; - - void LibraryManagerService() - { - mem = new Memory::MemMgr; - - while (true) - { - { - SmartLock(ExecuteServiceLock); - foreach (auto &Lib in Libs) - { - if (Lib.RefCount > 0) - { - Lib.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes); - debug("Reset timeout for %s", Lib.Identifier); - continue; - } - if (Lib.Timeout < TimeManager->GetCounter()) - { - // TODO: Remove library from memory - fixme("Removed library %s because of timeout", Lib.Identifier); - } - else - { - debug("Timeout for %s is %ld", Lib.Identifier, Lib.Timeout); - } - } - debug("Waiting 10 seconds..."); - } - TaskManager->Sleep(10000); - } - } - - bool AddLibrary(char *Identifier, - VirtualFileSystem::File &ExFile, - const Memory::Virtual &vmm) - { - SmartLock(ExecuteServiceLock); - SharedLibrary sl; - - foreach (auto lib in Libs) - { - if (strcmp(lib.Identifier, Identifier) == 0) - { - debug("Library %s already loaded", Identifier); - lib.RefCount++; - return true; - } - } - - PCB *Process = TaskManager->GetCurrentProcess(); - ELFObject *obj = new ELFObject(vfs->GetPathFromNode(ExFile.GetNode()).get(), Process, true); - if (!obj->IsValid()) - { - error("Failed to load dynamic ELF"); - return false; - } - ELFBaseLoad bl = obj->GetBaseLoadInfo(); - - strncpy(sl.Identifier, Identifier, sizeof(sl.Identifier) - 1); - char *AbsolutePath = vfs->GetPathFromNode(ExFile.GetNode()).get(); - strncpy(sl.Path, AbsolutePath, sizeof(sl.Path) - 1); - sl.Timeout = TimeManager->CalculateTarget(10, Time::Units::Minutes); - sl.RefCount = 0; - sl.MemoryImage = (uintptr_t)bl.MemoryImage; - sl.Length = ExFile.GetLength(); - Libs.push_back(sl); - debug("Library %s loaded at %#lx", Identifier, sl.MemoryImage); - - if (bl.InstructionPointer) - { - TCB *Thread = TaskManager->CreateThread(Process, - bl.InstructionPointer, - nullptr, - nullptr, - bl.auxv, - Process->Info.Architecture, - Process->Info.Compatibility, - true); - Thread->Rename(Identifier); - Thread->Status = TaskStatus::Ready; - - foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList()) - { - Thread->Memory->Add(p.Address, p.PageCount); - bl.TmpMem->DetachAddress(p.Address); - } - } - else - { - foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList()) - { - /* FIXME: MEMORY LEAK */ - // Process->Memory->Add(p.Address, p.PageCount); - bl.TmpMem->DetachAddress(p.Address); - fixme("Potential memory leak. (%#lx - %ld)", - p.Address, p.PageCount); - } - } - return true; - } - - SharedLibrary GetLibrary(char *Identifier) - { - SmartLock(ExecuteServiceLock); - foreach (auto Lib in Libs) - { - if (strcmp(Lib.Identifier, Identifier) == 0) - { - Lib.RefCount++; - debug("Library %s found at %#lx", Identifier, Lib.MemoryImage); - return Lib; - } - } - error("Library %s not found", Identifier); - return SharedLibrary(); - } -} diff --git a/Execute/Spawn.cpp b/Execute/Spawn.cpp deleted file mode 100644 index e33fa14..0000000 --- a/Execute/Spawn.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include -#include - -#include "../kernel.h" -#include "../Fex.hpp" - -using namespace Tasking; - -namespace Execute -{ - SpawnData Spawn(char *Path, const char **argv, const char **envp) - { - SpawnData ret = {.Status = ExStatus::Unknown, - .Process = nullptr, - .Thread = nullptr}; - - VirtualFileSystem::File ExFile = vfs->Open(Path); - - if (!ExFile.IsOK()) - { - if (ExFile.Status == VirtualFileSystem::FileStatus::NotFound) - { - ret.Status = ExStatus::InvalidFilePath; - goto Exit; - } - else - { - ret.Status = ExStatus::InvalidFile; - goto Exit; - } - - if (ExFile.GetFlags() != VirtualFileSystem::NodeFlags::FILE) - { - ret.Status = ExStatus::InvalidFilePath; - goto Exit; - } - } - - switch (GetBinaryType(Path)) - { - case BinaryType::BinTypeFex: - { - Fex FexHdr; - vfs->Read(ExFile, (uint8_t *)&FexHdr, sizeof(Fex)); - if (FexHdr.Type == FexFormatType::FexFormatType_Executable) - { - stub; - assert(false); - } - - ret.Status = ExStatus::InvalidFileHeader; - break; - } - case BinaryType::BinTypeELF: - { - ELFBaseLoad bl = ELFLoad(Path, argv, envp); - if (!bl.Success) - { - ret.Status = ExStatus::LoadingProcedureFailed; - break; - } - ret = bl.sd; - break; - } - default: - { - ret.Status = ExStatus::Unsupported; - break; - } - } - - Exit: - vfs->Close(ExFile); - return ret; - } -} diff --git a/ExecutionLayer/BinaryParse.cpp b/ExecutionLayer/BinaryParse.cpp new file mode 100644 index 0000000..730f9f2 --- /dev/null +++ b/ExecutionLayer/BinaryParse.cpp @@ -0,0 +1,115 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include + +#include "../kernel.h" +#include "../Fex.hpp" + +namespace Execute +{ + BinaryType GetBinaryType(const char *Path) + { + BinaryType Type; + int fd = fopen(Path, "r"); + + if (fd < 0) + return (BinaryType)fd; + + debug("File opened: %s, descriptor %d", Path, fd); + Memory::SmartHeap sh = Memory::SmartHeap(1024); + fread(fd, sh, 128); + + Fex *FexHdr = (Fex *)sh.GetObject(); + Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)sh.GetObject(); + IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)sh.GetObject(); + + /* Check Fex header. */ + if (FexHdr->Magic[0] == 'F' && + FexHdr->Magic[1] == 'E' && + FexHdr->Magic[2] == 'X' && + FexHdr->Magic[3] == '\0') + { + /* If the fex type is driver, we shouldn't return as Fex. */ + if (FexHdr->Type == FexFormatType_Executable) + { + debug("Image - Fex"); + Type = BinaryType::BinTypeFex; + goto Success; + } + else if (FexHdr->Type == FexFormatType_Driver) + { + fixme("Fex Driver is not supposed to be executed."); + /* TODO: Driver installation pop-up. */ + } + } + + /* Check ELF header. */ + else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 && + ELFHeader->e_ident[EI_MAG1] == ELFMAG1 && + ELFHeader->e_ident[EI_MAG2] == ELFMAG2 && + ELFHeader->e_ident[EI_MAG3] == ELFMAG3) + { + debug("Image - ELF"); + Type = BinaryType::BinTypeELF; + goto Success; + } + + /* Check MZ header. */ + else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE) + { + lseek(fd, MZHeader->e_lfanew, SEEK_SET); + fread(fd, sh, 512); + IMAGE_NT_HEADERS *PEHeader = + (IMAGE_NT_HEADERS *)(((char *)sh.GetObject()) + + MZHeader->e_lfanew); + + IMAGE_OS2_HEADER *NEHeader = + (IMAGE_OS2_HEADER *)(((char *)sh.GetObject()) + + MZHeader->e_lfanew); + + /* TODO: LE, EDOS */ + if (PEHeader->Signature == IMAGE_NT_SIGNATURE) + { + debug("Image - PE"); + Type = BinaryType::BinTypePE; + goto Success; + } + else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE) + { + debug("Image - NE"); + Type = BinaryType::BinTypeNE; + goto Success; + } + else + { + debug("Image - MZ"); + Type = BinaryType::BinTypeMZ; + goto Success; + } + } + + /* ... */ + + Type = BinaryType::BinTypeUnknown; + Success: + fclose(fd); + return Type; + } +} diff --git a/ExecutionLayer/Elf/ElfLoader.cpp b/ExecutionLayer/Elf/ElfLoader.cpp new file mode 100644 index 0000000..3f2c0d6 --- /dev/null +++ b/ExecutionLayer/Elf/ElfLoader.cpp @@ -0,0 +1,791 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../../kernel.h" +#include "../../Fex.hpp" + +using namespace Tasking; +using namespace VirtualFileSystem; + +namespace Execute +{ + void ELFObject::LoadExec_x86_32(int fd, PCB *TargetProcess) + { + stub; + UNUSED(fd); + UNUSED(TargetProcess); + } + + void ELFObject::LoadExec_x86_64(int fd, PCB *TargetProcess) + { + std::string InterpreterPath; + std::vector PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP); + foreach (auto Interp in PhdrINTERP) + { + Memory::SmartHeap sh = Memory::SmartHeap(256); + lseek(fd, Interp.p_offset, SEEK_SET); + fread(fd, sh, 256); + InterpreterPath = sh; + + int ifd = fopen(InterpreterPath.c_str(), "r"); + if (ifd < 0) + { + warn("Failed to open interpreter file: %s", + InterpreterPath.c_str()); + continue; + } + else + { + if (GetBinaryType(InterpreterPath.c_str()) != BinTypeELF) + { + warn("Interpreter %s is not an ELF file", + InterpreterPath.c_str()); + fclose(ifd); + continue; + } + + if (LoadInterpreter(ifd, TargetProcess)) + { + /* ba deci de aici trb sa fac + sa se incarce interperter-ul + argv[1] ar trb sa fie locatia pt intrep */ + + // modific argv-ul + + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + + debug("Interpreter loaded successfully"); + fclose(ifd); + return; + } + } + } + + Elf64_Ehdr ELFHeader; + fread(fd, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + uintptr_t EntryPoint = ELFHeader.e_entry; + debug("Entry point is %#lx", EntryPoint); + + debug("Solving symbols"); + std::vector DynamicString = ELFGetSections_x86_64(fd, ".dynstr"); + std::vector StringTable = ELFGetSections_x86_64(fd, ".strtab"); + + if (DynamicString.size() < 1) /* TODO: check if this is required */ + DynamicString = StringTable; + + Memory::Virtual vmm = Memory::Virtual(TargetProcess->PageTable); + Memory::MemMgr *mm = TargetProcess->Memory; + uint64_t BaseAddress = 0; + + /* Copy segments into memory */ + { + Elf64_Phdr ProgramHeader; + for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) + { + lseek(fd, ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET); + fread(fd, (uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr)); + switch (ProgramHeader.p_type) + { + case PT_LOAD: + { + if (ProgramHeader.p_memsz == 0) + continue; + + void *pAddr = mm->RequestPages(TO_PAGES(ProgramHeader.p_memsz), true); + void *SegmentDestination = (void *)ProgramHeader.p_vaddr; + + vmm.Map(SegmentDestination, pAddr, + ProgramHeader.p_memsz, + Memory::P | Memory::RW | Memory::US); + + debug("Mapped %#lx to %#lx", SegmentDestination, pAddr); + + if (BaseAddress == 0) + BaseAddress = (uintptr_t)SegmentDestination; + + debug("Copying segment to p: %#lx-%#lx; v: %#lx-%#lx (%ld file bytes, %ld mem bytes)", + pAddr, uintptr_t(pAddr) + ProgramHeader.p_memsz, + SegmentDestination, uintptr_t(SegmentDestination) + ProgramHeader.p_memsz, + ProgramHeader.p_filesz, ProgramHeader.p_memsz); + + if (ProgramHeader.p_filesz > 0) + { + lseek(fd, ProgramHeader.p_offset, SEEK_SET); + fread(fd, (uint8_t *)pAddr, ProgramHeader.p_filesz); + } + + if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0) + { + void *zAddr = (void *)(uintptr_t(pAddr) + ProgramHeader.p_filesz); + memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz); + } + break; + } + default: + { + fixme("Unhandled program header type: %#lx", + ProgramHeader.p_type); + break; + } + } + } + } + + struct stat statbuf; + fstat(fd, &statbuf); + Memory::SmartHeap sh = Memory::SmartHeap(statbuf.st_size); + lseek(fd, 0, SEEK_SET); + fread(fd, sh, statbuf.st_size); + TargetProcess->ELFSymbolTable->AppendSymbols(uintptr_t(sh.GetObject())); + + debug("Entry Point: %#lx", EntryPoint); + + char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */ + strcpy(aux_platform, "x86_64"); + + std::string execfn = thisProcess->FileDescriptors->GetAbsolutePath(fd); + void *execfn_str = mm->RequestPages(TO_PAGES(execfn.size() + 1), true); + strcpy((char *)execfn_str, execfn.c_str()); + + // prep. for AT_PHDR + void *phdr_array = mm->RequestPages(TO_PAGES(ELFHeader.e_phnum * sizeof(Elf64_Phdr)), true); + lseek(fd, ELFHeader.e_phoff, SEEK_SET); + fread(fd, (uint8_t *)phdr_array, ELFHeader.e_phnum * sizeof(Elf64_Phdr)); + + Elfauxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)execfn_str}}}); + // AT_HWCAP2 26 + // AT_RANDOM 25 + // AT_SECURE 23 + Elfauxv.push_back({.archaux = {.a_type = AT_EGID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_GID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_EUID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_UID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); + // AT_FLAGS 8 + Elfauxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)BaseAddress}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}}); + // AT_CLKTCK 17 + Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); + // AT_HWCAP 16 + // AT_MINSIGSTKSZ 51 + // AT_SYSINFO_EHDR 33 + + this->ip = EntryPoint; + this->IsElfValid = true; + } + + void ELFObject::LoadDyn_x86_32(int fd, PCB *TargetProcess) + { + stub; + UNUSED(fd); + UNUSED(TargetProcess); + } + + void ELFObject::LoadDyn_x86_64(int fd, PCB *TargetProcess) + { + std::string InterpreterPath; + std::vector PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP); + foreach (auto Interp in PhdrINTERP) + { + Memory::SmartHeap sh = Memory::SmartHeap(256); + lseek(fd, Interp.p_offset, SEEK_SET); + fread(fd, sh, 256); + InterpreterPath = sh; + + int ifd = fopen(InterpreterPath.c_str(), "r"); + if (ifd < 0) + { + warn("Failed to open interpreter file: %s", + InterpreterPath.c_str()); + continue; + } + else + { + if (GetBinaryType(InterpreterPath.c_str()) != BinTypeELF) + { + warn("Interpreter %s is not an ELF file", + InterpreterPath.c_str()); + fclose(ifd); + continue; + } + + if (LoadInterpreter(ifd, TargetProcess)) + { + /* ba deci de aici trb sa fac + sa se incarce interperter-ul + argv[1] ar trb sa fie locatia pt intrep */ + + // modific argv-ul + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + // TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME + + debug("Interpreter loaded successfully"); + fclose(ifd); + return; + } + } + } + + Elf64_Ehdr ELFHeader; + fread(fd, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + uintptr_t EntryPoint = ELFHeader.e_entry; + debug("Entry point is %#lx", EntryPoint); + + debug("Solving symbols"); + std::vector DynamicString = ELFGetSections_x86_64(fd, ".dynstr"); + std::vector StringTable = ELFGetSections_x86_64(fd, ".strtab"); + + if (DynamicString.size() < 1) /* TODO: check if this is required */ + DynamicString = StringTable; + + Memory::Virtual vmm = Memory::Virtual(TargetProcess->PageTable); + Memory::MemMgr *mm = TargetProcess->Memory; + uintptr_t BaseAddress = 0; + + /* Copy segments into memory */ + { + Elf64_Phdr ProgramHeader; + std::size_t SegmentsSize = 0; + for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) + { + lseek(fd, ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET); + fread(fd, (uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr)); + + if (ProgramHeader.p_type == PT_LOAD || + ProgramHeader.p_type == PT_DYNAMIC) + SegmentsSize += ProgramHeader.p_memsz; + } + + /* TODO: Check if this is correct and/or it needs more + complex calculations & allocations */ + void *SegmentsAddress = mm->RequestPages(TO_PAGES(SegmentsSize) + 1, true); + BaseAddress = (uintptr_t)SegmentsAddress; + debug("BaseAddress: %#lx, End: %#lx", BaseAddress, + BaseAddress + FROM_PAGES(TO_PAGES(SegmentsSize))); + + for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) + { + lseek(fd, ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET); + fread(fd, (uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr)); + + switch (ProgramHeader.p_type) + { + case PT_LOAD: + { + /* Because this is ET_DYN, we can load the segments + anywhere we want. */ + uintptr_t SegmentDestination = BaseAddress + ProgramHeader.p_vaddr; + + if (ProgramHeader.p_memsz == 0) + continue; + + debug("PIC: %#lx + %#lx", + BaseAddress, + ProgramHeader.p_vaddr); + + debug("Copying segment to %#lx-%#lx (%ld file bytes, %ld mem bytes)", + SegmentDestination, SegmentDestination + ProgramHeader.p_memsz, + ProgramHeader.p_filesz, ProgramHeader.p_memsz); + + if (ProgramHeader.p_filesz > 0) + { + lseek(fd, ProgramHeader.p_offset, SEEK_SET); + fread(fd, (uint8_t *)SegmentDestination, ProgramHeader.p_filesz); + } + + if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0) + { + void *zAddr = (void *)(SegmentDestination + ProgramHeader.p_filesz); + memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz); + } + break; + } + case PT_DYNAMIC: + { + /* PT_DYNAMIC contains the dynamic linking information for the + executable or shared library. */ + + uintptr_t DynamicSegmentDestination = BaseAddress + ProgramHeader.p_vaddr; + + if (ProgramHeader.p_memsz == 0) + continue; + + debug("Copying PT_DYNAMIC segment to %#lx-%#lx (%ld file bytes, %ld mem bytes)", + DynamicSegmentDestination, DynamicSegmentDestination + ProgramHeader.p_memsz, + ProgramHeader.p_filesz, ProgramHeader.p_memsz); + + if (ProgramHeader.p_filesz > 0) + { + lseek(fd, ProgramHeader.p_offset, SEEK_SET); + fread(fd, (uint8_t *)DynamicSegmentDestination, ProgramHeader.p_filesz); + } + + if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0) + { + void *zAddr = (void *)(DynamicSegmentDestination + ProgramHeader.p_filesz); + memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz); + } + break; + } + default: + { + fixme("Unhandled program header type: %#lx", + ProgramHeader.p_type); + break; + } + } + } + } + + EntryPoint += BaseAddress; + debug("The new ep is %#lx", EntryPoint); + + std::vector JmpRel = ELFGetDynamicTag_x86_64(fd, DT_JMPREL); + std::vector SymTab = ELFGetDynamicTag_x86_64(fd, DT_SYMTAB); + std::vector StrTab = ELFGetDynamicTag_x86_64(fd, DT_STRTAB); + std::vector RelaDyn = ELFGetDynamicTag_x86_64(fd, DT_RELA); + std::vector RelaDynSize = ELFGetDynamicTag_x86_64(fd, DT_RELASZ); + std::vector PltGot = ELFGetDynamicTag_x86_64(fd, DT_PLTGOT); + + std::size_t JmpRelSize = JmpRel.size(); + std::size_t SymTabSize = SymTab.size(); + std::size_t StrTabSize = StrTab.size(); + std::size_t RelaDynSize_v = RelaDyn.size(); + std::size_t PltGotSize = PltGot.size(); + + if (JmpRelSize < 1) + debug("No DT_JMPREL"); + + if (SymTabSize < 1) + debug("No DT_SYMTAB"); + + if (StrTabSize < 1) + debug("No DT_STRTAB"); + + if (RelaDynSize_v < 1) + debug("No DT_RELA"); + + if (RelaDynSize[0].d_un.d_val < 1) + debug("DT_RELASZ is < 1"); + + if (PltGotSize < 1) + debug("No DT_PLTGOT"); + + if (JmpRelSize > 0 && SymTabSize > 0 && StrTabSize > 0) + { + debug("JmpRel: %#lx, SymTab: %#lx, StrTab: %#lx", + JmpRel[0].d_un.d_ptr, SymTab[0].d_un.d_ptr, StrTab[0].d_un.d_ptr); + + Elf64_Rela *_JmpRel = (Elf64_Rela *)((uintptr_t)BaseAddress + JmpRel[0].d_un.d_ptr); + Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr); + char *_DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr); + Elf64_Rela *_RelaDyn = (Elf64_Rela *)((uintptr_t)BaseAddress + RelaDyn[0].d_un.d_ptr); + + Elf64_Shdr *gotSection = nullptr; + Elf64_Shdr shdr; + for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++) + { + lseek(fd, ELFHeader.e_shoff + i * sizeof(Elf64_Shdr), SEEK_SET); + fread(fd, (uint8_t *)&shdr, sizeof(Elf64_Shdr)); + if (shdr.sh_type == SHT_PROGBITS && + (shdr.sh_flags & SHF_WRITE) && + (shdr.sh_flags & SHF_ALLOC)) + { + gotSection = new Elf64_Shdr; + *gotSection = shdr; + debug("Found GOT section"); + break; + } + } + + if (gotSection) + { + // .rela.plt + // R_X86_64_JUMP_SLOT + Elf64_Xword numEntries = gotSection->sh_size / sizeof(Elf64_Addr); + for (Elf64_Xword i = 0; i < numEntries; i++) + { + Elf64_Addr *GOTEntry = (Elf64_Addr *)(gotSection->sh_addr + BaseAddress + i * sizeof(Elf64_Addr)); + Elf64_Addr GOTEntryValue = *GOTEntry; + + if (GOTEntryValue == 0) + continue; + + Elf64_Rela *Rel = _JmpRel + i; + Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info); + + switch (RelType) + { + case R_X86_64_JUMP_SLOT: + { + Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info); + Elf64_Sym *Sym = _SymTab + SymIndex; + + if (Sym->st_name) + { + char *SymName = _DynStr + Sym->st_name; + debug("SymName: %s", SymName); + + Elf64_Sym LibSym = ELFLookupSymbol(fd, SymName); + if (LibSym.st_value) + { + *GOTEntry = (Elf64_Addr)(BaseAddress + LibSym.st_value); + debug("GOT[%ld](%#lx): %#lx", + i, uintptr_t(GOTEntry) - BaseAddress, + *GOTEntry); + } + } + continue; + } + default: + { + fixme("Unhandled relocation type: %#lx", RelType); + break; + } + } + } + + // .rela.dyn + // R_X86_64_RELATIVE + // R_X86_64_GLOB_DAT + if (RelaDynSize_v > 0 && RelaDynSize[0].d_un.d_val > 0) + { + Elf64_Xword numRelaDynEntries = RelaDynSize[0].d_un.d_val / sizeof(Elf64_Rela); + for (Elf64_Xword i = 0; i < numRelaDynEntries; i++) + { + Elf64_Rela *Rel = _RelaDyn + i; + Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset + BaseAddress); + Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info); + + switch (RelType) + { + case R_X86_64_RELATIVE: + { + *GOTEntry = (Elf64_Addr)(BaseAddress + Rel->r_addend); + debug("GOT[%ld](%#lx): %#lx (R_X86_64_RELATIVE)", + i, uintptr_t(GOTEntry) - BaseAddress, + *GOTEntry); + break; + } + case R_X86_64_GLOB_DAT: + { + Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info); + Elf64_Sym *Sym = _SymTab + SymIndex; + + if (Sym->st_name) + { + char *SymName = _DynStr + Sym->st_name; + debug("SymName: %s", SymName); + + Elf64_Sym LibSym = ELFLookupSymbol(fd, SymName); + if (LibSym.st_value) + { + *GOTEntry = (Elf64_Addr)(BaseAddress + LibSym.st_value); + debug("GOT[%ld](%#lx): %#lx (R_X86_64_GLOB_DAT)", + i, uintptr_t(GOTEntry) - BaseAddress, + *GOTEntry); + } + } + break; + } + default: + { + fixme("Unhandled relocation type: %#lx", RelType); + break; + } + } + } + } + + // _GLOBAL_OFFSET_TABLE_ + if (PltGotSize > 0) + { + Elf64_Dyn got = PltGot[0]; + Elf64_Addr *GOTEntry = (Elf64_Addr *)(got.d_un.d_ptr + BaseAddress); + // *GOTEntry = (Elf64_Addr)(BaseAddress + PltGot[0].d_un.d_val); + + std::vector DYNAMICPhdrs = ELFGetSymbolType_x86_64(fd, PT_DYNAMIC); + if (DYNAMICPhdrs.size() > 0) + *GOTEntry = (Elf64_Addr)(BaseAddress + DYNAMICPhdrs[0].p_vaddr); + } + + delete gotSection; + } + else + { + debug("GOT section not found"); + } + } + + /* ------------------------------------------------------------------------ */ + + struct stat statbuf; + fstat(fd, &statbuf); + Memory::SmartHeap sh = Memory::SmartHeap(statbuf.st_size); + lseek(fd, 0, SEEK_SET); + fread(fd, sh, statbuf.st_size); + TargetProcess->ELFSymbolTable->AppendSymbols(uintptr_t(sh.GetObject()), BaseAddress); + + debug("Entry Point: %#lx", EntryPoint); + + char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */ + strcpy(aux_platform, "x86_64"); + + std::string execfn = thisProcess->FileDescriptors->GetAbsolutePath(fd); + void *execfn_str = mm->RequestPages(TO_PAGES(execfn.size() + 1), true); + strcpy((char *)execfn_str, execfn.c_str()); + + // prep. for AT_PHDR + void *phdr_array = mm->RequestPages(TO_PAGES(ELFHeader.e_phnum * sizeof(Elf64_Phdr)), true); + lseek(fd, ELFHeader.e_phoff, SEEK_SET); + fread(fd, (uint8_t *)phdr_array, ELFHeader.e_phnum * sizeof(Elf64_Phdr)); + + Elfauxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)execfn_str}}}); + // AT_HWCAP2 26 + // AT_RANDOM 25 + // AT_SECURE 23 + Elfauxv.push_back({.archaux = {.a_type = AT_EGID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_GID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_EUID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_UID, .a_un = {.a_val = (uint64_t)0}}}); /* FIXME */ + Elfauxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}}); + // AT_FLAGS 8 + Elfauxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)BaseAddress}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader.e_phnum}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader.e_phentsize}}}); + Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}}); + // AT_CLKTCK 17 + Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); + // AT_HWCAP 16 + // AT_MINSIGSTKSZ 51 + // AT_SYSINFO_EHDR 33 + + this->ip = EntryPoint; + this->IsElfValid = true; + } + + bool ELFObject::LoadInterpreter(int fd, PCB *TargetProcess) + { + Elf32_Ehdr ELFHeader; + fread(fd, &ELFHeader, sizeof(Elf32_Ehdr)); + + switch (ELFHeader.e_type) + { + case ET_REL: + { + fixme("ET_REL not implemented"); + break; + } + case ET_EXEC: + { + switch (ELFHeader.e_machine) + { + case EM_386: + this->LoadExec_x86_32(fd, TargetProcess); + return true; + case EM_X86_64: + this->LoadExec_x86_64(fd, TargetProcess); + return true; + case EM_ARM: + error("ARM is not supported yet!"); + break; + case EM_AARCH64: + error("ARM64 is not supported yet!"); + break; + default: + error("Unknown architecture: %d", ELFHeader.e_machine); + break; + } + break; + } + case ET_DYN: + { + switch (ELFHeader.e_machine) + { + case EM_386: + this->LoadDyn_x86_32(fd, TargetProcess); + return true; + case EM_X86_64: + this->LoadDyn_x86_64(fd, TargetProcess); + return true; + case EM_ARM: + error("ARM is not supported yet!"); + break; + case EM_AARCH64: + error("ARM64 is not supported yet!"); + break; + default: + error("Unknown architecture: %d", ELFHeader.e_machine); + break; + } + break; + } + case ET_CORE: + { + fixme("ET_CORE not implemented"); + break; + } + case ET_NONE: + default: + { + error("Unknown ELF Type: %d", ELFHeader.e_type); + break; + } + } + return false; + } + + ELFObject::ELFObject(char *AbsolutePath, + PCB *TargetProcess, + const char **argv, + const char **envp) + { + if (GetBinaryType(AbsolutePath) != BinaryType::BinTypeELF) + { + error("%s is not an ELF file or is invalid.", AbsolutePath); + return; + } + + int fd = fopen(AbsolutePath, "r"); + if (fd < 0) + { + error("Failed to open %s, errno: %d", AbsolutePath, fd); + return; + } + + int argc = 0; + int envc = 0; + + while (argv[argc] != nullptr) + argc++; + while (envp[envc] != nullptr) + envc++; + + // ELFargv = new const char *[argc + 2]; + std::size_t argv_size = TO_PAGES(argc + 2 * sizeof(char *)); + ELFargv = (const char **)TargetProcess->Memory->RequestPages(argv_size); + for (int i = 0; i < argc; i++) + ELFargv[i] = argv[i]; + ELFargv[argc] = nullptr; + + // ELFenvp = new const char *[envc + 1]; + std::size_t envp_size = TO_PAGES(envc + 1 * sizeof(char *)); + ELFenvp = (const char **)TargetProcess->Memory->RequestPages(envp_size); + for (int i = 0; i < envc; i++) + ELFenvp[i] = envp[i]; + ELFenvp[envc] = nullptr; + + Elf32_Ehdr ELFHeader; + fread(fd, &ELFHeader, sizeof(Elf32_Ehdr)); + + switch (ELFHeader.e_type) + { + case ET_REL: + { + fixme("ET_REL not implemented"); + break; + } + case ET_EXEC: + { + switch (ELFHeader.e_machine) + { + case EM_386: + this->LoadExec_x86_32(fd, TargetProcess); + break; + case EM_X86_64: + this->LoadExec_x86_64(fd, TargetProcess); + break; + case EM_ARM: + error("ARM is not supported yet!"); + break; + case EM_AARCH64: + error("ARM64 is not supported yet!"); + break; + default: + error("Unknown architecture: %d", ELFHeader.e_machine); + break; + } + break; + } + case ET_DYN: + { + switch (ELFHeader.e_machine) + { + case EM_386: + this->LoadDyn_x86_32(fd, TargetProcess); + break; + case EM_X86_64: + this->LoadDyn_x86_64(fd, TargetProcess); + break; + case EM_ARM: + error("ARM is not supported yet!"); + break; + case EM_AARCH64: + error("ARM64 is not supported yet!"); + break; + default: + error("Unknown architecture: %d", ELFHeader.e_machine); + break; + } + break; + } + case ET_CORE: + { + fixme("ET_CORE not implemented"); + break; + } + case ET_NONE: + default: + { + error("Unknown ELF Type: %d", ELFHeader.e_type); + break; + } + } + + fclose(fd); + } + + ELFObject::~ELFObject() + { + } +} diff --git a/ExecutionLayer/Elf/ElfParse.cpp b/ExecutionLayer/Elf/ElfParse.cpp new file mode 100644 index 0000000..b176d11 --- /dev/null +++ b/ExecutionLayer/Elf/ElfParse.cpp @@ -0,0 +1,203 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include + +#include "../../kernel.h" +#include "../../Fex.hpp" + +namespace Execute +{ + bool ELFIs64(void *Header) + { + Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)Header; + if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64) + return true; + return false; + } + + /* Originally from https://wiki.osdev.org/ELF_Tutorial */ + + Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header) + { + return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff); + } + + Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index) + { + return &GetELFSheader(Header)[Index]; + } + + char *GetELFStringTable(Elf64_Ehdr *Header) + { + if (Header->e_shstrndx == SHN_UNDEF) + return nullptr; + return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset; + } + + char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset) + { + char *StringTable = GetELFStringTable(Header); + if (StringTable == nullptr) + return nullptr; + return StringTable + Offset; + } + + Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name) + { + Elf64_Shdr *SymbolTable = nullptr; + Elf64_Shdr *StringTable = nullptr; + + for (Elf64_Half i = 0; i < Header->e_shnum; i++) + { + Elf64_Shdr *shdr = GetELFSection(Header, i); + switch (shdr->sh_type) + { + case SHT_SYMTAB: + SymbolTable = shdr; + StringTable = GetELFSection(Header, shdr->sh_link); + break; + default: + { + break; + } + } + } + + if (SymbolTable == nullptr || StringTable == nullptr) + return nullptr; + + for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++) + { + Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym))); + char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name); + if (strcmp(String, Name) == 0) + return Symbol; + } + return nullptr; + } + + Elf64_Sym ELFLookupSymbol(int fd, const char *Name) + { + off_t OldOffset = lseek(fd, 0, SEEK_CUR); + + Elf64_Ehdr Header; + lseek(fd, 0, SEEK_SET); + fread(fd, (uint8_t *)&Header, sizeof(Elf64_Ehdr)); + + Elf64_Shdr SymbolTable; + Elf64_Shdr StringTable; + + for (Elf64_Half i = 0; i < Header.e_shnum; i++) + { + Elf64_Shdr shdr; + lseek(fd, Header.e_shoff + (i * sizeof(Elf64_Shdr)), SEEK_SET); + fread(fd, (uint8_t *)&shdr, sizeof(Elf64_Shdr)); + + switch (shdr.sh_type) + { + case SHT_SYMTAB: + SymbolTable = shdr; + lseek(fd, Header.e_shoff + (shdr.sh_link * sizeof(Elf64_Shdr)), SEEK_SET); + fread(fd, (uint8_t *)&StringTable, sizeof(Elf64_Shdr)); + break; + default: + { + break; + } + } + } + + if (SymbolTable.sh_name == 0 || + StringTable.sh_name == 0) + { + error("Symbol table not found."); + lseek(fd, OldOffset, SEEK_SET); + return {}; + } + + for (size_t i = 0; i < (SymbolTable.sh_size / sizeof(Elf64_Sym)); i++) + { + // Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym))); + Elf64_Sym Symbol; + lseek(fd, SymbolTable.sh_offset + (i * sizeof(Elf64_Sym)), SEEK_SET); + fread(fd, (uint8_t *)&Symbol, sizeof(Elf64_Sym)); + + // char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name); + char String[256]; + lseek(fd, StringTable.sh_offset + Symbol.st_name, SEEK_SET); + fread(fd, (uint8_t *)&String, 256); + + if (strcmp(String, Name) == 0) + { + lseek(fd, OldOffset, SEEK_SET); + return Symbol; + } + } + error("Symbol not found."); + lseek(fd, OldOffset, SEEK_SET); + return {}; + } + + uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index) + { +#if defined(a64) + if (Table == SHN_UNDEF || Index == SHN_UNDEF) + return 0; + Elf64_Shdr *SymbolTable = GetELFSection(Header, Table); + + uint64_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize; + if (Index >= STEntries) + { + error("Symbol index out of range %d-%u.", Table, Index); + return 0xdead; + } + + uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset; + Elf64_Sym *Symbol = &((Elf64_Sym *)SymbolAddress)[Index]; + + if (Symbol->st_shndx == SHN_UNDEF) + { + Elf64_Shdr *StringTable = GetELFSection(Header, SymbolTable->sh_link); + const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name; + + void *Target = (void *)ELFLookupSymbol(Header, Name)->st_value; + if (Target == nullptr) + { + if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK) + return 0; + else + { + error("Undefined external symbol \"%s\".", Name); + return 0xdead; + } + } + else + return (uintptr_t)Target; + } + else if (Symbol->st_shndx == SHN_ABS) + return Symbol->st_value; + else + { + Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx); + return (uintptr_t)Header + Symbol->st_value + Target->sh_offset; + } +#endif + } +} diff --git a/Execute/Elf/ElfRel.cpp b/ExecutionLayer/Elf/ElfRel.cpp similarity index 87% rename from Execute/Elf/ElfRel.cpp rename to ExecutionLayer/Elf/ElfRel.cpp index 52b2377..dbfab36 100644 --- a/Execute/Elf/ElfRel.cpp +++ b/ExecutionLayer/Elf/ElfRel.cpp @@ -26,7 +26,7 @@ namespace Execute { /* Originally from https://wiki.osdev.org/ELF_Tutorial */ - ELFBaseLoad ELFLoadRel(void *BaseImage, + void ELFLoadRel(void *BaseImage, const char *Name, Tasking::PCB *Process) { @@ -35,11 +35,6 @@ namespace Execute debug("Relocatable"); /* TODO: I have to fully implement this, but for now I will leave it as it is now. */ warn("Relocatable ELF is not fully supported yet"); - /* This should be deleted after with kfree */ - ELFBaseLoad ELFBase = {}; - /* This should be deleted inside BaseLoad.cpp */ - ELFBase.TmpMem = new Memory::MemMgr(Process->PageTable); - Elf64_Shdr *shdr = GetELFSheader(((Elf64_Ehdr *)BaseImage)); for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++) { @@ -78,10 +73,7 @@ namespace Execute { SymbolValue = ELFGetSymbolValue(((Elf64_Ehdr *)BaseImage), Section->sh_link, ELF64_R_SYM(RelTable->r_info)); if (SymbolValue == 0xdead) - { - delete ELFBase.TmpMem, ELFBase.TmpMem = nullptr; - return {}; - } + return; } switch (ELF64_R_TYPE(RelTable->r_info)) @@ -97,17 +89,14 @@ namespace Execute default: { error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info)); - delete ELFBase.TmpMem, ELFBase.TmpMem = nullptr; - return {}; + return; } } debug("Symbol value: %#lx", SymbolValue); } } } - return ELFBase; #elif defined(a32) - return {}; #endif } } diff --git a/Execute/Elf/ParseFunctions/ELFGetDynamicTag.cpp b/ExecutionLayer/Elf/ParseFunctions/ELFGetDynamicTag.cpp similarity index 72% rename from Execute/Elf/ParseFunctions/ELFGetDynamicTag.cpp rename to ExecutionLayer/Elf/ParseFunctions/ELFGetDynamicTag.cpp index f3800b9..e386b60 100644 --- a/Execute/Elf/ParseFunctions/ELFGetDynamicTag.cpp +++ b/ExecutionLayer/Elf/ParseFunctions/ELFGetDynamicTag.cpp @@ -21,17 +21,18 @@ namespace Execute { - std::vector ELFGetDynamicTag_x86_64(VirtualFileSystem::File &ElfFile, + std::vector ELFGetDynamicTag_x86_64(int fd, DynamicArrayTags Tag) { - off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); +#if defined(a64) || defined(aa64) + off_t OldOffset = lseek(fd, 0, SEEK_CUR); std::vector Ret; Elf64_Ehdr ELFHeader; - vfs->Seek(ElfFile, 0, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + lseek(fd, 0, SEEK_SET); + fread(fd, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); - std::vector DYNAMICPhdrs = ELFGetSymbolType_x86_64(ElfFile, PT_DYNAMIC); + std::vector DYNAMICPhdrs = ELFGetSymbolType_x86_64(fd, PT_DYNAMIC); if (DYNAMICPhdrs.size() < 1) { @@ -44,19 +45,22 @@ namespace Execute Elf64_Dyn Dynamic; for (size_t i = 0; i < Phdr.p_filesz / sizeof(Elf64_Dyn); i++) { - vfs->Seek(ElfFile, Phdr.p_offset + (i * sizeof(Elf64_Dyn)), SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&Dynamic, sizeof(Elf64_Dyn)); + lseek(fd, Phdr.p_offset + (i * sizeof(Elf64_Dyn)), SEEK_SET); + fread(fd, (uint8_t *)&Dynamic, sizeof(Elf64_Dyn)); if (Dynamic.d_tag != Tag) continue; - debug("Found dynamic tag %d at %#lx [d_val: %#lx].", + debug("Found dynamic tag %d at %#lx [d_val: %#lx]", Tag, &Dynamic, Dynamic.d_un.d_val); Ret.push_back(Dynamic); } } - vfs->Seek(ElfFile, OldOffset, SEEK_SET); + lseek(fd, OldOffset, SEEK_SET); return Ret; +#elif defined(a32) + return {}; +#endif } } diff --git a/Execute/Elf/ParseFunctions/ELFGetSections.cpp b/ExecutionLayer/Elf/ParseFunctions/ELFGetSections.cpp similarity index 68% rename from Execute/Elf/ParseFunctions/ELFGetSections.cpp rename to ExecutionLayer/Elf/ParseFunctions/ELFGetSections.cpp index 78ab691..b2027c5 100644 --- a/Execute/Elf/ParseFunctions/ELFGetSections.cpp +++ b/ExecutionLayer/Elf/ParseFunctions/ELFGetSections.cpp @@ -21,23 +21,24 @@ namespace Execute { - std::vector ELFGetSections_x86_64(VirtualFileSystem::File &ElfFile, + std::vector ELFGetSections_x86_64(int fd, const char *SectionName) { - off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); +#if defined(a64) || defined(aa64) + off_t OldOffset = lseek(fd, 0, SEEK_CUR); std::vector Ret; Elf64_Ehdr ELFHeader; - vfs->Seek(ElfFile, 0, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + lseek(fd, 0, SEEK_SET); + fread(fd, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); Elf64_Shdr *SectionHeaders = new Elf64_Shdr[ELFHeader.e_shnum]; - vfs->Seek(ElfFile, ELFHeader.e_shoff, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)SectionHeaders, sizeof(Elf64_Shdr) * ELFHeader.e_shnum); + lseek(fd, ELFHeader.e_shoff, SEEK_SET); + fread(fd, (uint8_t *)SectionHeaders, sizeof(Elf64_Shdr) * ELFHeader.e_shnum); char *SectionNames = new char[SectionHeaders[ELFHeader.e_shstrndx].sh_size]; - vfs->Seek(ElfFile, SectionHeaders[ELFHeader.e_shstrndx].sh_offset, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)SectionNames, SectionHeaders[ELFHeader.e_shstrndx].sh_size); + lseek(fd, SectionHeaders[ELFHeader.e_shstrndx].sh_offset, SEEK_SET); + fread(fd, (uint8_t *)SectionNames, SectionHeaders[ELFHeader.e_shstrndx].sh_size); for (Elf64_Half i = 0; i < ELFHeader.e_shnum; ++i) { @@ -46,9 +47,12 @@ namespace Execute Ret.push_back(SectionHeaders[i]); } - vfs->Seek(ElfFile, OldOffset, SEEK_SET); + lseek(fd, OldOffset, SEEK_SET); delete[] SectionHeaders; delete[] SectionNames; return Ret; +#elif defined(a32) + return {}; +#endif } } diff --git a/Execute/Elf/ParseFunctions/ELFGetSymbolType.cpp b/ExecutionLayer/Elf/ParseFunctions/ELFGetSymbolType.cpp similarity index 66% rename from Execute/Elf/ParseFunctions/ELFGetSymbolType.cpp rename to ExecutionLayer/Elf/ParseFunctions/ELFGetSymbolType.cpp index 85bd4e5..071bd7f 100644 --- a/Execute/Elf/ParseFunctions/ELFGetSymbolType.cpp +++ b/ExecutionLayer/Elf/ParseFunctions/ELFGetSymbolType.cpp @@ -21,30 +21,34 @@ namespace Execute { - std::vector ELFGetSymbolType_x86_64(VirtualFileSystem::File &ElfFile, + std::vector ELFGetSymbolType_x86_64(int fd, SegmentTypes Tag) { - off_t OldOffset = vfs->Seek(ElfFile, 0, SEEK_CUR); +#if defined(a64) || defined(aa64) + off_t OldOffset = lseek(fd, 0, SEEK_CUR); std::vector Ret; Elf64_Ehdr ELFHeader; - vfs->Seek(ElfFile, 0, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); + lseek(fd, 0, SEEK_SET); + fread(fd, (uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr)); Elf64_Phdr ProgramHeaders; - vfs->Seek(ElfFile, ELFHeader.e_phoff, SEEK_SET); - vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); + lseek(fd, ELFHeader.e_phoff, SEEK_SET); + fread(fd, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++) { if (ProgramHeaders.p_type == Tag) Ret.push_back(ProgramHeaders); - vfs->Seek(ElfFile, sizeof(Elf64_Phdr), SEEK_CUR); - vfs->Read(ElfFile, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); + lseek(fd, sizeof(Elf64_Phdr), SEEK_CUR); + fread(fd, (uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr)); } - vfs->Seek(ElfFile, OldOffset, SEEK_SET); + lseek(fd, OldOffset, SEEK_SET); return Ret; +#elif defined(a32) + return {}; +#endif } } diff --git a/ExecutionLayer/Spawn.cpp b/ExecutionLayer/Spawn.cpp new file mode 100644 index 0000000..5de1373 --- /dev/null +++ b/ExecutionLayer/Spawn.cpp @@ -0,0 +1,161 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../kernel.h" +#include "../Fex.hpp" + +using namespace Tasking; + +namespace Execute +{ + int Spawn(char *Path, const char **argv, const char **envp, + Tasking::PCB *Parent, + Tasking::TaskCompatibility Compatibility) + { + int fd = fopen(Path, "r"); + if (fd < 0) + return fd; + + struct stat statbuf; + fstat(fd, &statbuf); + if (!S_ISREG(statbuf.st_mode)) + { + fclose(fd); + return -EISDIR; + } + + switch (GetBinaryType(Path)) + { + case BinaryType::BinTypeFex: + { + Fex FexHdr; + fread(fd, (uint8_t *)&FexHdr, sizeof(Fex)); + if (FexHdr.Type == FexFormatType::FexFormatType_Executable) + { + stub; + assert(false); + } + + fclose(fd); + return -ENOEXEC; + } + case BinaryType::BinTypeELF: + { + TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture; + const char *BaseName; + cwk_path_get_basename(Path, &BaseName, nullptr); + Elf32_Ehdr ELFHeader; + fread(fd, (uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr)); + + switch (ELFHeader.e_machine) + { + case EM_386: + Arch = TaskArchitecture::x32; + break; + case EM_X86_64: + Arch = TaskArchitecture::x64; + break; + case EM_ARM: + Arch = TaskArchitecture::ARM32; + break; + case EM_AARCH64: + Arch = TaskArchitecture::ARM64; + break; + default: + error("Unknown ELF architecture %d", + ELFHeader.e_machine); + break; + } + + // TODO: This shouldn't be ignored + if (ELFHeader.e_ident[EI_CLASS] == ELFCLASS32) + fixme("32-bit ELF"); + else if (ELFHeader.e_ident[EI_CLASS] == ELFCLASS64) + fixme("64-bit ELF"); + else + fixme("Unknown class %d", ELFHeader.e_ident[EI_CLASS]); + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + if (ELFHeader.e_ident[EI_DATA] != ELFDATA2LSB) + { + fixme("ELF32 LSB expected, got %d", ELFHeader.e_ident[EI_DATA]); + } +#else + if (ELFHeader.e_ident[EI_DATA] != ELFDATA2MSB) + { + fixme("ELF32 MSB expected, got %d", ELFHeader.e_ident[EI_DATA]); + } +#endif + + /* ------------------------------------------------------------------------------------------------------------------------------ */ + + void *ElfFile = KernelAllocator.RequestPages(TO_PAGES(statbuf.st_size + 1)); + fread(fd, (uint8_t *)ElfFile, statbuf.st_size); + debug("Loaded elf %s at %#lx with the length of %ld", + Path, ElfFile, statbuf.st_size); + + PCB *Process = TaskManager->CreateProcess(thisProcess, + BaseName, + TaskExecutionMode::User, + ElfFile, false, + 0, 0); + + KernelAllocator.FreePages(ElfFile, TO_PAGES(statbuf.st_size + 1)); + + Process->SetWorkingDirectory(vfs->GetNodeFromPath(Path)->Parent); + Process->Info.Compatibility = TaskCompatibility::Native; + Process->Info.Architecture = TaskArchitecture::x64; + + ELFObject *obj = new ELFObject(Path, Process, argv, envp); + if (!obj->IsValid) + { + error("Failed to load ELF object"); + fclose(fd); + delete Process; + return -ENOEXEC; + } + + TCB *Thread = TaskManager->CreateThread(Process, + obj->InstructionPointer, + obj->argv, obj->envp, obj->auxv, + Arch, + Compatibility); + fclose(fd); + return Thread->ID; + } + default: + { + debug("Unknown binary type: %d", + GetBinaryType(Path)); + fclose(fd); + return -ENOEXEC; + } + } + + fclose(fd); + return -ENOEXEC; + } +} diff --git a/FileSystem/FS/ustar.cpp b/FileSystem/FS/ustar.cpp index 3292c1c..51fe575 100644 --- a/FileSystem/FS/ustar.cpp +++ b/FileSystem/FS/ustar.cpp @@ -29,13 +29,13 @@ namespace VirtualFileSystem if (!Size) Size = node->Length; - if ((size_t)node->Offset > node->Length) + if (RefOffset > node->Length) return 0; - if (node->Offset + Size > node->Length) - Size = node->Length - node->Offset; + if (RefOffset + (off_t)Size > node->Length) + Size = node->Length - RefOffset; - memcpy(Buffer, (uint8_t *)(node->Address + node->Offset), Size); + memcpy(Buffer, (uint8_t *)(node->Address + RefOffset), Size); return Size; } @@ -113,7 +113,7 @@ namespace VirtualFileSystem } else { - trace("%s %dKB Type:%c", header->name, TO_KB(size), header->typeflag[0]); + debug("%s %d KiB, Type:%c", header->name, TO_KiB(size), header->typeflag[0]); node->Mode = string2int(header->mode); node->Address = (Address + 512); node->Length = size; @@ -128,6 +128,8 @@ namespace VirtualFileSystem break; case SYMLINK: node->Flags = NodeFlags::SYMLINK; + node->Symlink = new char[strlen(header->link) + 1]; + strncpy((char *)node->Symlink, header->link, strlen(header->link)); break; case DIRECTORY: node->Flags = NodeFlags::DIRECTORY; diff --git a/FileSystem/FileDescriptor.cpp b/FileSystem/FileDescriptor.cpp new file mode 100644 index 0000000..443d1d8 --- /dev/null +++ b/FileSystem/FileDescriptor.cpp @@ -0,0 +1,434 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../kernel.h" + +namespace VirtualFileSystem +{ + ReadFSFunction(fd_Read) + { + if (!Size) + Size = node->Length; + + if (RefOffset > node->Length) + return 0; + + if (RefOffset + (off_t)Size > node->Length) + Size = node->Length - RefOffset; + + memcpy(Buffer, (uint8_t *)(node->Address + RefOffset), Size); + return Size; + } + + WriteFSFunction(fd_Write) + { + if (!Size) + Size = node->Length; + + if (RefOffset > node->Length) + return 0; + + if (RefOffset + (off_t)Size > node->Length) + Size = node->Length - RefOffset; + + memcpy((uint8_t *)(node->Address + RefOffset), Buffer, Size); + return Size; + } + + VirtualFileSystem::FileSystemOperations fd_op = { + .Name = "fd", + // .Read = fd_Read, + // .Write = fd_Write, + }; + + FileDescriptorTable::FileDescriptor + FileDescriptorTable::GetFileDescriptor(int FileDescriptor) + { + foreach (auto fd in FileDescriptors) + { + if (fd.Descriptor == FileDescriptor) + return fd; + } + return {.Descriptor = -1}; + } + + int FileDescriptorTable::ProbeMode(mode_t Mode, int Flags) + { + if (Flags & O_RDONLY) + { + if (!(Mode & S_IRUSR)) + return -EACCES; + } + + if (Flags & O_WRONLY) + { + if (!(Mode & S_IWUSR)) + return -EACCES; + } + + if (Flags & O_RDWR) + { + if (!(Mode & S_IRUSR) || + !(Mode & S_IWUSR)) + return -EACCES; + } + + return 0; + } + + int FileDescriptorTable::AddFileDescriptor(const char *AbsolutePath, + mode_t Mode, int Flags) + { + Tasking::PCB *pcb = thisProcess; + + if (ProbeMode(Mode, Flags) < 0) + { + errno = EACCES; + return -1; + } + + if (Flags & O_CREAT) + { + Node *n = vfs->Create(AbsolutePath, + NodeFlags::FILE, + pcb->CurrentWorkingDirectory); + + if (!n) + { + error("Failed to create file %s: %d", + AbsolutePath, errno); + return -1; + } + } + + if (Flags & O_EXCL) + { + RefNode *File = vfs->Open(AbsolutePath, + pcb->CurrentWorkingDirectory); + + if (!File) + { + errno = EEXIST; + return -1; + } + } + + if (Flags & O_TRUNC) + { + fixme("Implement O_TRUNC"); + } + + if (Flags & O_APPEND) + { + fixme("Implement O_APPEND"); + } + + if (Flags & O_CLOEXEC) + { + fixme("Implement O_CLOEXEC"); + } + + RefNode *File = vfs->Open(AbsolutePath, + pcb->CurrentWorkingDirectory); + + if (!File) + { + error("Failed to open file %s: %d", + AbsolutePath, errno); + return -1; + } + + FileDescriptorTable::FileDescriptor fd; + fd.Descriptor = GetFreeFileDescriptor(); + + if (fd.Descriptor < 0) + { + errno = EMFILE; + return -1; + } + + fd.Mode = Mode; + fd.Flags = Flags; + fd.Handle = File; + + FileDescriptors.push_back(fd); + + char FileName[64]; + sprintf(FileName, "%d", fd.Descriptor); + VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->fdDir); + if (n) + { + /* FIXME: Implement proper file descriptors */ + n->Address = (uintptr_t)0xdeadbeef; + n->Length = File->FileSize; + n->Operator = &fd_op; + } + + return fd.Descriptor; + } + + int FileDescriptorTable::RemoveFileDescriptor(int FileDescriptor) + { + forItr(itr, FileDescriptors) + { + if (itr->Descriptor == FileDescriptor) + { + FileDescriptors.erase(itr); + + char FileName[64]; + sprintf(FileName, "%d", FileDescriptor); + vfs->Delete(FileName, false, this->fdDir); + return 0; + } + } + + errno = EBADF; + return -1; + } + + int FileDescriptorTable::GetFreeFileDescriptor() + { + int i = 0; + while (true) + { + bool Found = false; + foreach (auto fd in FileDescriptors) + { + if (fd.Descriptor == i) + { + Found = true; + break; + } + } + if (!Found) + return i; + i++; + } + + errno = EMFILE; + return -1; + } + + std::string FileDescriptorTable::GetAbsolutePath(int FileDescriptor) + { + FileDescriptorTable::FileDescriptor fd = + this->GetFileDescriptor(FileDescriptor); + if (fd.Descriptor == -1) + return ""; + + Node *node = fd.Handle->node; + std::string absolutePath = vfs->GetPathFromNode(node); + std::string path = absolutePath.c_str(); + return path; + } + + int FileDescriptorTable::_open(const char *pathname, int flags, + mode_t mode) + { + if (pathname == nullptr) + { + errno = EFAULT; + return -1; + } + + return AddFileDescriptor(pathname, mode, flags); + } + + int FileDescriptorTable::_creat(const char *pathname, mode_t mode) + { + return _open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode); + } + + ssize_t FileDescriptorTable::_read(int fd, void *buf, size_t count) + { + FileDescriptor fdesc; + fdesc = this->GetFileDescriptor(fd); + + if (fdesc.Descriptor < 0) + { + errno = EBADF; + return -1; + } + + return fdesc.Handle->Read((uint8_t *)buf, count); + } + + ssize_t FileDescriptorTable::_write(int fd, const void *buf, + size_t count) + { + FileDescriptor fdesc; + fdesc = this->GetFileDescriptor(fd); + + if (fdesc.Descriptor < 0) + return -1; + + return fdesc.Handle->Write((uint8_t *)buf, count); + } + + int FileDescriptorTable::_close(int fd) + { + FileDescriptor fdesc; + fdesc = this->GetFileDescriptor(fd); + + if (fdesc.Descriptor < 0) + { + errno = EBADF; + return -1; + } + + if (RemoveFileDescriptor(fd) < 0) + { + errno = EBADF; + return -1; + } + + delete fdesc.Handle; + return 0; + } + + off_t FileDescriptorTable::_lseek(int fd, off_t offset, int whence) + { + FileDescriptor fdesc; + fdesc = this->GetFileDescriptor(fd); + + if (fdesc.Descriptor < 0) + { + errno = EBADF; + return -1; + } + + return fdesc.Handle->Seek(offset, whence); + } + + int FileDescriptorTable::_stat(const char *pathname, + struct stat *statbuf) + { + if (pathname == nullptr) + { + errno = EINVAL; + return -1; + } + + RefNode *file = vfs->Open(pathname, + thisProcess->CurrentWorkingDirectory); + + if (!file) + { + error("Failed to open file %s: %d", + pathname, errno); + return -1; + } + + Node *node = file->node; + statbuf->st_dev = 0; /* FIXME: stub */ + statbuf->st_ino = node->IndexNode; + statbuf->st_mode = node->Flags | node->Mode; + statbuf->st_nlink = 0; /* FIXME: stub */ + statbuf->st_uid = node->UserIdentifier; + statbuf->st_gid = node->GroupIdentifier; + statbuf->st_rdev = 0; /* FIXME: stub */ + statbuf->st_size = node->Length; + statbuf->st_blksize = 0; /* FIXME: stub */ + statbuf->st_blocks = 0; /* FIXME: stub */ + statbuf->st_attr = 0; /* FIXME: stub */ + return 0; + } + + int FileDescriptorTable::_fstat(int fd, struct stat *statbuf) + { + FileDescriptor fdesc; + fdesc = this->GetFileDescriptor(fd); + + if (fdesc.Descriptor < 0) + { + errno = EBADF; + return -1; + } + + Node *node = fdesc.Handle->node; + statbuf->st_dev = 0; /* FIXME: stub */ + statbuf->st_ino = node->IndexNode; + statbuf->st_mode = node->Flags | node->Mode; + statbuf->st_nlink = 0; /* FIXME: stub */ + statbuf->st_uid = node->UserIdentifier; + statbuf->st_gid = node->GroupIdentifier; + statbuf->st_rdev = 0; /* FIXME: stub */ + statbuf->st_size = node->Length; + statbuf->st_blksize = 0; /* FIXME: stub */ + statbuf->st_blocks = 0; /* FIXME: stub */ + statbuf->st_attr = 0; /* FIXME: stub */ + return 0; + } + + int FileDescriptorTable::_lstat(const char *pathname, + struct stat *statbuf) + { + if (pathname == nullptr) + { + errno = EINVAL; + return -1; + } + + RefNode *file = vfs->Open(pathname, + thisProcess->CurrentWorkingDirectory); + + if (!file) + { + error("Failed to open file %s: %d", + pathname, errno); + return -1; + } + + Node *node = file->node; + statbuf->st_dev = 0; /* FIXME: stub */ + statbuf->st_ino = node->IndexNode; + statbuf->st_mode = node->Flags | node->Mode; + statbuf->st_nlink = 0; /* FIXME: stub */ + statbuf->st_uid = node->UserIdentifier; + statbuf->st_gid = node->GroupIdentifier; + statbuf->st_rdev = 0; /* FIXME: stub */ + statbuf->st_size = node->Length; + statbuf->st_blksize = 0; /* FIXME: stub */ + statbuf->st_blocks = 0; /* FIXME: stub */ + statbuf->st_attr = 0; /* FIXME: stub */ + return 0; + } + + FileDescriptorTable::FileDescriptorTable(void *Owner) + { + this->fdDir = vfs->Create("fd", VirtualFileSystem::NodeFlags::DIRECTORY, + ((Tasking::PCB *)Owner)->ProcessDirectory); + } + + FileDescriptorTable::~FileDescriptorTable() + { + foreach (auto var in FileDescriptors) + { + this->RemoveFileDescriptor(var.Descriptor); + delete var.Handle; + } + } +} diff --git a/FileSystem/FileNode.cpp b/FileSystem/FileNode.cpp new file mode 100644 index 0000000..17d277c --- /dev/null +++ b/FileSystem/FileNode.cpp @@ -0,0 +1,197 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +namespace VirtualFileSystem +{ + ReferenceNode *Node::CreateReference() + { + SmartLock(NodeLock); + ReferenceNode *rn = new ReferenceNode(this); + References.push_back(rn); + debug("Created reference %p for node %p", rn, this); + return rn; + } + + void Node::RemoveReference(ReferenceNode *Reference) + { + SmartLock(NodeLock); + debug("Removing reference %p for node %p", Reference, this); + References.erase(std::find(References.begin(), References.end(), Reference)); + } + + /**************************************************************/ + + size_t ReferenceNode::Read(uint8_t *Buffer, size_t Size) + { + if (this->SymlinkTo) + return this->SymlinkTo->Read(Buffer, Size); + + if (!this->node->Operator) + { + errno = EFAULT; + return -1; + } + + SmartLock(RefNodeLock); + + if (this->node->Operator->Read) + { + off_t RefOffset = off_t(this->Offset.load()); + return this->node->Operator->Read(this->node, Size, Buffer, RefOffset); + } + + errno = ENOSYS; + return -1; + } + + size_t ReferenceNode::Write(uint8_t *Buffer, size_t Size) + { + if (this->SymlinkTo) + return this->SymlinkTo->Write(Buffer, Size); + + if (!this->node->Operator) + { + errno = EFAULT; + return -1; + } + + SmartLock(RefNodeLock); + + if (this->node->Operator->Write) + { + off_t RefOffset = off_t(this->Offset.load()); + return this->node->Operator->Write(this->node, Size, Buffer, RefOffset); + } + + errno = ENOSYS; + return -1; + } + + off_t ReferenceNode::Seek(off_t Offset, int Whence) + { + if (this->SymlinkTo) + return this->SymlinkTo->Seek(Offset, Whence); + + if (!this->node->Operator) + { + errno = EFAULT; + return -1; + } + + SmartLock(RefNodeLock); + + if (this->node->Operator->Seek) + { + off_t RefOffset = off_t(this->Offset.load()); + return this->node->Operator->Seek(this->node, Offset, Whence, RefOffset); + } + + switch (Whence) + { + case SEEK_SET: + { + if (Offset > this->node->Length) + { + errno = EINVAL; + return -1; + } + + this->Offset.store(Offset); + break; + } + case SEEK_CUR: + { + off_t NewOffset = off_t(this->Offset.load()) + Offset; + if (NewOffset > this->node->Length || + NewOffset < 0) + { + errno = EINVAL; + return -1; + } + + this->Offset.store(NewOffset); + break; + } + case SEEK_END: + { + off_t NewOffset = this->node->Length + Offset; + if (NewOffset > this->node->Length || + NewOffset < 0) + { + errno = EINVAL; + return -1; + } + + this->Offset.store(NewOffset); + break; + } + default: + { + error("Invalid whence!"); + errno = EINVAL; + return -1; + } + } + + return (off_t)this->Offset.load(); + } + + ReferenceNode::ReferenceNode(Node *node) + { + SmartLock(RefNodeLock); + this->node = node; + this->FileSize = node->Length; + this->AbsolutePath += node->FileSystem->GetPathFromNode(node); + if (this->node->Flags == SYMLINK) + { + if (!this->node->SymlinkTarget) + { + this->node->SymlinkTarget = + node->FileSystem->GetNodeFromPath(this->node->Symlink); + + /* not standard but useful in kernel-space */ + this->node->Length = this->node->SymlinkTarget->Length; + } + + if (!this->node->SymlinkTarget) + { + error("Symlink target %s not found!", + this->node->Symlink); + errno = ENOENT; + return; + } + + this->SymlinkTo = this->node->SymlinkTarget->CreateReference(); + } + + debug("Created reference node for %s [%#lx]", + this->AbsolutePath.c_str(), (uintptr_t)this); + } + + ReferenceNode::~ReferenceNode() + { + SmartLock(RefNodeLock); + if (this->SymlinkTo) + this->node->SymlinkTarget->RemoveReference(this); + this->node->RemoveReference(this); + + debug("Destroyed reference node for %s [%#lx]", + this->AbsolutePath.c_str(), (uintptr_t)this); + } +} diff --git a/FileSystem/Filesystem.cpp b/FileSystem/Filesystem.cpp index 9da7152..086a67d 100644 --- a/FileSystem/Filesystem.cpp +++ b/FileSystem/Filesystem.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include "../kernel.h" @@ -34,679 +33,602 @@ #define vfsdbg(m, ...) #endif -NewLock(VFSLock); - namespace VirtualFileSystem { - std::shared_ptr Virtual::GetPathFromNode(Node *node) - { - vfsdbg("GetPathFromNode( Node: \"%s\" )", node->Name); - Node *Parent = node; - char **Path = nullptr; - size_t Size = 1; - size_t PathSize = 0; - - while (Parent != FileSystemRoot && Parent != nullptr) - { - bool Found = false; - foreach (const auto &Children in FileSystemRoot->Children) - if (Children == Parent) - { - Found = true; - break; - } - - if (Found) - break; - - if (strlen(Parent->Name) == 0) - break; - - char **new_path = new char *[PathSize + 1]; - if (Path != nullptr) - { - memcpy(new_path, Path, sizeof(char *) * PathSize); - delete[] Path; - } - - Path = new_path; - Path[PathSize] = Parent->Name; - PathSize++; - new_path = new char *[PathSize + 1]; - memcpy(new_path, Path, sizeof(char *) * PathSize); - delete[] Path; - Path = new_path; - Path[PathSize] = (char *)"/"; - PathSize++; - Parent = Parent->Parent; - } - - for (size_t i = 0; i < PathSize; i++) - Size += strlen(Path[i]); - - std::shared_ptr FinalPath; - FinalPath.reset(new char[Size]); - - size_t Offset = 0; - - for (size_t i = PathSize - 1; i < PathSize; i--) - { - if (Path[i] == nullptr) - continue; - - size_t ElementSize = strlen(Path[i]); - memcpy(FinalPath.get() + Offset, Path[i], ElementSize); - Offset += ElementSize; - } - - FinalPath.get()[Size - 1] = '\0'; - delete[] Path, Path = nullptr; - vfsdbg("GetPathFromNode()->\"%s\"", FinalPath.get()); - return FinalPath; - } - - Node *Virtual::GetNodeFromPath(const char *Path, Node *Parent) - { - vfsdbg("GetNodeFromPath( Path: \"%s\" Parent: \"%s\" )", Path, Parent ? Parent->Name : "(null)"); - - Node *ReturnNode = Parent; - bool IsAbsolutePath = cwk_path_is_absolute(Path); - - if (!ReturnNode) - ReturnNode = FileSystemRoot->Children[0]; // 0 - filesystem root - - if (IsAbsolutePath) - ReturnNode = FileSystemRoot->Children[0]; // 0 - filesystem root - - cwk_segment segment; - if (unlikely(!cwk_path_get_first_segment(Path, &segment))) - { - error("Path doesn't have any segments."); - return nullptr; - } - - do - { - char *SegmentName = new char[segment.end - segment.begin + 1]; - memcpy(SegmentName, segment.begin, segment.end - segment.begin); - vfsdbg("GetNodeFromPath()->SegmentName: \"%s\"", SegmentName); - GetNodeFromPathNextParent: - foreach (auto Child in ReturnNode->Children) - { - vfsdbg("comparing \"%s\" with \"%s\"", Child->Name, SegmentName); - if (strcmp(Child->Name, SegmentName) == 0) - { - ReturnNode = Child; - goto GetNodeFromPathNextParent; - } - } - delete[] SegmentName; - } while (cwk_path_get_next_segment(&segment)); - - const char *basename; - cwk_path_get_basename(Path, &basename, nullptr); - vfsdbg("BaseName: \"%s\" NodeName: \"%s\"", basename, ReturnNode->Name); - - if (strcmp(basename, ReturnNode->Name) == 0) - { - vfsdbg("GetNodeFromPath()->\"%s\"", ReturnNode->Name); - return ReturnNode; - } - - vfsdbg("GetNodeFromPath()->\"(null)\""); - return nullptr; - } - - File Virtual::ConvertNodeToFILE(Node *node) - { - File file{}; - file.Status = FileStatus::OK; - file.node = node; - return file; - } - - bool Virtual::PathIsRelative(const char *Path) - { - vfsdbg("PathIsRelative( Path: \"%s\" )", Path); - bool IsRelative = cwk_path_is_relative(Path); - vfsdbg("PathIsRelative()->%s", IsRelative ? "true" : "false"); - return IsRelative; - } - - Node *Virtual::GetParent(const char *Path, Node *Parent) - { - vfsdbg("GetParent( Path: \"%s\" Parent: \"%s\" )", Path, Parent->Name); - if (Parent) - { - vfsdbg("GetParent()->\"%s\"", Parent->Name); - return Parent; - } - - Node *ParentNode = nullptr; - if (FileSystemRoot->Children.size() >= 1) - { - assert(FileSystemRoot->Children[0] != nullptr); - ParentNode = FileSystemRoot->Children[0]; // 0 - filesystem root - } - else - { - // TODO: Check if here is a bug or something... - const char *PathCopy; - PathCopy = (char *)Path; - size_t length; - cwk_path_get_root(PathCopy, &length); // not working? - if (length > 0) - { - foreach (auto Child in FileSystemRoot->Children) - { - if (strcmp(Child->Name, PathCopy) == 0) - { - ParentNode = Child; - break; - } - } - } - } - vfsdbg("GetParent()->\"%s\"", ParentNode->Name); - return ParentNode; - } - - Node *Virtual::AddNewChild(const char *Name, Node *Parent) - { - if (!Parent) - { - error("Parent is null!"); - return nullptr; - } - vfsdbg("AddNewChild( Name: \"%s\" Parent: \"%s\" )", Name, Parent->Name); - - Node *newNode = new Node; - newNode->Parent = Parent; - strcpy(newNode->Name, Name); - - newNode->Operator = Parent->Operator; - Parent->Children.push_back(newNode); - - vfsdbg("AddNewChild()->\"%s\"", newNode->Name); - return newNode; - } - - Node *Virtual::GetChild(const char *Name, Node *Parent) - { - vfsdbg("GetChild( Name: \"%s\" Parent: \"%s\" )", Name, Parent->Name); - if (!Parent) - { - vfsdbg("GetChild()->nullptr"); - return nullptr; - } - - foreach (auto Child in Parent->Children) - if (strcmp(Child->Name, Name) == 0) - { - vfsdbg("GetChild()->\"%s\"", Child->Name); - return Child; - } - vfsdbg("GetChild()->nullptr (not found)"); - return nullptr; - } - - FileStatus Virtual::RemoveChild(const char *Name, Node *Parent) - { - vfsdbg("RemoveChild( Name: \"%s\" Parent: \"%s\" )", Name, Parent->Name); - for (size_t i = 0; i < Parent->Children.size(); i++) - { - if (strcmp(Parent->Children[i]->Name, Name) == 0) - { - delete Parent->Children[i], Parent->Children[i] = nullptr; - Parent->Children.remove(i); - vfsdbg("RemoveChild()->OK"); - return FileStatus::OK; - } - } - vfsdbg("RemoveChild()->NotFound"); - return FileStatus::NotFound; - } - - std::shared_ptr Virtual::NormalizePath(const char *Path, Node *Parent) - { - vfsdbg("NormalizePath( Path: \"%s\" Parent: \"%s\" )", Path, Parent->Name); - char *NormalizedPath = new char[strlen((char *)Path) + 1]; - std::shared_ptr RelativePath; - - cwk_path_normalize(Path, NormalizedPath, strlen((char *)Path) + 1); - - if (cwk_path_is_relative(NormalizedPath)) - { - std::shared_ptr ParentPath = GetPathFromNode(Parent); - size_t PathSize = cwk_path_get_absolute(ParentPath.get(), NormalizedPath, nullptr, 0); - RelativePath.reset(new char[PathSize + 1]); - cwk_path_get_absolute(ParentPath.get(), NormalizedPath, RelativePath.get(), PathSize + 1); - } - else - { - RelativePath.reset(new char[strlen(NormalizedPath) + 1]); - strcpy(RelativePath.get(), NormalizedPath); - } - delete[] NormalizedPath; - vfsdbg("NormalizePath()->\"%s\"", RelativePath.get()); - return RelativePath; - } - - bool Virtual::PathExists(const char *Path, Node *Parent) - { - if (isempty((char *)Path)) - { - vfsdbg("PathExists()->PathIsEmpty"); - return false; - } - - if (Parent == nullptr) - Parent = FileSystemRoot; - - vfsdbg("PathExists( Path: \"%s\" Parent: \"%s\" )", Path, Parent->Name); - - if (GetNodeFromPath(NormalizePath(Path, Parent).get(), Parent)) - { - vfsdbg("PathExists()->OK"); - return true; - } - - vfsdbg("PathExists()->NotFound"); - return false; - } - - Node *Virtual::CreateRoot(const char *RootName, FileSystemOperations *Operator) - { - if (Operator == nullptr) - return nullptr; - vfsdbg("Creating root %s", RootName); - Node *newNode = new Node; - strncpy(newNode->Name, RootName, FILENAME_LENGTH); - newNode->Flags = NodeFlags::DIRECTORY; - newNode->Operator = Operator; - FileSystemRoot->Children.push_back(newNode); - return newNode; - } - - /* TODO: Further testing needed */ - Node *Virtual::Create(const char *Path, NodeFlags Flag, Node *Parent) - { - SmartLock(VFSLock); - - if (isempty((char *)Path)) - return nullptr; - - Node *RootNode = FileSystemRoot->Children[0]; - Node *CurrentParent = this->GetParent(Path, Parent); - vfsdbg("Virtual::Create( Path: \"%s\" Parent: \"%s\" )", Path, Parent ? Parent->Name : CurrentParent->Name); - - std::shared_ptr CleanPath = this->NormalizePath(Path, CurrentParent); - vfsdbg("CleanPath: \"%s\"", CleanPath.get()); - - if (PathExists(CleanPath.get(), CurrentParent)) - { - error("Path %s already exists.", CleanPath.get()); - goto CreatePathError; - } - - cwk_segment segment; - if (!cwk_path_get_first_segment(CleanPath.get(), &segment)) - { - error("Path doesn't have any segments."); - goto CreatePathError; - } - - do - { - char *SegmentName = new char[segment.end - segment.begin + 1]; - memcpy(SegmentName, segment.begin, segment.end - segment.begin); - vfsdbg("SegmentName: \"%s\"", SegmentName); - - if (Parent) - if (GetChild(SegmentName, RootNode) != nullptr) - { - RootNode = GetChild(SegmentName, RootNode); - delete[] SegmentName; - continue; - } - - if (GetChild(SegmentName, CurrentParent) == nullptr) - { - CurrentParent = AddNewChild(SegmentName, CurrentParent); - CurrentParent->Flags = Flag; - } - else - { - CurrentParent = GetChild(SegmentName, CurrentParent); - } - - delete[] SegmentName; - } while (cwk_path_get_next_segment(&segment)); - - vfsdbg("Virtual::Create()->\"%s\"", CurrentParent->Name); - vfsdbg("Path created: \"%s\"", GetPathFromNode(CurrentParent).get()); - return CurrentParent; - - CreatePathError: - vfsdbg("Virtual::Create()->nullptr"); - return nullptr; - } - - FileStatus Virtual::Delete(const char *Path, bool Recursive, Node *Parent) - { - SmartLock(VFSLock); - vfsdbg("Virtual::Delete( Path: \"%s\" Parent: \"%s\" )", Path, Parent ? Parent->Name : "(null)"); - - if (isempty((char *)Path)) - return InvalidParameter; - - if (Parent == nullptr) - Parent = FileSystemRoot; - - std::shared_ptr CleanPath = this->NormalizePath(Path, Parent); - vfsdbg("CleanPath: \"%s\"", CleanPath.get()); - - if (!PathExists(CleanPath.get(), Parent)) - { - vfsdbg("Path %s doesn't exist.", CleanPath.get()); - return InvalidPath; - } - - Node *NodeToDelete = GetNodeFromPath(CleanPath.get(), Parent); - Node *ParentNode = GetParent(CleanPath.get(), Parent); - - if (NodeToDelete->Flags == NodeFlags::DIRECTORY) - { - if (Recursive) - { - foreach (auto Child in NodeToDelete->Children) - { - VFSLock.Unlock(); - FileStatus Status = Delete(GetPathFromNode(Child).get(), true); - VFSLock.Lock(__FUNCTION__); - if (Status != FileStatus::OK) - { - vfsdbg("Failed to delete child %s with status %d. (%s)", Child->Name, Status, Path); - return PartiallyCompleted; - } - } - } - else if (NodeToDelete->Children.size() > 0) - { - vfsdbg("Directory %s is not empty.", CleanPath.get()); - return DirectoryNotEmpty; - } - } - - if (RemoveChild(NodeToDelete->Name, ParentNode) != FileStatus::OK) - { - vfsdbg("Failed to remove child %s from parent %s. (%s)", NodeToDelete->Name, ParentNode->Name, Path); - return NotFound; - } - - vfsdbg("Virtual::Delete()->OK"); - return OK; - } - - FileStatus Virtual::Delete(Node *Path, bool Recursive, Node *Parent) { return Delete(GetPathFromNode(Path).get(), Recursive, Parent); } - - /* TODO: REWORK */ - File Virtual::Mount(const char *Path, FileSystemOperations *Operator) - { - SmartLock(VFSLock); - File file{}; - - if (unlikely(!Operator)) - { - file.Status = FileStatus::InvalidOperator; - return file; - } - - if (unlikely(isempty((char *)Path))) - { - file.Status = FileStatus::InvalidParameter; - return file; - } - - vfsdbg("Mounting %s", Path); - const char *PathCopy; - cwk_path_get_basename(Path, &PathCopy, 0); - strcpy(file.Name, PathCopy); - file.Status = FileStatus::OK; - file.node = Create(Path, NodeFlags::MOUNTPOINT); - file.node->Operator = Operator; - return file; - } - - FileStatus Virtual::Unmount(File &File) - { - SmartLock(VFSLock); - if (unlikely(!File.node)) - return FileStatus::InvalidParameter; - fixme("Unmounting %s", File.Name); - return FileStatus::OK; - } - - size_t Virtual::Read(File &File, uint8_t *Buffer, size_t Size) - { - SmartLock(VFSLock); - if (unlikely(!File.node)) - { - File.Status = FileStatus::InvalidNode; - return 0; - } - - if (unlikely(!File.node->Operator)) - { - File.Status = FileStatus::InvalidOperator; - return 0; - } - - File.Status = FileStatus::OK; - - vfsdbg("Reading %s out->%016x", File.Name, Buffer); - return File.node->Operator->Read(File.node, Size, Buffer); - } - - size_t Virtual::Write(File &File, uint8_t *Buffer, size_t Size) - { - SmartLock(VFSLock); - if (unlikely(!File.node)) - { - File.Status = FileStatus::InvalidNode; - return 0; - } - - if (unlikely(!File.node->Operator)) - { - File.Status = FileStatus::InvalidOperator; - return 0; - } - - File.Status = FileStatus::OK; - - vfsdbg("Writing %s out->%016x", File.Name, Buffer); - return File.node->Operator->Write(File.node, Size, Buffer); - } - - off_t Virtual::Seek(File &File, off_t Offset, uint8_t Whence) - { - SmartLock(VFSLock); - Node *node = File.node; - File.Status = FileStatus::OK; - - if (unlikely(!node)) - { - File.Status = FileStatus::InvalidNode; - return -1; - } - - if (unlikely(!node->Operator)) - { - File.Status = FileStatus::InvalidOperator; - return -1; - } - - if (unlikely(node->Operator->Seek)) - { - node->Offset = File.ContextOffset; - File.ContextOffset = node->Operator->Seek(node, Offset, Whence); - return File.ContextOffset; - } - - switch (Whence) - { - case SEEK_SET: - { - if ((size_t)Offset > node->Length) - return -1; - - File.ContextOffset = node->Offset = Offset; - break; - } - case SEEK_CUR: - { - off_t NewOffset = File.ContextOffset + Offset; - if ((size_t)NewOffset > node->Length || - NewOffset < 0) - return -1; - - File.ContextOffset = node->Offset = NewOffset; - break; - } - case SEEK_END: - { - off_t NewOffset = node->Length + Offset; - if ((size_t)NewOffset > node->Length || - NewOffset < 0) - return -1; - - File.ContextOffset = node->Offset = NewOffset; - break; - } - default: - { - error("Invalid whence!"); - return -1; - } - } - - return File.ContextOffset; - } - - /* TODO: CHECK Open */ - File Virtual::Open(const char *Path, Node *Parent) - { - SmartLock(VFSLock); - vfsdbg("Opening %s with parent %s", Path, Parent ? Parent->Name : "(null)"); - const char *basename; - - if (strcmp(Path, "/") == 0) - { - File file{}; - file.node = FileSystemRoot; - - strcpy(file.Name, "/"); - return file; - } - - if (strcmp(Path, ".") == 0) - { - File file{}; - file.node = Parent; - - if (unlikely(!file.node)) - file.Status = FileStatus::NotFound; - - cwk_path_get_basename(GetPathFromNode(Parent).get(), &basename, nullptr); - strcpy(file.Name, basename); - return file; - } - - if (strcmp(Path, "..") == 0) - { - File file{}; - - if (Parent->Parent != nullptr) - file.node = Parent->Parent; - - if (!file.node) - file.Status = FileStatus::NotFound; - - cwk_path_get_basename(GetPathFromNode(Parent).get(), &basename, nullptr); - strcpy(file.Name, basename); - return file; - } - - Node *CurrentParent = this->GetParent(Path, Parent); - std::shared_ptr CleanPath = NormalizePath(Path, CurrentParent); - - File file{}; - /* TODO: Check for other errors */ - - if (!PathExists(CleanPath.get(), CurrentParent)) - { - foreach (auto Child in FileSystemRoot->Children) - { - if (strcmp(Child->Name, CleanPath.get()) == 0) - { - file.node = Child; - if (file.node == nullptr) - { - file.Status = FileStatus::UnknownFileStatusError; - file.node = nullptr; - return file; - } - cwk_path_get_basename(GetPathFromNode(Child).get(), &basename, nullptr); - strcpy(file.Name, basename); - return file; - } - } - - file.node = GetNodeFromPath(CleanPath.get(), FileSystemRoot->Children[0]); - if (file.node) - { - cwk_path_get_basename(GetPathFromNode(file.node).get(), &basename, nullptr); - strcpy(file.Name, basename); - return file; - } - } - else - { - file.node = GetNodeFromPath(CleanPath.get(), CurrentParent); - cwk_path_get_basename(CleanPath.get(), &basename, nullptr); - strcpy(file.Name, basename); - return file; - } - - file.Status = FileStatus::NotFound; - return file; - } - - FileStatus Virtual::Close(File &File) - { - SmartLock(VFSLock); - if (unlikely(!File.node)) - return FileStatus::InvalidHandle; - vfsdbg("Closing %s", File.Name); - - File.node->Offset = 0; - return FileStatus::OK; - } - - Virtual::Virtual() - { - trace("Initializing virtual file system..."); - FileSystemRoot = new Node; - FileSystemRoot->Flags = NodeFlags::MOUNTPOINT; - FileSystemRoot->Operator = nullptr; - FileSystemRoot->Parent = nullptr; - strncpy(FileSystemRoot->Name, "root", 4); - cwk_path_set_style(CWK_STYLE_UNIX); - } - - Virtual::~Virtual() - { - debug("Destructor called"); - } + std::string Virtual::GetPathFromNode(Node *File) + { + vfsdbg("GetPathFromNode( Node: \"%s\" )", File->Name); + SmartLock(VirtualLock); + + Node *Parent = File; + char **Path = nullptr; + size_t PathSize = 0; + std::string FinalPath; + + while (Parent != FileSystemRoot && Parent != nullptr) + { + if (File == FileSystemRoot->Children[0]) + { + FinalPath = "/"; + break; + } + + bool Found = false; + foreach (const auto &Children in FileSystemRoot->Children) + if (Children == Parent) + { + Found = true; + break; + } + + if (Found) + break; + + if (strlen(Parent->Name) == 0) + break; + + char **new_path = new char *[PathSize + 1]; + if (Path != nullptr) + { + memcpy(new_path, Path, sizeof(char *) * PathSize); + delete[] Path; + } + + Path = new_path; + Path[PathSize] = (char *)Parent->Name; + PathSize++; + new_path = new char *[PathSize + 1]; + memcpy(new_path, Path, sizeof(char *) * PathSize); + delete[] Path; + Path = new_path; + Path[PathSize] = (char *)"/"; + PathSize++; + Parent = Parent->Parent; + } + + for (size_t i = PathSize - 1; i < PathSize; i--) + { + if (Path[i] == nullptr) + continue; + FinalPath += Path[i]; + } + + FinalPath += "\0"; + delete[] Path, Path = nullptr; + vfsdbg("GetPathFromNode()->\"%s\"", FinalPath.c_str()); + return FinalPath; + } + + Node *Virtual::GetNodeFromPath_Unsafe(const char *Path, Node *Parent) + { + vfsdbg("GetNodeFromPath( Path: \"%s\" Parent: \"%s\" )", + Path, Parent ? Parent->Name : "(null)"); + + if (strcmp(Path, "/") == 0) + return FileSystemRoot->Children[0]; // 0 - filesystem root + + if (strcmp(Path, ".") == 0) + return Parent; + + if (strcmp(Path, "..") == 0) + { + if (Parent) + { + if (Parent->Parent) + return Parent->Parent; + else + return Parent; + } + else + return nullptr; + } + + Node *ReturnNode = Parent; + bool IsAbsolutePath = cwk_path_is_absolute(Path); + + if (!ReturnNode) + ReturnNode = FileSystemRoot->Children[0]; // 0 - filesystem root + + if (IsAbsolutePath) + ReturnNode = FileSystemRoot->Children[0]; // 0 - filesystem root + + cwk_segment segment; + if (unlikely(!cwk_path_get_first_segment(Path, &segment))) + { + error("Path doesn't have any segments."); + errno = ENOENT; + return nullptr; + } + + do + { + char *SegmentName = new char[segment.end - segment.begin + 1]; + memcpy(SegmentName, segment.begin, segment.end - segment.begin); + vfsdbg("GetNodeFromPath()->SegmentName: \"%s\"", SegmentName); + GetNodeFromPathNextParent: + foreach (auto Child in ReturnNode->Children) + { + vfsdbg("comparing \"%s\" with \"%s\"", + Child->Name, SegmentName); + if (strcmp(Child->Name, SegmentName) == 0) + { + ReturnNode = Child; + goto GetNodeFromPathNextParent; + } + } + delete[] SegmentName; + } while (cwk_path_get_next_segment(&segment)); + + const char *basename; + cwk_path_get_basename(Path, &basename, nullptr); + vfsdbg("BaseName: \"%s\" NodeName: \"%s\"", + basename, ReturnNode->Name); + + if (strcmp(basename, ReturnNode->Name) == 0) + { + vfsdbg("GetNodeFromPath()->\"%s\"", ReturnNode->Name); + return ReturnNode; + } + + vfsdbg("GetNodeFromPath()->\"(null)\""); + errno = ENOENT; + return nullptr; + } + + Node *Virtual::GetNodeFromPath(const char *Path, Node *Parent) + { + SmartLock(VirtualLock); + return GetNodeFromPath_Unsafe(Path, Parent); + } + + bool Virtual::PathIsRelative(const char *Path) + { + vfsdbg("PathIsRelative( Path: \"%s\" )", Path); + bool IsRelative = cwk_path_is_relative(Path); + vfsdbg("PathIsRelative()->%s", IsRelative ? "true" : "false"); + return IsRelative; + } + + Node *Virtual::GetParent(const char *Path, Node *Parent) + { + vfsdbg("GetParent( Path: \"%s\" Parent: \"%s\" )", + Path, Parent->Name); + + if (Parent) + { + vfsdbg("GetParent()->\"%s\"", Parent->Name); + return Parent; + } + + Node *ParentNode = nullptr; + if (FileSystemRoot->Children.size() >= 1) + { + assert(FileSystemRoot->Children[0] != nullptr); + ParentNode = FileSystemRoot->Children[0]; // 0 - filesystem root + } + else + { + // TODO: Check if here is a bug or something... + const char *PathCopy; + PathCopy = (char *)Path; + size_t length; + cwk_path_get_root(PathCopy, &length); // not working? + if (length > 0) + { + foreach (auto Child in FileSystemRoot->Children) + { + if (strcmp(Child->Name, PathCopy) == 0) + { + ParentNode = Child; + break; + } + } + } + } + vfsdbg("GetParent()->\"%s\"", ParentNode->Name); + return ParentNode; + } + + Node *Virtual::AddNewChild(const char *Name, Node *Parent) + { + if (!Parent) + { + error("Parent is null!"); + return nullptr; + } + vfsdbg("AddNewChild( Name: \"%s\" Parent: \"%s\" )", + Name, Parent->Name); + + Node *newNode = new Node; + newNode->Parent = Parent; + newNode->Name = new char[strlen(Name) + 1]; + strncpy((char *)newNode->Name, Name, strlen(Name)); + + newNode->Operator = Parent->Operator; + newNode->FileSystem = this; + Parent->Children.push_back(newNode); + + vfsdbg("AddNewChild()->\"%s\"", newNode->Name); + return newNode; + } + + Node *Virtual::GetChild(const char *Name, Node *Parent) + { + vfsdbg("GetChild( Name: \"%s\" Parent: \"%s\" )", + Name, Parent->Name); + + if (!Parent) + { + vfsdbg("GetChild()->nullptr"); + return nullptr; + } + + foreach (auto Child in Parent->Children) + if (strcmp(Child->Name, Name) == 0) + { + vfsdbg("GetChild()->\"%s\"", Child->Name); + return Child; + } + vfsdbg("GetChild()->nullptr (not found)"); + return nullptr; + } + + int Virtual::RemoveChild(const char *Name, Node *Parent) + { + vfsdbg("RemoveChild( Name: \"%s\" Parent: \"%s\" )", + Name, Parent->Name); + + forItr(itr, Parent->Children) + { + if (strcmp((*itr)->Name, Name) == 0) + { + delete *itr, *itr = nullptr; + Parent->Children.erase(itr); + vfsdbg("RemoveChild()->OK"); + return 0; + } + } + + + vfsdbg("RemoveChild()->NotFound"); + return -1; + } + + std::string Virtual::NormalizePath(const char *Path, Node *Parent) + { + vfsdbg("NormalizePath( Path: \"%s\" Parent: \"%s\" )", + Path, Parent->Name); + + char *NormalizedPath = new char[strlen((char *)Path) + 1]; + std::string RelativePath; + + cwk_path_normalize(Path, NormalizedPath, strlen((char *)Path) + 1); + + if (cwk_path_is_relative(NormalizedPath)) + { + std::string ParentPath = GetPathFromNode(Parent); + size_t PathSize = cwk_path_join(ParentPath.c_str(), + NormalizedPath, + nullptr, 0); + + RelativePath.resize(PathSize + 1); + + cwk_path_join(ParentPath.c_str(), NormalizedPath, + (char *)RelativePath.c_str(), + PathSize + 1); + } + else + { + RelativePath = NormalizedPath; + } + delete[] NormalizedPath; + vfsdbg("NormalizePath()->\"%s\"", RelativePath.get()); + return RelativePath; + } + + bool Virtual::PathExists(const char *Path, Node *Parent) + { + if (isempty((char *)Path)) + { + vfsdbg("PathExists()->PathIsEmpty"); + return false; + } + + if (Parent == nullptr) + Parent = FileSystemRoot; + + vfsdbg("PathExists( Path: \"%s\" Parent: \"%s\" )", + Path, Parent->Name); + + if (GetNodeFromPath(NormalizePath(Path, Parent).c_str(), Parent)) + { + vfsdbg("PathExists()->OK"); + return true; + } + + vfsdbg("PathExists()->NotFound"); + return false; + } + + Node *Virtual::CreateRoot(const char *RootName, + FileSystemOperations *Operator) + { + if (Operator == nullptr) + return nullptr; + + debug("Creating root %s", RootName); + + SmartLock(VirtualLock); + Node *newNode = new Node; + newNode->Name = RootName; + newNode->Flags = NodeFlags::DIRECTORY; + newNode->Operator = Operator; + newNode->FileSystem = this; + FileSystemRoot->Children.push_back(newNode); + return newNode; + } + + /* TODO: Further testing needed */ + Node *Virtual::Create(const char *Path, NodeFlags Flag, Node *Parent) + { + if (isempty((char *)Path)) + return nullptr; + + SmartLock(VirtualLock); + Node *RootNode = FileSystemRoot->Children[0]; + Node *CurrentParent = this->GetParent(Path, Parent); + vfsdbg("Virtual::Create( Path: \"%s\" Parent: \"%s\" )", + Path, Parent ? Parent->Name : CurrentParent->Name); + + VirtualLock.Unlock(); + std::string CleanPath = this->NormalizePath(Path, CurrentParent); + VirtualLock.Lock(__FUNCTION__); + vfsdbg("CleanPath: \"%s\"", CleanPath.get()); + + VirtualLock.Unlock(); + if (PathExists(CleanPath.c_str(), CurrentParent)) + { + error("Path %s already exists.", CleanPath.c_str()); + goto CreatePathError; + } + VirtualLock.Lock(__FUNCTION__); + + cwk_segment segment; + if (!cwk_path_get_first_segment(CleanPath.c_str(), &segment)) + { + error("Path doesn't have any segments."); + goto CreatePathError; + } + + do + { + char *SegmentName = new char[segment.end - segment.begin + 1]; + memcpy(SegmentName, segment.begin, segment.end - segment.begin); + vfsdbg("SegmentName: \"%s\"", SegmentName); + + if (Parent) + { + if (GetChild(SegmentName, RootNode) != nullptr) + { + RootNode = GetChild(SegmentName, RootNode); + delete[] SegmentName; + continue; + } + } + + if (GetChild(SegmentName, CurrentParent) == nullptr) + { + CurrentParent = AddNewChild(SegmentName, CurrentParent); + CurrentParent->Flags = Flag; + } + else + { + CurrentParent = GetChild(SegmentName, CurrentParent); + } + + delete[] SegmentName; + } while (cwk_path_get_next_segment(&segment)); + + vfsdbg("Virtual::Create()->\"%s\"", CurrentParent->Name); +#ifdef DEBUG + VirtualLock.Unlock(); + debug("Path created: \"%s\"", + GetPathFromNode(CurrentParent).c_str()); + VirtualLock.Lock(__FUNCTION__); +#endif + return CurrentParent; + + CreatePathError: + vfsdbg("Virtual::Create()->nullptr"); + return nullptr; + } + + int Virtual::Delete(const char *Path, bool Recursive, Node *Parent) + { + vfsdbg("Virtual::Delete( Path: \"%s\" Parent: \"%s\" )", + Path, Parent ? Parent->Name : "(null)"); + + if (isempty((char *)Path)) + { + errno = EINVAL; + return -1; + } + + if (Parent == nullptr) + Parent = FileSystemRoot; + + std::string CleanPath = this->NormalizePath(Path, Parent); + vfsdbg("CleanPath: \"%s\"", CleanPath.c_str()); + + if (!PathExists(CleanPath.c_str(), Parent)) + { + vfsdbg("Path %s doesn't exist.", CleanPath.c_str()); + errno = ENOENT; + return -1; + } + + Node *NodeToDelete = GetNodeFromPath(CleanPath.c_str(), Parent); + + if (NodeToDelete->Flags == NodeFlags::DIRECTORY) + { + SmartLock(VirtualLock); + if (Recursive) + { + foreach (auto Child in NodeToDelete->Children) + { + VirtualLock.Unlock(); + int Status = Delete(GetPathFromNode(Child).c_str(), true); + VirtualLock.Lock(__FUNCTION__); + if (Status != 0) + { + error("Failed to delete child %s with status %d. (%s)", + Child->Name, Status, Path); + errno = EIO; + return -1; + } + } + } + else if (NodeToDelete->Children.size() > 0) + { + error("Directory %s is not empty.", CleanPath.c_str()); + errno = ENOTEMPTY; + return -1; + } + } + + SmartLock(VirtualLock); + Node *ParentNode = GetParent(CleanPath.c_str(), Parent); + if (RemoveChild(NodeToDelete->Name, ParentNode) != 0) + { + error("Failed to remove child %s from parent %s. (%s)", NodeToDelete->Name, ParentNode->Name, Path); + errno = EIO; + return -1; + } + + debug("Deleted %s", CleanPath.c_str()); + vfsdbg("Virtual::Delete()->OK"); + return 0; + } + + int Virtual::Delete(Node *Path, bool Recursive, Node *Parent) + { + std::string PathString = GetPathFromNode(Path); + return Delete(PathString.c_str(), Recursive, Parent); + } + + /* TODO: REWORK */ + Node *Virtual::Mount(const char *Path, FileSystemOperations *Operator) + { + if (unlikely(!Operator)) + { + errno = EFAULT; + return nullptr; + } + + if (unlikely(isempty((char *)Path))) + { + errno = EINVAL; + return nullptr; + } + + vfsdbg("Mounting %s", Path); + const char *PathCopy; + cwk_path_get_basename(Path, &PathCopy, 0); + Node *MountPoint = Create(Path, NodeFlags::MOUNTPOINT); + MountPoint->Operator = Operator; + return MountPoint; + } + + int Virtual::Unmount(Node *File) + { + if (unlikely(!File)) + { + errno = EINVAL; + return -1; + } + + if (unlikely(File->Flags != NodeFlags::MOUNTPOINT)) + { + errno = ENOTDIR; + return -1; + } + + fixme("Unmounting %s", + File->Name); + errno = ENOSYS; + return -1; + } + + RefNode *Virtual::Open(const char *Path, Node *Parent) + { + vfsdbg("Opening %s with parent %s", Path, Parent ? Parent->Name : "(null)"); + + if (strcmp(Path, "/") == 0) + return FileSystemRoot->CreateReference(); + + if (!Parent) + Parent = FileSystemRoot->Children[0]; + + if (strcmp(Path, ".") == 0) + return Parent->CreateReference(); + + if (strcmp(Path, "..") == 0) + { + if (Parent->Parent) + return Parent->Parent->CreateReference(); + else + return Parent->CreateReference(); + } + + Node *CurrentParent = this->GetParent(Path, Parent); + std::string CleanPath = NormalizePath(Path, CurrentParent); + + /* TODO: Check for other errors */ + if (!PathExists(CleanPath.c_str(), CurrentParent)) + { + { + SmartLock(VirtualLock); + foreach (auto Child in FileSystemRoot->Children) + { + if (strcmp(Child->Name, CleanPath.c_str()) != 0) + continue; + + return Child->CreateReference(); + } + } + + Node *node = GetNodeFromPath(CleanPath.c_str(), FileSystemRoot->Children[0]); + if (node) + return node->CreateReference(); + } + else + { + Node *node = GetNodeFromPath(CleanPath.c_str(), CurrentParent); + if (node) + return node->CreateReference(); + } + + errno = ENOENT; + return nullptr; + } + + Virtual::Virtual() + { + SmartLock(VirtualLock); + trace("Initializing virtual file system..."); + FileSystemRoot = new Node; + FileSystemRoot->Flags = NodeFlags::MOUNTPOINT; + FileSystemRoot->Operator = nullptr; + FileSystemRoot->Parent = nullptr; + FileSystemRoot->Name = "root"; + FileSystemRoot->FileSystem = this; + cwk_path_set_style(CWK_STYLE_UNIX); + } + + Virtual::~Virtual() + { + SmartLock(VirtualLock); + stub; + /* TODO: sync, cache */ + } } diff --git a/FileSystem/Kernel_IO.cpp b/FileSystem/Kernel_IO.cpp new file mode 100644 index 0000000..e787f12 --- /dev/null +++ b/FileSystem/Kernel_IO.cpp @@ -0,0 +1,157 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include +#include + +#include "../kernel.h" + +using Tasking::PCB; +using VirtualFileSystem::FileDescriptorTable; + +static bool CheckForScheduler() +{ + if (TaskManager == nullptr) + return false; + return true; +} + +int fopen(const char *pathname, const char *mode) +{ + if (!CheckForScheduler()) + { + errno = ENOSYS; + return -1; + } + + PCB *pcb = thisProcess; + FileDescriptorTable *fdt = pcb->FileDescriptors; + int fd = fdt->_open(pathname, ConvertFileFlags(mode), 0666); + return fd; +} + +int creat(const char *pathname, mode_t mode) +{ + if (!CheckForScheduler()) + { + errno = ENOSYS; + return -1; + } + + PCB *pcb = thisProcess; + FileDescriptorTable *fdt = pcb->FileDescriptors; + int fd = fdt->_creat(pathname, mode); + return fd; +} + +ssize_t fread(int fd, void *buf, size_t count) +{ + if (!CheckForScheduler()) + { + errno = ENOSYS; + return -1; + } + + PCB *pcb = thisProcess; + FileDescriptorTable *fdt = pcb->FileDescriptors; + ssize_t r = fdt->_read(fd, buf, count); + return r; +} + +ssize_t fwrite(int fd, const void *buf, size_t count) +{ + if (!CheckForScheduler()) + { + errno = ENOSYS; + return -1; + } + + PCB *pcb = thisProcess; + FileDescriptorTable *fdt = pcb->FileDescriptors; + ssize_t r = fdt->_write(fd, buf, count); + return r; +} + +int fclose(int fd) +{ + if (!CheckForScheduler()) + { + errno = ENOSYS; + return -1; + } + + PCB *pcb = thisProcess; + FileDescriptorTable *fdt = pcb->FileDescriptors; + int r = fdt->_close(fd); + return r; +} + +off_t lseek(int fd, off_t offset, int whence) +{ + if (!CheckForScheduler()) + { + errno = ENOSYS; + return -1; + } + + PCB *pcb = thisProcess; + FileDescriptorTable *fdt = pcb->FileDescriptors; + off_t r = fdt->_lseek(fd, offset, whence); + return r; +} + +int stat(const char *pathname, struct stat *statbuf) +{ + if (!CheckForScheduler()) + { + errno = ENOSYS; + return -1; + } + + PCB *pcb = thisProcess; + FileDescriptorTable *fdt = pcb->FileDescriptors; + int r = fdt->_stat(pathname, statbuf); + return r; +} + +int fstat(int fd, struct stat *statbuf) +{ + if (!CheckForScheduler()) + { + errno = ENOSYS; + return -1; + } + + PCB *pcb = thisProcess; + FileDescriptorTable *fdt = pcb->FileDescriptors; + int r = fdt->_fstat(fd, statbuf); + return r; +} + +int lstat(const char *pathname, struct stat *statbuf) +{ + if (!CheckForScheduler()) + { + errno = ENOSYS; + return -1; + } + + PCB *pcb = thisProcess; + FileDescriptorTable *fdt = pcb->FileDescriptors; + int r = fdt->_lstat(pathname, statbuf); + return r; +} diff --git a/GUI/GUITools.cpp b/GUI/GUITools.cpp deleted file mode 100644 index 9907261..0000000 --- a/GUI/GUITools.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include "../kernel.h" - -namespace GraphicalUserInterface -{ - Ofast inline void InlineSetPixel(ScreenBitmap *Bitmap, int64_t X, int64_t Y, uint32_t Color) - { - if (unlikely(X < 0 || Y < 0 || X >= (int64_t)Bitmap->Width || Y >= (int64_t)Bitmap->Height)) - return; - - uint32_t *Pixel = (uint32_t *)((uintptr_t)Bitmap->Data + (Y * Bitmap->Width + X) * (Bitmap->BitsPerPixel / 8)); - *Pixel = Color; - // Bitmap->Data[Y * Bitmap->Width + X] = Color; - } - - void SetPixel(ScreenBitmap *Bitmap, size_t X, size_t Y, uint32_t Color) - { - if (unlikely(!Bitmap)) - return; - - if (unlikely(!Bitmap->Data)) - return; - - InlineSetPixel(Bitmap, X, Y, Color); - } - - uint32_t GetPixel(ScreenBitmap *Bitmap, int64_t X, int64_t Y) - { - if (unlikely(!Bitmap)) - return 0; - - if (unlikely(!Bitmap->Data)) - return 0; - - if (unlikely(X < 0 || Y < 0 || X >= (int64_t)Bitmap->Width || Y >= (int64_t)Bitmap->Height)) - return 0; - - uint32_t *Pixel = (uint32_t *)((uintptr_t)Bitmap->Data + (Y * Bitmap->Width + X) * (Bitmap->BitsPerPixel / 8)); - return *Pixel; - } - - Ofast void DrawOverBitmap(ScreenBitmap *DestinationBitmap, - ScreenBitmap *SourceBitmap, - int64_t Top, - int64_t Left, bool IgnoreZero) - { - if (unlikely(!SourceBitmap) || unlikely(!SourceBitmap->Data) || - unlikely(!DestinationBitmap) || unlikely(!DestinationBitmap->Data)) - return; - - // for (uint32_t i = 0; i < SourceBitmap->Width; i++) - // for (uint32_t j = 0; j < SourceBitmap->Height; j++) - // { - // uint32_t *Pixel = (uint32_t *)((uintptr_t)SourceBitmap->Data + (j * SourceBitmap->Width + i) * (SourceBitmap->BitsPerPixel / 8)); - // if (IgnoreZero && (*Pixel != 0x000000)) - // InlineSetPixel(DestinationBitmap, Left + i, Top + j, *Pixel); - // } - - for (uint32_t j = 0; j < SourceBitmap->Height; j++) - { - uint32_t *Pixel = (uint32_t *)((uintptr_t)SourceBitmap->Data + j * SourceBitmap->Width * (SourceBitmap->BitsPerPixel / 8)); - if (IgnoreZero) - { - for (uint32_t i = 0; i < SourceBitmap->Width; i++) - { - if (Pixel[i] != 0x000000) - InlineSetPixel(DestinationBitmap, Left + i, Top + j, Pixel[i]); - } - } - else - { - memcpy((void *)((uintptr_t)DestinationBitmap->Data + (Top + j) * DestinationBitmap->Width * (DestinationBitmap->BitsPerPixel / 8) + Left * (DestinationBitmap->BitsPerPixel / 8)), - (void *)((uintptr_t)SourceBitmap->Data + j * SourceBitmap->Width * (SourceBitmap->BitsPerPixel / 8)), - (size_t)(SourceBitmap->Width * (SourceBitmap->BitsPerPixel / 8))); - } - } - } - - Ofast void PutRect(ScreenBitmap *Bitmap, Rect rect, uint32_t Color) - { - if (unlikely(!Bitmap)) - return; - - if (unlikely(!Bitmap->Data)) - return; - - for (uint32_t i = 0; i < rect.Width; i++) - for (uint32_t j = 0; j < rect.Height; j++) - InlineSetPixel(Bitmap, rect.Left + i, rect.Top + j, Color); - } - - void PutBorder(ScreenBitmap *Bitmap, Rect rect, uint32_t Color) - { - if (unlikely(!Bitmap)) - return; - - if (unlikely(!Bitmap->Data)) - return; - - for (uint32_t i = 0; i < rect.Width; i++) - { - InlineSetPixel(Bitmap, rect.Left + i, rect.Top, Color); - InlineSetPixel(Bitmap, rect.Left + i, rect.Top + rect.Height - 1, Color); - } - for (uint32_t i = 0; i < rect.Height; i++) - { - InlineSetPixel(Bitmap, rect.Left, rect.Top + i, Color); - InlineSetPixel(Bitmap, rect.Left + rect.Width - 1, rect.Top + i, Color); - } - } - - uint32_t BlendColors(uint32_t c1, uint32_t c2, float t) - { - uint8_t r1 = (c1 >> 16) & 0xFF; - uint8_t g1 = (c1 >> 8) & 0xFF; - uint8_t b1 = c1 & 0xFF; - uint8_t r2 = (c2 >> 16) & 0xFF; - uint8_t g2 = (c2 >> 8) & 0xFF; - uint8_t b2 = c2 & 0xFF; - - uint8_t r = (uint8_t)(r1 + t * (r2 - r1)); - uint8_t g = (uint8_t)(g1 + t * (g2 - g1)); - uint8_t b = (uint8_t)(b1 + t * (b2 - b1)); - - return (r << 16) | (g << 8) | b; - } - - void PutBorderWithShadow(ScreenBitmap *Bitmap, Rect rect, uint32_t Color) - { - UNUSED(Bitmap); - UNUSED(rect); - UNUSED(Color); - } - -#define SHADOW_SIZE 12 - - void DrawShadow(ScreenBitmap *Bitmap, Rect rect) - { - UNUSED(Bitmap); - UNUSED(rect); - } - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-overflow" - void PaintChar(Video::Font *font, ScreenBitmap *Bitmap, char c, uint32_t Color, int64_t *CharCursorX, int64_t *CharCursorY) - { - switch (font->GetInfo().Type) - { - case Video::FontType::PCScreenFont1: - { - // uint32_t *PixelPtr = (uint32_t *)Bitmap->Data; - char *FontPtr = (char *)font->GetInfo().PSF1Font->GlyphBuffer + (c * font->GetInfo().PSF1Font->Header->charsize); - for (int64_t Y = *CharCursorY; Y < *CharCursorY + 16; Y++) - { - for (int64_t X = *CharCursorX; X < *CharCursorX + 8; X++) - if ((*FontPtr & (0b10000000 >> (X - *CharCursorX))) > 0) - InlineSetPixel(Bitmap, X, Y, Color); - FontPtr++; - } - *CharCursorX += 8; - break; - } - case Video::FontType::PCScreenFont2: - { - // if (font->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE - // Char = font->PSF2Font->GlyphBuffer[Char]; - int BytesPerLine = (font->GetInfo().PSF2Font->Header->width + 7) / 8; - char *FontPtr = (char *)font->GetInfo().StartAddress + - font->GetInfo().PSF2Font->Header->headersize + - (c > 0 && (unsigned char)c < font->GetInfo().PSF2Font->Header->length ? c : 0) * - font->GetInfo().PSF2Font->Header->charsize; - - uint32_t fonthdrWidth = font->GetInfo().PSF2Font->Header->width; - uint32_t fonthdrHeight = font->GetInfo().PSF2Font->Header->height; - - for (int64_t Y = *CharCursorY; Y < *CharCursorY + fonthdrHeight; Y++) - { - for (int64_t X = *CharCursorX; X < *CharCursorX + fonthdrWidth; X++) - if ((*FontPtr & (0b10000000 >> (X - *CharCursorX))) > 0) - InlineSetPixel(Bitmap, X, Y, Color); - FontPtr += BytesPerLine; - } - *CharCursorX += fonthdrWidth; - break; - } - default: - warn("Unsupported font type"); - break; - } - } -#pragma GCC diagnostic pop - - void DrawString(ScreenBitmap *Bitmap, Rect rect, const char *Text, uint32_t Color) - { - UNUSED(Bitmap); - UNUSED(rect); - UNUSED(Text); - UNUSED(Color); - } -} diff --git a/GUI/GraphicalUserInterface.cpp b/GUI/GraphicalUserInterface.cpp deleted file mode 100644 index 9fc5b08..0000000 --- a/GUI/GraphicalUserInterface.cpp +++ /dev/null @@ -1,667 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include -#include -#include -#include - -#include "icons.hpp" -#include "../kernel.h" -#include "../DAPI.hpp" -#include "../Fex.hpp" - -extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start; -extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end; -extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_size; - -#ifdef DEBUG -size_t FIi = 0, PDi = 0, PWi = 0, PWWi = 0, PCi = 0, mmi = 0; -#endif - -namespace GraphicalUserInterface -{ - void GUI::FetchInputs() - { - MouseData Mouse; - bool FoundMouseDriver = false; - if (likely(DriverManager->GetDrivers().size() > 0)) - { - foreach (auto Driver in DriverManager->GetDrivers()) - { - if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Input && - ((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.TypeFlags & FexDriverInputTypes::FexDriverInputTypes_Mouse) - { -#ifdef DEBUG - static int once = 0; - if (!once++) - debug("Found mouse driver %ld", Driver.DriverUID); -#endif - KernelCallback callback{}; - callback.Reason = FetchReason; - DriverManager->IOCB(Driver.DriverUID, &callback); - Mouse.X = callback.InputCallback.Mouse.X; - Mouse.Y = callback.InputCallback.Mouse.Y; - Mouse.Z = callback.InputCallback.Mouse.Z; - Mouse.Left = callback.InputCallback.Mouse.Buttons.Left; - Mouse.Right = callback.InputCallback.Mouse.Buttons.Right; - Mouse.Middle = callback.InputCallback.Mouse.Buttons.Middle; - FoundMouseDriver = true; - break; - } - } - } - - if (unlikely(!FoundMouseDriver)) - { - static int once = 0; - if (!once++) - debug("No mouse driver found."); - Mouse.X = Display->GetBuffer(200)->Width / 2; - Mouse.Y = Display->GetBuffer(200)->Height / 2; - Mouse.Z = 0; - Mouse.Left = false; - Mouse.Right = false; - Mouse.Middle = false; - } - - Event eTemplate; - memset(&eTemplate, 0, sizeof(Event)); - foreach (auto wnd in this->Windows) - { - /* On mouse down event */ - if (unlikely((!MouseArray[1].Left || !MouseArray[1].Right || !MouseArray[1].Middle) && - (Mouse.Left || Mouse.Right || Mouse.Middle))) - { - eTemplate.MouseDown.X = Mouse.X; - eTemplate.MouseDown.Y = Mouse.Y; - eTemplate.MouseDown.Left = Mouse.Left; - eTemplate.MouseDown.Right = Mouse.Right; - eTemplate.MouseDown.Middle = Mouse.Middle; - wnd->OnMouseDown(&eTemplate); - } - - /* On mouse up event */ - if (unlikely((MouseArray[1].Left || MouseArray[1].Right || MouseArray[1].Middle) && - (!Mouse.Left || !Mouse.Right || !Mouse.Middle))) - { - eTemplate.MouseUp.X = Mouse.X; - eTemplate.MouseUp.Y = Mouse.Y; - eTemplate.MouseUp.Left = Mouse.Left; - eTemplate.MouseUp.Right = Mouse.Right; - eTemplate.MouseUp.Middle = Mouse.Middle; - wnd->OnMouseUp(&eTemplate); - } - - static int Idle = 0; - - if (likely(Mouse.X != MouseArray[1].X || Mouse.Y != MouseArray[1].Y)) - { - Idle = 0; - Rect TopBarPos = wnd->GetPosition(); - TopBarPos.Top -= 20; - TopBarPos.Height = 20; - TopBarPos.Width -= 60; /* buttons */ - if (unlikely((int64_t)TopBarPos.Top < 0)) - { - TopBarPos.Top = 0; - wnd->GetPositionPtr()->Top = 20; - } - - Rect ResizeHintPos = wnd->GetPosition(); - ResizeHintPos.Left += ResizeHintPos.Width - 20; - ResizeHintPos.Top += ResizeHintPos.Height - 20; - ResizeHintPos.Width = 20; - ResizeHintPos.Height = 20; - - if (unlikely(TopBarPos.Contains(Mouse.X, Mouse.Y) || - TopBarPos.Contains(MouseArray[0].X, MouseArray[0].Y) || - TopBarPos.Contains(MouseArray[1].X, MouseArray[1].Y))) - { - if (likely(Mouse.Left)) - { - if (likely(MouseArray[1].Left)) - { - wnd->GetPositionPtr()->Left += Mouse.X - MouseArray[0].X; - wnd->GetPositionPtr()->Top += Mouse.Y - MouseArray[0].Y; - OverlayBufferRepaint = true; - OverlayFullRepaint = true; - } - } - } - - if (ResizeHintPos.Contains(Mouse.X, Mouse.Y) || - ResizeHintPos.Contains(MouseArray[0].X, MouseArray[0].Y) || - ResizeHintPos.Contains(MouseArray[1].X, MouseArray[1].Y)) - { - if (Mouse.Left) - { - if (MouseArray[1].Left) - { - wnd->GetPositionPtr()->Width += (size_t)(Mouse.X - MouseArray[0].X); - wnd->GetPositionPtr()->Height += (size_t)(Mouse.Y - MouseArray[0].Y); - - if (wnd->GetPositionPtr()->Width < 200) - { - wnd->GetPositionPtr()->Width = 200; - Mouse.X = MouseArray[0].X; - } - - if (wnd->GetPositionPtr()->Height < 100) - { - wnd->GetPositionPtr()->Height = 100; - Mouse.Y = MouseArray[0].Y; - } - - OverlayBufferRepaint = true; - OverlayFullRepaint = true; - eTemplate.Resize.Width = wnd->GetPosition().Width; - eTemplate.Resize.Height = wnd->GetPosition().Height; - - wnd->OnResize(&eTemplate); - } - } - - if (unlikely(Cursor != CursorType::ResizeAll)) - { - Cursor = CursorType::ResizeAll; - CursorBufferRepaint = true; - } - } - else - { - if (unlikely(Cursor != CursorType::Arrow)) - { - Cursor = CursorType::Arrow; - CursorBufferRepaint = true; - } - } - - eTemplate.MouseMove.X = Mouse.X; - eTemplate.MouseMove.Y = Mouse.Y; - eTemplate.MouseMove.Left = Mouse.Left; - eTemplate.MouseMove.Right = Mouse.Right; - eTemplate.MouseMove.Middle = Mouse.Middle; - wnd->OnMouseMove(&eTemplate); - } - else - { - if (unlikely(Idle > 1000)) - CPU::Pause(); - else - Idle++; - } - } - - foreach (auto wdg in this->Widgets) - { - // TODO: Implement mouse events for widgets - UNUSED(wdg); - } - - memmove(MouseArray + 1, MouseArray, sizeof(MouseArray) - sizeof(MouseArray[1])); - MouseArray[0] = Mouse; - - LastCursor = Cursor; - } - - void GUI::PaintDesktop() - { - if (DesktopBufferRepaint) - { - // PutRect(this->DesktopBuffer, this->Desktop, 0x404040); - memset(this->DesktopBuffer->Data, 0x404040, this->DesktopBuffer->Size); - DesktopBufferRepaint = false; - } - // Well... I have to do some code optimization on DrawOverBitmap. It's too slow and it's not even using SIMD - memcpy(this->BackBuffer->Data, this->DesktopBuffer->Data, this->DesktopBuffer->Size); - } - - void GUI::PaintWidgets() - { - Event eTemplate; - memset(&eTemplate, 0, sizeof(Event)); - foreach (auto wdg in this->Widgets) - wdg->OnPaint(nullptr); - } - - void GUI::PaintWindows() - { - foreach (auto wnd in this->Windows) - { - ScreenBitmap *wndBuffer = wnd->GetBuffer(); - if (unlikely(wndBuffer == nullptr)) // I think "unlikely" is not needed here - continue; - - Rect WndPos = wnd->GetPosition(); - - // Draw window content - DrawOverBitmap(this->BackBuffer, - wndBuffer, - WndPos.Top, - WndPos.Left); - - /* We can't use memcpy because the window buffer - is not the same size as the screen buffer - https://i.imgur.com/OHfaYnS.png */ - // memcpy(this->BackBuffer->Data + wnd->GetPositionPtr()->Top * this->BackBuffer->Width + wnd->GetPositionPtr()->Left, wndBuffer->Data, wndBuffer->Size); - - Rect TopBarPos = WndPos; - TopBarPos.Top -= 20; - TopBarPos.Height = 20; - if ((int64_t)TopBarPos.Top < 0) - { - TopBarPos.Top = 0; - wnd->GetPositionPtr()->Top = 20; - } - - Rect CloseButtonPos; - Rect MinimizeButtonPos; - - CloseButtonPos.Left = TopBarPos.Left + TopBarPos.Width - 20; - CloseButtonPos.Top = TopBarPos.Top; - CloseButtonPos.Width = 20; - CloseButtonPos.Height = 20; - - MinimizeButtonPos.Left = TopBarPos.Left + TopBarPos.Width - 60; - - if (unlikely(MouseArray[0].X >= (size_t)MinimizeButtonPos.Left && - MouseArray[0].X <= (size_t)CloseButtonPos.Left + CloseButtonPos.Width && - MouseArray[0].Y >= (size_t)CloseButtonPos.Top && - MouseArray[0].Y <= (size_t)CloseButtonPos.Top + CloseButtonPos.Height)) - { - OverlayBufferRepaint = true; - } - - // Title bar - if (unlikely(OverlayBufferRepaint)) - { - if (OverlayFullRepaint) - { - memset(this->OverlayBuffer->Data, 0, this->OverlayBuffer->Size); - OverlayFullRepaint = false; - } - - static bool RepaintNeeded = false; - DrawShadow(this->OverlayBuffer, wnd->GetPosition()); - - Rect MaximizeButtonPos; - MaximizeButtonPos.Left = TopBarPos.Left + TopBarPos.Width - 40; - MaximizeButtonPos.Top = TopBarPos.Top; - MaximizeButtonPos.Width = 20; - MaximizeButtonPos.Height = 20; - - MinimizeButtonPos.Top = TopBarPos.Top; - MinimizeButtonPos.Width = 20; - MinimizeButtonPos.Height = 20; - - PutRect(this->OverlayBuffer, TopBarPos, 0x282828); - // Title bar buttons (close, minimize, maximize) on the right - if (MouseArray[0].X >= (size_t)CloseButtonPos.Left && - MouseArray[0].X <= (size_t)CloseButtonPos.Left + CloseButtonPos.Width && - MouseArray[0].Y >= (size_t)CloseButtonPos.Top && - MouseArray[0].Y <= (size_t)CloseButtonPos.Top + CloseButtonPos.Height) - { - PutRect(this->OverlayBuffer, CloseButtonPos, MouseArray[0].Left ? 0xFF5500 : 0xFF0000); - RepaintNeeded = true; - } - else - { - PutRect(this->OverlayBuffer, MaximizeButtonPos, 0x282828); - } - - if (MouseArray[0].X >= (size_t)MaximizeButtonPos.Left && - MouseArray[0].X <= (size_t)MaximizeButtonPos.Left + MaximizeButtonPos.Width && - MouseArray[0].Y >= (size_t)MaximizeButtonPos.Top && - MouseArray[0].Y <= (size_t)MaximizeButtonPos.Top + MaximizeButtonPos.Height) - { - PutRect(this->OverlayBuffer, MaximizeButtonPos, MouseArray[0].Left ? 0x454545 : 0x404040); - RepaintNeeded = true; - } - else - { - PutRect(this->OverlayBuffer, MaximizeButtonPos, 0x282828); - } - - if (MouseArray[0].X >= (size_t)MinimizeButtonPos.Left && - MouseArray[0].X <= (size_t)MinimizeButtonPos.Left + MinimizeButtonPos.Width && - MouseArray[0].Y >= (size_t)MinimizeButtonPos.Top && - MouseArray[0].Y <= (size_t)MinimizeButtonPos.Top + MinimizeButtonPos.Height) - { - PutRect(this->OverlayBuffer, MinimizeButtonPos, MouseArray[0].Left ? 0x454545 : 0x404040); - RepaintNeeded = true; - } - else - { - PutRect(this->OverlayBuffer, MinimizeButtonPos, 0x282828); - } - - // Title bar icons (close, minimize, maximize) on the right - for (short i = 0; i < 20; i++) - { - for (short j = 0; j < 20; j++) - { - if (CloseButton[i * 20 + j] == 1) - SetPixel(this->OverlayBuffer, - CloseButtonPos.Left + j, - CloseButtonPos.Top + i, - 0xFFFFFF); - - if ((MaximizeButtonMaximized[i * 20 + j] == 1) && !wnd->IsMaximized()) - SetPixel(this->OverlayBuffer, - MaximizeButtonPos.Left + j, - MaximizeButtonPos.Top + i, - 0xFFFFFF); - else if ((MaximizeButtonNormal[i * 20 + j] == 1) && wnd->IsMaximized()) - SetPixel(this->OverlayBuffer, - MaximizeButtonPos.Left + j, - MaximizeButtonPos.Top + i, - 0xFFFFFF); - - if (MinimizeButton[i * 20 + j] == 1) - SetPixel(this->OverlayBuffer, - MinimizeButtonPos.Left + j, - MinimizeButtonPos.Top + i, - 0xFFFFFF); - } - } - - Rect wndPos = wnd->GetPosition(); - - // Resize hint - for (short i = 0; i < 20; i++) - for (short j = 0; j < 20; j++) - if (ResizeHint[i * 20 + j] == 1) - SetPixel(this->OverlayBuffer, wndPos.Left + wndPos.Width - 20 + j, wndPos.Top + wndPos.Height - 20 + i, 0xFFFFFF); - - // Title bar border - PutBorder(this->OverlayBuffer, TopBarPos, 0xFF000000); - // Window border - PutBorder(this->OverlayBuffer, wndPos, 0xFF000000); - - Rect TopBarTextPos = TopBarPos; - TopBarTextPos.Left += 4; - TopBarTextPos.Top += 4; - - // Title bar text - int64_t CharCursorX = TopBarTextPos.Left; - int64_t CharCursorY = TopBarTextPos.Top; - for (uint64_t i = 0; i < strlen(wnd->GetTitle()); i++) - PaintChar(this->CurrentFont, this->OverlayBuffer, wnd->GetTitle()[i], 0xFFFFFF, &CharCursorX, &CharCursorY); - - if (!RepaintNeeded) - { - OverlayBufferRepaint = false; - RepaintNeeded = false; - } - } - wnd->OnPaint(nullptr); - } - DrawOverBitmap(this->BackBuffer, this->OverlayBuffer, 0, 0); - } - -/* - "* 2" to increase the size of the cursor - "/ 2" to decrease the size of the cursor -*/ -#define ICON_SIZE - - void GUI::PaintCursor() - { - uint32_t CursorColorInner = 0xFFFFFFFF; - uint32_t CursorColorOuter = 0xFF000000; - - if (MouseArray[0].X != MouseArray[1].X || - MouseArray[0].Y != MouseArray[1].Y || - MouseArray[0].Z != MouseArray[1].Z || - Cursor != LastCursor) - CursorBufferRepaint = true; - - if (CursorBufferRepaint) - { - memset(this->CursorBuffer->Data, 0, this->CursorBuffer->Size); - switch (this->Cursor) - { - case CursorType::Visible: - { - CursorVisible = true; - break; - } - case CursorType::Hidden: - { - CursorVisible = false; - break; - } - default: - fixme("Unknown cursor type %d", this->Cursor); - [[fallthrough]]; - case CursorType::Arrow: - { - if (CursorVisible) - for (int i = 0; i < 19; i++) - { - for (int j = 0; j < 12; j++) - { - if (CursorArrow[i * 12 + j] == 1) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorOuter); - } - else if (CursorArrow[i * 12 + j] == 2) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorInner); - } - } - } - break; - } - case CursorType::Hand: - { - if (CursorVisible) - for (int i = 0; i < 24; i++) - { - for (int j = 0; j < 17; j++) - { - if (CursorHand[i * 17 + j] == 1) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorOuter); - } - else if (CursorHand[i * 17 + j] == 2) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorInner); - } - } - } - break; - } - case CursorType::Wait: - { - if (CursorVisible) - for (int i = 0; i < 22; i++) - { - for (int j = 0; j < 13; j++) - { - if (CursorWait[i * 13 + j] == 1) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorOuter); - } - else if (CursorWait[i * 13 + j] == 2) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorInner); - } - } - } - break; - } - case CursorType::IBeam: - { - if (CursorVisible) - for (int i = 0; i < 22; i++) - { - for (int j = 0; j < 13; j++) - { - if (CursorIBeam[i * 13 + j] == 1) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorOuter); - } - else if (CursorIBeam[i * 13 + j] == 2) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorInner); - } - } - } - break; - } - case CursorType::ResizeAll: - { - if (CursorVisible) - for (int i = 0; i < 23; i++) - { - for (int j = 0; j < 23; j++) - { - if (CursorResizeAll[i * 23 + j] == 1) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorOuter); - } - else if (CursorResizeAll[i * 23 + j] == 2) - { - SetPixel(this->CursorBuffer, j ICON_SIZE, i ICON_SIZE, CursorColorInner); - } - } - } - break; - } - } - CursorBufferRepaint = false; - } - DrawOverBitmap(this->BackBuffer, this->CursorBuffer, MouseArray[0].Y, MouseArray[0].X); - } - - void GUI::Loop() - { - /* - Because we do not use a gpu to do the rendering, we need to do it manually. - This is why the mouse is slow when we have to draw a bunch of things. - */ - while (IsRunning) - { -#ifdef DEBUG - FIi = CPU::Counter(); -#endif - FetchInputs(); -#ifdef DEBUG - FIi = CPU::Counter() - FIi; - PDi = CPU::Counter(); -#endif - PaintDesktop(); -#ifdef DEBUG - PDi = CPU::Counter() - PDi; - PWi = CPU::Counter(); -#endif - PaintWidgets(); -#ifdef DEBUG - PWi = CPU::Counter() - PWi; - PWWi = CPU::Counter(); -#endif - PaintWindows(); -#ifdef DEBUG - PWWi = CPU::Counter() - PWWi; - PCi = CPU::Counter(); -#endif - PaintCursor(); -#ifdef DEBUG - PCi = CPU::Counter() - PCi; - mmi = CPU::Counter(); -#endif - memcpy(Display->GetBuffer(200)->Buffer, this->BackBuffer->Data, this->BackBuffer->Size); - Display->SetBuffer(200); -#ifdef DEBUG - mmi = CPU::Counter() - mmi; -#endif - } - } - - void GUI::AddWindow(Window *window) - { - this->Windows.push_back(window); - } - - void GUI::AddWidget(WidgetCollection *widget) - { - this->Widgets.push_back(widget); - } - - GUI::GUI() - { - Display->CreateBuffer(0, 0, 200); - this->CurrentFont = new Video::Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, Video::FontType::PCScreenFont2); - this->mem = new Memory::MemMgr; - this->Desktop.Top = 0; - this->Desktop.Left = 0; - this->Desktop.Width = Display->GetBuffer(200)->Width; - this->Desktop.Height = Display->GetBuffer(200)->Height; - - this->BackBuffer = new ScreenBitmap; - this->BackBuffer->Width = this->Desktop.Width; - this->BackBuffer->Height = this->Desktop.Height; - this->BackBuffer->BitsPerPixel = Display->GetBitsPerPixel(); - this->BackBuffer->Pitch = Display->GetPitch(); - this->BackBuffer->Size = Display->GetBuffer(200)->Size; - this->BackBuffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->BackBuffer->Size + 1)); - memset(this->BackBuffer->Data, 0, this->BackBuffer->Size); - - this->DesktopBuffer = new ScreenBitmap; - this->DesktopBuffer->Width = this->Desktop.Width; - this->DesktopBuffer->Height = this->Desktop.Height; - this->DesktopBuffer->BitsPerPixel = Display->GetBitsPerPixel(); - this->DesktopBuffer->Pitch = Display->GetPitch(); - this->DesktopBuffer->Size = Display->GetBuffer(200)->Size; - this->DesktopBuffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->DesktopBuffer->Size + 1)); - memset(this->DesktopBuffer->Data, 0, this->DesktopBuffer->Size); - - this->OverlayBuffer = new ScreenBitmap; - this->OverlayBuffer->Width = this->Desktop.Width; - this->OverlayBuffer->Height = this->Desktop.Height; - this->OverlayBuffer->BitsPerPixel = Display->GetBitsPerPixel(); - this->OverlayBuffer->Pitch = Display->GetPitch(); - this->OverlayBuffer->Size = Display->GetBuffer(200)->Size; - this->OverlayBuffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->OverlayBuffer->Size + 1)); - memset(this->OverlayBuffer->Data, 0, this->OverlayBuffer->Size); - - this->CursorBuffer = new ScreenBitmap; - this->CursorBuffer->Width = 25; - this->CursorBuffer->Height = 25; - this->CursorBuffer->BitsPerPixel = Display->GetBitsPerPixel(); - this->CursorBuffer->Pitch = Display->GetPitch(); - this->CursorBuffer->Size = (size_t)(this->CursorBuffer->Width * this->CursorBuffer->Height * (this->CursorBuffer->BitsPerPixel / 8)); - this->CursorBuffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->CursorBuffer->Size + 1)); - memset(this->CursorBuffer->Data, 0, this->CursorBuffer->Size); - - this->IsRunning = true; - } - - GUI::~GUI() - { - debug("Destructor called"); - delete this->mem, this->mem = nullptr; - delete this->BackBuffer, this->BackBuffer = nullptr; - delete this->DesktopBuffer, this->DesktopBuffer = nullptr; - delete this->OverlayBuffer, this->OverlayBuffer = nullptr; - delete this->CursorBuffer, this->CursorBuffer = nullptr; - Display->DeleteBuffer(200); - this->Windows.clear(); - } -} diff --git a/GUI/Icons.cpp b/GUI/Icons.cpp deleted file mode 100644 index 8974bae..0000000 --- a/GUI/Icons.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include "icons.hpp" - -char CursorArrow[] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 12x19 - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, // - 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, // - 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, // - 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, // - 1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, // - 1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, // - 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, // - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, // - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, // - 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, // - 1, 2, 2, 2, 1, 2, 2, 1, 0, 0, 0, 0, // - 1, 2, 2, 1, 0, 1, 2, 2, 1, 0, 0, 0, // - 1, 2, 1, 0, 0, 1, 2, 2, 1, 0, 0, 0, // - 1, 1, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, // - 1, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, // -}; - -char CursorHand[] = { - 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 17x24 - 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 1, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 1, 2, 2, 1, 2, 2, 1, 1, 1, 0, 0, 0, 0, // - 0, 0, 0, 0, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 1, 0, 0, // - 0, 0, 0, 0, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 0, // - 0, 0, 0, 0, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, // - 1, 1, 1, 0, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, // - 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, // - 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, // - 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, // - 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, // - 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, // - 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, // - 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, // - 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, // - 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, // - 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, // - 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, // - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -}; - -char CursorWait[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 13x22 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, // - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // - 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, // - 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, // - 0, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 0, // - 0, 1, 2, 2, 2, 1, 2, 1, 2, 2, 2, 1, 0, // - 0, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 0, // - 0, 0, 1, 1, 2, 2, 2, 2, 2, 1, 1, 0, 0, // - 0, 0, 0, 1, 1, 2, 1, 2, 1, 1, 0, 0, 0, // - 0, 0, 0, 0, 1, 1, 2, 1, 1, 0, 0, 0, 0, // - 0, 0, 0, 0, 1, 1, 2, 1, 1, 0, 0, 0, 0, // - 0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0, // - 0, 0, 1, 1, 2, 2, 1, 2, 2, 1, 1, 0, 0, // - 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, // - 0, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 0, // - 0, 1, 2, 2, 2, 1, 2, 1, 2, 2, 2, 1, 0, // - 0, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 0, // - 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, // - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, // - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // -}; - -char CursorIBeam[] = { - 1, 1, 1, 0, 1, 1, 1, // 7x17 - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 1, 0, 0, 0, // - 1, 1, 1, 0, 1, 1, 1, // -}; - -char CursorResizeAll[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 23x23 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, // - 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, // - 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, // - 0, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0, // - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, // - 0, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 0, // - 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, // - 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, // - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -}; - -char CloseButton[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -}; - -char MinimizeButton[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -}; - -char MaximizeButtonNormal[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -}; - -char MaximizeButtonMaximized[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -}; - -char ResizeHint[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // -}; diff --git a/GUI/WidgetEvents.cpp b/GUI/WidgetEvents.cpp deleted file mode 100644 index 699e75f..0000000 --- a/GUI/WidgetEvents.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include - -#include "../kernel.h" -#include "../DAPI.hpp" -#include "../Fex.hpp" - -namespace GraphicalUserInterface -{ - void WidgetCollection::OnPaintBackground(Event *e) - { - UNUSED(e); - } - - void WidgetCollection::OnPaintForeground(Event *e) - { - UNUSED(e); - foreach (auto Panel in this->Panels) - { - PutRect(this->Buffer, Panel->rect, Panel->Color); - } - - foreach (auto Label in this->Labels) - { - Label->CharCursorX = Label->rect.Left; - Label->CharCursorY = Label->rect.Top; - for (uint64_t i = 0; i < strlen(Label->Text); i++) - PaintChar(this->CurrentFont, this->Buffer, Label->Text[i], 0xFFFFFF, &Label->CharCursorX, &Label->CharCursorY); - } - - foreach (auto Button in this->Buttons) - { - if (Button->Pressed) - PutRect(this->Buffer, Button->rect, Button->PressedColor); - else if (Button->Hover) - PutRect(this->Buffer, Button->rect, Button->HoverColor); - else - PutRect(this->Buffer, Button->rect, Button->Color); - Button->CharCursorX = Button->rect.Left + (((Button->rect.Width / 2) - (this->CurrentFont->GetInfo().Width * strlen(Button->Text) / 2))); - Button->CharCursorY = Button->rect.Top + (((Button->rect.Height / 2) - (this->CurrentFont->GetInfo().Height / 2))); - for (uint64_t i = 0; i < strlen(Button->Text); i++) - PaintChar(this->CurrentFont, this->Buffer, Button->Text[i], 0xFFFFFF, &Button->CharCursorX, &Button->CharCursorY); - } - } - - void WidgetCollection::OnPaint(Event *e) - { - static size_t LastWidth = 0; - static size_t LastHeight = 0; - - if (LastWidth != ((Window *)this->ParentWindow)->GetPosition().Width || - LastHeight != ((Window *)this->ParentWindow)->GetPosition().Height) - { - LastWidth = ((Window *)this->ParentWindow)->GetPosition().Width; - LastHeight = ((Window *)this->ParentWindow)->GetPosition().Height; - - this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1)); - this->Buffer->Data = nullptr; - delete this->Buffer, this->Buffer = nullptr; - - this->Buffer = new ScreenBitmap; - this->Buffer->Width = LastWidth; - this->Buffer->Height = LastHeight; - this->Buffer->BitsPerPixel = Display->GetBitsPerPixel(); - this->Buffer->Pitch = Display->GetPitch(); - this->Buffer->Size = this->Buffer->Pitch * (size_t)LastHeight; - this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1)); - memset(this->Buffer->Data, 0, this->Buffer->Size); - - this->NeedRedraw = true; - } - - if (this->NeedRedraw) - { - memset(this->Buffer->Data, 0, this->Buffer->Size); - this->OnPaintBackground(e); - this->OnPaintForeground(e); - this->NeedRedraw = false; - } - DrawOverBitmap(((Window *)this->ParentWindow)->GetBuffer(), this->Buffer, 0, 0); - } - - void WidgetCollection::OnMouseDown(Event *e) - { - foreach (auto Button in this->Buttons) - { - if (Button->rect.Contains(e->MouseDown.X, e->MouseDown.Y)) - { - if (e->MouseDown.Left) - { - debug("Button Hold"); - Button->Pressed = true; - this->NeedRedraw = true; - } - } - } - } - - void WidgetCollection::OnMouseUp(Event *e) - { - foreach (auto Button in this->Buttons) - { - if (Button->rect.Contains(e->MouseUp.X, e->MouseUp.Y)) - { - if (e->MouseUp.Left) - { - debug("Button Release"); - if (Button->Pressed) - { - debug("Button Clicked"); - if (Button->OnClick != (uintptr_t) nullptr) - ((void (*)(void))Button->OnClick)(); - - Button->Pressed = false; - this->NeedRedraw = true; - } - } - } - } - } - - void WidgetCollection::OnMouseMove(Event *e) - { - foreach (auto Button in this->Buttons) - { - if (Button->rect.Contains(e->MouseMove.X, e->MouseMove.Y)) - { - Button->Hover = true; - this->NeedRedraw = true; - } - else - { - Button->Hover = false; - this->NeedRedraw = true; - } - } - } -} diff --git a/GUI/Widgets.cpp b/GUI/Widgets.cpp deleted file mode 100644 index 4eba05b..0000000 --- a/GUI/Widgets.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include - -#include "../kernel.h" -#include "../DAPI.hpp" -#include "../Fex.hpp" - -extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn10x20r_psf_start; -extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn10x20r_psf_end; -extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn10x20r_psf_size; - -namespace GraphicalUserInterface -{ - Handle WidgetCollection::CreatePanel(Rect rect, uint32_t Color) - { - PanelObject *panel = (PanelObject *)this->mem->RequestPages(TO_PAGES(sizeof(PanelObject) + 1)); - - panel->Handle.Type[0] = 'P'; - panel->Handle.Type[1] = 'N'; - panel->Handle.Type[2] = 'L'; - panel->Handle.Type[3] = '\0'; - - panel->rect = rect; - panel->Color = Color; - panel->BorderColor = 0xFF000000; - panel->ShadowColor = 0xFF000000; - panel->Shadow = false; - - Panels.push_back(panel); - this->NeedRedraw = true; - return (Handle)panel; - } - - Handle WidgetCollection::CreateLabel(Rect rect, const char *Text) - { - LabelObject *label = (LabelObject *)this->mem->RequestPages(TO_PAGES(sizeof(LabelObject) + 1)); - - label->Handle.Type[0] = 'L'; - label->Handle.Type[1] = 'B'; - label->Handle.Type[2] = 'L'; - label->Handle.Type[3] = '\0'; - - label->rect = rect; - strcpy(label->Text, Text); - label->Color = 0xFFFFFF; - label->CharCursorX = rect.Left; - label->CharCursorY = rect.Top; - - Labels.push_back(label); - NeedRedraw = true; - return (Handle)label; - } - - Handle WidgetCollection::CreateButton(Rect rect, const char *Text, uintptr_t OnClick) - { - ButtonObject *button = (ButtonObject *)this->mem->RequestPages(TO_PAGES(sizeof(ButtonObject) + 1)); - - button->Handle.Type[0] = 'B'; - button->Handle.Type[1] = 'T'; - button->Handle.Type[2] = 'N'; - button->Handle.Type[3] = '\0'; - - button->rect = rect; - strcpy(button->Text, Text); - button->Color = 0x252525; - button->HoverColor = 0x353535; - button->PressedColor = 0x555555; - button->BorderColor = 0xFF000000; - button->ShadowColor = 0xFF000000; - button->Shadow = false; - button->Hover = false; - button->Pressed = false; - button->OnClick = OnClick; - - Buttons.push_back(button); - this->NeedRedraw = true; - return (Handle)button; - } - - void WidgetCollection::SetText(Handle handle, const char *Text) - { - HandleMeta *meta = (HandleMeta *)handle; - if (meta->Type[0] == 'L' && meta->Type[1] == 'B' && meta->Type[2] == 'L') - { - LabelObject *label = (LabelObject *)handle; - strcpy(label->Text, Text); - this->NeedRedraw = true; - } - } - - WidgetCollection::WidgetCollection(void *ParentWindow) - { - if (!ParentWindow) - { - error("ParentWindow is null"); - return; - } - this->ParentWindow = ParentWindow; - - this->mem = new Memory::MemMgr; - - this->Buffer = new ScreenBitmap; - this->Buffer->Width = ((Window *)this->ParentWindow)->GetPosition().Width; - this->Buffer->Height = ((Window *)this->ParentWindow)->GetPosition().Height; - this->Buffer->BitsPerPixel = Display->GetBitsPerPixel(); - this->Buffer->Pitch = Display->GetPitch(); - this->Buffer->Size = (size_t)(this->Buffer->Pitch * ((Window *)this->ParentWindow)->GetPosition().Height); - this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1)); - memset(this->Buffer->Data, 0, this->Buffer->Size); - - this->CurrentFont = new Video::Font(&_binary_Files_tamsyn_font_1_11_Tamsyn10x20r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn10x20r_psf_end, Video::FontType::PCScreenFont2); - } - - WidgetCollection::~WidgetCollection() - { - delete this->mem, this->mem = nullptr; - delete this->Buffer, this->Buffer = nullptr; - delete this->CurrentFont, this->CurrentFont = nullptr; - } -} diff --git a/GUI/Window.cpp b/GUI/Window.cpp deleted file mode 100644 index 226007b..0000000 --- a/GUI/Window.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include - -#include "../kernel.h" -#include "../DAPI.hpp" -#include "../Fex.hpp" - -namespace GraphicalUserInterface -{ - -#define TASKBAR_HEIGHT 25 - - // if (!Maximized) - // { - // this->LastPosition.Left = this->Position.Left; - // this->LastPosition.Top = this->Position.Top; - // this->LastPosition.Width = this->Position.Width; - // this->LastPosition.Height = this->Position.Height; - // this->Position.Left = 0; - // this->Position.Top = 0; - // this->Position.Width = Display->GetBuffer(200)->Width; - // this->Position.Height = Display->GetBuffer(200)->Height - 20 - TASKBAR_HEIGHT; - // Maximized = true; - // } - // else - // { - // this->Position.Left = this->LastPosition.Left; - // this->Position.Top = this->LastPosition.Top; - // this->Position.Width = this->LastPosition.Width; - // this->Position.Height = this->LastPosition.Height; - // Maximized = false; - // } - - void Window::AddWidget(WidgetCollection *widget) - { - this->Widgets.push_back(widget); - } - - Window::Window(void *ParentGUI, Rect rect, const char *Title) - { - this->mem = new Memory::MemMgr; - this->Buffer = new ScreenBitmap; - this->Buffer->Width = rect.Width; - this->Buffer->Height = rect.Height; - this->Buffer->BitsPerPixel = Display->GetBitsPerPixel(); - this->Buffer->Pitch = Display->GetPitch(); - this->Buffer->Size = this->Buffer->Pitch * rect.Height; - this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1)); - memset(this->Buffer->Data, 0, this->Buffer->Size); - this->ParentGUI = ParentGUI; - this->Position = rect; - strcpy(this->Title, Title); - this->Maximized = false; - this->Minimized = false; - } - - Window::~Window() - { - delete this->mem, this->mem = nullptr; - } -} diff --git a/GUI/WindowEvents.cpp b/GUI/WindowEvents.cpp deleted file mode 100644 index 850c257..0000000 --- a/GUI/WindowEvents.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include -#include - -#include "../kernel.h" -#include "../DAPI.hpp" -#include "../Fex.hpp" - -namespace GraphicalUserInterface -{ - void Window::OnResize(Event *e) - { - // TODO: Optimize this - this->mem->FreePages(this->Buffer->Data, TO_PAGES(this->Buffer->Size + 1)); - this->Buffer->Data = nullptr; - delete this->Buffer, this->Buffer = nullptr; - - this->Buffer = new ScreenBitmap; - this->Buffer->Width = e->Resize.Width; - this->Buffer->Height = e->Resize.Height; - this->Buffer->BitsPerPixel = Display->GetBitsPerPixel(); - this->Buffer->Pitch = Display->GetPitch(); - this->Buffer->Size = this->Buffer->Pitch * e->Resize.Height; - this->Buffer->Data = (uint8_t *)this->mem->RequestPages(TO_PAGES(this->Buffer->Size + 1)); - memset(this->Buffer->Data, 0, this->Buffer->Size); - this->OnPaint(e); - } - - void Window::OnMinimize(Event *e) - { - UNUSED(e); - fixme("Window::OnMinimize() not implemented"); - } - - void Window::OnMaximize(Event *e) - { - UNUSED(e); - fixme("Window::OnMaximize() not implemented"); - } - - void Window::OnClose(Event *e) - { - UNUSED(e); - fixme("Window::OnClose() not implemented"); - } - - void Window::OnPaintBackground(Event *e) - { - UNUSED(e); - Rect PaintPosition = this->Position; - PaintPosition.Left = 0; - PaintPosition.Top = 0; - PutRect(this->Buffer, PaintPosition, 0x121212); - } - - void Window::OnPaintForeground(Event *e) - { - // Window content - if (!this->Maximized) - { - char buf[256]; - sprintf(buf, "Left:\eAA11FF%ld\eFFFFFF Top:\eAA11FF%ld\eFFFFFF W:\eAA11FF%ld\eFFFFFF H:\eAA11FF%ld\eFFFFFF", this->Position.Left, this->Position.Top, this->Position.Width, this->Position.Height); - // Display->DrawString(buf, this->Position.Left + 20, this->Position.Top + 25, 200); - } - - foreach (auto var in this->Widgets) - { - var->OnPaint(e); - } - } - - void Window::OnPaint(Event *e) - { - memset(this->Buffer->Data, 0, this->Buffer->Size); - this->OnPaintBackground(e); - this->OnPaintForeground(e); - } - - void Window::OnMouseDown(Event *e) - { - Event WindowPos = *e; - - WindowPos.MouseDown.X -= this->Position.Left; - WindowPos.MouseDown.Y -= this->Position.Top; - - foreach (auto var in this->Widgets) - { - var->OnMouseDown(&WindowPos); - } - } - - void Window::OnMouseUp(Event *e) - { - Event WindowPos = *e; - - WindowPos.MouseUp.X -= this->Position.Left; - WindowPos.MouseUp.Y -= this->Position.Top; - - foreach (auto var in this->Widgets) - { - var->OnMouseUp(&WindowPos); - } - } - - void Window::OnMouseMove(Event *e) - { - Event WindowPos = *e; - - WindowPos.MouseMove.X -= this->Position.Left; - WindowPos.MouseMove.Y -= this->Position.Top; - - foreach (auto var in this->Widgets) - { - var->OnMouseMove(&WindowPos); - } - } -} diff --git a/Kernel.cpp b/Kernel.cpp index 77de90e..f1ba763 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -67,12 +67,11 @@ LockClass mExtTrkLock; * - [x] The cleanup should be done by a thread (tasking). This is done to avoid a deadlock. * - [ ] Implement a better Display::SetBrightness() function. * - [ ] Fix memcpy, memset and memcmp functions (they are not working properly with SIMD). - * - [ ] Support Aarch64. * - [ ] Fully support i386. + * - [ ] Support Aarch64. * - [ ] SMP trampoline shouldn't be hardcoded at 0x2000. * - [ ] Rework the stack guard. - * - [ ] Mutex implementation. - * - [ ] Vector should have a mutex. + * - [x] Mutex implementation. * - [ ] Update SMBIOS functions to support newer versions and actually use it. * - [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write) * - [ ] Bootstrap should have a separate bss section + PHDR. @@ -183,6 +182,10 @@ LockClass mExtTrkLock; * https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3 * https://itanium-cxx-abi.github.io/cxx-abi/abi.html * + * - Keyboard: + * https://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html + * https://wiki.osdev.org/PS/2_Keyboard + * */ #ifdef a64 @@ -207,8 +210,6 @@ NewLock(KernelLock); #include -using VirtualFileSystem::File; -using VirtualFileSystem::FileStatus; using VirtualFileSystem::Node; using VirtualFileSystem::NodeFlags; @@ -223,9 +224,10 @@ VirtualFileSystem::Virtual *vfs = nullptr; KernelConfig Config = { .AllocatorType = Memory::MemoryAllocatorType::XallocV1, - .SchedulerType = 1, - .DriverDirectory = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'd', 'r', 'i', 'v', 'e', 'r', 's', '\0'}, - .InitPath = {'/', 's', 'y', 's', 't', 'e', 'm', '/', 'i', 'n', 'i', 't', '\0'}, + .SchedulerType = Multi, + .DriverDirectory = {'/', 'm', 'o', 'd', 'u', 'l', 'e', 's', '\0'}, + .InitPath = {'/', 'b', 'i', 'n', '/', 'i', 'n', 'i', 't', '\0'}, + .UseLinuxSyscalls = false, .InterruptsOnCrash = true, .Cores = 0, .IOAPICInterruptCore = 0, @@ -280,6 +282,9 @@ EXTERNC NIF void Main() KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s", CPU::Hypervisor(), CPU::Vendor(), CPU::Name()); + debug("CPU: %s %s %s", + CPU::Hypervisor(), CPU::Vendor(), CPU::Name()); + if (DebuggerIsAttached) KPrint("\eFFA500Kernel debugger detected."); @@ -291,14 +296,11 @@ EXTERNC NIF void Main() KPrint("Loading Kernel Symbols"); KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase); - if (KernelSymbolTable->GetTotalEntries() == 0 && - bInfo.Kernel.Symbols.Num && - bInfo.Kernel.Symbols.EntSize && - bInfo.Kernel.Symbols.Shndx) - KernelSymbolTable->AddBySymbolInfo(bInfo.Kernel.Symbols.Num, - bInfo.Kernel.Symbols.EntSize, - bInfo.Kernel.Symbols.Shndx, - bInfo.Kernel.Symbols.Sections); + if (!KernelSymbolTable->SymTableExists) + KernelSymbolTable->AddSymbolInfoFromGRUB(bInfo.Kernel.Symbols.Num, + bInfo.Kernel.Symbols.EntSize, + bInfo.Kernel.Symbols.Shndx, + bInfo.Kernel.Symbols.Sections); KPrint("Reading Kernel Parameters"); ParseConfig((char *)bInfo.Kernel.CommandLine, &Config); @@ -453,74 +455,74 @@ EXTERNC NIF void Main() DevFS = vfs->Create("/dev", NodeFlags::DIRECTORY); else { - File dev = vfs->Open("/dev"); - if (dev.GetFlags() != NodeFlags::DIRECTORY) + RefNode *dev = vfs->Open("/dev"); + if (dev->GetNode()->Flags != NodeFlags::DIRECTORY) { KPrint("\eE85230/dev is not a directory! Halting..."); CPU::Stop(); } - vfs->Close(dev); - DevFS = dev.GetNode(); + DevFS = dev->GetNode(); + delete dev; } if (!vfs->PathExists("/mnt")) MntFS = vfs->Create("/mnt", NodeFlags::DIRECTORY); else { - File mnt = vfs->Open("/mnt"); - if (mnt.GetFlags() != NodeFlags::DIRECTORY) + RefNode *mnt = vfs->Open("/mnt"); + if (mnt->GetNode()->Flags != NodeFlags::DIRECTORY) { KPrint("\eE85230/mnt is not a directory! Halting..."); CPU::Stop(); } - vfs->Close(mnt); - MntFS = mnt.GetNode(); + MntFS = mnt->GetNode(); + delete mnt; } if (!vfs->PathExists("/proc")) ProcFS = vfs->Create("/proc", NodeFlags::DIRECTORY); else { - File proc = vfs->Open("/proc", nullptr); - if (proc.GetFlags() != NodeFlags::DIRECTORY) + RefNode *proc = vfs->Open("/proc", nullptr); + if (proc->GetNode()->Flags != NodeFlags::DIRECTORY) { KPrint("\eE85230/proc is not a directory! Halting..."); CPU::Stop(); } - vfs->Close(proc); - ProcFS = proc.GetNode(); + ProcFS = proc->GetNode(); + delete proc; } if (!vfs->PathExists("/var")) VarLogFS = vfs->Create("/var", NodeFlags::DIRECTORY); else { - File var = vfs->Open("/var", nullptr); - if (var.GetFlags() != NodeFlags::DIRECTORY) + RefNode *var = vfs->Open("/var", nullptr); + if (var->GetNode()->Flags != NodeFlags::DIRECTORY) { KPrint("\eE85230/var is not a directory! Halting..."); CPU::Stop(); } - vfs->Close(var); - VarLogFS = var.GetNode(); + VarLogFS = var->GetNode(); + delete var; if (!vfs->PathExists("/var/log")) VarLogFS = vfs->Create("/var/log", NodeFlags::DIRECTORY); else { - File var_log = vfs->Open("/var/log", nullptr); - if (var_log.GetFlags() != NodeFlags::DIRECTORY) + RefNode *var_log = vfs->Open("/var/log", nullptr); + if (var_log->GetNode()->Flags != NodeFlags::DIRECTORY) { KPrint("\eE85230/var/log is not a directory! Halting..."); CPU::Stop(); } - vfs->Close(var_log); - VarLogFS = var_log.GetNode(); + VarLogFS = var_log->GetNode(); + delete var_log; } } KPrint("\e058C19################################"); - TaskManager = new Tasking::Task((Tasking::IP)KernelMainThread); + TaskManager = new Tasking::Task(Tasking::IP(KernelMainThread)); CPU::Halt(true); } @@ -573,14 +575,16 @@ EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info) * memory management to be initialized first. */ TestString(); + Test_std(); TestMemoryAllocation(); #endif EnableProfiler = true; Main(); } +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" - +extern "C" void __cxa_finalize(void *); EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot) { UNUSED(Reboot); @@ -588,9 +592,6 @@ EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot) trace("\n\n\n#################### SYSTEM SHUTTING DOWN ####################\n\n"); - if (RecoveryScreen) - delete RecoveryScreen, RecoveryScreen = nullptr; - if (NIManager) delete NIManager, NIManager = nullptr; @@ -620,8 +621,10 @@ EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot) debug("Calling destructors..."); for (CallPtr *func = __fini_array_start; func != __fini_array_end; func++) (*func)(); + __cxa_finalize(nullptr); debug("Done."); } +#pragma GCC diagnostic pop EXTERNC void TaskingPanic() { diff --git a/KernelConfig.cpp b/KernelConfig.cpp index 2af0ec4..d331bb5 100644 --- a/KernelConfig.cpp +++ b/KernelConfig.cpp @@ -27,245 +27,249 @@ // TODO: Implement proper fprintf EXTERNC void fprintf(FILE *stream, const char *Format, ...) { - va_list args; - va_start(args, Format); - vprintf(Format, args); - va_end(args); - UNUSED(stream); + va_list args; + va_start(args, Format); + vprintf(Format, args); + va_end(args); + UNUSED(stream); } // TODO: Implement proper fputs EXTERNC void fputs(const char *s, FILE *stream) { - printf("%s", s); - UNUSED(stream); + printf("%s", s); + UNUSED(stream); } static struct cag_option ConfigOptions[] = { - {.identifier = 'a', - .access_letters = "aA", - .access_name = "alloc", - .value_name = "TYPE", - .description = "Memory allocator to use"}, + {.identifier = 'a', + .access_letters = "aA", + .access_name = "alloc", + .value_name = "TYPE", + .description = "Memory allocator to use"}, - {.identifier = 'c', - .access_letters = "cC", - .access_name = "cores", - .value_name = "VALUE", - .description = "Number of cores to use (0 = all; 1 is the first code, not 0)"}, + {.identifier = 'c', + .access_letters = "cC", + .access_name = "cores", + .value_name = "VALUE", + .description = "Number of cores to use (0 = all; 1 is the first code, not 0)"}, - {.identifier = 'p', - .access_letters = "pP", - .access_name = "ioapicirq", - .value_name = "VALUE", - .description = "Which core will be used for I/O APIC interrupts"}, + {.identifier = 'p', + .access_letters = "pP", + .access_name = "ioapicirq", + .value_name = "VALUE", + .description = "Which core will be used for I/O APIC interrupts"}, - {.identifier = 't', - .access_letters = "tT", - .access_name = "tasking", - .value_name = "MODE", - .description = "Tasking mode (multi, single)"}, + {.identifier = 't', + .access_letters = "tT", + .access_name = "tasking", + .value_name = "MODE", + .description = "Tasking mode (multi, single)"}, - {.identifier = 'd', - .access_letters = "dD", - .access_name = "drvdir", - .value_name = "PATH", - .description = "Directory to load drivers from"}, + {.identifier = 'd', + .access_letters = "dD", + .access_name = "drvdir", + .value_name = "PATH", + .description = "Directory to load drivers from"}, - {.identifier = 'i', - .access_letters = "iI", - .access_name = "init", - .value_name = "PATH", - .description = "Path to init program"}, + {.identifier = 'i', + .access_letters = "iI", + .access_name = "init", + .value_name = "PATH", + .description = "Path to init program"}, - {.identifier = 'l', - .access_letters = NULL, - .access_name = "udl", - .value_name = "BOOL", - .description = "Unlock the deadlock after 10 retries"}, + {.identifier = 'y', + .access_letters = "yY", + .access_name = "linux", + .value_name = "BOOL", + .description = "Use Linux syscalls by default"}, - {.identifier = 'o', - .access_letters = NULL, - .access_name = "ioc", - .value_name = "BOOL", - .description = "Enable Interrupts On Crash. If enabled, the navigation keys will be enabled on crash"}, + {.identifier = 'l', + .access_letters = NULL, + .access_name = "udl", + .value_name = "BOOL", + .description = "Unlock the deadlock after 10 retries"}, - {.identifier = 's', - .access_letters = NULL, - .access_name = "simd", - .value_name = "BOOL", - .description = "Enable SIMD instructions"}, + {.identifier = 'o', + .access_letters = NULL, + .access_name = "ioc", + .value_name = "BOOL", + .description = "Enable Interrupts On Crash. If enabled, the navigation keys will be enabled on crash"}, - {.identifier = 'b', - .access_letters = NULL, - .access_name = "bootanim", - .value_name = "BOOL", - .description = "Enable boot animation"}, + {.identifier = 's', + .access_letters = NULL, + .access_name = "simd", + .value_name = "BOOL", + .description = "Enable SIMD instructions"}, - {.identifier = 'h', - .access_letters = "h", - .access_name = "help", - .value_name = NULL, - .description = "Show help on screen and halt"}}; + {.identifier = 'b', + .access_letters = NULL, + .access_name = "bootanim", + .value_name = "BOOL", + .description = "Enable boot animation"}, + + {.identifier = 'h', + .access_letters = "h", + .access_name = "help", + .value_name = NULL, + .description = "Show help on screen and halt"}}; void ParseConfig(char *ConfigString, KernelConfig *ModConfig) { - if (ConfigString == NULL) - { - KPrint("Empty kernel parameters!"); - return; - } - else if (strlen(ConfigString) == 0) - { - KPrint("Empty kernel parameters!"); - return; - } + if (ConfigString == NULL || + strlen(ConfigString) == 0) + { + KPrint("Empty kernel parameters!"); + return; + } - if (ModConfig == NULL) - { - KPrint("ModConfig is NULL!"); - return; - } + if (ModConfig == NULL) + { + KPrint("ModConfig is NULL!"); + return; + } - KPrint("Kernel parameters: %s", ConfigString); - debug("Kernel parameters: %s", ConfigString); + KPrint("Kernel parameters: %s", ConfigString); + debug("Kernel parameters: %s", ConfigString); - char *argv[32]; - int argc = 0; - /* Not sure if the quotes are being parsed correctly. */ - targp_parse(ConfigString, argv, &argc); + char *argv[32]; + int argc = 0; + /* Not sure if the quotes are being parsed correctly. */ + targp_parse(ConfigString, argv, &argc); #ifdef DEBUG - for (int i = 0; i < argc; i++) - debug("argv[%d] = %s", i, argv[i]); - debug("argc = %d", argc); + for (int i = 0; i < argc; i++) + debug("argv[%d] = %s", i, argv[i]); + debug("argc = %d", argc); #endif - char identifier; - const char *value; - cag_option_context context; + char identifier; + const char *value; + cag_option_context context; - cag_option_prepare(&context, ConfigOptions, CAG_ARRAY_SIZE(ConfigOptions), argc, argv); + cag_option_prepare(&context, ConfigOptions, CAG_ARRAY_SIZE(ConfigOptions), argc, argv); - while (cag_option_fetch(&context)) - { - identifier = cag_option_get(&context); - switch (identifier) - { - case 'a': - { - value = cag_option_get_value(&context); - if (strcmp(value, "xallocv1") == 0) - { - KPrint("\eAAFFAAUsing XallocV1 as memory allocator"); - ModConfig->AllocatorType = Memory::MemoryAllocatorType::XallocV1; - } - else if (strcmp(value, "liballoc11") == 0) - { - KPrint("\eAAFFAAUsing Liballoc11 as memory allocator"); - ModConfig->AllocatorType = Memory::MemoryAllocatorType::liballoc11; - } - else if (strcmp(value, "pages") == 0) - { - KPrint("\eAAFFAAUsing Pages as memory allocator"); - ModConfig->AllocatorType = Memory::MemoryAllocatorType::Pages; - } - else - { - KPrint("\eAAFFAAUnknown memory allocator: %s", value); - ModConfig->AllocatorType = Memory::MemoryAllocatorType::None; - } - break; - } - case 'c': - { - value = cag_option_get_value(&context); - KPrint("\eAAFFAAUsing %s cores", atoi(value) ? value : "all"); - ModConfig->Cores = atoi(value); - break; - } - case 'p': - { - value = cag_option_get_value(&context); - KPrint("\eAAFFAARedirecting I/O APIC interrupts to %s%s", atoi(value) ? "core " : "", atoi(value) ? value : "BSP"); - ModConfig->IOAPICInterruptCore = atoi(value); - break; - } - case 't': - { - value = cag_option_get_value(&context); - if (strcmp(value, "multi") == 0) - { - KPrint("\eAAFFAAUsing Multi-Tasking Scheduler"); - ModConfig->SchedulerType = 1; - } - else if (strcmp(value, "single") == 0) - { - KPrint("\eAAFFAAUsing Single-Tasking Scheduler"); - ModConfig->SchedulerType = 0; - } - else - { - KPrint("\eAAFFAAUnknown scheduler: %s", value); - ModConfig->SchedulerType = 1; - } - break; - } - case 'd': - { - value = cag_option_get_value(&context); - strncpy(ModConfig->DriverDirectory, value, strlen(value)); - KPrint("\eAAFFAAUsing %s as driver directory", value); - break; - } - case 'i': - { - value = cag_option_get_value(&context); - strncpy(ModConfig->InitPath, value, strlen(value)); - KPrint("\eAAFFAAUsing %s as init program", value); - break; - } - case 'o': - { - value = cag_option_get_value(&context); - strcmp(value, "true") == 0 ? ModConfig->InterruptsOnCrash = true : ModConfig->InterruptsOnCrash = false; - KPrint("\eAAFFAAInterrupts on crash: %s", value); - break; - } - case 'l': - { - value = cag_option_get_value(&context); - strcmp(value, "true") == 0 ? ModConfig->UnlockDeadLock = true : ModConfig->UnlockDeadLock = false; - KPrint("\eAAFFAAUnlocking the deadlock after 10 retries"); - break; - } - case 's': - { - value = cag_option_get_value(&context); - strcmp(value, "true") == 0 ? ModConfig->SIMD = true : ModConfig->SIMD = false; - KPrint("\eAAFFAASingle Instruction, Multiple Data (SIMD): %s", value); - break; - } - case 'b': - { - value = cag_option_get_value(&context); - strcmp(value, "true") == 0 ? ModConfig->BootAnimation = true : ModConfig->BootAnimation = false; - KPrint("\eAAFFAABoot animation: %s", value); - break; - } - case 'h': - { - KPrint("\n---------------------------------------------------------------------------\nUsage: kernel.fsys [OPTION]...\nKernel configuration."); - cag_option_print(ConfigOptions, CAG_ARRAY_SIZE(ConfigOptions), nullptr); - KPrint("\eFF2200System Halted."); - CPU::Stop(); - } - default: - { - KPrint("\eFF2200Unknown option: %c", identifier); - break; - } - } - } - debug("Config loaded"); + while (cag_option_fetch(&context)) + { + identifier = cag_option_get(&context); + switch (identifier) + { + case 'a': + { + value = cag_option_get_value(&context); + if (strcmp(value, "xallocv1") == 0) + { + KPrint("\eAAFFAAUsing XallocV1 as memory allocator"); + ModConfig->AllocatorType = Memory::MemoryAllocatorType::XallocV1; + } + else if (strcmp(value, "liballoc11") == 0) + { + KPrint("\eAAFFAAUsing Liballoc11 as memory allocator"); + ModConfig->AllocatorType = Memory::MemoryAllocatorType::liballoc11; + } + else if (strcmp(value, "pages") == 0) + { + KPrint("\eAAFFAAUsing Pages as memory allocator"); + ModConfig->AllocatorType = Memory::MemoryAllocatorType::Pages; + } + break; + } + case 'c': + { + value = cag_option_get_value(&context); + KPrint("\eAAFFAAUsing %s cores", atoi(value) ? value : "all"); + ModConfig->Cores = atoi(value); + break; + } + case 'p': + { + value = cag_option_get_value(&context); + KPrint("\eAAFFAARedirecting I/O APIC interrupts to %s%s", atoi(value) ? "core " : "", atoi(value) ? value : "BSP"); + ModConfig->IOAPICInterruptCore = atoi(value); + break; + } + case 't': + { + value = cag_option_get_value(&context); + if (strcmp(value, "multi") == 0) + { + KPrint("\eAAFFAAUsing Multi-Tasking Scheduler"); + ModConfig->SchedulerType = Multi; + } + else if (strcmp(value, "single") == 0) + { + KPrint("\eAAFFAAUsing Single-Tasking Scheduler"); + ModConfig->SchedulerType = Mono; + } + else + { + KPrint("\eAAFFAAUnknown scheduler: %s", value); + ModConfig->SchedulerType = Multi; + } + break; + } + case 'd': + { + value = cag_option_get_value(&context); + strncpy(ModConfig->DriverDirectory, value, strlen(value)); + KPrint("\eAAFFAAUsing %s as driver directory", value); + break; + } + case 'i': + { + value = cag_option_get_value(&context); + strncpy(ModConfig->InitPath, value, strlen(value)); + KPrint("\eAAFFAAUsing %s as init program", value); + break; + } + case 'y': + { + value = cag_option_get_value(&context); + strcmp(value, "true") == 0 ? ModConfig->UseLinuxSyscalls = true : ModConfig->UseLinuxSyscalls = false; + KPrint("\eAAFFAAUse Linux syscalls by default: %s", value); + break; + } + case 'o': + { + value = cag_option_get_value(&context); + strcmp(value, "true") == 0 ? ModConfig->InterruptsOnCrash = true : ModConfig->InterruptsOnCrash = false; + KPrint("\eAAFFAAInterrupts on crash: %s", value); + break; + } + case 'l': + { + value = cag_option_get_value(&context); + strcmp(value, "true") == 0 ? ModConfig->UnlockDeadLock = true : ModConfig->UnlockDeadLock = false; + KPrint("\eAAFFAAUnlocking the deadlock after 10 retries"); + break; + } + case 's': + { + value = cag_option_get_value(&context); + strcmp(value, "true") == 0 ? ModConfig->SIMD = true : ModConfig->SIMD = false; + KPrint("\eAAFFAASingle Instruction, Multiple Data (SIMD): %s", value); + break; + } + case 'b': + { + value = cag_option_get_value(&context); + strcmp(value, "true") == 0 ? ModConfig->BootAnimation = true : ModConfig->BootAnimation = false; + KPrint("\eAAFFAABoot animation: %s", value); + break; + } + case 'h': + { + KPrint("\n---------------------------------------------------------------------------\nUsage: kernel.fsys [OPTION]...\nKernel configuration."); + cag_option_print(ConfigOptions, CAG_ARRAY_SIZE(ConfigOptions), nullptr); + KPrint("\eFF2200System Halted."); + CPU::Stop(); + } + default: + { + KPrint("\eFF2200Unknown option: %c", identifier); + break; + } + } + } + debug("Config loaded"); } diff --git a/KernelShell/Commands/cat.cpp b/KernelShell/Commands/cat.cpp new file mode 100644 index 0000000..741df05 --- /dev/null +++ b/KernelShell/Commands/cat.cpp @@ -0,0 +1,55 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +void cmd_cat(const char *args) +{ + if (args[0] == '\0') + return; + + Node *thisNode = vfs->GetNodeFromPath(args, thisProcess->CurrentWorkingDirectory); + if (thisNode == nullptr) + { + printf("cat: %s: No such file or directory\n", args); + return; + } + + if (thisNode->Flags != NodeFlags::FILE && + thisNode->Flags != NodeFlags::CHARDEVICE) + { + printf("cat: %s: Not a file\n", args); + return; + } + std::string path = vfs->GetPathFromNode(thisNode); + + int fd = fopen(path.c_str(), "r"); + struct stat st; + fstat(fd, &st); + + char *buffer = new char[st.st_size + 1]; + fread(fd, buffer, st.st_size); + printf("%s\n", buffer); + delete[] buffer; + fclose(fd); +} diff --git a/KernelShell/Commands/cd.cpp b/KernelShell/Commands/cd.cpp new file mode 100644 index 0000000..8fe4826 --- /dev/null +++ b/KernelShell/Commands/cd.cpp @@ -0,0 +1,46 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +void cmd_cd(const char *args) +{ + if (args[0] == '\0') + return; + + Node *thisNode = vfs->GetNodeFromPath(args, thisProcess->CurrentWorkingDirectory); + + if (thisNode == nullptr) + { + printf("cd: %s: No such file or directory\n", args); + return; + } + + if (thisNode->Flags != NodeFlags::DIRECTORY) + { + printf("cd: %s: Not a directory\n", args); + return; + } + + thisProcess->CurrentWorkingDirectory = thisNode; +} diff --git a/KernelShell.cpp b/KernelShell/Commands/echo.cpp similarity index 86% rename from KernelShell.cpp rename to KernelShell/Commands/echo.cpp index 49f5ba3..66a77c3 100644 --- a/KernelShell.cpp +++ b/KernelShell/Commands/echo.cpp @@ -15,10 +15,11 @@ along with Fennix Kernel. If not, see . */ -#include -#include +#include "../cmds.hpp" -void StartKernelShell() +#include "../../kernel.h" + +void cmd_echo(const char *args) { - stub; + printf("%s\n", args); } diff --git a/include/recovery.hpp b/KernelShell/Commands/exit.cpp similarity index 63% rename from include/recovery.hpp rename to KernelShell/Commands/exit.cpp index ae56d1a..3606114 100644 --- a/include/recovery.hpp +++ b/KernelShell/Commands/exit.cpp @@ -15,27 +15,19 @@ along with Fennix Kernel. If not, see . */ -#ifndef __FENNIX_KERNEL_RECOVERY_H__ -#define __FENNIX_KERNEL_RECOVERY_H__ +#include "../cmds.hpp" -#include -#include +#include #include -namespace Recovery +#include "../../kernel.h" + +using namespace VirtualFileSystem; +using namespace Tasking; + +void cmd_exit(const char *) { - class KernelRecovery - { - private: - Memory::MemMgr *mem; - Tasking::TCB *guiThread; - Tasking::TCB *recoveryThread; - - public: - void RecoveryThread(); - KernelRecovery(); - ~KernelRecovery(); - }; + KernelShutdownThread(false); + // TaskManager->KillThread(thisThread, KILL_SUCCESS); + CPU::Halt(true); } - -#endif // !__FENNIX_KERNEL_RECOVERY_H__ diff --git a/GUI/icons.hpp b/KernelShell/Commands/kill.cpp similarity index 60% rename from GUI/icons.hpp rename to KernelShell/Commands/kill.cpp index 3efe708..7541faa 100644 --- a/GUI/icons.hpp +++ b/KernelShell/Commands/kill.cpp @@ -15,20 +15,25 @@ along with Fennix Kernel. If not, see . */ -#ifndef __FENNIX_KERNEL_ICONS_AND_FONTS_H__ -#define __FENNIX_KERNEL_ICONS_AND_FONTS_H__ +#include "../cmds.hpp" -#include +#include +#include -extern char CursorArrow[]; -extern char CursorHand[]; -extern char CursorWait[]; -extern char CursorIBeam[]; -extern char CursorResizeAll[]; -extern char CloseButton[]; -extern char MinimizeButton[]; -extern char MaximizeButtonNormal[]; -extern char MaximizeButtonMaximized[]; -extern char ResizeHint[]; +#include "../../kernel.h" -#endif // !__FENNIX_KERNEL_ICONS_AND_FONTS_H__ +using namespace VirtualFileSystem; +using namespace Tasking; + +void cmd_kill(const char *args) +{ + PID pid = atoi(args); + PCB *pcb = TaskManager->GetProcessByID(pid); + + if (pcb == nullptr) + { + printf("No process with PID %d\n", pid); + return; + } + TaskManager->KillProcess(pcb, KILL_BY_OTHER_PROCESS); +} diff --git a/KernelShell/Commands/killall.cpp b/KernelShell/Commands/killall.cpp new file mode 100644 index 0000000..2c00a80 --- /dev/null +++ b/KernelShell/Commands/killall.cpp @@ -0,0 +1,37 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; +using namespace Tasking; + +void cmd_killall(const char *args) +{ + foreach (auto Proc in TaskManager->GetProcessList()) + { + if (strcmp(Proc->Name, args) == 0) + { + TaskManager->KillProcess(Proc, KILL_BY_OTHER_PROCESS); + } + } +} diff --git a/KernelShell/Commands/ls.cpp b/KernelShell/Commands/ls.cpp new file mode 100644 index 0000000..8344ab2 --- /dev/null +++ b/KernelShell/Commands/ls.cpp @@ -0,0 +1,57 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +void cmd_ls(const char *args) +{ + if (args[0] == '\0') + { + Node *rootNode = thisProcess->CurrentWorkingDirectory; + + if (rootNode == nullptr) + rootNode = vfs->GetRootNode()->Children[0]; + + foreach (auto var in rootNode->Children) + printf("%s\n", var->Name); + } + else + { + Node *thisNode = vfs->GetNodeFromPath(args, thisProcess->CurrentWorkingDirectory); + + if (thisNode == nullptr) + { + printf("ls: %s: No such file or directory\n", args); + return; + } + + if (thisNode->Flags != NodeFlags::DIRECTORY) + { + printf("%s\n", thisNode->Name); + return; + } + + foreach (auto var in thisNode->Children) + printf("%s\n", var->Name); + } +} diff --git a/KernelShell/Commands/lsof.cpp b/KernelShell/Commands/lsof.cpp new file mode 100644 index 0000000..5fe92a7 --- /dev/null +++ b/KernelShell/Commands/lsof.cpp @@ -0,0 +1,35 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include "../../kernel.h" + +void cmd_lsof(const char *) +{ + printf("PROCESS FD NAME\n"); + foreach (auto Proc in TaskManager->GetProcessList()) + { + if (!Proc) + continue; + + std::vector fds_array = Proc->FileDescriptors->GetFileDescriptors(); + foreach (auto fd in fds_array) + printf("%s %d: %s\n", Proc->Name, fd.Descriptor, + fd.Handle->AbsolutePath.c_str()); + } +} diff --git a/KernelShell/Commands/lspci.cpp b/KernelShell/Commands/lspci.cpp new file mode 100644 index 0000000..677430f --- /dev/null +++ b/KernelShell/Commands/lspci.cpp @@ -0,0 +1,41 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +void cmd_lspci(const char *) +{ + foreach (auto Device in PCIManager->GetDevices()) + { + printf("%02x:%02x.%d: %s: %s %s %s\n", + // Device->Bus, + // Device->Device, + // Device->Function, + // FIXME + 0, 0, 0, + PCI::Descriptors::BridgeDeviceSubclassName(Device->Subclass), + PCI::Descriptors::GetVendorName(Device->VendorID), + PCI::Descriptors::GetDeviceName(Device->VendorID, Device->DeviceID), + PCI::Descriptors::GetSubclassName(Device->Class, Device->Subclass)); + } +} diff --git a/KernelShell/Commands/mem.cpp b/KernelShell/Commands/mem.cpp new file mode 100644 index 0000000..b7c73b7 --- /dev/null +++ b/KernelShell/Commands/mem.cpp @@ -0,0 +1,64 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; +using namespace Tasking; + +void cmd_mem(const char *) +{ + uint64_t total = KernelAllocator.GetTotalMemory(); + uint64_t used = KernelAllocator.GetUsedMemory(); + uint64_t free = KernelAllocator.GetFreeMemory(); + uint64_t reserved = KernelAllocator.GetReservedMemory(); + + int usedPercent = (int)((used * 100) / total); + int usedBar = (int)(usedPercent / 2); + + int reservedPercent = (int)((reserved * 100) / total); + int reservedBar = (int)(reservedPercent / 2); + + printf("["); + for (int i = 0; i < usedBar; i++) + printf("="); + for (int i = 0; i < 50 - usedBar; i++) + printf(" "); + printf("] %d%% Used\n", usedPercent); + + printf("["); + for (int i = 0; i < reservedBar; i++) + printf("="); + for (int i = 0; i < 50 - reservedBar; i++) + printf(" "); + printf("] %d%% Reserved\n", reservedPercent); + + // printf("Total: %d MiB\n", (int)(TO_MiB(total))); + // printf("Used: %d MiB\n", (int)(TO_MiB(used))); + // printf("Free: %d MiB\n", (int)(TO_MiB(free))); + // printf("Reserved: %d MiB\n", (int)(TO_MiB(reserved))); + + printf("TOTAL USED FREE RESERVED\n"); + printf("%d MiB %d MiB %d MiB %d MiB\n", + (int)(TO_MiB(total)), (int)(TO_MiB(used)), + (int)(TO_MiB(free)), (int)(TO_MiB(reserved))); +} diff --git a/KernelShell/Commands/ps.cpp b/KernelShell/Commands/ps.cpp new file mode 100644 index 0000000..d738021 --- /dev/null +++ b/KernelShell/Commands/ps.cpp @@ -0,0 +1,33 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; +using namespace Tasking; + +void cmd_ps(const char *) +{ + printf("PID Name\n"); + foreach (auto p in TaskManager->GetProcessList()) + printf("%d %s\n", p->ID, p->Name); +} diff --git a/KernelShell/Commands/reboot.cpp b/KernelShell/Commands/reboot.cpp new file mode 100644 index 0000000..a2c8766 --- /dev/null +++ b/KernelShell/Commands/reboot.cpp @@ -0,0 +1,32 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; +using namespace Tasking; + +void cmd_reboot(const char *) +{ + KernelShutdownThread(true); + CPU::Halt(true); +} diff --git a/KernelShell/Commands/shutdown.cpp b/KernelShell/Commands/shutdown.cpp new file mode 100644 index 0000000..2e72275 --- /dev/null +++ b/KernelShell/Commands/shutdown.cpp @@ -0,0 +1,32 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; +using namespace Tasking; + +void cmd_shutdown(const char *) +{ + KernelShutdownThread(false); + CPU::Halt(true); +} diff --git a/KernelShell/Commands/top.cpp b/KernelShell/Commands/top.cpp new file mode 100644 index 0000000..fe33ab0 --- /dev/null +++ b/KernelShell/Commands/top.cpp @@ -0,0 +1,46 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; +using namespace Tasking; + +void cmd_top(const char *) +{ + printf("\e9400A1PID \e9CA100Name \e00A15BState \eCCCCCCPriority Memory Usage CPU Usage\n"); + foreach (auto Proc in TaskManager->GetProcessList()) + { + printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n", + Proc->ID, Proc->Name, Proc->Status == Running ? "Running" : "Stopped", + Proc->Info.Priority, Proc->Memory->GetAllocatedMemorySize(), + Proc->Info.UserTime + Proc->Info.KernelTime); + + foreach (auto Thrd in Proc->Threads) + { + printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n", + Thrd->ID, Thrd->Name, Thrd->Status == Running ? "Running" : "Stopped", + Thrd->Info.Priority, Thrd->Memory->GetAllocatedMemorySize(), + Thrd->Info.UserTime + Thrd->Info.KernelTime); + } + } +} diff --git a/KernelShell/Commands/uname.cpp b/KernelShell/Commands/uname.cpp new file mode 100644 index 0000000..087eba9 --- /dev/null +++ b/KernelShell/Commands/uname.cpp @@ -0,0 +1,65 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +void cmd_uname(const char *args) +{ + if (args) + { + if (strcmp(args, "-a") == 0) + { + printf("Fennix Kernel %s %s %s %s\n", + KERNEL_VERSION, KERNEL_NAME, __DATE__, + KERNEL_ARCH); + } + else if (strcmp(args, "-s") == 0) + { + printf("%s\n", KERNEL_NAME); + } + else if (strcmp(args, "-v") == 0) + { + printf("%s\n", KERNEL_VERSION); + } + else if (strcmp(args, "-n") == 0) + { + printf("unknown\n"); + } + else if (strcmp(args, "-r") == 0) + { + printf("%s\n", KERNEL_NAME); + } + else if (strcmp(args, "-m") == 0) + { + printf("%s\n", KERNEL_ARCH); + } + else + { + printf("uname: invalid option: %s\n", args); + } + } + else + { + printf("Fennix Kernel\n"); + } +} diff --git a/KernelShell/Commands/uptime.cpp b/KernelShell/Commands/uptime.cpp new file mode 100644 index 0000000..72f0af2 --- /dev/null +++ b/KernelShell/Commands/uptime.cpp @@ -0,0 +1,51 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +void cmd_uptime(const char *) +{ + if (TimeManager) + { + size_t Nanoseconds = + TimeManager->GetNanosecondsSinceClassCreation(); + size_t Seconds = Nanoseconds / 10000000; + size_t Minutes = Seconds / 60; + size_t Hours = Minutes / 60; + size_t Days = Hours / 24; + + debug("Nanoseconds: %ld", Nanoseconds); + + Seconds %= 60; + Minutes %= 60; + Hours %= 24; + + printf("%ld days, %ld hours, %ld minutes, %ld %s\n", + Days, Hours, Minutes, Seconds, + Seconds == 1 ? "second" : "seconds"); + } + else + { + printf("Could not get uptime\n"); + } +} diff --git a/KernelShell/Commands/whoami.cpp b/KernelShell/Commands/whoami.cpp new file mode 100644 index 0000000..0a07607 --- /dev/null +++ b/KernelShell/Commands/whoami.cpp @@ -0,0 +1,29 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "../cmds.hpp" + +#include + +#include "../../kernel.h" + +using namespace VirtualFileSystem; + +void cmd_whoami(const char *) +{ + printf("kernel\n"); +} diff --git a/KernelShell/Shell.cpp b/KernelShell/Shell.cpp new file mode 100644 index 0000000..2e684bc --- /dev/null +++ b/KernelShell/Shell.cpp @@ -0,0 +1,422 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include + +#include "../Modules/PersonalSystem2/keyboard.hpp" +#include "../kernel.h" +#include "../Fex.hpp" +#include "../DAPI.hpp" +#include "cmds.hpp" + +using namespace PS2Keyboard; + +NewLock(ShellLock); + +const char sc_ascii_low[] = {'?', '?', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '?', '?', 'q', 'w', 'e', 'r', 't', 'y', + 'u', 'i', 'o', 'p', '[', ']', '?', '?', 'a', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', ';', '\'', '`', '?', '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', '?', '?', '?', ' '}; + +const char sc_ascii_high[] = {'?', '?', '!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', '?', '?', 'Q', 'W', 'E', 'R', 'T', 'Y', + 'U', 'I', 'O', 'P', '{', '}', '?', '?', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ';', '\"', '~', '?', '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', '?', '?', '?', ' '}; + +static int LowerCase = true; + +char GetLetterFromScanCode(uint8_t ScanCode) +{ + if (ScanCode & 0x80) + { + switch (ScanCode) + { + case KEY_U_LSHIFT: + LowerCase = true; + return 0; + case KEY_U_RSHIFT: + LowerCase = true; + return 0; + default: + return 0; + } + } + else + { + switch (ScanCode) + { + case KEY_D_RETURN: + return '\n'; + case KEY_D_LSHIFT: + LowerCase = false; + return 0; + case KEY_D_RSHIFT: + LowerCase = false; + return 0; + case KEY_D_BACKSPACE: + return ScanCode; + default: + { + if (ScanCode > 0x39) + break; + if (LowerCase) + return sc_ascii_low[ScanCode]; + else + return sc_ascii_high[ScanCode]; + } + } + } + return 0; +} + +int GetChar() +{ + return 0; +} + +struct Command +{ + const char *Name; + void (*Function)(const char *); +}; + +static Command commands[] = { + {"lsof", cmd_lsof}, + {"ls", cmd_ls}, + {"cd", cmd_cd}, + {"cat", cmd_cat}, + {"echo", cmd_echo}, + {"mkdir", nullptr}, + {"touch", nullptr}, + {"rm", nullptr}, + {"rmdir", nullptr}, + {"mv", nullptr}, + {"cp", nullptr}, + {"clear", nullptr}, + {"help", nullptr}, + {"exit", cmd_exit}, + {"reboot", cmd_reboot}, + {"shutdown", cmd_shutdown}, + {"ps", cmd_ps}, + {"kill", cmd_kill}, + {"killall", cmd_killall}, + {"top", cmd_top}, + {"mem", cmd_mem}, + {"mount", nullptr}, + {"umount", nullptr}, + {"uname", cmd_uname}, + {"whoami", cmd_whoami}, + {"passwd", nullptr}, + {"su", nullptr}, + {"login", nullptr}, + {"logout", nullptr}, + {"uptime", cmd_uptime}, + {"chown", nullptr}, + {"chgrp", nullptr}, + {"chmod", nullptr}, + {"chroot", nullptr}, + {"lspci", cmd_lspci}}; + +void StartKernelShell() +{ + SmartLock(ShellLock); + + debug("Starting kernel shell..."); + printf("Starting kernel shell...\n"); + thisThread->SetPriority(Tasking::TaskPriority::High); + Display->SetBuffer(0); + + Driver::DriverFile KeyboardModule; + if (likely(DriverManager->GetDrivers().size() > 0)) + { + foreach (auto Driver in DriverManager->GetDrivers()) + { + if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Input && + ((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.TypeFlags & FexDriverInputTypes::FexDriverInputTypes_Keyboard) + { + KeyboardModule = Driver; + printf("Using driver \eCA21F6%s\eCCCCCC for keyboard input.\n", + ((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Name); + break; + } + } + } + + Display->SetBuffer(0); + std::string Buffer; + std::vector History; + size_t HistoryIndex = 0; + bool CtrlDown = false; + bool TabDoublePress = false; + + while (true) + { + size_t BackspaceCount = 0; + Buffer.clear(); + + VirtualFileSystem::Node *cwd = thisProcess->CurrentWorkingDirectory; + if (!cwd) + cwd = vfs->GetNodeFromPath("/"); + + printf("\e34C6EB%s@%s:%s$ \eCCCCCC", + "kernel", + "fennix", + cwd->FileSystem->GetPathFromNode(cwd).c_str()); + Display->SetBuffer(0); + + while (true) + { + KernelCallback callback{}; + callback.Reason = PollWaitReason; + DriverManager->IOCB(KeyboardModule.DriverUID, &callback); + char c = GetLetterFromScanCode(callback.InputCallback.Keyboard.Key); + + switch (callback.InputCallback.Keyboard.Key) + { + case KEY_D_LCTRL: + { + CtrlDown = true; + continue; + } + case KEY_U_LCTRL: + { + CtrlDown = false; + continue; + } + case KEY_D_BACKSPACE: + { + if (BackspaceCount == 0) + continue; + + Display->Print('\b', 0); + Buffer.pop_back(); + BackspaceCount--; + Display->SetBuffer(0); + continue; + } + case KEY_D_UP: + { + if (History.size() == 0 || + HistoryIndex == 0) + continue; + + HistoryIndex--; + + for (size_t i = 0; i < Buffer.size(); i++) + Display->Print('\b', 0); + Display->SetBuffer(0); + + Buffer = History[HistoryIndex]->c_str(); + + for (size_t i = 0; i < strlen(Buffer.c_str()); i++) + Display->Print(Buffer[i], 0); + BackspaceCount = Buffer.size(); + Display->SetBuffer(0); + continue; + } + case KEY_D_DOWN: + { + if (History.size() == 0 || + HistoryIndex == History.size()) + continue; + + if (HistoryIndex == History.size() - 1) + { + HistoryIndex++; + for (size_t i = 0; i < Buffer.size(); i++) + Display->Print('\b', 0); + BackspaceCount = Buffer.size(); + Display->SetBuffer(0); + continue; + } + + for (size_t i = 0; i < Buffer.size(); i++) + Display->Print('\b', 0); + Display->SetBuffer(0); + + HistoryIndex++; + Buffer = History[HistoryIndex]->c_str(); + + for (size_t i = 0; i < strlen(Buffer.c_str()); i++) + Display->Print(Buffer[i], 0); + + BackspaceCount = Buffer.size(); + Display->SetBuffer(0); + continue; + } + case KEY_D_TAB: + { + if (!TabDoublePress) + { + TabDoublePress = true; + continue; + } + TabDoublePress = false; + if (Buffer.size() == 0) + { + for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) + { + printf("%s ", commands[i].Name); + Display->SetBuffer(0); + } + Display->Print('\n', 0); + Display->SetBuffer(0); + goto SecLoopEnd; + } + + for (size_t i = 0; i < Buffer.size(); i++) + Display->Print('\b', 0); + Display->SetBuffer(0); + + for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) + { + if (strncmp(Buffer.c_str(), commands[i].Name, Buffer.size()) == 0) + { + Buffer = commands[i].Name; + for (size_t i = 0; i < strlen(Buffer.c_str()); i++) + Display->Print(Buffer[i], 0); + BackspaceCount = Buffer.size(); + Display->SetBuffer(0); + break; + } + } + continue; + } + default: + break; + } + + if (c == 0) + continue; + + if (CtrlDown) + { + switch (std::toupper((char)c)) + { + case 'C': + { + Display->Print('^', 0); + Display->Print('C', 0); + Display->Print('\n', 0); + fixme("No SIGINT handler yet."); + Display->SetBuffer(0); + goto SecLoopEnd; + } + case 'D': + { + Display->Print('^', 0); + Display->Print('D', 0); + Display->Print('\n', 0); + fixme("No SIGKILL handler yet."); + Display->SetBuffer(0); + goto SecLoopEnd; + } + default: + continue; + } + } + + Display->Print(c, 0); + if (c == '\n') + { + if (Buffer.length() > 0) + { + std::string *hBuff = new std::string(Buffer.c_str()); + History.push_back(hBuff); + HistoryIndex = History.size(); + } + break; + } + + Buffer += c; + BackspaceCount++; + Display->SetBuffer(0); + } + SecLoopEnd: + + if (Buffer.length() == 0) + continue; + + bool Found = false; + for (size_t i = 0; i < sizeof(commands) / sizeof(Command); i++) + { + std::string cmd_extracted; + for (size_t i = 0; i < Buffer.length(); i++) + { + if (Buffer[i] == ' ') + break; + cmd_extracted += Buffer[i]; + } + + debug("cmd: %s, array[%d]: %s", cmd_extracted.c_str(), i, commands[i].Name); + if (strncmp(commands[i].Name, cmd_extracted.c_str(), cmd_extracted.size()) == 0) + { + if (strlen(commands[i].Name) != cmd_extracted.size()) + continue; + + Found = true; + + std::string arg_only; + const char *cmd_name = commands[i].Name; + for (size_t i = strlen(cmd_name) + 1; i < Buffer.length(); i++) + arg_only += Buffer[i]; + + if (commands[i].Function) + commands[i].Function(arg_only.c_str()); + else + { + std::string cmd_only; + for (size_t i = 0; i < Buffer.length(); i++) + { + if (Buffer[i] == ' ') + break; + cmd_only += Buffer[i]; + } + printf("%s: command not implemented\n", + cmd_only.c_str()); + } + break; + } + } + + if (!Found) + { + std::string cmd_only; + for (size_t i = 0; i < Buffer.length(); i++) + { + if (Buffer[i] == ' ') + break; + cmd_only += Buffer[i]; + } + printf("%s: command not found\n", + cmd_only.c_str()); + } + } +} + +void KShellThread() +{ + StartKernelShell(); + inf_loop; +} diff --git a/Tests/TestSyscalls.c b/KernelShell/cmds.hpp similarity index 50% rename from Tests/TestSyscalls.c rename to KernelShell/cmds.hpp index 65533db..9ec79d7 100644 --- a/Tests/TestSyscalls.c +++ b/KernelShell/cmds.hpp @@ -15,36 +15,27 @@ along with Fennix Kernel. If not, see . */ +#ifndef __FENNIX_KERNEL_SHELL_CMDS_H__ +#define __FENNIX_KERNEL_SHELL_CMDS_H__ + #include -#include "../syscalls.h" +void cmd_lsof(const char *args); +void cmd_echo(const char *args); +void cmd_ls(const char *args); +void cmd_cd(const char *args); +void cmd_cat(const char *args); +void cmd_ps(const char *args); +void cmd_uptime(const char *args); +void cmd_whoami(const char *args); +void cmd_uname(const char *args); +void cmd_mem(const char *args); +void cmd_kill(const char *args); +void cmd_killall(const char *args); +void cmd_top(const char *args); +void cmd_exit(const char *args); +void cmd_shutdown(const char *args); +void cmd_reboot(const char *args); +void cmd_lspci(const char *args); -#ifdef DEBUG - -__aligned(0x1000) __no_stack_protector void TestSyscalls() -{ -#if defined(a64) - __asm__ __volatile__("syscall" - : - : "a"(_Print), "D"('H'), "S"(0) - : "rcx", "r11", "memory"); - - int fork_id = -0xda; - - __asm__ __volatile__("syscall" - : "=a"(fork_id) - : "a"(_Fork) - : "rcx", "r11", "memory"); - - __asm__ __volatile__("syscall" - : - : "a"(_Exit), "D"(fork_id) - : "rcx", "r11", "memory"); -#elif defined(a32) -#elif defined(aa64) -#endif - while (1) - ; -} - -#endif +#endif // !__FENNIX_KERNEL_SHELL_CMDS_H__ diff --git a/KernelThread.cpp b/KernelThread.cpp index 79c30ce..0b56e4e 100644 --- a/KernelThread.cpp +++ b/KernelThread.cpp @@ -21,13 +21,14 @@ #endif #include +#include #include #include #include #include #include +#include #include - #define STB_IMAGE_IMPLEMENTATION #define STBI_NO_STDIO #define STBI_NO_LINEAR @@ -39,22 +40,17 @@ #include "DAPI.hpp" #include "Fex.hpp" -using VirtualFileSystem::File; -using VirtualFileSystem::FileStatus; using VirtualFileSystem::Node; using VirtualFileSystem::NodeFlags; Driver::Driver *DriverManager = nullptr; Disk::Manager *DiskManager = nullptr; NetworkInterfaceManager::NetworkInterface *NIManager = nullptr; -Recovery::KernelRecovery *RecoveryScreen = nullptr; VirtualFileSystem::Node *DevFS = nullptr; VirtualFileSystem::Node *MntFS = nullptr; VirtualFileSystem::Node *ProcFS = nullptr; VirtualFileSystem::Node *VarLogFS = nullptr; -NewLock(ShutdownLock); - #ifdef DEBUG void TreeFS(Node *node, int Depth) { @@ -62,6 +58,7 @@ void TreeFS(Node *node, int Depth) foreach (auto Chld in node->Children) { printf("%*c %s\eFFFFFF\n", Depth, ' ', Chld->Name); + if (!Config.BootAnimation) Display->SetBuffer(0); TaskManager->Sleep(100); @@ -74,8 +71,8 @@ const char *Statuses[] = { "AAFF00", /* Ready */ "00AA00", /* Running */ "FFAA00", /* Sleeping */ - "FFAA00", /* Waiting */ - "FF0088", /* Stopped */ + "FFAA00", /* Blocked */ + "FF0088", /* Zombie */ "FF0000", /* Terminated */ }; @@ -135,14 +132,16 @@ static int ShowTaskManager = 0; void TaskMgr() { - TaskManager->GetCurrentThread()->Rename("Debug Task Manager"); - TaskManager->GetCurrentThread()->SetPriority(Tasking::Low); + thisThread->Rename("Debug Task Manager"); + thisThread->SetPriority(Tasking::Idle); while (ShowTaskManager == 0) CPU::Pause(); - TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy100Usage)->Rename("Dummy 100% Usage"); - TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr_Dummy0Usage)->Rename("Dummy 0% Usage"); + thisThread->SetPriority(Tasking::Idle); + + TaskManager->CreateThread(thisProcess, Tasking::IP(TaskMgr_Dummy100Usage))->Rename("Dummy 100% Usage"); + TaskManager->CreateThread(thisProcess, Tasking::IP(TaskMgr_Dummy0Usage))->Rename("Dummy 0% Usage"); while (true) { @@ -169,7 +168,7 @@ void TaskMgr() { if (!Proc) continue; - int Status = Proc->Status; + int Status = Proc->Status.load(); uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info); printf("\e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n", Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime); @@ -178,7 +177,7 @@ void TaskMgr() { if (!Thd) continue; - Status = Thd->Status; + Status = Thd->Status.load(); uint64_t ThreadCpuUsage = GetUsage(OldSystemTime, &Thd->Info); #if defined(a64) printf(" \e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC", @@ -213,49 +212,87 @@ void TaskMgr() } } -void TestSyscallsKernel() +static int ShowOpenFiles = 0; + +void lsof() { - return; - KPrint("Testing syscalls..."); - Tasking::PCB *SyscallsTestProcess = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), - "Syscalls Test", - Tasking::TaskTrustLevel::User, - KernelSymbolTable); + thisThread->Rename("Debug File List"); + thisThread->SetPriority(Tasking::Idle); - Tasking::TCB *SyscallsTestThread = TaskManager->CreateThread(SyscallsTestProcess, - (Tasking::IP)TestSyscalls, - nullptr, - nullptr, - std::vector(), - Tasking::TaskArchitecture::x64, - Tasking::TaskCompatibility::Native, - true); - SyscallsTestThread->SetCritical(true); - TaskManager->GetSecurityManager()->TrustToken(SyscallsTestThread->Security.UniqueToken, Tasking::TTL::FullTrust); + while (ShowOpenFiles == 0) + CPU::Pause(); - Memory::Virtual vmm = Memory::Virtual(SyscallsTestProcess->PageTable); + thisThread->SetPriority(Tasking::High); - // vmm.Remap((void *)TestSyscalls, vmm.GetPhysical((void *)TestSyscalls), Memory::P | Memory::RW | Memory::US); + vfs->Create("/dummy_lsof_file", NodeFlags::FILE); + fopen("/dummy_lsof_file", "r"); - // for (uintptr_t k = (uintptr_t)&_kernel_start; k < (uintptr_t)&_kernel_end; k += PAGE_SIZE) - // { - // vmm.Remap((void *)k, (void *)vmm.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US); - // debug("Remapped %#lx %#lx", k, vmm.GetPhysical((void *)k)); - // } - - for (uintptr_t k = (uintptr_t)TestSyscalls - PAGE_SIZE; k < (uintptr_t)TestSyscalls + FROM_PAGES(5); k += PAGE_SIZE) + while (true) { - vmm.Remap((void *)k, (void *)vmm.GetPhysical((void *)k), Memory::P | Memory::RW | Memory::US); - debug("Remapped %#lx %#lx", k, vmm.GetPhysical((void *)k)); - } + while (ShowOpenFiles == 0) + CPU::Pause(); - SyscallsTestThread->Status = Tasking::TaskStatus::Ready; - TaskManager->WaitForThread(SyscallsTestThread); - KPrint("Test complete"); + Video::ScreenBuffer *sb = Display->GetBuffer(0); + for (short i = 0; i < 500; i++) + { + for (short j = 0; j < 500; j++) + { + uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8)); + *Pixel = 0x222222; + } + } + + uint32_t tmpX, tmpY; + Display->GetBufferCursor(0, &tmpX, &tmpY); + Display->SetBufferCursor(0, 0, 0); + printf("\eF02C21Open Files (%ld):\e00AAAA\n", + TaskManager->GetProcessList().size()); + foreach (auto Proc in TaskManager->GetProcessList()) + { + if (!Proc) + continue; + + printf("%s:\n", Proc->Name); + + std::vector fds_array = Proc->FileDescriptors->GetFileDescriptors(); + foreach (auto fd in fds_array) + printf(" %d: %s\n", fd.Descriptor, fd.Handle->AbsolutePath.c_str()); + } + Display->SetBufferCursor(0, tmpX, tmpY); + if (!Config.BootAnimation) + Display->SetBuffer(0); + } +} + +#include +std::mutex test_mutex; + +void mutex_test_long() +{ + while (true) + { + test_mutex.lock(); + debug("Long Thread %d got mutex", + thisThread->ID); + // TaskManager->Sleep(2000); + test_mutex.unlock(); + } +} + +void mutex_test() +{ + while (true) + { + test_mutex.lock(); + debug("Thread %d got mutex", + thisThread->ID); + // TaskManager->Sleep(200); + test_mutex.unlock(); + } } #endif -Execute::SpawnData SpawnInit() +int SpawnInit() { const char *envp[5] = { "PATH=/bin:/usr/bin", @@ -284,18 +321,17 @@ void BootLogoAnimationThread() while (FrameCount < 27) { sprintf(BootAnimPath, "/etc/boot/%ld.tga", FrameCount); - File ba = vfs->Open(BootAnimPath); - if (!ba.IsOK()) + RefNode *frame = vfs->Open(BootAnimPath); + if (!frame) { - vfs->Close(ba); debug("Failed to load boot animation frame %s", BootAnimPath); break; } - FrameSizes[FrameCount] = s_cst(uint32_t, ba.GetLength()); - Frames[FrameCount] = new uint8_t[ba.GetLength()]; - vfs->Read(ba, Frames[FrameCount], ba.GetLength()); - vfs->Close(ba); + FrameSizes[FrameCount] = s_cst(uint32_t, frame->Length); + Frames[FrameCount] = new uint8_t[frame->Length]; + frame->Read(Frames[FrameCount], frame->Length); + delete frame; FrameCount++; } @@ -306,10 +342,13 @@ void BootLogoAnimationThread() { int x, y, channels; - if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels)) + if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], + &x, &y, &channels)) continue; - uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha); + uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], + FrameSizes[i], &x, &y, + &channels, STBI_rgb_alpha); if (img == NULL) continue; @@ -332,7 +371,8 @@ void BootLogoAnimationThread() b = (b * a) / 0xFF; } - Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1); + Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, + (r << 16) | (g << 8) | (b << 0), 1); } free(img); @@ -359,14 +399,17 @@ void ExitLogoAnimationThread() uint32_t DispX = Display->GetBuffer(1)->Width; uint32_t DispY = Display->GetBuffer(1)->Height; - for (size_t i = 40; i > 25; i--) + for (size_t i = FrameCount - 1; i > 0; i--) { int x, y, channels; - if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels)) + if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i], + &x, &y, &channels)) continue; - uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], FrameSizes[i], &x, &y, &channels, STBI_rgb_alpha); + uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i], + FrameSizes[i], &x, &y, + &channels, STBI_rgb_alpha); if (img == NULL) continue; @@ -389,7 +432,8 @@ void ExitLogoAnimationThread() b = (b * a) / 0xFF; } - Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, (r << 16) | (g << 8) | (b << 0), 1); + Display->SetPixel((i % x) + offsetX, (i / x) + offsetY, + (r << 16) | (g << 8) | (b << 0), 1); } free(img); @@ -411,28 +455,49 @@ void CleanupProcessesThreadWrapper() { TaskManager->CleanupProcessesThread(); } void KernelMainThread() { - Tasking::TCB *clnThd = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CleanupProcessesThreadWrapper); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test_long)); + // TaskManager->Yield(); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test)); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test)); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test)); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test)); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test)); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test)); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test)); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test)); + // TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test)); + // ilp; + + Tasking::TCB *clnThd = + TaskManager->CreateThread(thisProcess, + Tasking::IP(CleanupProcessesThreadWrapper)); clnThd->SetPriority(Tasking::Idle); TaskManager->SetCleanupThread(clnThd); - TaskManager->GetCurrentThread()->SetPriority(Tasking::Critical); + thisThread->SetPriority(Tasking::Critical); Tasking::TCB *blaThread = nullptr; if (Config.BootAnimation) { - blaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)BootLogoAnimationThread); + blaThread = + TaskManager->CreateThread(thisProcess, + Tasking::IP(BootLogoAnimationThread)); blaThread->Rename("Logo Animation"); } #ifdef DEBUG - TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)TaskMgr); + TaskManager->CreateThread(thisProcess, Tasking::IP(TaskMgr)); + TaskManager->CreateThread(thisProcess, Tasking::IP(lsof)); TreeFS(vfs->GetRootNode(), 0); - TestSyscallsKernel(); #endif - KPrint("Kernel Compiled at: %s %s with C++ Standard: %d", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD); + KPrint("Kernel Compiled at: %s %s with C++ Standard: %d", + __DATE__, __TIME__, CPP_LANGUAGE_STANDARD); KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus); + if (IsVirtualizedEnvironment()) + KPrint("Running in Virtualized Environment"); + KPrint("Initializing Disk Manager..."); DiskManager = new Disk::Manager; @@ -455,47 +520,23 @@ void KernelMainThread() KPrint("Starting Network Interface Manager..."); NIManager->StartService(); - printf("\eCCCCCC[\e00AEFFKernel Thread\eCCCCCC] Setting up userspace"); - if (!Config.BootAnimation) - Display->SetBuffer(0); - - Execute::SpawnData ret = {Execute::ExStatus::Unknown, nullptr, nullptr}; - Tasking::TCB *ExecuteThread = nullptr; + KPrint("Setting up userspace"); int ExitCode = -1; - ExecuteThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)Execute::LibraryManagerService); - ExecuteThread->Rename("Library Manager"); - ExecuteThread->SetCritical(true); - ExecuteThread->SetPriority(Tasking::Idle); - - Display->Print('.', 0); - if (!Config.BootAnimation) - Display->SetBuffer(0); - - ret = SpawnInit(); - - Display->Print('.', 0); - if (!Config.BootAnimation) - Display->SetBuffer(0); - - if (ret.Status != Execute::ExStatus::OK) + Tasking::TCB *initThread = nullptr; + int tid = SpawnInit(); + if (tid < 0) { - KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, ret.Status); + KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, tid); goto Exit; } - ret.Thread->SetCritical(true); - TaskManager->GetSecurityManager()->TrustToken(ret.Process->Security.UniqueToken, Tasking::TTL::FullTrust); - TaskManager->GetSecurityManager()->TrustToken(ret.Thread->Security.UniqueToken, Tasking::TTL::FullTrust); - - Display->Print('.', 0); - Display->Print('\n', 0); - if (!Config.BootAnimation) - Display->SetBuffer(0); + initThread = TaskManager->GetThreadByID(tid); + initThread->SetCritical(true); KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath); - TaskManager->GetCurrentThread()->SetPriority(Tasking::Idle); + thisThread->SetPriority(Tasking::Idle); - TaskManager->WaitForThread(ret.Thread); - ExitCode = ret.Thread->GetExitCode(); + TaskManager->WaitForThread(initThread); + ExitCode = initThread->GetExitCode(); Exit: if (ExitCode == 0) { @@ -505,25 +546,27 @@ Exit: CPU::Halt(true); } - KPrint("\eE85230Userspace process exited with code %d (%#x)", ExitCode, - ExitCode < 0 ? -ExitCode : ExitCode); - KPrint("Dropping to recovery screen..."); - TaskManager->Sleep(2500); + KPrint("\eE85230Userspace process exited with code %d (%#x)", + ExitCode, ExitCode < 0 ? -ExitCode : ExitCode); + KPrint("Dropping to kernel shell..."); + TaskManager->Sleep(1000); TaskManager->WaitForThread(blaThread); - RecoveryScreen = new Recovery::KernelRecovery; + TaskManager->CreateThread(thisProcess, + Tasking::IP(KShellThread)) + ->Rename("Kernel Shell"); CPU::Halt(true); } +NewLock(ShutdownLock); void __no_stack_protector KernelShutdownThread(bool Reboot) { SmartLock(ShutdownLock); debug("KernelShutdownThread(%s)", Reboot ? "true" : "false"); if (Config.BootAnimation && TaskManager) { - if (RecoveryScreen) - delete RecoveryScreen, RecoveryScreen = nullptr; - - Tasking::TCB *elaThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)ExitLogoAnimationThread); + Tasking::TCB *elaThread = + TaskManager->CreateThread(thisProcess, + Tasking::IP(ExitLogoAnimationThread)); elaThread->Rename("Logo Animation"); TaskManager->WaitForThread(elaThread); } diff --git a/LICENSE b/LICENSE index 314c596..f288702 100644 --- a/LICENSE +++ b/LICENSE @@ -631,10 +631,8 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - A kernel that serves as the core of an operating system, managing - hardware resources and providing essential services to user-level - applications. - Copyright (C) 2023 EnderIce2 + + Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -643,7 +641,7 @@ the "copyright" line and a pointer to where the full notice is found. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License @@ -654,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: - Fennix Kernel Copyright (C) 2023 EnderIce2 + Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff --git a/Library/Bitmap.cpp b/Library/Bitmap.cpp index 391d77b..92e60c6 100644 --- a/Library/Bitmap.cpp +++ b/Library/Bitmap.cpp @@ -17,29 +17,35 @@ #include -bool Bitmap::operator[](uint64_t index) { return Get(index); } - bool Bitmap::Get(uint64_t index) { - if (index > Size * 8) - return false; - uint64_t byteIndex = index / 8; - uint8_t bitIndex = index % 8; - uint8_t bitIndexer = 0b10000000 >> bitIndex; - if ((Buffer[byteIndex] & bitIndexer) > 0) - return true; - return false; + if (index > Size * 8) + return false; + + uint64_t byteIndex = index / 8; + uint8_t bitIndex = index % 8; + uint8_t bitIndexer = 0b10000000 >> bitIndex; + + if ((Buffer[byteIndex] & bitIndexer) > 0) + return true; + + return false; } bool Bitmap::Set(uint64_t index, bool value) { - if (index > Size * 8) - return false; - uint64_t byteIndex = index / 8; - uint8_t bitIndex = index % 8; - uint8_t bitIndexer = 0b10000000 >> bitIndex; - Buffer[byteIndex] &= ~bitIndexer; - if (value) - Buffer[byteIndex] |= bitIndexer; - return true; + if (index > Size * 8) + return false; + + uint64_t byteIndex = index / 8; + uint8_t bitIndex = index % 8; + uint8_t bitIndexer = 0b10000000 >> bitIndex; + + Buffer[byteIndex] &= ~bitIndexer; + if (value) + Buffer[byteIndex] |= bitIndexer; + + return true; } + +bool Bitmap::operator[](uint64_t index) { return this->Get(index); } diff --git a/Library/Convert.cpp b/Library/Convert.cpp index 9e9ed74..b86d2e6 100644 --- a/Library/Convert.cpp +++ b/Library/Convert.cpp @@ -474,6 +474,7 @@ size_t wcslen(const wchar_t *s) size_t wcsrtombs(char *dst, const wchar_t **src, size_t len, mbstate_t *ps) { + UNUSED(ps); size_t count = 0; while (len > 0) @@ -792,21 +793,31 @@ EXTERNC __no_stack_protector void *__memcpy_chk(void *dest, const void *src, siz __chk_fail(); void *ret = nullptr; - uint64_t simd = CPU::CheckSIMD(); - if (simd & CPU::x86SIMDType::SIMD_SSE42) - ret = memcpy_sse4_2(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE41) - ret = memcpy_sse4_1(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSSE3) - ret = memcpy_ssse3(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE3) - ret = memcpy_sse3(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE2) - ret = memcpy_sse2(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE) - ret = memcpy_sse(dest, src, len); + if (0) /* FIXME */ + { + uint64_t simd = CPU::CheckSIMD(); + if (simd & CPU::x86SIMDType::SIMD_SSE42) + ret = memcpy_sse4_2(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE41) + ret = memcpy_sse4_1(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSSE3) + ret = memcpy_ssse3(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE3) + ret = memcpy_sse3(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE2) + ret = memcpy_sse2(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE) + ret = memcpy_sse(dest, src, len); + else + ret = memcpy_unsafe(dest, src, len); + } else + { + static int once = 0; + if (!once++) + fixme("SIMD memcpy disabled"); ret = memcpy_unsafe(dest, src, len); + } #ifdef DEBUG if (EnableExternalMemoryTracer) { @@ -857,21 +868,31 @@ EXTERNC __no_stack_protector void *__memset_chk(void *dest, int val, size_t len, __chk_fail(); void *ret = nullptr; - uint64_t simd = CPU::CheckSIMD(); - if (simd & CPU::x86SIMDType::SIMD_SSE42) - ret = memset_sse4_2(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE41) - ret = memset_sse4_1(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSSE3) - ret = memset_ssse3(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE3) - ret = memset_sse3(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE2) - ret = memset_sse2(dest, val, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE) - ret = memset_sse(dest, val, len); + if (0) /* FIXME */ + { + uint64_t simd = CPU::CheckSIMD(); + if (simd & CPU::x86SIMDType::SIMD_SSE42) + ret = memset_sse4_2(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE41) + ret = memset_sse4_1(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSSE3) + ret = memset_ssse3(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE3) + ret = memset_sse3(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE2) + ret = memset_sse2(dest, val, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE) + ret = memset_sse(dest, val, len); + else + ret = memset_unsafe(dest, val, len); + } else + { + static int once = 0; + if (!once++) + fixme("SIMD memset disabled"); ret = memset_unsafe(dest, val, len); + } #ifdef DEBUG if (EnableExternalMemoryTracer) { @@ -928,21 +949,31 @@ EXTERNC __no_stack_protector void *__memmove_chk(void *dest, const void *src, si __chk_fail(); void *ret = nullptr; - uint64_t simd = CPU::CheckSIMD(); - if (simd & CPU::x86SIMDType::SIMD_SSE42) - ret = memmove_sse4_2(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE41) - ret = memmove_sse4_1(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSSE3) - ret = memmove_ssse3(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE3) - ret = memmove_sse3(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE2) - ret = memmove_sse2(dest, src, len); - else if (simd & CPU::x86SIMDType::SIMD_SSE) - ret = memmove_sse(dest, src, len); + if (0) /* FIXME */ + { + uint64_t simd = CPU::CheckSIMD(); + if (simd & CPU::x86SIMDType::SIMD_SSE42) + ret = memmove_sse4_2(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE41) + ret = memmove_sse4_1(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSSE3) + ret = memmove_ssse3(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE3) + ret = memmove_sse3(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE2) + ret = memmove_sse2(dest, src, len); + else if (simd & CPU::x86SIMDType::SIMD_SSE) + ret = memmove_sse(dest, src, len); + else + ret = memmove_unsafe(dest, src, len); + } else + { + static int once = 0; + if (!once++) + fixme("SIMD memmove disabled"); ret = memmove_unsafe(dest, src, len); + } #ifdef DEBUG if (EnableExternalMemoryTracer) { diff --git a/Library/libstdc++/cxxabi.cpp b/Library/libstdc++/cxxabi.cpp index 68ff010..942dd8d 100644 --- a/Library/libstdc++/cxxabi.cpp +++ b/Library/libstdc++/cxxabi.cpp @@ -37,10 +37,25 @@ namespace __cxxabiv1 return &GetCurrentCPU()->EHGlobals; } + /** + * @param f The destructor + * @param objptr The object to be destructed + * @param dso The DSO from which the object was obtained (unused in our case) + * @return Zero on success, non-zero on failure + */ extern "C" int __cxa_atexit(void (*f)(void *), void *objptr, void *dso) { - debug("Registering atexit function %p( %p, %p )", - f, objptr, dso); + if (KernelSymbolTable) + { + debug("Registering atexit function for \"%s\" with destructor \"%s\"", + KernelSymbolTable->GetSymbolFromAddress((uintptr_t)objptr), + KernelSymbolTable->GetSymbolFromAddress((uintptr_t)f)); + } + else + { + debug("Registering atexit function for %p with destructor %p", + objptr, f); + } if (__atexit_func_count >= ATEXIT_MAX_FUNCS) return -1; @@ -53,23 +68,38 @@ namespace __cxxabiv1 extern "C" void __cxa_finalize(void *f) { - fixme("__cxa_finalize( %p ) called.", f); + function("%p", f); uarch_t i = __atexit_func_count; - if (!f) + if (f == nullptr) { while (i--) + { if (__atexit_funcs[i].destructor_func) + { + if (KernelSymbolTable) + { + debug("Calling atexit function \"%s\"", + KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__atexit_funcs[i].destructor_func)); + } + else + { + debug("Calling atexit function %p", + __atexit_funcs[i].destructor_func); + } (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); - + } + } return; } while (i--) + { if (__atexit_funcs[i].destructor_func == f) { (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); __atexit_funcs[i].destructor_func = 0; } + } } extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, _Unwind_Exception *ue_header, _Unwind_Context *context) @@ -122,8 +152,8 @@ namespace __cxxabiv1 { if (TaskManager && !TaskManager->IsPanic()) { - TaskManager->KillThread(TaskManager->GetCurrentThread(), Tasking::KILL_CXXABI_EXCEPTION); - TaskManager->Schedule(); + TaskManager->KillThread(thisThread, Tasking::KILL_CXXABI_EXCEPTION); + TaskManager->Yield(); } error("No task manager to kill thread!"); diff --git a/Library/libstdc++/pbase_type_info.cpp b/Library/libstdc++/pbase_type_info.cpp index 5d1e134..c7658f3 100644 --- a/Library/libstdc++/pbase_type_info.cpp +++ b/Library/libstdc++/pbase_type_info.cpp @@ -26,6 +26,9 @@ namespace __cxxabiv1 unsigned outer) const { #ifndef __GXX_RTTI + UNUSED(ThrowType); + UNUSED(ThrowObject); + UNUSED(outer); return false; #else if (*this == *ThrowType) diff --git a/Library/libstdc++/pointer_type_info.cpp b/Library/libstdc++/pointer_type_info.cpp index ef51941..622ac2d 100644 --- a/Library/libstdc++/pointer_type_info.cpp +++ b/Library/libstdc++/pointer_type_info.cpp @@ -28,6 +28,9 @@ namespace __cxxabiv1 unsigned Outer) const { #ifndef __GXX_RTTI + UNUSED(ThrownType); + UNUSED(ThrowObject); + UNUSED(Outer); return false; #else if (Outer < 2 && *this->Pointee == typeid(void)) diff --git a/Library/std/errno.cpp b/Library/std/errno.cpp index cc35306..5a17ab2 100644 --- a/Library/std/errno.cpp +++ b/Library/std/errno.cpp @@ -19,9 +19,15 @@ #include #include +#include + +#include "../../kernel.h" + +__aligned(16) static int errno_value = 0; int *__errno_location(void) { - fixme("errno_location() is not implemented yet!"); - return nullptr; + if (unlikely(!TaskManager || !thisThread)) + return &errno_value; + return &thisThread->ErrorNumber; } diff --git a/Library/std/mutex.cpp b/Library/std/mutex.cpp new file mode 100644 index 0000000..37681da --- /dev/null +++ b/Library/std/mutex.cpp @@ -0,0 +1,81 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include + +#include "../../kernel.h" + +using namespace Tasking; + +namespace std +{ + void mutex::lock() + { + bool Result = this->Locked.exchange(true, std::memory_order_acquire); + __sync; + + if (Result) + { + this->Waiting.push_back(thisThread); + thisThread->Block(); + TaskManager->Yield(); + return; + } + + this->Holder = thisThread; + this->Waiting.erase(std::find(this->Waiting.begin(), + this->Waiting.end(), + thisThread)); + } + + bool mutex::try_lock() + { + bool Result = this->Locked.exchange(true, std::memory_order_acquire); + __sync; + + if (!Result) + { + this->Holder = thisThread; + this->Waiting.erase(std::find(this->Waiting.begin(), + this->Waiting.end(), + thisThread)); + } + return !Result; + } + + void mutex::unlock() + { + __sync; + this->Locked.store(false, std::memory_order_release); + + if (!this->Waiting.empty()) + { + this->Holder = this->Waiting[0]; + + this->Holder = this->Waiting.front(); + this->Waiting.erase(this->Waiting.begin()); + this->Holder->Unblock(); + TaskManager->Yield(); + } + else + this->Holder = nullptr; + } +} diff --git a/Library/std/typeinfo.cpp b/Library/std/typeinfo.cpp index ef20fd0..8d8dd54 100644 --- a/Library/std/typeinfo.cpp +++ b/Library/std/typeinfo.cpp @@ -27,6 +27,9 @@ namespace std unsigned Outer) const { stub; + UNUSED(ThrowType); + UNUSED(ThrowObject); + UNUSED(Outer); return false; } @@ -34,6 +37,8 @@ namespace std void **ObjectPointer) const { stub; + UNUSED(Target); + UNUSED(ObjectPointer); return false; } } diff --git a/Makefile b/Makefile index 74dd6e9..26e3d01 100644 --- a/Makefile +++ b/Makefile @@ -52,12 +52,13 @@ LDFLAGS := -Wl,-Map kernel.map -static -nostdlib -nodefaultlibs -nolibc WARNCFLAG = -Wall -Wextra \ -Wfloat-equal -Wpointer-arith -Wcast-align \ -Wredundant-decls -Winit-self -Wswitch-default \ - -Wstrict-overflow=5 -Wconversion + -Wstrict-overflow=5 -Wconversion -Wno-error=cpp -Werror # https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html CFLAGS := \ $(INCLUDE_DIR) \ -DKERNEL_NAME='"$(OSNAME)"' \ + -DKERNEL_ARCH='"$(OSARCH)"' \ -DKERNEL_VERSION='"$(KERNEL_VERSION)"' \ -DGIT_COMMIT='"$(GIT_COMMIT)"' \ -DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"' @@ -66,9 +67,8 @@ SIMD_FLAGS := -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mavx -mavx2 -mavx51 ifeq ($(OSARCH), amd64) -CFLAGS += -fno-pic -fno-pie \ - -mno-red-zone -march=core2 -pipe \ - -mcmodel=kernel -fno-builtin -Da64 -Da86 +CFLAGS += -fno-pic -fno-pie -mno-red-zone -march=core2 \ + -mcmodel=kernel -fno-builtin -Da64 -Da86 -m64 CFLAG_STACK_PROTECTOR := -fstack-protector-all LDFLAGS += -TArchitecture/amd64/linker.ld \ -fno-pic -fno-pie \ @@ -78,9 +78,8 @@ LDFLAGS += -TArchitecture/amd64/linker.ld \ else ifeq ($(OSARCH), i386) -CFLAGS += -fno-pic -fno-pie -mno-80387 -mno-mmx -mno-3dnow \ - -mno-red-zone -march=pentium -pipe -fno-builtin \ - -Da32 -Da86 +CFLAGS += -fno-pic -fno-pie -mno-red-zone -march=pentium \ + -fno-builtin -Da32 -Da86 -m32 CFLAG_STACK_PROTECTOR := -fstack-protector-all LDFLAGS += -TArchitecture/i386/linker.ld \ -fno-pic -fno-pie \ @@ -90,7 +89,7 @@ LDFLAGS += -TArchitecture/i386/linker.ld \ else ifeq ($(OSARCH), aarch64) -CFLAGS += -pipe -fno-builtin -Wstack-protector -Daa64 -fPIC -mno-outline-atomics +CFLAGS += -fno-builtin -Wstack-protector -Daa64 -fPIC -mno-outline-atomics CFLAG_STACK_PROTECTOR := -fstack-protector-all LDFLAGS += -TArchitecture/aarch64/linker.ld -fPIC -pie \ -Wl,-static,--no-dynamic-linker,-ztext \ @@ -112,7 +111,10 @@ ifeq ($(DEBUG), 1) # CFLAGS += --coverage # CFLAGS += -pg # CFLAGS += -finstrument-functions - CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm -fstack-usage -fsanitize=undefined + CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fstack-usage -fsanitize=undefined +ifeq ($(OSARCH), amd64) + CFLAGS += -fverbose-asm +endif ifneq ($(OSARCH), aarch64) CFLAGS += -fstack-check endif diff --git a/Modules/AHCI/AdvancedHostControllerInterface.cpp b/Modules/AHCI/AdvancedHostControllerInterface.cpp index b21afd7..4ec8e01 100644 --- a/Modules/AHCI/AdvancedHostControllerInterface.cpp +++ b/Modules/AHCI/AdvancedHostControllerInterface.cpp @@ -273,7 +273,7 @@ namespace AdvancedHostControllerInterface Ports[i]->Configure(); break; } - case FetchReason: + case QueryReason: { Data->DiskCallback.Fetch.Ports = PortCount; Data->DiskCallback.Fetch.BytesPerSector = 512; diff --git a/Modules/ATA/AdvancedTechnologyAttachment.cpp b/Modules/ATA/AdvancedTechnologyAttachment.cpp index c85c9db..8466238 100644 --- a/Modules/ATA/AdvancedTechnologyAttachment.cpp +++ b/Modules/ATA/AdvancedTechnologyAttachment.cpp @@ -52,7 +52,7 @@ namespace AdvancedTechnologyAttachment debug("Driver received configuration data."); break; } - case FetchReason: + case QueryReason: { break; } diff --git a/Modules/AdvancedMicroDevices/PCNET.cpp b/Modules/AdvancedMicroDevices/PCNET.cpp index 82290f4..e7d15a6 100644 --- a/Modules/AdvancedMicroDevices/PCNET.cpp +++ b/Modules/AdvancedMicroDevices/PCNET.cpp @@ -82,7 +82,7 @@ namespace PCNET return DEVICE_NOT_SUPPORTED; break; } - case FetchReason: + case QueryReason: { memcpy(Data->NetworkCallback.Fetch.Name, (void *)"AMD PCNET", 10); Data->NetworkCallback.Fetch.MAC = MAC.ToHex(); diff --git a/Modules/AudioCodec97/AudioCodec97.cpp b/Modules/AudioCodec97/AudioCodec97.cpp index b513ba6..619059f 100644 --- a/Modules/AudioCodec97/AudioCodec97.cpp +++ b/Modules/AudioCodec97/AudioCodec97.cpp @@ -212,7 +212,7 @@ namespace AudioCodec97 } break; } - case FetchReason: + case QueryReason: { Data->AudioCallback.Fetch.Volume = (unsigned char)((inw(BAR.MixerAddress + NAM_MasterVolume) & 0x3F) * 100 / 0x3F); Data->AudioCallback.Fetch.Encoding = Encoding; /* FIXME */ diff --git a/Modules/BuiltinDriverLoader.cpp b/Modules/BuiltinModuleLoader.cpp similarity index 91% rename from Modules/BuiltinDriverLoader.cpp rename to Modules/BuiltinModuleLoader.cpp index 7f98100..64bc3f1 100644 --- a/Modules/BuiltinDriverLoader.cpp +++ b/Modules/BuiltinModuleLoader.cpp @@ -20,6 +20,7 @@ #include "AHCI/ahci.hpp" #include "VMware/mouse.hpp" #include "PersonalSystem2/mouse.hpp" +#include "PersonalSystem2/keyboard.hpp" #include "ATA/ata.hpp" #include "AudioCodec97/ac97.hpp" #include "Realtek/rtl8139.hpp" @@ -80,6 +81,19 @@ FexExtended PS2MouseExtendedHeader = { .Vector = {12}, // IRQ12 }}}}; +FexExtended PS2KeyboardExtendedHeader = { + .Driver = { + .Name = "PS/2 Keyboard", + .Type = FexDriverType_Input, + .TypeFlags = FexDriverInputTypes_Keyboard, + .Callback = PS2Keyboard::CallbackHandler, + .InterruptCallback = PS2Keyboard::InterruptCallback, + .Bind = { + .Type = BIND_INTERRUPT, + .Interrupt = { + .Vector = {1}, // IRQ1 + }}}}; + FexExtended ATAExtendedHeader = { .Driver = { .Name = "Advanced Technology Attachment", @@ -217,6 +231,18 @@ bool StartPS2Mouse() return false; } +bool StartPS2Keyboard() +{ + Driver::BuiltInDriverInfo BIDI = { + .EntryPoint = PS2Keyboard::DriverEntry, + .ExtendedHeader = &PS2KeyboardExtendedHeader}; + + if (DriverManager->DriverLoadBindInterrupt((uintptr_t)&BIDI, 0, true) == Driver::DriverCode::OK) + return true; + + return false; +} + bool StartATA() { Driver::BuiltInDriverInfo BIDI = { diff --git a/Modules/Intel/Gigabit.cpp b/Modules/Intel/Gigabit.cpp index 8edba36..7d22905 100644 --- a/Modules/Intel/Gigabit.cpp +++ b/Modules/Intel/Gigabit.cpp @@ -203,7 +203,9 @@ namespace Gigabit if (!GetMAC().Valid()) return NOT_AVAILABLE; else + { debug("MAC address found."); + } MAC = GetMAC(); // Start link @@ -244,7 +246,9 @@ namespace Gigabit if (!GetMAC().Valid()) return NOT_AVAILABLE; else + { debug("MAC address found."); + } MAC = GetMAC(); return NOT_IMPLEMENTED; @@ -273,7 +277,9 @@ namespace Gigabit if (!GetMAC().Valid()) return NOT_AVAILABLE; else + { debug("MAC address found."); + } MAC = GetMAC(); return NOT_IMPLEMENTED; @@ -296,7 +302,7 @@ namespace Gigabit } return ERROR; } - case FetchReason: + case QueryReason: { memcpy(Data->NetworkCallback.Fetch.Name, (void *)"Intel Gigabit Ethernet Controller", 34); Data->NetworkCallback.Fetch.MAC = MAC.ToHex(); diff --git a/Modules/PersonalSystem2/Keyboard.cpp b/Modules/PersonalSystem2/Keyboard.cpp new file mode 100644 index 0000000..a55f99d --- /dev/null +++ b/Modules/PersonalSystem2/Keyboard.cpp @@ -0,0 +1,107 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "keyboard.hpp" + +#include +#include +#include + +#include "../../DAPI.hpp" +#include "../drv.hpp" +#include "../../kernel.h" + +namespace PS2Keyboard +{ + KernelAPI KAPI; + + uint8_t ScanCode = 0; + bool InputReceived = false; + + int DriverEntry(void *Data) + { + if (!Data) + return INVALID_KERNEL_API; + KAPI = *(KernelAPI *)Data; + if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0) + return KERNEL_API_VERSION_NOT_SUPPORTED; + + return OK; + } + + int CallbackHandler(KernelCallback *Data) + { + switch (Data->Reason) + { + case AcknowledgeReason: + { + debug("Kernel acknowledged the driver."); + break; + } + case ConfigurationReason: + { + while (inb(0x64) & 0x1) + inb(0x60); + + outb(0x64, 0xAE); + outb(0x64, 0x20); + uint8_t ret = (inb(0x60) | 1) & ~0x10; + outb(0x64, 0x60); + outb(0x60, ret); + outb(0x60, 0xF4); + + outb(0x21, 0xFD); + outb(0xA1, 0xFF); + + trace("PS/2 keyboard configured."); + break; + } + case QueryReason: + { + Data->InputCallback.Keyboard.Key = ScanCode; + break; + } + case PollWaitReason: + { + while (!InputReceived) + TaskManager->Yield(); + InputReceived = false; + + Data->InputCallback.Keyboard.Key = ScanCode; + break; + } + case StopReason: + { + fixme("Driver stopped."); + break; + } + default: + { + warn("Unknown reason."); + break; + } + } + return OK; + } + + int InterruptCallback(CPURegisters *) + { + ScanCode = inb(0x60); + InputReceived = true; + return OK; + } +} diff --git a/Modules/PersonalSystem2/Mouse.cpp b/Modules/PersonalSystem2/Mouse.cpp index 7059197..4323a6b 100644 --- a/Modules/PersonalSystem2/Mouse.cpp +++ b/Modules/PersonalSystem2/Mouse.cpp @@ -1,3 +1,20 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + #include "mouse.hpp" #include @@ -5,6 +22,7 @@ #include "../../DAPI.hpp" #include "../drv.hpp" +#include "../../kernel.h" namespace PS2Mouse { @@ -83,7 +101,7 @@ namespace PS2Mouse trace("PS/2 mouse configured."); break; } - case FetchReason: + case QueryReason: { Data->InputCallback.Mouse.X = MouseX; Data->InputCallback.Mouse.Y = MouseY; @@ -93,6 +111,19 @@ namespace PS2Mouse Data->InputCallback.Mouse.Buttons.Middle = MouseMiddle; break; } + case PollWaitReason: + { + while (!PacketReady) + TaskManager->Yield(); + + Data->InputCallback.Mouse.X = MouseX; + Data->InputCallback.Mouse.Y = MouseY; + Data->InputCallback.Mouse.Z = MouseZ; + Data->InputCallback.Mouse.Buttons.Left = MouseLeft; + Data->InputCallback.Mouse.Buttons.Right = MouseRight; + Data->InputCallback.Mouse.Buttons.Middle = MouseMiddle; + break; + } case StopReason: { outb(COMMAND, 0xA8); diff --git a/Modules/PersonalSystem2/keyboard.hpp b/Modules/PersonalSystem2/keyboard.hpp new file mode 100644 index 0000000..f565a1a --- /dev/null +++ b/Modules/PersonalSystem2/keyboard.hpp @@ -0,0 +1,237 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_PS2_KEYBOARD_H__ +#define __FENNIX_KERNEL_PS2_KEYBOARD_H__ + +#include +#include "../../DAPI.hpp" + +namespace PS2Keyboard +{ + enum DownKeys + { + KEY_D_ESCAPE = 0x1, + + KEY_D_1 = 0x2, + KEY_D_2 = 0x3, + KEY_D_3 = 0x4, + KEY_D_4 = 0x5, + KEY_D_5 = 0x6, + KEY_D_6 = 0x7, + KEY_D_7 = 0x8, + KEY_D_8 = 0x9, + KEY_D_9 = 0xa, + KEY_D_0 = 0xb, + + KEY_D_MINUS = 0xc, + KEY_D_EQUALS = 0xd, + KEY_D_BACKSPACE = 0xe, + KEY_D_TAB = 0xf, + + KEY_D_Q = 0x10, + KEY_D_W = 0x11, + KEY_D_E = 0x12, + KEY_D_R = 0x13, + KEY_D_T = 0x14, + KEY_D_Y = 0x15, + KEY_D_U = 0x16, + KEY_D_I = 0x17, + KEY_D_O = 0x18, + KEY_D_P = 0x19, + + KEY_D_LBRACKET = 0x1a, + KEY_D_RBRACKET = 0x1b, + KEY_D_RETURN = 0x1c, + KEY_D_LCTRL = 0x1d, + + KEY_D_A = 0x1e, + KEY_D_S = 0x1f, + KEY_D_D = 0x20, + KEY_D_F = 0x21, + KEY_D_G = 0x22, + KEY_D_H = 0x23, + KEY_D_J = 0x24, + KEY_D_K = 0x25, + KEY_D_L = 0x26, + + KEY_D_SEMICOLON = 0x27, + KEY_D_APOSTROPHE = 0x28, + KEY_D_GRAVE = 0x29, + KEY_D_LSHIFT = 0x2a, + KEY_D_BACKSLASH = 0x2b, + + KEY_D_Z = 0x2c, + KEY_D_X = 0x2d, + KEY_D_C = 0x2e, + KEY_D_V = 0x2f, + KEY_D_B = 0x30, + KEY_D_N = 0x31, + KEY_D_M = 0x32, + + KEY_D_COMMA = 0x33, + KEY_D_PERIOD = 0x34, + KEY_D_SLASH = 0x35, + KEY_D_RSHIFT = 0x36, + KEY_D_PRTSC = 0x37, + KEY_D_LALT = 0x38, + KEY_D_SPACE = 0x39, + KEY_D_CAPSLOCK = 0x3a, + KEY_D_NUMLOCK = 0x45, + KEY_D_SCROLLLOCK = 0x46, + + KEY_D_KP_MULTIPLY = 0x37, + KEY_D_KP_7 = 0x47, + KEY_D_KP_8 = 0x48, + KEY_D_KP_9 = 0x49, + KEY_D_KP_MINUS = 0x4a, + KEY_D_KP_4 = 0x4b, + KEY_D_KP_5 = 0x4c, + KEY_D_KP_6 = 0x4d, + KEY_D_KP_PLUS = 0x4e, + KEY_D_KP_1 = 0x4f, + KEY_D_KP_2 = 0x50, + KEY_D_KP_3 = 0x51, + KEY_D_KP_0 = 0x52, + KEY_D_KP_PERIOD = 0x53, + + KEY_D_F1 = 0x3b, + KEY_D_F2 = 0x3c, + KEY_D_F3 = 0x3d, + KEY_D_F4 = 0x3e, + KEY_D_F5 = 0x3f, + KEY_D_F6 = 0x40, + KEY_D_F7 = 0x41, + KEY_D_F8 = 0x42, + KEY_D_F9 = 0x43, + KEY_D_F10 = 0x44, + KEY_D_F11 = 0x57, + KEY_D_F12 = 0x58, + + KEY_D_UP = 0x48, + KEY_D_LEFT = 0x4b, + KEY_D_RIGHT = 0x4d, + KEY_D_DOWN = 0x50, + }; + + enum UpKeys + { + KEY_U_ESCAPE = 0x81, + + KEY_U_1 = 0x82, + KEY_U_2 = 0x83, + KEY_U_3 = 0x84, + KEY_U_4 = 0x85, + KEY_U_5 = 0x86, + KEY_U_6 = 0x87, + KEY_U_7 = 0x88, + KEY_U_8 = 0x89, + KEY_U_9 = 0x8a, + KEY_U_0 = 0x8b, + + KEY_U_MINUS = 0x8c, + KEY_U_EQUALS = 0x8d, + KEY_U_BACKSPACE = 0x8e, + KEY_U_TAB = 0x8f, + + KEY_U_Q = 0x90, + KEY_U_W = 0x91, + KEY_U_E = 0x92, + KEY_U_R = 0x93, + KEY_U_T = 0x94, + KEY_U_Y = 0x95, + KEY_U_U = 0x96, + KEY_U_I = 0x97, + KEY_U_O = 0x98, + KEY_U_P = 0x99, + + KEY_U_LBRACKET = 0x9a, + KEY_U_RBRACKET = 0x9b, + KEY_U_RETURN = 0x9c, + KEY_U_LCTRL = 0x9d, + + KEY_U_A = 0x9e, + KEY_U_S = 0x9f, + KEY_U_D = 0xa0, + KEY_U_F = 0xa1, + KEY_U_G = 0xa2, + KEY_U_H = 0xa3, + KEY_U_J = 0xa4, + KEY_U_K = 0xa5, + KEY_U_L = 0xa6, + + KEY_U_SEMICOLON = 0xa7, + KEY_U_APOSTROPHE = 0xa8, + KEY_U_GRAVE = 0xa9, + KEY_U_LSHIFT = 0xaa, + KEY_U_BACKSLASH = 0xab, + + KEY_U_Z = 0xac, + KEY_U_X = 0xad, + KEY_U_C = 0xae, + KEY_U_V = 0xaf, + KEY_U_B = 0xb0, + KEY_U_N = 0xb1, + KEY_U_M = 0xb2, + + KEY_U_COMMA = 0xb3, + KEY_U_PERIOD = 0xb4, + KEY_U_SLASH = 0xb5, + KEY_U_RSHIFT = 0xb6, + KEY_U_KP_MULTIPLY = 0xb7, + KEY_U_LALT = 0xb8, + KEY_U_SPACE = 0xb9, + KEY_U_CAPSLOCK = 0xba, + + KEY_U_F1 = 0xbb, + KEY_U_F2 = 0xbc, + KEY_U_F3 = 0xbd, + KEY_U_F4 = 0xbe, + KEY_U_F5 = 0xbf, + KEY_U_F6 = 0xc0, + KEY_U_F7 = 0xc1, + KEY_U_F8 = 0xc2, + KEY_U_F9 = 0xc3, + KEY_U_F10 = 0xc4, + + KEY_U_NUMLOCK = 0xc5, + KEY_U_SCROLLLOCK = 0xc6, + + KEY_U_KP_7 = 0xc7, + KEY_U_KP_8 = 0xc8, + KEY_U_KP_9 = 0xc9, + KEY_U_KP_MINUS = 0xca, + KEY_U_KP_4 = 0xcb, + KEY_U_KP_5 = 0xcc, + KEY_U_KP_6 = 0xcd, + KEY_U_KP_PLUS = 0xce, + KEY_U_KP_1 = 0xcf, + KEY_U_KP_2 = 0xd0, + KEY_U_KP_3 = 0xd1, + KEY_U_KP_0 = 0xd2, + KEY_U_KP_PERIOD = 0xd3, + + KEY_U_F11 = 0xd7, + KEY_U_F12 = 0xd8, + }; + + int DriverEntry(void *); + int CallbackHandler(KernelCallback *); + int InterruptCallback(CPURegisters *); +} + +#endif // !__FENNIX_KERNEL_PS2_KEYBOARD_H__ diff --git a/Modules/Realtek/RTL8139.cpp b/Modules/Realtek/RTL8139.cpp index e981fa2..01cc24b 100644 --- a/Modules/Realtek/RTL8139.cpp +++ b/Modules/Realtek/RTL8139.cpp @@ -141,7 +141,7 @@ namespace RTL8139 return DEVICE_NOT_SUPPORTED; break; } - case FetchReason: + case QueryReason: { memcpy(Data->NetworkCallback.Fetch.Name, (void *)"RTL-8139", 9); Data->NetworkCallback.Fetch.MAC = MAC.ToHex(); diff --git a/Modules/VMware/Mouse.cpp b/Modules/VMware/Mouse.cpp index 22ab43e..86bea91 100644 --- a/Modules/VMware/Mouse.cpp +++ b/Modules/VMware/Mouse.cpp @@ -5,6 +5,7 @@ #include "../../DAPI.hpp" #include "../drv.hpp" +#include "../../kernel.h" /* https://wiki.osdev.org/VMware_tools */ @@ -129,6 +130,8 @@ namespace VMwareMouse int MouseX = 0, MouseY = 0, MouseZ = 0; int MouseButton = 0; + bool InputReceived = false; + int CallbackHandler(KernelCallback *Data) { switch (Data->Reason) @@ -156,7 +159,7 @@ namespace VMwareMouse trace("VMware mouse configured."); break; } - case FetchReason: + case QueryReason: { Data->InputCallback.Mouse.X = (MouseX * KAPI.Display.GetWidth()) / 0xFFFF; Data->InputCallback.Mouse.Y = (MouseY * KAPI.Display.GetHeight()) / 0xFFFF; @@ -166,6 +169,20 @@ namespace VMwareMouse Data->InputCallback.Mouse.Buttons.Middle = MouseButton & 0x08; break; } + case PollWaitReason: + { + while (!InputReceived) + TaskManager->Yield(); + InputReceived = false; + + Data->InputCallback.Mouse.X = (MouseX * KAPI.Display.GetWidth()) / 0xFFFF; + Data->InputCallback.Mouse.Y = (MouseY * KAPI.Display.GetHeight()) / 0xFFFF; + Data->InputCallback.Mouse.Z = MouseZ; + Data->InputCallback.Mouse.Buttons.Left = MouseButton & 0x20; + Data->InputCallback.Mouse.Buttons.Right = MouseButton & 0x10; + Data->InputCallback.Mouse.Buttons.Middle = MouseButton & 0x08; + break; + } case StopReason: { Relative(); @@ -220,6 +237,7 @@ namespace VMwareMouse MouseX = cmd.bx; /* Both X and Y are scaled from 0 to 0xFFFF */ MouseY = cmd.cx; /* You should map these somewhere to the actual resolution. */ MouseZ = (int8_t)cmd.dx; /* Z is a single signed byte indicating scroll direction. */ + InputReceived = true; return OK; } } diff --git a/Modules/drv.hpp b/Modules/drv.hpp index 7fc66bc..16b0f6f 100644 --- a/Modules/drv.hpp +++ b/Modules/drv.hpp @@ -23,6 +23,7 @@ bool StartAHCI(); bool StartVMwareMouse(); bool StartPS2Mouse(); +bool StartPS2Keyboard(); bool StartATA(); bool StartAC97(); bool StartRTL8139(); diff --git a/Network/AddressResolutionProtocol.cpp b/Network/AddressResolutionProtocol.cpp index 5df2fec..8c4f63e 100644 --- a/Network/AddressResolutionProtocol.cpp +++ b/Network/AddressResolutionProtocol.cpp @@ -26,220 +26,221 @@ namespace NetworkARP { - DiscoveredAddress *ARP::ManageDiscoveredAddresses(DAType Type, InternetProtocol IP, MediaAccessControl MAC) - { - switch (Type) - { - case DA_ADD: - { - DiscoveredAddress *tmp = new DiscoveredAddress; - tmp->IP = IP; - tmp->MAC = MAC; - DiscoveredAddresses.push_back(tmp); - netdbg("Added %s to discovered addresses", IP.v4.ToStringLittleEndian()); - return tmp; - } - case DA_DEL: - { - for (size_t i = 0; i < DiscoveredAddresses.size(); i++) - { - if (DiscoveredAddresses[i]->IP.v4 == IP.v4) - { - DiscoveredAddress *tmp = DiscoveredAddresses[i]; - netdbg("Removed %s from discovered addresses", IP.v4.ToStringLittleEndian()); - delete tmp, tmp = nullptr; - DiscoveredAddresses.remove(i); - break; - } - } - return nullptr; - } - case DA_SEARCH: - { - for (size_t i = 0; i < DiscoveredAddresses.size(); i++) - { - if (DiscoveredAddresses[i]->IP.v4 == IP.v4) - { - netdbg("Found %s in discovered addresses", IP.v4.ToStringLittleEndian()); - return DiscoveredAddresses[i]; - } - } - return nullptr; - } - case DA_UPDATE: - { - for (size_t i = 0; i < DiscoveredAddresses.size(); i++) - { - if (DiscoveredAddresses[i]->IP.v4 == IP.v4) - { - DiscoveredAddresses[i]->MAC = MAC; - netdbg("Updated %s in discovered addresses", IP.v4.ToStringLittleEndian()); - return DiscoveredAddresses[i]; - } - } - return nullptr; - } - default: - { - return nullptr; - } - } - return nullptr; - } + DiscoveredAddress *ARP::ManageDiscoveredAddresses(DAType Type, InternetProtocol IP, MediaAccessControl MAC) + { + switch (Type) + { + case DA_ADD: + { + DiscoveredAddress *tmp = new DiscoveredAddress; + tmp->IP = IP; + tmp->MAC = MAC; + DiscoveredAddresses.push_back(tmp); + netdbg("Added %s to discovered addresses", IP.v4.ToStringLittleEndian()); + return tmp; + } + case DA_DEL: + { + forItr(itr, DiscoveredAddresses) + { + if ((*itr)->IP.v4 == IP.v4) + { + DiscoveredAddress *tmp = *itr; + netdbg("Removed %s from discovered addresses", IP.v4.ToStringLittleEndian()); + delete tmp, tmp = nullptr; + DiscoveredAddresses.erase(itr); + break; + } + } - ARP::ARP(NetworkEthernet::Ethernet *Ethernet) : NetworkEthernet::EthernetEvents(NetworkEthernet::TYPE_ARP) - { - debug("ARP interface %#lx created.", this); - this->Ethernet = Ethernet; - } + return nullptr; + } + case DA_SEARCH: + { + for (size_t i = 0; i < DiscoveredAddresses.size(); i++) + { + if (DiscoveredAddresses[i]->IP.v4 == IP.v4) + { + netdbg("Found %s in discovered addresses", IP.v4.ToStringLittleEndian()); + return DiscoveredAddresses[i]; + } + } + return nullptr; + } + case DA_UPDATE: + { + for (size_t i = 0; i < DiscoveredAddresses.size(); i++) + { + if (DiscoveredAddresses[i]->IP.v4 == IP.v4) + { + DiscoveredAddresses[i]->MAC = MAC; + netdbg("Updated %s in discovered addresses", IP.v4.ToStringLittleEndian()); + return DiscoveredAddresses[i]; + } + } + return nullptr; + } + default: + { + return nullptr; + } + } + return nullptr; + } - ARP::~ARP() - { - debug("ARP interface %#lx destroyed.", this); - } + ARP::ARP(NetworkEthernet::Ethernet *Ethernet) : NetworkEthernet::EthernetEvents(NetworkEthernet::TYPE_ARP) + { + debug("ARP interface %#lx created.", this); + this->Ethernet = Ethernet; + } - MediaAccessControl InvalidMAC; - InternetProtocol InvalidIP; - DiscoveredAddress InvalidRet = {.MAC = InvalidMAC, .IP = InvalidIP}; + ARP::~ARP() + { + debug("ARP interface %#lx destroyed.", this); + } - DiscoveredAddress *ARP::Search(InternetProtocol TargetIP) - { - DiscoveredAddress *ret = ManageDiscoveredAddresses(DA_SEARCH, TargetIP, MediaAccessControl()); - if (ret) - return ret; - warn("No address found for %s", TargetIP.v4.ToStringLittleEndian()); - return &InvalidRet; - } + MediaAccessControl InvalidMAC; + InternetProtocol InvalidIP; + DiscoveredAddress InvalidRet = {.MAC = InvalidMAC, .IP = InvalidIP}; - DiscoveredAddress *ARP::Update(InternetProtocol TargetIP, MediaAccessControl TargetMAC) - { - DiscoveredAddress *ret = ManageDiscoveredAddresses(DA_UPDATE, TargetIP, TargetMAC); - if (ret) - return ret; - warn("No address found for %s", TargetIP.v4.ToStringLittleEndian()); - return &InvalidRet; - } + DiscoveredAddress *ARP::Search(InternetProtocol TargetIP) + { + DiscoveredAddress *ret = ManageDiscoveredAddresses(DA_SEARCH, TargetIP, MediaAccessControl()); + if (ret) + return ret; + warn("No address found for %s", TargetIP.v4.ToStringLittleEndian()); + return &InvalidRet; + } - uint48_t ARP::Resolve(InternetProtocol IP) - { - netdbg("Resolving %s", IP.v4.ToStringLittleEndian()); - if (IP.v4 == 0xFFFFFFFF) - return 0xFFFFFFFFFFFF; + DiscoveredAddress *ARP::Update(InternetProtocol TargetIP, MediaAccessControl TargetMAC) + { + DiscoveredAddress *ret = ManageDiscoveredAddresses(DA_UPDATE, TargetIP, TargetMAC); + if (ret) + return ret; + warn("No address found for %s", TargetIP.v4.ToStringLittleEndian()); + return &InvalidRet; + } - /* If we can't find the MAC, return the default value which is 0xFFFFFFFFFFFF. */ - uint48_t ret = this->Search(IP)->MAC.ToHex(); - netdbg("Resolved %s to %lx", IP.v4.ToStringLittleEndian(), ret); + uint48_t ARP::Resolve(InternetProtocol IP) + { + netdbg("Resolving %s", IP.v4.ToStringLittleEndian()); + if (IP.v4 == 0xFFFFFFFF) + return 0xFFFFFFFFFFFF; - if (ret == 0xFFFFFFFFFFFF) - { - netdbg("Sending request"); - /* If we can't find the MAC, send a request. - Because we are going to send this over the network, we need to byteswap first. - This is actually very confusing for me. */ - ARPHeader *Header = new ARPHeader; - Header->HardwareType = b16(ARPHardwareType::HTYPE_ETHERNET); - Header->ProtocolType = b16(NetworkEthernet::FrameType::TYPE_IPV4); - Header->HardwareSize = b8(6); - Header->ProtocolSize = b8(4); - Header->Operation = b16(ARPOperation::REQUEST); - Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); - Header->SenderIP = b32(Ethernet->GetInterface()->IP.v4.ToHex()); - Header->TargetMAC = b48(0xFFFFFFFFFFFF); - Header->TargetIP = b32(IP.v4.ToHex()); - netdbg("SIP: %s; TIP: %s", InternetProtocol().v4.FromHex(Header->SenderIP).ToStringLittleEndian(), - InternetProtocol().v4.FromHex(Header->TargetIP).ToStringLittleEndian()); - /* Send the request to the broadcast MAC address. */ - Ethernet->Send({.Address = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); - delete Header, Header = nullptr; - } + /* If we can't find the MAC, return the default value which is 0xFFFFFFFFFFFF. */ + uint48_t ret = this->Search(IP)->MAC.ToHex(); + netdbg("Resolved %s to %lx", IP.v4.ToStringLittleEndian(), ret); - int RequestTimeout = 20; - debug("Waiting for response"); - while (ret == 0xFFFFFFFFFFFF) - { - ret = this->Search(IP)->MAC.ToHex(); - if (--RequestTimeout == 0) - { - warn("Request timeout."); - return 0; - } - netdbg("Still waiting..."); - TaskManager->Sleep(1000); - } + if (ret == 0xFFFFFFFFFFFF) + { + netdbg("Sending request"); + /* If we can't find the MAC, send a request. + Because we are going to send this over the network, we need to byteswap first. + This is actually very confusing for me. */ + ARPHeader *Header = new ARPHeader; + Header->HardwareType = b16(ARPHardwareType::HTYPE_ETHERNET); + Header->ProtocolType = b16(NetworkEthernet::FrameType::TYPE_IPV4); + Header->HardwareSize = b8(6); + Header->ProtocolSize = b8(4); + Header->Operation = b16(ARPOperation::REQUEST); + Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); + Header->SenderIP = b32(Ethernet->GetInterface()->IP.v4.ToHex()); + Header->TargetMAC = b48(0xFFFFFFFFFFFF); + Header->TargetIP = b32(IP.v4.ToHex()); + netdbg("SIP: %s; TIP: %s", InternetProtocol().v4.FromHex(Header->SenderIP).ToStringLittleEndian(), + InternetProtocol().v4.FromHex(Header->TargetIP).ToStringLittleEndian()); + /* Send the request to the broadcast MAC address. */ + Ethernet->Send({.Address = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}, NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); + delete Header, Header = nullptr; + } - return ret; - } + int RequestTimeout = 20; + debug("Waiting for response"); + while (ret == 0xFFFFFFFFFFFF) + { + ret = this->Search(IP)->MAC.ToHex(); + if (--RequestTimeout == 0) + { + warn("Request timeout."); + return 0; + } + netdbg("Still waiting..."); + TaskManager->Sleep(1000); + } - void ARP::Broadcast(InternetProtocol IP) - { - netdbg("Sending broadcast"); - uint48_t ResolvedMAC = this->Resolve(IP); - ARPHeader *Header = new ARPHeader; - Header->HardwareType = b16(ARPHardwareType::HTYPE_ETHERNET); - Header->ProtocolType = b16(NetworkEthernet::FrameType::TYPE_IPV4); - Header->HardwareSize = b8(0x6); - Header->ProtocolSize = b8(0x4); - Header->Operation = b16(ARPOperation::REQUEST); - Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); - Header->SenderIP = b32(Ethernet->GetInterface()->IP.v4.ToHex()); - Header->TargetMAC = b48(ResolvedMAC); - Header->TargetIP = b32(IP.v4.ToHex()); - Ethernet->Send(MediaAccessControl().FromHex(ResolvedMAC), NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); - delete Header, Header = nullptr; - } + return ret; + } - bool ARP::OnEthernetPacketReceived(uint8_t *Data, size_t Length) - { - UNUSED(Length); - netdbg("Received packet"); - ARPHeader *Header = (ARPHeader *)Data; + void ARP::Broadcast(InternetProtocol IP) + { + netdbg("Sending broadcast"); + uint48_t ResolvedMAC = this->Resolve(IP); + ARPHeader *Header = new ARPHeader; + Header->HardwareType = b16(ARPHardwareType::HTYPE_ETHERNET); + Header->ProtocolType = b16(NetworkEthernet::FrameType::TYPE_IPV4); + Header->HardwareSize = b8(0x6); + Header->ProtocolSize = b8(0x4); + Header->Operation = b16(ARPOperation::REQUEST); + Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); + Header->SenderIP = b32(Ethernet->GetInterface()->IP.v4.ToHex()); + Header->TargetMAC = b48(ResolvedMAC); + Header->TargetIP = b32(IP.v4.ToHex()); + Ethernet->Send(MediaAccessControl().FromHex(ResolvedMAC), NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); + delete Header, Header = nullptr; + } - InternetProtocol SenderIPv4; - SenderIPv4.v4 = SenderIPv4.v4.FromHex(b32(Header->SenderIP)); + bool ARP::OnEthernetPacketReceived(uint8_t *Data, size_t Length) + { + UNUSED(Length); + netdbg("Received packet"); + ARPHeader *Header = (ARPHeader *)Data; - /* We only support Ethernet and IPv4. */ - if (b16(Header->HardwareType) != ARPHardwareType::HTYPE_ETHERNET || b16(Header->ProtocolType) != NetworkEthernet::FrameType::TYPE_IPV4) - { - warn("Invalid hardware/protocol type (%d/%d)", b16(Header->HardwareType), b16(Header->ProtocolType)); - return false; - } + InternetProtocol SenderIPv4; + SenderIPv4.v4 = SenderIPv4.v4.FromHex(b32(Header->SenderIP)); - InternetProtocol TmpIPStruct; - InternetProtocol().v4.FromHex(b32(Header->SenderIP)); + /* We only support Ethernet and IPv4. */ + if (b16(Header->HardwareType) != ARPHardwareType::HTYPE_ETHERNET || b16(Header->ProtocolType) != NetworkEthernet::FrameType::TYPE_IPV4) + { + warn("Invalid hardware/protocol type (%d/%d)", b16(Header->HardwareType), b16(Header->ProtocolType)); + return false; + } - if (ManageDiscoveredAddresses(DA_SEARCH, TmpIPStruct, MediaAccessControl().FromHex(b48(Header->SenderMAC))) == nullptr) - { - netdbg("Discovered new address %s", SenderIPv4.v4.ToStringLittleEndian()); - TmpIPStruct.v4.FromHex(b32(Header->SenderIP)); - ManageDiscoveredAddresses(DA_ADD, TmpIPStruct, MediaAccessControl().FromHex(b48(Header->SenderMAC))); - } - else - { - netdbg("Updated address %s", SenderIPv4.v4.ToStringLittleEndian()); - TmpIPStruct.v4.FromHex(b32(Header->SenderIP)); - ManageDiscoveredAddresses(DA_UPDATE, TmpIPStruct, MediaAccessControl().FromHex(b48(Header->SenderMAC))); - } + InternetProtocol TmpIPStruct; + InternetProtocol().v4.FromHex(b32(Header->SenderIP)); - switch (b16(Header->Operation)) - { - case ARPOperation::REQUEST: - netdbg("Received request from %s", SenderIPv4.v4.ToStringLittleEndian()); - /* We need to byteswap before we send it back. */ - Header->TargetMAC = b48(Header->SenderMAC); - Header->TargetIP = b32(Header->SenderIP); - Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); - Header->SenderIP = b32(Ethernet->GetInterface()->IP.v4.ToHex()); - Header->Operation = b16(ARPOperation::REPLY); - Ethernet->Send(MediaAccessControl().FromHex(Header->TargetMAC), NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); - netdbg("Sent request for %s", SenderIPv4.v4.ToStringLittleEndian()); - break; - case ARPOperation::REPLY: - fixme("Received reply from %s", SenderIPv4.v4.ToStringLittleEndian()); - break; - default: - warn("Invalid operation (%d)", b16(Header->Operation)); - break; - } - return false; - } + if (ManageDiscoveredAddresses(DA_SEARCH, TmpIPStruct, MediaAccessControl().FromHex(b48(Header->SenderMAC))) == nullptr) + { + netdbg("Discovered new address %s", SenderIPv4.v4.ToStringLittleEndian()); + TmpIPStruct.v4.FromHex(b32(Header->SenderIP)); + ManageDiscoveredAddresses(DA_ADD, TmpIPStruct, MediaAccessControl().FromHex(b48(Header->SenderMAC))); + } + else + { + netdbg("Updated address %s", SenderIPv4.v4.ToStringLittleEndian()); + TmpIPStruct.v4.FromHex(b32(Header->SenderIP)); + ManageDiscoveredAddresses(DA_UPDATE, TmpIPStruct, MediaAccessControl().FromHex(b48(Header->SenderMAC))); + } + + switch (b16(Header->Operation)) + { + case ARPOperation::REQUEST: + netdbg("Received request from %s", SenderIPv4.v4.ToStringLittleEndian()); + /* We need to byteswap before we send it back. */ + Header->TargetMAC = b48(Header->SenderMAC); + Header->TargetIP = b32(Header->SenderIP); + Header->SenderMAC = b48(Ethernet->GetInterface()->MAC.ToHex()); + Header->SenderIP = b32(Ethernet->GetInterface()->IP.v4.ToHex()); + Header->Operation = b16(ARPOperation::REPLY); + Ethernet->Send(MediaAccessControl().FromHex(Header->TargetMAC), NetworkEthernet::FrameType::TYPE_ARP, (uint8_t *)Header, sizeof(ARPHeader)); + netdbg("Sent request for %s", SenderIPv4.v4.ToStringLittleEndian()); + break; + case ARPOperation::REPLY: + fixme("Received reply from %s", SenderIPv4.v4.ToStringLittleEndian()); + break; + default: + warn("Invalid operation (%d)", b16(Header->Operation)); + break; + } + return false; + } } diff --git a/Network/Ethernet.cpp b/Network/Ethernet.cpp index e21363f..eb5b87d 100644 --- a/Network/Ethernet.cpp +++ b/Network/Ethernet.cpp @@ -25,124 +25,126 @@ namespace NetworkEthernet { - struct EthernetEventHelperStruct - { - EthernetEvents *Ptr; - uint16_t Type; - }; + struct EthernetEventHelperStruct + { + EthernetEvents *Ptr; + uint16_t Type; + }; - std::vector RegisteredEvents; + std::vector RegisteredEvents; - Ethernet::Ethernet(NetworkInterfaceManager::DeviceInterface *Interface) : NetworkInterfaceManager::Events(Interface) - { - debug("Ethernet interface %#lx created.", this); - this->Interface = Interface; - } - Ethernet::~Ethernet() - { - debug("Ethernet interface %#lx destroyed.", this); - } + Ethernet::Ethernet(NetworkInterfaceManager::DeviceInterface *Interface) : NetworkInterfaceManager::Events(Interface) + { + debug("Ethernet interface %#lx created.", this); + this->Interface = Interface; + } + Ethernet::~Ethernet() + { + debug("Ethernet interface %#lx destroyed.", this); + } - void Ethernet::Send(MediaAccessControl MAC, FrameType Type, uint8_t *Data, size_t Length) - { - netdbg("Sending frame type %#x to %s", Type, MAC.ToString()); - size_t PacketLength = sizeof(EthernetHeader) + Length; - EthernetPacket *Packet = (EthernetPacket *)kmalloc(PacketLength); + void Ethernet::Send(MediaAccessControl MAC, FrameType Type, uint8_t *Data, size_t Length) + { + netdbg("Sending frame type %#x to %s", Type, MAC.ToString()); + size_t PacketLength = sizeof(EthernetHeader) + Length; + EthernetPacket *Packet = (EthernetPacket *)kmalloc(PacketLength); - Packet->Header.DestinationMAC = b48(MAC.ToHex()); - Packet->Header.SourceMAC = b48(this->Interface->MAC.ToHex()); - Packet->Header.Type = b16(Type); + Packet->Header.DestinationMAC = b48(MAC.ToHex()); + Packet->Header.SourceMAC = b48(this->Interface->MAC.ToHex()); + Packet->Header.Type = b16(Type); - memcpy(Packet->Data, Data, Length); - /* Network Interface Manager takes care of physical allocation. - So basically, we allocate here and then it allocates again but 1:1 mapped. */ - NIManager->Send(Interface, (uint8_t *)Packet, PacketLength); - kfree(Packet); - } + memcpy(Packet->Data, Data, Length); + /* Network Interface Manager takes care of physical allocation. + So basically, we allocate here and then it allocates again but 1:1 mapped. */ + NIManager->Send(Interface, (uint8_t *)Packet, PacketLength); + kfree(Packet); + } - void Ethernet::Receive(uint8_t *Data, size_t Length) - { - EthernetPacket *Packet = (EthernetPacket *)Data; - size_t PacketLength = Length - sizeof(EthernetHeader); - /* TODO: I have to do checks here to be sure that PacketLength is right */ - UNUSED(PacketLength); + void Ethernet::Receive(uint8_t *Data, size_t Length) + { + EthernetPacket *Packet = (EthernetPacket *)Data; + size_t PacketLength = Length - sizeof(EthernetHeader); + /* TODO: I have to do checks here to be sure that PacketLength is right */ + UNUSED(PacketLength); - MediaAccessControl SourceMAC; - SourceMAC.FromHex(b48(Packet->Header.SourceMAC)); - MediaAccessControl DestinationMAC; - DestinationMAC.FromHex(b48(Packet->Header.DestinationMAC)); + MediaAccessControl SourceMAC; + SourceMAC.FromHex(b48(Packet->Header.SourceMAC)); + MediaAccessControl DestinationMAC; + DestinationMAC.FromHex(b48(Packet->Header.DestinationMAC)); - netdbg("Received frame type %#x from %s to %s", b16(Packet->Header.Type), SourceMAC.ToString(), DestinationMAC.ToString()); + netdbg("Received frame type %#x from %s to %s", b16(Packet->Header.Type), SourceMAC.ToString(), DestinationMAC.ToString()); - /* Byte-swapped little-endian */ - if (b48(Packet->Header.DestinationMAC) == 0xFFFFFFFFFFFF || - /* Byte-swapped Driver interface has little-endian order */ - b48(Packet->Header.DestinationMAC) == this->Interface->MAC.ToHex()) - /* This is true only if the packet is for us (Interface MAC or broadcast) */ - { - netdbg("Received data from %s [Type %#x]", SourceMAC.ToString(), b16(Packet->Header.Type)); - bool Reply = false; + /* Byte-swapped little-endian */ + if (b48(Packet->Header.DestinationMAC) == 0xFFFFFFFFFFFF || + /* Byte-swapped Driver interface has little-endian order */ + b48(Packet->Header.DestinationMAC) == this->Interface->MAC.ToHex()) + /* This is true only if the packet is for us (Interface MAC or broadcast) */ + { + netdbg("Received data from %s [Type %#x]", SourceMAC.ToString(), b16(Packet->Header.Type)); + bool Reply = false; - switch (b16(Packet->Header.Type)) - { - case TYPE_IPV4: - foreach (auto e in RegisteredEvents) - if (e.Type == TYPE_IPV4) - Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); - break; - case TYPE_ARP: - foreach (auto e in RegisteredEvents) - if (e.Type == TYPE_ARP) - Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); - break; - case TYPE_RARP: - foreach (auto e in RegisteredEvents) - if (e.Type == TYPE_RARP) - Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); - break; - case TYPE_IPV6: - foreach (auto e in RegisteredEvents) - if (e.Type == TYPE_IPV6) - Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); - break; - default: - warn("Unknown packet type %#lx", Packet->Header.Type); - break; - } - if (Reply) - { - /* FIXME: I should reply, right? I have to do more research here... */ - // Packet->Header.DestinationMAC = Packet->Header.SourceMAC; - // Packet->Header.SourceMAC = b48(this->Interface->MAC.ToHex()); - fixme("Replying to %s [%s]=>[%s]", SourceMAC.ToString(), - this->Interface->MAC.ToString(), DestinationMAC.ToString()); - } - } - else - { - netdbg("Packet not for us [%s]=>[%s]", this->Interface->MAC.ToString(), DestinationMAC.ToString()); - } - } + switch (b16(Packet->Header.Type)) + { + case TYPE_IPV4: + foreach (auto e in RegisteredEvents) + if (e.Type == TYPE_IPV4) + Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); + break; + case TYPE_ARP: + foreach (auto e in RegisteredEvents) + if (e.Type == TYPE_ARP) + Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); + break; + case TYPE_RARP: + foreach (auto e in RegisteredEvents) + if (e.Type == TYPE_RARP) + Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); + break; + case TYPE_IPV6: + foreach (auto e in RegisteredEvents) + if (e.Type == TYPE_IPV6) + Reply = e.Ptr->OnEthernetPacketReceived((uint8_t *)Packet->Data, Length); + break; + default: + warn("Unknown packet type %#lx", Packet->Header.Type); + break; + } + if (Reply) + { + /* FIXME: I should reply, right? I have to do more research here... */ + // Packet->Header.DestinationMAC = Packet->Header.SourceMAC; + // Packet->Header.SourceMAC = b48(this->Interface->MAC.ToHex()); + fixme("Replying to %s [%s]=>[%s]", SourceMAC.ToString(), + this->Interface->MAC.ToString(), DestinationMAC.ToString()); + } + } + else + { + netdbg("Packet not for us [%s]=>[%s]", this->Interface->MAC.ToString(), DestinationMAC.ToString()); + } + } - void Ethernet::OnInterfaceReceived(NetworkInterfaceManager::DeviceInterface *Interface, uint8_t *Data, size_t Length) - { - if (Interface == this->Interface) - this->Receive(Data, Length); - } + void Ethernet::OnInterfaceReceived(NetworkInterfaceManager::DeviceInterface *Interface, uint8_t *Data, size_t Length) + { + if (Interface == this->Interface) + this->Receive(Data, Length); + } - EthernetEvents::EthernetEvents(FrameType Type) - { - this->FType = Type; - RegisteredEvents.push_back({.Ptr = this, .Type = (uint16_t)Type}); - } + EthernetEvents::EthernetEvents(FrameType Type) + { + this->FType = Type; + RegisteredEvents.push_back({.Ptr = this, .Type = (uint16_t)Type}); + } - EthernetEvents::~EthernetEvents() - { - for (size_t i = 0; i < RegisteredEvents.size(); i++) - if (RegisteredEvents[i].Ptr == this) - { - RegisteredEvents.remove(i); - return; - } - } + EthernetEvents::~EthernetEvents() + { + forItr(itr, RegisteredEvents) + { + if (itr->Ptr == this) + { + RegisteredEvents.erase(itr); + return; + } + } + } } diff --git a/Network/InternetProtocol.cpp b/Network/InternetProtocol.cpp index ae897c7..562d439 100644 --- a/Network/InternetProtocol.cpp +++ b/Network/InternetProtocol.cpp @@ -127,12 +127,14 @@ namespace NetworkIPv4 IPv4Events::~IPv4Events() { - for (size_t i = 0; i < RegisteredEvents.size(); i++) - if (RegisteredEvents[i] == this) + forItr(itr, RegisteredEvents) + { + if (*itr == this) { - RegisteredEvents.remove(i); + RegisteredEvents.erase(itr); break; } + } } } diff --git a/Network/NetworkController.cpp b/Network/NetworkController.cpp index 7f759e0..0043de2 100644 --- a/Network/NetworkController.cpp +++ b/Network/NetworkController.cpp @@ -38,7 +38,7 @@ namespace NetworkInterfaceManager NetworkInterface::NetworkInterface() { - mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory); + mem = new Memory::MemMgr(nullptr, thisProcess->memDirectory); if (DriverManager->GetDrivers().size() > 0) { foreach (auto Driver in DriverManager->GetDrivers()) @@ -61,14 +61,8 @@ namespace NetworkInterfaceManager // Unregister all events RegisteredEvents.clear(); - foreach (auto inf in Interfaces) - { - if (inf) - { - Interfaces.remove(inf); - delete inf, inf = nullptr; - } - } + forItr(itr, Interfaces) delete *itr; + Interfaces.clear(); // Delete all interfaces and their callbacks and free the memory delete mem, mem = nullptr; @@ -77,7 +71,7 @@ namespace NetworkInterfaceManager void NetworkInterface::FetchNetworkCards(unsigned long DriverUID) { KernelCallback cb{}; - cb.Reason = FetchReason; + cb.Reason = QueryReason; DriverManager->IOCB(DriverUID, &cb); DeviceInterface *Iface = (DeviceInterface *)mem->RequestPages(TO_PAGES(sizeof(DeviceInterface) + 1)); @@ -101,7 +95,7 @@ namespace NetworkInterfaceManager void NetworkInterface::StartNetworkStack() { - TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Critical); + thisThread->SetPriority(Tasking::TaskPriority::Critical); DeviceInterface *DefaultDevice = nullptr; foreach (auto inf in Interfaces) if (inf) @@ -121,7 +115,8 @@ namespace NetworkInterfaceManager NetworkUDP::UDP *udp = new NetworkUDP::UDP(ipv4, DefaultDevice); NetworkUDP::Socket *DHCP_Socket = udp->Connect(InternetProtocol() /* Default value is 255.255.255.255 */, 67); NetworkDHCP::DHCP *dhcp = new NetworkDHCP::DHCP(DHCP_Socket, DefaultDevice); - debug("eth: %p; arp: %p; ipv4: %p; udp: %p; dhcp: %p", eth, arp, ipv4, udp, dhcp); + debug("eth: %p; arp: %p; ipv4: %p; udp: %p; dhcp: %p", + eth, arp, ipv4, udp, dhcp); udp->Bind(DHCP_Socket, dhcp); dhcp->Request(); @@ -159,7 +154,7 @@ namespace NetworkInterfaceManager /* TODO: Store everything in an vector and initialize all network cards */ } - TaskManager->GetCurrentThread()->SetPriority(Tasking::TaskPriority::Idle); + thisThread->SetPriority(Tasking::TaskPriority::Idle); CPU::Halt(true); } @@ -172,7 +167,7 @@ namespace NetworkInterfaceManager void NetworkInterface::StartService() { - this->NetSvcThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)CallStartNetworkStackWrapper); + this->NetSvcThread = TaskManager->CreateThread(thisProcess, Tasking::IP(CallStartNetworkStackWrapper)); this->NetSvcThread->Rename("Network Service"); } @@ -220,11 +215,13 @@ namespace NetworkInterfaceManager Events::~Events() { - for (size_t i = 0; i < RegisteredEvents.size(); i++) - if (RegisteredEvents[i] == this) + forItr(itr, RegisteredEvents) + { + if (*itr == this) { - RegisteredEvents.remove(i); - return; + RegisteredEvents.erase(itr); + break; } + } } } diff --git a/Recovery/RecoveryMain.cpp b/Recovery/RecoveryMain.cpp deleted file mode 100644 index 87ebe39..0000000 --- a/Recovery/RecoveryMain.cpp +++ /dev/null @@ -1,371 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include -#include -#include -#include -#include -#include - -#include "../kernel.h" -#include "../Fex.hpp" -#include "../DAPI.hpp" - -using Tasking::IP; -using Tasking::PCB; -using Tasking::TaskTrustLevel; -using Tasking::TCB; -using VirtualFileSystem::File; -using VirtualFileSystem::FileStatus; -using namespace GraphicalUserInterface; - -#ifdef DEBUG -extern uint64_t FIi, PDi, PWi, PWWi, PCi, mmi; -#endif - -extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start; -extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end; - -NewLock(PlayAudioLock); - -namespace Recovery -{ - WidgetCollection *wdgDbgWin = nullptr; - Window *DbgWin = nullptr; - - char *AudioFile = (char *)"none"; - - void PlayAudio() - { - TaskManager->GetCurrentThread()->Rename("PlayAudio Test"); - SmartLock(PlayAudioLock); - Driver::DriverFile AudioDrv; - - foreach (auto Driver in DriverManager->GetDrivers()) - { - if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Audio) - { - AudioDrv = Driver; - break; - } - } - - if (!AudioDrv.Enabled) - { - error("No audio drivers found! Cannot play audio!"); - return; - } - - VirtualFileSystem::File pcm = vfs->Open(AudioFile); - - if (!pcm.IsOK()) - { - error("Cannot open audio file! Cannot play audio!"); - return; - } - - void *PCMRaw = KernelAllocator.RequestPages(TO_PAGES(pcm.GetLength() + 1)); - vfs->Read(pcm, (uint8_t *)PCMRaw, pcm.GetLength()); - - KernelCallback callback{}; - callback.Reason = SendReason; - callback.AudioCallback.Send.Data = (uint8_t *)PCMRaw; - callback.AudioCallback.Send.Length = pcm.GetLength(); - debug("Playing audio..."); - int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback); - UNUSED(status); - debug("Audio played! %d", status); - KernelAllocator.FreePages((void *)PCMRaw, TO_PAGES(pcm.GetLength() + 1)); - vfs->Close(pcm); - TEXIT(0); - } - - void PlayAudioWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)PlayAudio)->SetPriority(Tasking::TaskPriority::Idle); } - - void ChangeSampleRate(char SR) - { - Driver::DriverFile AudioDrv; - - foreach (auto Driver in DriverManager->GetDrivers()) - { - if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Audio) - { - AudioDrv = Driver; - break; - } - } - - if (!AudioDrv.Enabled) - { - error("No audio drivers found! Cannot play audio!"); - return; - } - - KernelCallback callback{}; - callback.Reason = AdjustReason; - callback.AudioCallback.Adjust._SampleRate = true; - callback.AudioCallback.Adjust.SampleRate = SR; - int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback); - UNUSED(status); - debug("Sample rate changed! %d", status); - } - - void CSR8000() { ChangeSampleRate(0); } - void CSR11025() { ChangeSampleRate(1); } - void CSR16000() { ChangeSampleRate(2); } - void CSR22050() { ChangeSampleRate(3); } - void CSR32000() { ChangeSampleRate(4); } - void CSR44100() { ChangeSampleRate(5); } - void CSR48000() { ChangeSampleRate(6); } - void CSR88200() { ChangeSampleRate(7); } - void CSR96000() { ChangeSampleRate(8); } - - void ChangeVolume(char percentage) - { - Driver::DriverFile AudioDrv; - - foreach (auto Driver in DriverManager->GetDrivers()) - { - if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Audio) - { - AudioDrv = Driver; - break; - } - } - - if (!AudioDrv.Enabled) - { - error("No audio drivers found! Cannot play audio!"); - return; - } - - KernelCallback callback{}; - callback.Reason = AdjustReason; - callback.AudioCallback.Adjust._Volume = true; - callback.AudioCallback.Adjust.Volume = percentage; - int status = DriverManager->IOCB(AudioDrv.DriverUID, &callback); - UNUSED(status); - debug("Volume changed! %d", status); - } - - void CV0() { ChangeVolume(0); } - void CV10() { ChangeVolume(10); } - void CV20() { ChangeVolume(20); } - void CV30() { ChangeVolume(30); } - void CV40() { ChangeVolume(40); } - void CV50() { ChangeVolume(50); } - void CV60() { ChangeVolume(60); } - void CV70() { ChangeVolume(70); } - void CV80() { ChangeVolume(80); } - void CV90() { ChangeVolume(90); } - void CV100() { ChangeVolume(100); } - - void BufBight10() { Display->SetBrightness(10, 200); } - void BufBight20() { Display->SetBrightness(20, 200); } - void BufBight30() { Display->SetBrightness(30, 200); } - void BufBight40() { Display->SetBrightness(40, 200); } - void BufBight50() { Display->SetBrightness(50, 200); } - void BufBight60() { Display->SetBrightness(60, 200); } - void BufBight70() { Display->SetBrightness(70, 200); } - void BufBight80() { Display->SetBrightness(80, 200); } - void BufBight90() { Display->SetBrightness(90, 200); } - void BufBight100() { Display->SetBrightness(100, 200); } - - void KernelRecovery::RecoveryThread() - { - while (wdgDbgWin == nullptr || DbgWin == nullptr) - TaskManager->Sleep(100); - - wdgDbgWin->CreateLabel({5, 0, 0, 0}, "Scheduler Ticks / Last Task Ticks"); - GraphicalUserInterface::Handle SchedLblHnd = wdgDbgWin->CreateLabel({5, 15, 0, 0}, "0000000000000000 / 0000000000000000"); - - wdgDbgWin->CreateLabel({5, 40, 0, 0}, "Memory Usage"); - GraphicalUserInterface::Handle MemLblHnd = wdgDbgWin->CreateLabel({5, 55, 0, 0}, "0MB / 0GB (0MB reserved) 0% (0000000000000000 bytes allocated)"); - -#ifdef DEBUG - wdgDbgWin->CreateLabel({5, 95, 0, 0}, "GUI Info"); - wdgDbgWin->CreateLabel({5, 110, 0, 0}, " Fetch Inputs / Paint Desktop / Paint Widgets"); - GraphicalUserInterface::Handle GUI1LblHnd = wdgDbgWin->CreateLabel({5, 125, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000"); - wdgDbgWin->CreateLabel({5, 140, 0, 0}, " Paint Windows / Paint Cursor / Memset & Update"); - GraphicalUserInterface::Handle GUI2LblHnd = wdgDbgWin->CreateLabel({5, 155, 0, 0}, "0000000000000000 / 0000000000000000 / 0000000000000000"); -#endif - - wdgDbgWin->CreateLabel({5, 195, 0, 0}, "Audio"); - wdgDbgWin->CreateButton({5, 210, 85, 15}, "Play Audio", (uintptr_t)PlayAudioWrapper); - - wdgDbgWin->CreateLabel({5, 235, 0, 0}, "Sample Rate"); - wdgDbgWin->CreateButton({5, 250, 45, 15}, "8000", (uintptr_t)CSR8000); - wdgDbgWin->CreateButton({55, 250, 45, 15}, "11025", (uintptr_t)CSR11025); - wdgDbgWin->CreateButton({105, 250, 45, 15}, "16000", (uintptr_t)CSR16000); - wdgDbgWin->CreateButton({155, 250, 45, 15}, "22050", (uintptr_t)CSR22050); - wdgDbgWin->CreateButton({205, 250, 45, 15}, "32000", (uintptr_t)CSR32000); - wdgDbgWin->CreateButton({255, 250, 45, 15}, "44100", (uintptr_t)CSR44100); - wdgDbgWin->CreateButton({305, 250, 45, 15}, "48000", (uintptr_t)CSR48000); - wdgDbgWin->CreateButton({355, 250, 45, 15}, "88200", (uintptr_t)CSR88200); - wdgDbgWin->CreateButton({405, 250, 45, 15}, "96000", (uintptr_t)CSR96000); - - wdgDbgWin->CreateLabel({5, 265, 0, 0}, "Volume"); - wdgDbgWin->CreateButton({5, 280, 25, 15}, "0%", (uintptr_t)CV0); - wdgDbgWin->CreateButton({35, 280, 25, 15}, "10%", (uintptr_t)CV10); - wdgDbgWin->CreateButton({65, 280, 25, 15}, "20%", (uintptr_t)CV20); - wdgDbgWin->CreateButton({95, 280, 25, 15}, "30%", (uintptr_t)CV30); - wdgDbgWin->CreateButton({125, 280, 25, 15}, "40%", (uintptr_t)CV40); - wdgDbgWin->CreateButton({155, 280, 25, 15}, "50%", (uintptr_t)CV50); - wdgDbgWin->CreateButton({185, 280, 25, 15}, "60%", (uintptr_t)CV60); - wdgDbgWin->CreateButton({215, 280, 25, 15}, "70%", (uintptr_t)CV70); - wdgDbgWin->CreateButton({245, 280, 25, 15}, "80%", (uintptr_t)CV80); - wdgDbgWin->CreateButton({275, 280, 25, 15}, "90%", (uintptr_t)CV90); - wdgDbgWin->CreateButton({305, 280, 25, 15}, "100%", (uintptr_t)CV100); - - GraphicalUserInterface::Handle wdgDbgCurrentAudioLbl = wdgDbgWin->CreateLabel({5, 295, 0, 0}, "Current Audio: "); - // wdgDbgWin->CreateButton({5, 310, 85, 15}, "dev_connected.mp3", (uintptr_t)audio_dev_connected); - // wdgDbgWin->CreateButton({95, 310, 85, 15}, "dev_disconnected.mp3", (uintptr_t)audio_dev_disconnected); - // wdgDbgWin->CreateButton({185, 310, 85, 15}, "dev_error.mp3", (uintptr_t)audio_dev_error); - // wdgDbgWin->CreateButton({275, 310, 85, 15}, "error.mp3", (uintptr_t)audio_error); - // wdgDbgWin->CreateButton({365, 310, 85, 15}, "notification.mp3", (uintptr_t)audio_notification); - // wdgDbgWin->CreateButton({455, 310, 85, 15}, "warning.mp3", (uintptr_t)audio_warning); - - wdgDbgWin->CreateLabel({5, 325, 0, 0}, "Display Brightness"); - wdgDbgWin->CreateButton({5, 340, 25, 15}, "10%", (uintptr_t)BufBight10); - wdgDbgWin->CreateButton({35, 340, 25, 15}, "20%", (uintptr_t)BufBight20); - wdgDbgWin->CreateButton({65, 340, 25, 15}, "30%", (uintptr_t)BufBight30); - wdgDbgWin->CreateButton({95, 340, 25, 15}, "40%", (uintptr_t)BufBight40); - wdgDbgWin->CreateButton({125, 340, 25, 15}, "50%", (uintptr_t)BufBight50); - wdgDbgWin->CreateButton({155, 340, 25, 15}, "60%", (uintptr_t)BufBight60); - wdgDbgWin->CreateButton({185, 340, 25, 15}, "70%", (uintptr_t)BufBight70); - wdgDbgWin->CreateButton({215, 340, 25, 15}, "80%", (uintptr_t)BufBight80); - wdgDbgWin->CreateButton({245, 340, 25, 15}, "90%", (uintptr_t)BufBight90); - wdgDbgWin->CreateButton({275, 340, 25, 15}, "100%", (uintptr_t)BufBight100); - - GraphicalUserInterface::Handle wdgDbgCurrentCPUSchedCoreLbl = wdgDbgWin->CreateLabel({5, 355, 0, 0}, "CPU Scheduled Core: Unknown"); - - DbgWin->AddWidget(wdgDbgWin); - - char TicksText[128]; - uint64_t MemUsed = 0; - uint64_t MemTotal = 0; - uint64_t MemReserved = 0; - while (true) - { - sprintf(TicksText, "%016ld / %016ld", TaskManager->GetSchedulerTicks(), TaskManager->GetLastTaskTicks()); - wdgDbgWin->SetText(SchedLblHnd, TicksText); - sprintf(TicksText, "CPU Scheduled Core: %d", TaskManager->GetLastCore()); - wdgDbgWin->SetText(wdgDbgCurrentCPUSchedCoreLbl, TicksText); - static int RefreshMemCounter = 0; - if (RefreshMemCounter-- == 0) - { - MemUsed = KernelAllocator.GetUsedMemory(); - MemTotal = KernelAllocator.GetTotalMemory(); - MemReserved = KernelAllocator.GetReservedMemory(); - uint64_t MemPercent = (MemUsed * 100) / MemTotal; - sprintf(TicksText, "%ldMB / %ldGB (%ldMB reserved) %ld%% (%ld bytes allocated)", TO_MB(MemUsed), TO_GB(MemTotal), TO_MB(MemReserved), MemPercent, MemUsed); - wdgDbgWin->SetText(MemLblHnd, TicksText); - RefreshMemCounter = 25; - } - sprintf(TicksText, "Debug - %ldx%ld", DbgWin->GetPosition().Width, DbgWin->GetPosition().Height); - DbgWin->SetTitle(TicksText); - sprintf(TicksText, "Current Audio: %s", AudioFile); - wdgDbgWin->SetText(wdgDbgCurrentAudioLbl, TicksText); - -#ifdef DEBUG - static int RefreshGUIDbgCounter = 0; - if (RefreshGUIDbgCounter-- == 0) - { - sprintf(TicksText, "%016ld / %016ld / %016ld", FIi, PDi, PWi); - wdgDbgWin->SetText(GUI1LblHnd, TicksText); - sprintf(TicksText, "%016ld / %016ld / %016ld", PWWi, PCi, mmi); - wdgDbgWin->SetText(GUI2LblHnd, TicksText); - RefreshGUIDbgCounter = 5; - } -#endif - TaskManager->Sleep(100); - } - } - - void RecoveryThreadWrapper() - { - while (!RecoveryScreen) - CPU::Pause(); - RecoveryScreen->RecoveryThread(); - } - - void RebootCommandThread() { KST_Reboot(); } - void ShutdownCommandThread() { KST_Shutdown(); } - - void RebootCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RebootCommandThread); } - void ShutdownCommandWrapper() { TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ShutdownCommandThread); } - void ShellCommandWrapper() - { - delete RecoveryScreen, RecoveryScreen = nullptr; - StartKernelShell(); - inf_loop; - } - - GraphicalUserInterface::GUI *gui = nullptr; - void GUIWrapper() { gui->Loop(); } - - KernelRecovery::KernelRecovery() - { - // PCB *proc = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), "Recovery", TaskTrustLevel::Kernel, nullptr); - - gui = new GraphicalUserInterface::GUI; - - guiThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)GUIWrapper); - guiThread->Rename("GUI Thread"); - guiThread->SetPriority(Tasking::TaskPriority::Critical); - - Rect RecoveryModeWindow; - RecoveryModeWindow.Width = 460; - RecoveryModeWindow.Height = 100; - RecoveryModeWindow.Left = Display->GetBuffer(200)->Width / 2 - RecoveryModeWindow.Width / 2; - RecoveryModeWindow.Top = Display->GetBuffer(200)->Height / 2 - RecoveryModeWindow.Height / 2; - Window *RecWin = new Window(gui, RecoveryModeWindow, "Recovery Mode"); - gui->AddWindow(RecWin); - - WidgetCollection *wdgRecWin = new WidgetCollection(RecWin); - wdgRecWin->CreateLabel({80, 10, 0, 0}, "This is not fully implemented."); - wdgRecWin->CreateLabel({10, 40, 0, 0}, "All you can do is shutdown/reboot the system."); - wdgRecWin->CreateButton({10, 70, 90, 20}, "Reboot", (uintptr_t)RebootCommandWrapper); - wdgRecWin->CreateButton({110, 70, 90, 20}, "Shutdown", (uintptr_t)ShutdownCommandWrapper); - wdgRecWin->CreateButton({210, 70, 90, 20}, "Shell", (uintptr_t)ShellCommandWrapper); - RecWin->AddWidget(wdgRecWin); - - Rect DebugWindow; - DebugWindow.Width = 460; - DebugWindow.Height = 380; - DebugWindow.Left = 5; - DebugWindow.Top = 25; - DbgWin = new Window(gui, DebugWindow, "Debug"); - gui->AddWindow(DbgWin); - - wdgDbgWin = new WidgetCollection(DbgWin); - Video::Font *NewFont = new Video::Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, Video::FontType::PCScreenFont2); - wdgDbgWin->ReplaceFont(NewFont); - recoveryThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)RecoveryThreadWrapper); - recoveryThread->Rename("Recovery Thread"); - recoveryThread->SetPriority(Tasking::TaskPriority::Idle); - } - - KernelRecovery::~KernelRecovery() - { - debug("Destructor called"); - TaskManager->KillThread(guiThread, Tasking::KILL_SUCCESS); - TaskManager->KillThread(recoveryThread, Tasking::KILL_SUCCESS); - delete gui, gui = nullptr; - } -} diff --git a/SystemCalls/Linux.cpp b/SystemCalls/Linux.cpp deleted file mode 100644 index 6eeb8f4..0000000 --- a/SystemCalls/Linux.cpp +++ /dev/null @@ -1,2458 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include - -#include "../kernel.h" - -typedef __INT32_TYPE__ mode_t; - -#define internal_unimpl(a, b, c, d, e, f, g) \ - { \ - fixme("Unimplemented Syscall: %lld %lld %lld %lld %lld %lld %lld", a, b, c, d, e, f, g); \ - } - -#define syscall_stub(a, b, c, d, e, f, g) \ - { \ - fixme("( %lld %lld %lld %lld %lld %lld %lld ) stub", a, b, c, d, e, f, g); \ - } - -static ssize_t sys_read(int fd, void *buf, size_t count) -{ - fixme("read( %p %p %ld )", fd, buf, count); - return -1; -} - -static ssize_t sys_write(int fd, const char *buf, size_t count) -{ - fixme("write( %p %p %ld )", fd, buf, count); - return -1; -} - -static ssize_t sys_open(const char *filename, int flags, mode_t mode) -{ - fixme("open( %s %d %d )", filename, flags, mode); - return -1; -} - -static ssize_t sys_close(int fd) -{ - fixme("close( %d )", fd); - return -1; -} - -static ssize_t sys_stat(const char *filename, void *statbuf) -{ - fixme("stat( %s %p )", filename, statbuf); - return -1; -} - -static uint64_t sys_fstat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_lstat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_poll(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_lseek(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mmap(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mprotect(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_munmap(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_brk(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rt_sigaction(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rt_sigprocmask(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rt_sigreturn(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_ioctl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_pread64(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_pwrite64(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_readv(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_writev(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_access(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_pipe(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_select(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_yield(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mremap(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_msync(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mincore(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_madvise(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_shmget(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_shmat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_shmctl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_dup(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_dup2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_pause(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_nanosleep(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getitimer(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_alarm(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setitimer(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getpid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sendfile(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_socket(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_connect(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_accept(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sendto(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_recvfrom(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sendmsg(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_recvmsg(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_shutdown(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_bind(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_listen(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getsockname(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getpeername(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_socketpair(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setsockopt(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getsockopt(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_clone(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fork(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_vfork(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static int sys_execve(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_exit(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_wait4(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_kill(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_uname(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_semget(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_semop(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_semctl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_shmdt(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_msgget(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_msgsnd(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_msgrcv(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_msgctl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fcntl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_flock(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fsync(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fdatasync(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_truncate(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_ftruncate(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getdents(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getcwd(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_chdir(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fchdir(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rename(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mkdir(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rmdir(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_creat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_link(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_unlink(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_symlink(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_readlink(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_chmod(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fchmod(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_chown(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fchown(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_lchown(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_umask(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_gettimeofday(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getrlimit(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getrusage(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sysinfo(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_times(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_ptrace(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static unsigned int sys_getuid(void) -{ - syscall_stub(0, 0, 0, 0, 0, 0, 0); - return 0; -} - -static uint64_t sys_syslog(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static unsigned int sys_getgid(void) -{ - syscall_stub(0, 0, 0, 0, 0, 0, 0); - return 0; -} - -static uint64_t sys_setuid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setgid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static unsigned int sys_geteuid(void) -{ - syscall_stub(0, 0, 0, 0, 0, 0, 0); - return 0; -} - -static unsigned int sys_getegid(void) -{ - syscall_stub(0, 0, 0, 0, 0, 0, 0); - return 0; -} - -static uint64_t sys_setpgid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getppid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getpgrp(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setsid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setreuid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setregid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getgroups(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setgroups(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setresuid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getresuid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setresgid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getresgid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getpgid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setfsuid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setfsgid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getsid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_capget(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_capset(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rt_sigpending(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rt_sigtimedwait(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rt_sigqueueinfo(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rt_sigsuspend(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sigaltstack(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_utime(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mknod(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_uselib(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_personality(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_ustat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_statfs(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fstatfs(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sysfs(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getpriority(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setpriority(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_setparam(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_getparam(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_setscheduler(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_getscheduler(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_get_priority_max(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_get_priority_min(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_rr_get_interval(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mlock(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_munlock(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mlockall(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_munlockall(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_vhangup(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_modify_ldt(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_pivot_root(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys__sysctl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_prctl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_arch_prctl(int code, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) -{ - trace("( code=%#lx, arg2=%lx, arg3=%lx, arg4=%lx, arg5=%lx )", code, arg2, arg3, arg4, arg5); - - switch (code) - { - case 0x1001: // ARCH_SET_GS - { -#if defined(a64) - CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, arg2); -#elif defined(a32) - CPU::x32::wrmsr(CPU::x32::MSRID::MSR_GS_BASE, arg2); -#endif - return arg2; - } - case 0x1002: // ARCH_SET_FS - { -#if defined(a64) - CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, arg2); -#elif defined(a32) - CPU::x32::wrmsr(CPU::x32::MSRID::MSR_FS_BASE, arg2); -#endif - return arg2; - } - case 0x1003: // ARCH_GET_FS - { -#if defined(a64) - return CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); -#elif defined(a32) - return CPU::x32::rdmsr(CPU::x32::MSRID::MSR_FS_BASE); -#endif - } - case 0x1004: // ARCH_GET_GS - { -#if defined(a64) - return CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); -#elif defined(a32) - return CPU::x32::rdmsr(CPU::x32::MSRID::MSR_GS_BASE); -#endif - } - default: - warn("Unimplemented prctl code %#lx (arg2=%lx, arg3=%lx, arg4=%lx, arg5=%lx)", code, arg2, arg3, arg4, arg5); - return -1; /* EINVAL */ - } - return -1; -} - -static uint64_t sys_adjtimex(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setrlimit(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_chroot(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sync(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_acct(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_settimeofday(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mount(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_umount2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_swapon(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_swapoff(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_reboot(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sethostname(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setdomainname(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_iopl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_ioperm(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_create_module(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_init_module(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_delete_module(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_get_kernel_syms(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_query_module(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_quotactl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_nfsservctl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getpmsg(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_putpmsg(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_afs_syscall(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_tuxcall(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_security(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_gettid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_readahead(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setxattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_lsetxattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fsetxattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getxattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_lgetxattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fgetxattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_listxattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_llistxattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_flistxattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_removexattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_lremovexattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fremovexattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_tkill(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_time(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_futex(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_setaffinity(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_getaffinity(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_set_thread_area(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_io_setup(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_io_destroy(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_io_getevents(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_io_submit(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_io_cancel(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_get_thread_area(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_lookup_dcookie(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_epoll_create(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_epoll_ctl_old(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_epoll_wait_old(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_remap_file_pages(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getdents64(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_set_tid_address(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_restart_syscall(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_semtimedop(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fadvise64(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_timer_create(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_timer_settime(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_timer_gettime(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_timer_getoverrun(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_timer_delete(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_clock_settime(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_clock_gettime(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_clock_getres(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_clock_nanosleep(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_exit_group(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_epoll_wait(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_epoll_ctl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_tgkill(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_utimes(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_vserver(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mbind(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_set_mempolicy(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_get_mempolicy(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mq_open(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mq_unlink(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mq_timedsend(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mq_timedreceive(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mq_notify(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mq_getsetattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_kexec_load(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_waitid(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_add_key(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_request_key(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_keyctl(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_ioprio_set(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_ioprio_get(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_inotify_init(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_inotify_add_watch(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_inotify_rm_watch(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_migrate_pages(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_openat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mkdirat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_mknodat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fchownat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_futimesat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_newfstatat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_unlinkat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_renameat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_linkat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_symlinkat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_readlinkat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fchmodat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_faccessat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_pselect6(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_ppoll(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_unshare(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_set_robust_list(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_get_robust_list(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_splice(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_tee(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sync_file_range(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_vmsplice(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_move_pages(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_utimensat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_epoll_pwait(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_signalfd(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_timerfd_create(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_eventfd(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fallocate(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_timerfd_settime(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_timerfd_gettime(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_accept4(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_signalfd4(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_eventfd2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_epoll_create1(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_dup3(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_pipe2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_inotify_init1(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_preadv(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_pwritev(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_rt_tgsigqueueinfo(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_perf_event_open(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_recvmmsg(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fanotify_init(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_fanotify_mark(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_prlimit64(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_name_to_handle_at(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_open_by_handle_at(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_clock_adjtime(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_syncfs(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sendmmsg(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_setns(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getcpu(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_process_vm_readv(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_process_vm_writev(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_kcmp(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_finit_module(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_setattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_sched_getattr(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_renameat2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_seccomp(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_getrandom(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_memfd_create(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_kexec_file_load(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t sys_bpf(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t stub_execveat(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t userfaultfd(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t membarrier(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t mlock2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t copy_file_range(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t preadv2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t pwritev2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t pkey_mprotect(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t pkey_alloc(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t pkey_free(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t statx(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t io_pgetevents(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t rseq(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -static uint64_t pkey_mprotect_(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g) -{ - internal_unimpl(a, b, c, d, e, f, g); - return -1; -} - -// Syscalls list: https://filippo.io/linux-syscall-table/ https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/ - -static void *LinuxSyscallsTable[] = { - [0] = (void *)sys_read, - [1] = (void *)sys_write, - [2] = (void *)sys_open, - [3] = (void *)sys_close, - [4] = (void *)sys_stat, - [5] = (void *)sys_fstat, - [6] = (void *)sys_lstat, - [7] = (void *)sys_poll, - [8] = (void *)sys_lseek, - [9] = (void *)sys_mmap, - [10] = (void *)sys_mprotect, - [11] = (void *)sys_munmap, - [12] = (void *)sys_brk, - [13] = (void *)sys_rt_sigaction, - [14] = (void *)sys_rt_sigprocmask, - [15] = (void *)sys_rt_sigreturn, - [16] = (void *)sys_ioctl, - [17] = (void *)sys_pread64, - [18] = (void *)sys_pwrite64, - [19] = (void *)sys_readv, - [20] = (void *)sys_writev, - [21] = (void *)sys_access, - [22] = (void *)sys_pipe, - [23] = (void *)sys_select, - [24] = (void *)sys_sched_yield, - [25] = (void *)sys_mremap, - [26] = (void *)sys_msync, - [27] = (void *)sys_mincore, - [28] = (void *)sys_madvise, - [29] = (void *)sys_shmget, - [30] = (void *)sys_shmat, - [31] = (void *)sys_shmctl, - [32] = (void *)sys_dup, - [33] = (void *)sys_dup2, - [34] = (void *)sys_pause, - [35] = (void *)sys_nanosleep, - [36] = (void *)sys_getitimer, - [37] = (void *)sys_alarm, - [38] = (void *)sys_setitimer, - [39] = (void *)sys_getpid, - [40] = (void *)sys_sendfile, - [41] = (void *)sys_socket, - [42] = (void *)sys_connect, - [43] = (void *)sys_accept, - [44] = (void *)sys_sendto, - [45] = (void *)sys_recvfrom, - [46] = (void *)sys_sendmsg, - [47] = (void *)sys_recvmsg, - [48] = (void *)sys_shutdown, - [49] = (void *)sys_bind, - [50] = (void *)sys_listen, - [51] = (void *)sys_getsockname, - [52] = (void *)sys_getpeername, - [53] = (void *)sys_socketpair, - [54] = (void *)sys_setsockopt, - [55] = (void *)sys_getsockopt, - [56] = (void *)sys_clone, - [57] = (void *)sys_fork, - [58] = (void *)sys_vfork, - [59] = (void *)sys_execve, - [60] = (void *)sys_exit, - [61] = (void *)sys_wait4, - [62] = (void *)sys_kill, - [63] = (void *)sys_uname, - [64] = (void *)sys_semget, - [65] = (void *)sys_semop, - [66] = (void *)sys_semctl, - [67] = (void *)sys_shmdt, - [68] = (void *)sys_msgget, - [69] = (void *)sys_msgsnd, - [70] = (void *)sys_msgrcv, - [71] = (void *)sys_msgctl, - [72] = (void *)sys_fcntl, - [73] = (void *)sys_flock, - [74] = (void *)sys_fsync, - [75] = (void *)sys_fdatasync, - [76] = (void *)sys_truncate, - [77] = (void *)sys_ftruncate, - [78] = (void *)sys_getdents, - [79] = (void *)sys_getcwd, - [80] = (void *)sys_chdir, - [81] = (void *)sys_fchdir, - [82] = (void *)sys_rename, - [83] = (void *)sys_mkdir, - [84] = (void *)sys_rmdir, - [85] = (void *)sys_creat, - [86] = (void *)sys_link, - [87] = (void *)sys_unlink, - [88] = (void *)sys_symlink, - [89] = (void *)sys_readlink, - [90] = (void *)sys_chmod, - [91] = (void *)sys_fchmod, - [92] = (void *)sys_chown, - [93] = (void *)sys_fchown, - [94] = (void *)sys_lchown, - [95] = (void *)sys_umask, - [96] = (void *)sys_gettimeofday, - [97] = (void *)sys_getrlimit, - [98] = (void *)sys_getrusage, - [99] = (void *)sys_sysinfo, - [100] = (void *)sys_times, - [101] = (void *)sys_ptrace, - [102] = (void *)sys_getuid, - [103] = (void *)sys_syslog, - [104] = (void *)sys_getgid, - [105] = (void *)sys_setuid, - [106] = (void *)sys_setgid, - [107] = (void *)sys_geteuid, - [108] = (void *)sys_getegid, - [109] = (void *)sys_setpgid, - [110] = (void *)sys_getppid, - [111] = (void *)sys_getpgrp, - [112] = (void *)sys_setsid, - [113] = (void *)sys_setreuid, - [114] = (void *)sys_setregid, - [115] = (void *)sys_getgroups, - [116] = (void *)sys_setgroups, - [117] = (void *)sys_setresuid, - [118] = (void *)sys_getresuid, - [119] = (void *)sys_setresgid, - [120] = (void *)sys_getresgid, - [121] = (void *)sys_getpgid, - [122] = (void *)sys_setfsuid, - [123] = (void *)sys_setfsgid, - [124] = (void *)sys_getsid, - [125] = (void *)sys_capget, - [126] = (void *)sys_capset, - [127] = (void *)sys_rt_sigpending, - [128] = (void *)sys_rt_sigtimedwait, - [129] = (void *)sys_rt_sigqueueinfo, - [130] = (void *)sys_rt_sigsuspend, - [131] = (void *)sys_sigaltstack, - [132] = (void *)sys_utime, - [133] = (void *)sys_mknod, - [134] = (void *)sys_uselib, - [135] = (void *)sys_personality, - [136] = (void *)sys_ustat, - [137] = (void *)sys_statfs, - [138] = (void *)sys_fstatfs, - [139] = (void *)sys_sysfs, - [140] = (void *)sys_getpriority, - [141] = (void *)sys_setpriority, - [142] = (void *)sys_sched_setparam, - [143] = (void *)sys_sched_getparam, - [144] = (void *)sys_sched_setscheduler, - [145] = (void *)sys_sched_getscheduler, - [146] = (void *)sys_sched_get_priority_max, - [147] = (void *)sys_sched_get_priority_min, - [148] = (void *)sys_sched_rr_get_interval, - [149] = (void *)sys_mlock, - [150] = (void *)sys_munlock, - [151] = (void *)sys_mlockall, - [152] = (void *)sys_munlockall, - [153] = (void *)sys_vhangup, - [154] = (void *)sys_modify_ldt, - [155] = (void *)sys_pivot_root, - [156] = (void *)sys__sysctl, - [157] = (void *)sys_prctl, - [158] = (void *)sys_arch_prctl, - [159] = (void *)sys_adjtimex, - [160] = (void *)sys_setrlimit, - [161] = (void *)sys_chroot, - [162] = (void *)sys_sync, - [163] = (void *)sys_acct, - [164] = (void *)sys_settimeofday, - [165] = (void *)sys_mount, - [166] = (void *)sys_umount2, - [167] = (void *)sys_swapon, - [168] = (void *)sys_swapoff, - [169] = (void *)sys_reboot, - [170] = (void *)sys_sethostname, - [171] = (void *)sys_setdomainname, - [172] = (void *)sys_iopl, - [173] = (void *)sys_ioperm, - [174] = (void *)sys_create_module, - [175] = (void *)sys_init_module, - [176] = (void *)sys_delete_module, - [177] = (void *)sys_get_kernel_syms, - [178] = (void *)sys_query_module, - [179] = (void *)sys_quotactl, - [180] = (void *)sys_nfsservctl, - [181] = (void *)sys_getpmsg, - [182] = (void *)sys_putpmsg, - [183] = (void *)sys_afs_syscall, - [184] = (void *)sys_tuxcall, - [185] = (void *)sys_security, - [186] = (void *)sys_gettid, - [187] = (void *)sys_readahead, - [188] = (void *)sys_setxattr, - [189] = (void *)sys_lsetxattr, - [190] = (void *)sys_fsetxattr, - [191] = (void *)sys_getxattr, - [192] = (void *)sys_lgetxattr, - [193] = (void *)sys_fgetxattr, - [194] = (void *)sys_listxattr, - [195] = (void *)sys_llistxattr, - [196] = (void *)sys_flistxattr, - [197] = (void *)sys_removexattr, - [198] = (void *)sys_lremovexattr, - [199] = (void *)sys_fremovexattr, - [200] = (void *)sys_tkill, - [201] = (void *)sys_time, - [202] = (void *)sys_futex, - [203] = (void *)sys_sched_setaffinity, - [204] = (void *)sys_sched_getaffinity, - [205] = (void *)sys_set_thread_area, - [206] = (void *)sys_io_setup, - [207] = (void *)sys_io_destroy, - [208] = (void *)sys_io_getevents, - [209] = (void *)sys_io_submit, - [210] = (void *)sys_io_cancel, - [211] = (void *)sys_get_thread_area, - [212] = (void *)sys_lookup_dcookie, - [213] = (void *)sys_epoll_create, - [214] = (void *)sys_epoll_ctl_old, - [215] = (void *)sys_epoll_wait_old, - [216] = (void *)sys_remap_file_pages, - [217] = (void *)sys_getdents64, - [218] = (void *)sys_set_tid_address, - [219] = (void *)sys_restart_syscall, - [220] = (void *)sys_semtimedop, - [221] = (void *)sys_fadvise64, - [222] = (void *)sys_timer_create, - [223] = (void *)sys_timer_settime, - [224] = (void *)sys_timer_gettime, - [225] = (void *)sys_timer_getoverrun, - [226] = (void *)sys_timer_delete, - [227] = (void *)sys_clock_settime, - [228] = (void *)sys_clock_gettime, - [229] = (void *)sys_clock_getres, - [230] = (void *)sys_clock_nanosleep, - [231] = (void *)sys_exit_group, - [232] = (void *)sys_epoll_wait, - [233] = (void *)sys_epoll_ctl, - [234] = (void *)sys_tgkill, - [235] = (void *)sys_utimes, - [236] = (void *)sys_vserver, - [237] = (void *)sys_mbind, - [238] = (void *)sys_set_mempolicy, - [239] = (void *)sys_get_mempolicy, - [240] = (void *)sys_mq_open, - [241] = (void *)sys_mq_unlink, - [242] = (void *)sys_mq_timedsend, - [243] = (void *)sys_mq_timedreceive, - [244] = (void *)sys_mq_notify, - [245] = (void *)sys_mq_getsetattr, - [246] = (void *)sys_kexec_load, - [247] = (void *)sys_waitid, - [248] = (void *)sys_add_key, - [249] = (void *)sys_request_key, - [250] = (void *)sys_keyctl, - [251] = (void *)sys_ioprio_set, - [252] = (void *)sys_ioprio_get, - [253] = (void *)sys_inotify_init, - [254] = (void *)sys_inotify_add_watch, - [255] = (void *)sys_inotify_rm_watch, - [256] = (void *)sys_migrate_pages, - [257] = (void *)sys_openat, - [258] = (void *)sys_mkdirat, - [259] = (void *)sys_mknodat, - [260] = (void *)sys_fchownat, - [261] = (void *)sys_futimesat, - [262] = (void *)sys_newfstatat, - [263] = (void *)sys_unlinkat, - [264] = (void *)sys_renameat, - [265] = (void *)sys_linkat, - [266] = (void *)sys_symlinkat, - [267] = (void *)sys_readlinkat, - [268] = (void *)sys_fchmodat, - [269] = (void *)sys_faccessat, - [270] = (void *)sys_pselect6, - [271] = (void *)sys_ppoll, - [272] = (void *)sys_unshare, - [273] = (void *)sys_set_robust_list, - [274] = (void *)sys_get_robust_list, - [275] = (void *)sys_splice, - [276] = (void *)sys_tee, - [277] = (void *)sys_sync_file_range, - [278] = (void *)sys_vmsplice, - [279] = (void *)sys_move_pages, - [280] = (void *)sys_utimensat, - [281] = (void *)sys_epoll_pwait, - [282] = (void *)sys_signalfd, - [283] = (void *)sys_timerfd_create, - [284] = (void *)sys_eventfd, - [285] = (void *)sys_fallocate, - [286] = (void *)sys_timerfd_settime, - [287] = (void *)sys_timerfd_gettime, - [288] = (void *)sys_accept4, - [289] = (void *)sys_signalfd4, - [290] = (void *)sys_eventfd2, - [291] = (void *)sys_epoll_create1, - [292] = (void *)sys_dup3, - [293] = (void *)sys_pipe2, - [294] = (void *)sys_inotify_init1, - [295] = (void *)sys_preadv, - [296] = (void *)sys_pwritev, - [297] = (void *)sys_rt_tgsigqueueinfo, - [298] = (void *)sys_perf_event_open, - [299] = (void *)sys_recvmmsg, - [300] = (void *)sys_fanotify_init, - [301] = (void *)sys_fanotify_mark, - [302] = (void *)sys_prlimit64, - [303] = (void *)sys_name_to_handle_at, - [304] = (void *)sys_open_by_handle_at, - [305] = (void *)sys_clock_adjtime, - [306] = (void *)sys_syncfs, - [307] = (void *)sys_sendmmsg, - [308] = (void *)sys_setns, - [309] = (void *)sys_getcpu, - [310] = (void *)sys_process_vm_readv, - [311] = (void *)sys_process_vm_writev, - [312] = (void *)sys_kcmp, - [313] = (void *)sys_finit_module, - [314] = (void *)sys_sched_setattr, - [315] = (void *)sys_sched_getattr, - [316] = (void *)sys_renameat2, - [317] = (void *)sys_seccomp, - [318] = (void *)sys_getrandom, - [319] = (void *)sys_memfd_create, - [320] = (void *)sys_kexec_file_load, - [321] = (void *)sys_bpf, - [322] = (void *)stub_execveat, - [323] = (void *)userfaultfd, - [324] = (void *)membarrier, - [325] = (void *)mlock2, - [326] = (void *)copy_file_range, - [327] = (void *)preadv2, - [328] = (void *)pwritev2, - [329] = (void *)pkey_mprotect, - [330] = (void *)pkey_alloc, - [331] = (void *)pkey_free, - [332] = (void *)statx, - [333] = (void *)io_pgetevents, - [334] = (void *)rseq, - [335] = (void *)pkey_mprotect_, -}; - -uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame) -{ -#if defined(a64) - if (Frame->rax > sizeof(LinuxSyscallsTable)) - { - fixme("Syscall %lld not implemented", Frame->rax); - return -1; - } - - uint64_t (*call)(uint64_t, ...) = reinterpret_cast(LinuxSyscallsTable[Frame->rax]); - if (!call) - { - error("Syscall %#llx failed.", Frame->rax); - return -1; - } - uint64_t ret = call(Frame->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9); - Frame->rax = ret; - return ret; -#elif defined(a32) - return 0; -#elif defined(aa64) - return 0; -#endif -} diff --git a/SystemCalls/Linux/Linux.cpp b/SystemCalls/Linux/Linux.cpp new file mode 100644 index 0000000..9a7dc45 --- /dev/null +++ b/SystemCalls/Linux/Linux.cpp @@ -0,0 +1,857 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include + +#include "../../kernel.h" +#include "linux_syscalls.hpp" + +struct SyscallData +{ + const char *Name; + void *Handler; +}; + +using InterProcessCommunication::IPC; +using InterProcessCommunication::IPCID; +using Tasking::TaskStatus::Ready; +using Tasking::TaskStatus::Terminated; + +#define ARCH_SET_GS 0x1001 +#define ARCH_SET_FS 0x1002 +#define ARCH_GET_FS 0x1003 +#define ARCH_GET_GS 0x1004 + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 +#define PROT_GROWSDOWN 0x01000000 +#define PROT_GROWSUP 0x02000000 + +#define MAP_FAILED ((void *)-1) + +#define MAP_FILE 0 +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_SHARED_VALIDATE 0x03 +#define MAP_TYPE 0x0f +#define MAP_FIXED 0x10 +#define MAP_ANON 0x20 +#define MAP_ANONYMOUS MAP_ANON +#define MAP_NORESERVE 0x4000 +#define MAP_GROWSDOWN 0x0100 +#define MAP_DENYWRITE 0x0800 +#define MAP_EXECUTABLE 0x1000 +#define MAP_LOCKED 0x2000 +#define MAP_POPULATE 0x8000 +#define MAP_NONBLOCK 0x10000 +#define MAP_STACK 0x20000 +#define MAP_HUGETLB 0x40000 +#define MAP_SYNC 0x80000 +#define MAP_FIXED_NOREPLACE 0x100000 + +typedef int pid_t; + +struct iovec +{ + void *iov_base; + size_t iov_len; +}; + +#if defined(a64) || defined(aa64) +static ssize_t ConvertErrno(ssize_t r) +{ + if (r >= 0) + return r; + return -errno; +} +#endif + +static int ConvertErrno(int r) +{ + if (r >= 0) + return r; + return -errno; +} + +/* https://man7.org/linux/man-pages/man2/read.2.html */ +static ssize_t sys_read(int fd, void *buf, size_t count) +{ + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_read(fd, buf, count)); +} + +/* https://man7.org/linux/man-pages/man2/write.2.html */ +static ssize_t sys_write(int fd, const void *buf, size_t count) +{ + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_write(fd, buf, count)); +} + +/* https://man7.org/linux/man-pages/man2/open.2.html */ +static int sys_open(const char *pathname, int flags, mode_t mode) +{ + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_open(pathname, flags, mode)); +} + +/* https://man7.org/linux/man-pages/man2/close.2.html */ +static int sys_close(int fd) +{ + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_close(fd)); +} + +/* https://man7.org/linux/man-pages/man3/stat.3p.html */ +static int sys_stat(const char *pathname, struct stat *statbuf) +{ + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_stat(pathname, statbuf)); +} + +/* https://man7.org/linux/man-pages/man3/fstat.3p.html */ +static int sys_fstat(int fd, struct stat *statbuf) +{ +#undef fstat + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_fstat(fd, statbuf)); +} + +/* https://man7.org/linux/man-pages/man2/lstat.2.html */ +static int sys_lstat(const char *pathname, struct stat *statbuf) +{ +#undef lstat + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_lstat(pathname, statbuf)); +} + +/* https://man7.org/linux/man-pages/man2/lseek.2.html */ +static off_t sys_lseek(int fd, off_t offset, int whence) +{ + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_lseek(fd, offset, whence)); +} + +/* https://man7.org/linux/man-pages/man3/mmap.3p.html */ +static void *sys_mmap(void *addr, size_t length, int prot, + int flags, int fildes, off_t offset) +{ + UNUSED(offset); /* FIXME */ + Tasking::PCB *pcb = thisProcess; + Memory::MemMgr *mgr = pcb->Memory; + + if (!addr) + { + void *newPages = mgr->RequestPages(TO_PAGES(length)); + if (newPages == nullptr) + return MAP_FAILED; + + Memory::Virtual vma = Memory::Virtual(pcb->PageTable); + + if (prot & PROT_READ) + vma.Map(newPages, newPages, length, Memory::P | Memory::US, Memory::Virtual::FourKiB); + if (prot & PROT_WRITE) + vma.Map(newPages, newPages, length, Memory::RW, Memory::Virtual::FourKiB); + if (prot & PROT_EXEC) + fixme("PROT_EXEC not implemented"); + + if (flags & MAP_FILE) + fixme("MAP_FILE not implemented"); + if (flags & MAP_SHARED) + fixme("MAP_SHARED not implemented"); + if (flags & MAP_PRIVATE) + fixme("MAP_PRIVATE not implemented"); + if (flags & MAP_SHARED_VALIDATE) + fixme("MAP_SHARED_VALIDATE not implemented"); + if (flags & MAP_TYPE) + fixme("MAP_TYPE not implemented"); + if (flags & MAP_FIXED) + fixme("MAP_FIXED not implemented"); + if (flags & MAP_ANONYMOUS) + fixme("MAP_ANONYMOUS not implemented"); + + if (fildes != -1) + { + fixme("File mapping not implemented"); + return MAP_FAILED; + } + + return newPages; + } + + stub; + return MAP_FAILED; +} + +/* https://man7.org/linux/man-pages/man3/mprotect.3p.html */ +static int sys_mprotect(void *addr, size_t len, int prot) +{ + Tasking::PCB *pcb = thisProcess; + + Memory::Virtual vma = Memory::Virtual(pcb->PageTable); + vma.Map(addr, addr, len, Memory::P, Memory::Virtual::FourKiB); + + if (prot & PROT_READ) + vma.Map(addr, addr, len, Memory::P | Memory::US, Memory::Virtual::FourKiB); + if (prot & PROT_WRITE) + vma.Map(addr, addr, len, Memory::RW, Memory::Virtual::FourKiB); + if (prot & PROT_EXEC) + fixme("PROT_EXEC not implemented"); + + return 0; +} + +/* https://man7.org/linux/man-pages/man2/brk.2.html */ +static void *sys_brk(intptr_t increment) +{ + Tasking::PCB *pcb = thisProcess; + Memory::MemMgr *mgr = pcb->Memory; + + stub; + size_t PagesToAllocate = increment ? TO_PAGES(increment) : 1; + return (void *)mgr->RequestPages(PagesToAllocate, true); +} + +/* https://man7.org/linux/man-pages/man2/ioctl.2.html */ +static int sys_ioctl(int fd, unsigned long request, void *argp) +{ + UNUSED(fd); + UNUSED(request); + UNUSED(argp); + return -ENOSYS; +} + +/* https://man7.org/linux/man-pages/man3/readv.3p.html */ +static ssize_t sys_readv(int fildes, const struct iovec *iov, int iovcnt) +{ + ssize_t Total = 0; + for (int i = 0; i < iovcnt; i++) + { + ssize_t n = sys_read(fildes, iov[i].iov_base, iov[i].iov_len); + if (n < 0) + return n; + + Total += n; + if (n < (ssize_t)iov[i].iov_len) + break; + } + return Total; +} + +/* https://man7.org/linux/man-pages/man3/writev.3p.html */ +static ssize_t sys_writev(int fildes, const struct iovec *iov, int iovcnt) +{ + ssize_t Total = 0; + for (int i = 0; i < iovcnt; i++) + { + ssize_t n = sys_write(fildes, iov[i].iov_base, iov[i].iov_len); + if (n < 0) + return n; + + Total += n; + if (n < (ssize_t)iov[i].iov_len) + break; + } + return Total; +} + +/* https://man7.org/linux/man-pages/man3/exit.3.html */ +static __noreturn void sys_exit(int status) +{ + trace("Userspace thread %s(%d) exited with code %d (%#x)", + thisThread->Name, + thisThread->ID, status, + status < 0 ? -status : status); + + thisThread->ExitCode = status; + thisThread->Status = Terminated; + TaskManager->Yield(); + __builtin_unreachable(); +} + +/* https://man7.org/linux/man-pages/man3/creat.3p.html */ +static int sys_creat(const char *pathname, mode_t mode) +{ + Tasking::PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_creat(pathname, mode)); +} + +/* https://man7.org/linux/man-pages/man2/arch_prctl.2.html */ +static int sys_arch_prctl(int code, unsigned long addr) +{ + switch (code) + { + case 0x1001: // ARCH_SET_GS + { +#if defined(a64) + CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, addr); +#elif defined(a32) + CPU::x32::wrmsr(CPU::x32::MSRID::MSR_GS_BASE, addr); +#endif + return 0; + } + case 0x1002: // ARCH_SET_FS + { +#if defined(a64) + CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, addr); +#elif defined(a32) + CPU::x32::wrmsr(CPU::x32::MSRID::MSR_FS_BASE, addr); +#endif + return 0; + } + case 0x1003: // ARCH_GET_FS + { +#if defined(a64) + *r_cst(uint64_t *, addr) = + CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); +#elif defined(a32) + *r_cst(uint64_t *, addr) = + CPU::x32::rdmsr(CPU::x32::MSRID::MSR_FS_BASE); +#endif + return 0; + } + case 0x1004: // ARCH_GET_GS + { +#if defined(a64) + *r_cst(uint64_t *, addr) = + CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); +#elif defined(a32) + *r_cst(uint64_t *, addr) = + CPU::x32::rdmsr(CPU::x32::MSRID::MSR_GS_BASE); +#endif + return 0; + } + default: + fixme("code=%d", code); + return -ENOSYS; + } +} + +/* https://man7.org/linux/man-pages/man2/set_tid_address.2.html */ +static pid_t sys_set_tid_address(int *tidptr) +{ + Tasking::TCB *tcb = thisThread; + *tidptr = tcb->ID; + return tcb->ID; +} + +/* https://man7.org/linux/man-pages/man2/exit_group.2.html */ +static __noreturn void sys_exit_group(int status) +{ + fixme("status=%d", status); + sys_exit(status); +} + +static SyscallData LinuxSyscallsTable[] = { + [__NR_read] = {"read", (void *)sys_read}, + [__NR_write] = {"write", (void *)sys_write}, + [__NR_open] = {"open", (void *)sys_open}, + [__NR_close] = {"close", (void *)sys_close}, + [__NR_stat] = {"stat", (void *)sys_stat}, + [__NR_fstat] = {"fstat", (void *)sys_fstat}, + [__NR_lstat] = {"lstat", (void *)sys_lstat}, + [__NR_poll] = {"poll", (void *)nullptr}, + [__NR_lseek] = {"lseek", (void *)sys_lseek}, + [__NR_mmap] = {"mmap", (void *)sys_mmap}, + [__NR_mprotect] = {"mprotect", (void *)sys_mprotect}, + [__NR_munmap] = {"munmap", (void *)nullptr}, + [__NR_brk] = {"brk", (void *)sys_brk}, + [__NR_rt_sigaction] = {"rt_sigaction", (void *)nullptr}, + [__NR_rt_sigprocmask] = {"rt_sigprocmask", (void *)nullptr}, + [__NR_rt_sigreturn] = {"rt_sigreturn", (void *)nullptr}, + [__NR_ioctl] = {"ioctl", (void *)sys_ioctl}, + [__NR_pread64] = {"pread64", (void *)nullptr}, + [__NR_pwrite64] = {"pwrite64", (void *)nullptr}, + [__NR_readv] = {"readv", (void *)sys_readv}, + [__NR_writev] = {"writev", (void *)sys_writev}, + [__NR_access] = {"access", (void *)nullptr}, + [__NR_pipe] = {"pipe", (void *)nullptr}, + [__NR_select] = {"select", (void *)nullptr}, + [__NR_sched_yield] = {"sched_yield", (void *)nullptr}, + [__NR_mremap] = {"mremap", (void *)nullptr}, + [__NR_msync] = {"msync", (void *)nullptr}, + [__NR_mincore] = {"mincore", (void *)nullptr}, + [__NR_madvise] = {"madvise", (void *)nullptr}, + [__NR_shmget] = {"shmget", (void *)nullptr}, + [__NR_shmat] = {"shmat", (void *)nullptr}, + [__NR_shmctl] = {"shmctl", (void *)nullptr}, + [__NR_dup] = {"dup", (void *)nullptr}, + [__NR_dup2] = {"dup2", (void *)nullptr}, + [__NR_pause] = {"pause", (void *)nullptr}, + [__NR_nanosleep] = {"nanosleep", (void *)nullptr}, + [__NR_getitimer] = {"getitimer", (void *)nullptr}, + [__NR_alarm] = {"alarm", (void *)nullptr}, + [__NR_setitimer] = {"setitimer", (void *)nullptr}, + [__NR_getpid] = {"getpid", (void *)nullptr}, + [__NR_sendfile] = {"sendfile", (void *)nullptr}, + [__NR_socket] = {"socket", (void *)nullptr}, + [__NR_connect] = {"connect", (void *)nullptr}, + [__NR_accept] = {"accept", (void *)nullptr}, + [__NR_sendto] = {"sendto", (void *)nullptr}, + [__NR_recvfrom] = {"recvfrom", (void *)nullptr}, + [__NR_sendmsg] = {"sendmsg", (void *)nullptr}, + [__NR_recvmsg] = {"recvmsg", (void *)nullptr}, + [__NR_shutdown] = {"shutdown", (void *)nullptr}, + [__NR_bind] = {"bind", (void *)nullptr}, + [__NR_listen] = {"listen", (void *)nullptr}, + [__NR_getsockname] = {"getsockname", (void *)nullptr}, + [__NR_getpeername] = {"getpeername", (void *)nullptr}, + [__NR_socketpair] = {"socketpair", (void *)nullptr}, + [__NR_setsockopt] = {"setsockopt", (void *)nullptr}, + [__NR_getsockopt] = {"getsockopt", (void *)nullptr}, + [__NR_clone] = {"clone", (void *)nullptr}, + [__NR_fork] = {"fork", (void *)nullptr}, + [__NR_vfork] = {"vfork", (void *)nullptr}, + [__NR_execve] = {"execve", (void *)nullptr}, + [__NR_exit] = {"exit", (void *)sys_exit}, + [__NR_wait4] = {"wait4", (void *)nullptr}, + [__NR_kill] = {"kill", (void *)nullptr}, + [__NR_uname] = {"uname", (void *)nullptr}, + [__NR_semget] = {"semget", (void *)nullptr}, + [__NR_semop] = {"semop", (void *)nullptr}, + [__NR_semctl] = {"semctl", (void *)nullptr}, + [__NR_shmdt] = {"shmdt", (void *)nullptr}, + [__NR_msgget] = {"msgget", (void *)nullptr}, + [__NR_msgsnd] = {"msgsnd", (void *)nullptr}, + [__NR_msgrcv] = {"msgrcv", (void *)nullptr}, + [__NR_msgctl] = {"msgctl", (void *)nullptr}, + [__NR_fcntl] = {"fcntl", (void *)nullptr}, + [__NR_flock] = {"flock", (void *)nullptr}, + [__NR_fsync] = {"fsync", (void *)nullptr}, + [__NR_fdatasync] = {"fdatasync", (void *)nullptr}, + [__NR_truncate] = {"truncate", (void *)nullptr}, + [__NR_ftruncate] = {"ftruncate", (void *)nullptr}, + [__NR_getdents] = {"getdents", (void *)nullptr}, + [__NR_getcwd] = {"getcwd", (void *)nullptr}, + [__NR_chdir] = {"chdir", (void *)nullptr}, + [__NR_fchdir] = {"fchdir", (void *)nullptr}, + [__NR_rename] = {"rename", (void *)nullptr}, + [__NR_mkdir] = {"mkdir", (void *)nullptr}, + [__NR_rmdir] = {"rmdir", (void *)nullptr}, + [__NR_creat] = {"creat", (void *)sys_creat}, + [__NR_link] = {"link", (void *)nullptr}, + [__NR_unlink] = {"unlink", (void *)nullptr}, + [__NR_symlink] = {"symlink", (void *)nullptr}, + [__NR_readlink] = {"readlink", (void *)nullptr}, + [__NR_chmod] = {"chmod", (void *)nullptr}, + [__NR_fchmod] = {"fchmod", (void *)nullptr}, + [__NR_chown] = {"chown", (void *)nullptr}, + [__NR_fchown] = {"fchown", (void *)nullptr}, + [__NR_lchown] = {"lchown", (void *)nullptr}, + [__NR_umask] = {"umask", (void *)nullptr}, + [__NR_gettimeofday] = {"gettimeofday", (void *)nullptr}, + [__NR_getrlimit] = {"getrlimit", (void *)nullptr}, + [__NR_getrusage] = {"getrusage", (void *)nullptr}, + [__NR_sysinfo] = {"sysinfo", (void *)nullptr}, + [__NR_times] = {"times", (void *)nullptr}, + [__NR_ptrace] = {"ptrace", (void *)nullptr}, + [__NR_getuid] = {"getuid", (void *)nullptr}, + [__NR_syslog] = {"syslog", (void *)nullptr}, + [__NR_getgid] = {"getgid", (void *)nullptr}, + [__NR_setuid] = {"setuid", (void *)nullptr}, + [__NR_setgid] = {"setgid", (void *)nullptr}, + [__NR_geteuid] = {"geteuid", (void *)nullptr}, + [__NR_getegid] = {"getegid", (void *)nullptr}, + [__NR_setpgid] = {"setpgid", (void *)nullptr}, + [__NR_getppid] = {"getppid", (void *)nullptr}, + [__NR_getpgrp] = {"getpgrp", (void *)nullptr}, + [__NR_setsid] = {"setsid", (void *)nullptr}, + [__NR_setreuid] = {"setreuid", (void *)nullptr}, + [__NR_setregid] = {"setregid", (void *)nullptr}, + [__NR_getgroups] = {"getgroups", (void *)nullptr}, + [__NR_setgroups] = {"setgroups", (void *)nullptr}, + [__NR_setresuid] = {"setresuid", (void *)nullptr}, + [__NR_getresuid] = {"getresuid", (void *)nullptr}, + [__NR_setresgid] = {"setresgid", (void *)nullptr}, + [__NR_getresgid] = {"getresgid", (void *)nullptr}, + [__NR_getpgid] = {"getpgid", (void *)nullptr}, + [__NR_setfsuid] = {"setfsuid", (void *)nullptr}, + [__NR_setfsgid] = {"setfsgid", (void *)nullptr}, + [__NR_getsid] = {"getsid", (void *)nullptr}, + [__NR_capget] = {"capget", (void *)nullptr}, + [__NR_capset] = {"capset", (void *)nullptr}, + [__NR_rt_sigpending] = {"rt_sigpending", (void *)nullptr}, + [__NR_rt_sigtimedwait] = {"rt_sigtimedwait", (void *)nullptr}, + [__NR_rt_sigqueueinfo] = {"rt_sigqueueinfo", (void *)nullptr}, + [__NR_rt_sigsuspend] = {"rt_sigsuspend", (void *)nullptr}, + [__NR_sigaltstack] = {"sigaltstack", (void *)nullptr}, + [__NR_utime] = {"utime", (void *)nullptr}, + [__NR_mknod] = {"mknod", (void *)nullptr}, + [__NR_uselib] = {"uselib", (void *)nullptr}, + [__NR_personality] = {"personality", (void *)nullptr}, + [__NR_ustat] = {"ustat", (void *)nullptr}, + [__NR_statfs] = {"statfs", (void *)nullptr}, + [__NR_fstatfs] = {"fstatfs", (void *)nullptr}, + [__NR_sysfs] = {"sysfs", (void *)nullptr}, + [__NR_getpriority] = {"getpriority", (void *)nullptr}, + [__NR_setpriority] = {"setpriority", (void *)nullptr}, + [__NR_sched_setparam] = {"sched_setparam", (void *)nullptr}, + [__NR_sched_getparam] = {"sched_getparam", (void *)nullptr}, + [__NR_sched_setscheduler] = {"sched_setscheduler", (void *)nullptr}, + [__NR_sched_getscheduler] = {"sched_getscheduler", (void *)nullptr}, + [__NR_sched_get_priority_max] = {"sched_get_priority_max", (void *)nullptr}, + [__NR_sched_get_priority_min] = {"sched_get_priority_min", (void *)nullptr}, + [__NR_sched_rr_get_interval] = {"sched_rr_get_interval", (void *)nullptr}, + [__NR_mlock] = {"mlock", (void *)nullptr}, + [__NR_munlock] = {"munlock", (void *)nullptr}, + [__NR_mlockall] = {"mlockall", (void *)nullptr}, + [__NR_munlockall] = {"munlockall", (void *)nullptr}, + [__NR_vhangup] = {"vhangup", (void *)nullptr}, + [__NR_modify_ldt] = {"modify_ldt", (void *)nullptr}, + [__NR_pivot_root] = {"pivot_root", (void *)nullptr}, + [__NR__sysctl] = {"_sysctl", (void *)nullptr}, + [__NR_prctl] = {"prctl", (void *)nullptr}, + [__NR_arch_prctl] = {"arch_prctl", (void *)sys_arch_prctl}, + [__NR_adjtimex] = {"adjtimex", (void *)nullptr}, + [__NR_setrlimit] = {"setrlimit", (void *)nullptr}, + [__NR_chroot] = {"chroot", (void *)nullptr}, + [__NR_sync] = {"sync", (void *)nullptr}, + [__NR_acct] = {"acct", (void *)nullptr}, + [__NR_settimeofday] = {"settimeofday", (void *)nullptr}, + [__NR_mount] = {"mount", (void *)nullptr}, + [__NR_umount2] = {"umount2", (void *)nullptr}, + [__NR_swapon] = {"swapon", (void *)nullptr}, + [__NR_swapoff] = {"swapoff", (void *)nullptr}, + [__NR_reboot] = {"reboot", (void *)nullptr}, + [__NR_sethostname] = {"sethostname", (void *)nullptr}, + [__NR_setdomainname] = {"setdomainname", (void *)nullptr}, + [__NR_iopl] = {"iopl", (void *)nullptr}, + [__NR_ioperm] = {"ioperm", (void *)nullptr}, + [__NR_create_module] = {"create_module", (void *)nullptr}, + [__NR_init_module] = {"init_module", (void *)nullptr}, + [__NR_delete_module] = {"delete_module", (void *)nullptr}, + [__NR_get_kernel_syms] = {"get_kernel_syms", (void *)nullptr}, + [__NR_query_module] = {"query_module", (void *)nullptr}, + [__NR_quotactl] = {"quotactl", (void *)nullptr}, + [__NR_nfsservctl] = {"nfsservctl", (void *)nullptr}, + [__NR_getpmsg] = {"getpmsg", (void *)nullptr}, + [__NR_putpmsg] = {"putpmsg", (void *)nullptr}, + [__NR_afs_syscall] = {"afs_syscall", (void *)nullptr}, + [__NR_tuxcall] = {"tuxcall", (void *)nullptr}, + [__NR_security] = {"security", (void *)nullptr}, + [__NR_gettid] = {"gettid", (void *)nullptr}, + [__NR_readahead] = {"readahead", (void *)nullptr}, + [__NR_setxattr] = {"setxattr", (void *)nullptr}, + [__NR_lsetxattr] = {"lsetxattr", (void *)nullptr}, + [__NR_fsetxattr] = {"fsetxattr", (void *)nullptr}, + [__NR_getxattr] = {"getxattr", (void *)nullptr}, + [__NR_lgetxattr] = {"lgetxattr", (void *)nullptr}, + [__NR_fgetxattr] = {"fgetxattr", (void *)nullptr}, + [__NR_listxattr] = {"listxattr", (void *)nullptr}, + [__NR_llistxattr] = {"llistxattr", (void *)nullptr}, + [__NR_flistxattr] = {"flistxattr", (void *)nullptr}, + [__NR_removexattr] = {"removexattr", (void *)nullptr}, + [__NR_lremovexattr] = {"lremovexattr", (void *)nullptr}, + [__NR_fremovexattr] = {"fremovexattr", (void *)nullptr}, + [__NR_tkill] = {"tkill", (void *)nullptr}, + [__NR_time] = {"time", (void *)nullptr}, + [__NR_futex] = {"futex", (void *)nullptr}, + [__NR_sched_setaffinity] = {"sched_setaffinity", (void *)nullptr}, + [__NR_sched_getaffinity] = {"sched_getaffinity", (void *)nullptr}, + [__NR_set_thread_area] = {"set_thread_area", (void *)nullptr}, + [__NR_io_setup] = {"io_setup", (void *)nullptr}, + [__NR_io_destroy] = {"io_destroy", (void *)nullptr}, + [__NR_io_getevents] = {"io_getevents", (void *)nullptr}, + [__NR_io_submit] = {"io_submit", (void *)nullptr}, + [__NR_io_cancel] = {"io_cancel", (void *)nullptr}, + [__NR_get_thread_area] = {"get_thread_area", (void *)nullptr}, + [__NR_lookup_dcookie] = {"lookup_dcookie", (void *)nullptr}, + [__NR_epoll_create] = {"epoll_create", (void *)nullptr}, + [__NR_epoll_ctl_old] = {"epoll_ctl_old", (void *)nullptr}, + [__NR_epoll_wait_old] = {"epoll_wait_old", (void *)nullptr}, + [__NR_remap_file_pages] = {"remap_file_pages", (void *)nullptr}, + [__NR_getdents64] = {"getdents64", (void *)nullptr}, + [__NR_set_tid_address] = {"set_tid_address", (void *)sys_set_tid_address}, + [__NR_restart_syscall] = {"restart_syscall", (void *)nullptr}, + [__NR_semtimedop] = {"semtimedop", (void *)nullptr}, + [__NR_fadvise64] = {"fadvise64", (void *)nullptr}, + [__NR_timer_create] = {"timer_create", (void *)nullptr}, + [__NR_timer_settime] = {"timer_settime", (void *)nullptr}, + [__NR_timer_gettime] = {"timer_gettime", (void *)nullptr}, + [__NR_timer_getoverrun] = {"timer_getoverrun", (void *)nullptr}, + [__NR_timer_delete] = {"timer_delete", (void *)nullptr}, + [__NR_clock_settime] = {"clock_settime", (void *)nullptr}, + [__NR_clock_gettime] = {"clock_gettime", (void *)nullptr}, + [__NR_clock_getres] = {"clock_getres", (void *)nullptr}, + [__NR_clock_nanosleep] = {"clock_nanosleep", (void *)nullptr}, + [__NR_exit_group] = {"exit_group", (void *)sys_exit_group}, + [__NR_epoll_wait] = {"epoll_wait", (void *)nullptr}, + [__NR_epoll_ctl] = {"epoll_ctl", (void *)nullptr}, + [__NR_tgkill] = {"tgkill", (void *)nullptr}, + [__NR_utimes] = {"utimes", (void *)nullptr}, + [__NR_vserver] = {"vserver", (void *)nullptr}, + [__NR_mbind] = {"mbind", (void *)nullptr}, + [__NR_set_mempolicy] = {"set_mempolicy", (void *)nullptr}, + [__NR_get_mempolicy] = {"get_mempolicy", (void *)nullptr}, + [__NR_mq_open] = {"mq_open", (void *)nullptr}, + [__NR_mq_unlink] = {"mq_unlink", (void *)nullptr}, + [__NR_mq_timedsend] = {"mq_timedsend", (void *)nullptr}, + [__NR_mq_timedreceive] = {"mq_timedreceive", (void *)nullptr}, + [__NR_mq_notify] = {"mq_notify", (void *)nullptr}, + [__NR_mq_getsetattr] = {"mq_getsetattr", (void *)nullptr}, + [__NR_kexec_load] = {"kexec_load", (void *)nullptr}, + [__NR_waitid] = {"waitid", (void *)nullptr}, + [__NR_add_key] = {"add_key", (void *)nullptr}, + [__NR_request_key] = {"request_key", (void *)nullptr}, + [__NR_keyctl] = {"keyctl", (void *)nullptr}, + [__NR_ioprio_set] = {"ioprio_set", (void *)nullptr}, + [__NR_ioprio_get] = {"ioprio_get", (void *)nullptr}, + [__NR_inotify_init] = {"inotify_init", (void *)nullptr}, + [__NR_inotify_add_watch] = {"inotify_add_watch", (void *)nullptr}, + [__NR_inotify_rm_watch] = {"inotify_rm_watch", (void *)nullptr}, + [__NR_migrate_pages] = {"migrate_pages", (void *)nullptr}, + [__NR_openat] = {"openat", (void *)nullptr}, + [__NR_mkdirat] = {"mkdirat", (void *)nullptr}, + [__NR_mknodat] = {"mknodat", (void *)nullptr}, + [__NR_fchownat] = {"fchownat", (void *)nullptr}, + [__NR_futimesat] = {"futimesat", (void *)nullptr}, + [__NR_newfstatat] = {"newfstatat", (void *)nullptr}, + [__NR_unlinkat] = {"unlinkat", (void *)nullptr}, + [__NR_renameat] = {"renameat", (void *)nullptr}, + [__NR_linkat] = {"linkat", (void *)nullptr}, + [__NR_symlinkat] = {"symlinkat", (void *)nullptr}, + [__NR_readlinkat] = {"readlinkat", (void *)nullptr}, + [__NR_fchmodat] = {"fchmodat", (void *)nullptr}, + [__NR_faccessat] = {"faccessat", (void *)nullptr}, + [__NR_pselect6] = {"pselect6", (void *)nullptr}, + [__NR_ppoll] = {"ppoll", (void *)nullptr}, + [__NR_unshare] = {"unshare", (void *)nullptr}, + [__NR_set_robust_list] = {"set_robust_list", (void *)nullptr}, + [__NR_get_robust_list] = {"get_robust_list", (void *)nullptr}, + [__NR_splice] = {"splice", (void *)nullptr}, + [__NR_tee] = {"tee", (void *)nullptr}, + [__NR_sync_file_range] = {"sync_file_range", (void *)nullptr}, + [__NR_vmsplice] = {"vmsplice", (void *)nullptr}, + [__NR_move_pages] = {"move_pages", (void *)nullptr}, + [__NR_utimensat] = {"utimensat", (void *)nullptr}, + [__NR_epoll_pwait] = {"epoll_pwait", (void *)nullptr}, + [__NR_signalfd] = {"signalfd", (void *)nullptr}, + [__NR_timerfd_create] = {"timerfd_create", (void *)nullptr}, + [__NR_eventfd] = {"eventfd", (void *)nullptr}, + [__NR_fallocate] = {"fallocate", (void *)nullptr}, + [__NR_timerfd_settime] = {"timerfd_settime", (void *)nullptr}, + [__NR_timerfd_gettime] = {"timerfd_gettime", (void *)nullptr}, + [__NR_accept4] = {"accept4", (void *)nullptr}, + [__NR_signalfd4] = {"signalfd4", (void *)nullptr}, + [__NR_eventfd2] = {"eventfd2", (void *)nullptr}, + [__NR_epoll_create1] = {"epoll_create1", (void *)nullptr}, + [__NR_dup3] = {"dup3", (void *)nullptr}, + [__NR_pipe2] = {"pipe2", (void *)nullptr}, + [__NR_inotify_init1] = {"inotify_init1", (void *)nullptr}, + [__NR_preadv] = {"preadv", (void *)nullptr}, + [__NR_pwritev] = {"pwritev", (void *)nullptr}, + [__NR_rt_tgsigqueueinfo] = {"rt_tgsigqueueinfo", (void *)nullptr}, + [__NR_perf_event_open] = {"perf_event_open", (void *)nullptr}, + [__NR_recvmmsg] = {"recvmmsg", (void *)nullptr}, + [__NR_fanotify_init] = {"fanotify_init", (void *)nullptr}, + [__NR_fanotify_mark] = {"fanotify_mark", (void *)nullptr}, + [__NR_prlimit64] = {"prlimit64", (void *)nullptr}, + [__NR_name_to_handle_at] = {"name_to_handle_at", (void *)nullptr}, + [__NR_open_by_handle_at] = {"open_by_handle_at", (void *)nullptr}, + [__NR_clock_adjtime] = {"clock_adjtime", (void *)nullptr}, + [__NR_syncfs] = {"syncfs", (void *)nullptr}, + [__NR_sendmmsg] = {"sendmmsg", (void *)nullptr}, + [__NR_setns] = {"setns", (void *)nullptr}, + [__NR_getcpu] = {"getcpu", (void *)nullptr}, + [__NR_process_vm_readv] = {"process_vm_readv", (void *)nullptr}, + [__NR_process_vm_writev] = {"process_vm_writev", (void *)nullptr}, + [__NR_kcmp] = {"kcmp", (void *)nullptr}, + [__NR_finit_module] = {"finit_module", (void *)nullptr}, + [__NR_sched_setattr] = {"sched_setattr", (void *)nullptr}, + [__NR_sched_getattr] = {"sched_getattr", (void *)nullptr}, + [__NR_renameat2] = {"renameat2", (void *)nullptr}, + [__NR_seccomp] = {"seccomp", (void *)nullptr}, + [__NR_getrandom] = {"getrandom", (void *)nullptr}, + [__NR_memfd_create] = {"memfd_create", (void *)nullptr}, + [__NR_kexec_file_load] = {"kexec_file_load", (void *)nullptr}, + [__NR_bpf] = {"bpf", (void *)nullptr}, + [__NR_execveat] = {"execveat", (void *)nullptr}, + [__NR_userfaultfd] = {"userfaultfd", (void *)nullptr}, + [__NR_membarrier] = {"membarrier", (void *)nullptr}, + [__NR_mlock2] = {"mlock2", (void *)nullptr}, + [__NR_copy_file_range] = {"copy_file_range", (void *)nullptr}, + [__NR_preadv2] = {"preadv2", (void *)nullptr}, + [__NR_pwritev2] = {"pwritev2", (void *)nullptr}, + [__NR_pkey_mprotect] = {"pkey_mprotect", (void *)nullptr}, + [__NR_pkey_alloc] = {"pkey_alloc", (void *)nullptr}, + [__NR_pkey_free] = {"pkey_free", (void *)nullptr}, + [__NR_statx] = {"statx", (void *)nullptr}, + [__NR_io_pgetevents] = {"io_pgetevents", (void *)nullptr}, + [__NR_rseq] = {"rseq", (void *)nullptr}, + [335] = {"reserved", (void *)nullptr}, + [336] = {"reserved", (void *)nullptr}, + [337] = {"reserved", (void *)nullptr}, + [338] = {"reserved", (void *)nullptr}, + [339] = {"reserved", (void *)nullptr}, + [340] = {"reserved", (void *)nullptr}, + [341] = {"reserved", (void *)nullptr}, + [342] = {"reserved", (void *)nullptr}, + [343] = {"reserved", (void *)nullptr}, + [344] = {"reserved", (void *)nullptr}, + [345] = {"reserved", (void *)nullptr}, + [346] = {"reserved", (void *)nullptr}, + [347] = {"reserved", (void *)nullptr}, + [348] = {"reserved", (void *)nullptr}, + [349] = {"reserved", (void *)nullptr}, + [350] = {"reserved", (void *)nullptr}, + [351] = {"reserved", (void *)nullptr}, + [352] = {"reserved", (void *)nullptr}, + [353] = {"reserved", (void *)nullptr}, + [354] = {"reserved", (void *)nullptr}, + [355] = {"reserved", (void *)nullptr}, + [356] = {"reserved", (void *)nullptr}, + [357] = {"reserved", (void *)nullptr}, + [358] = {"reserved", (void *)nullptr}, + [359] = {"reserved", (void *)nullptr}, + [360] = {"reserved", (void *)nullptr}, + [361] = {"reserved", (void *)nullptr}, + [362] = {"reserved", (void *)nullptr}, + [363] = {"reserved", (void *)nullptr}, + [364] = {"reserved", (void *)nullptr}, + [365] = {"reserved", (void *)nullptr}, + [366] = {"reserved", (void *)nullptr}, + [367] = {"reserved", (void *)nullptr}, + [368] = {"reserved", (void *)nullptr}, + [369] = {"reserved", (void *)nullptr}, + [370] = {"reserved", (void *)nullptr}, + [371] = {"reserved", (void *)nullptr}, + [372] = {"reserved", (void *)nullptr}, + [373] = {"reserved", (void *)nullptr}, + [374] = {"reserved", (void *)nullptr}, + [375] = {"reserved", (void *)nullptr}, + [376] = {"reserved", (void *)nullptr}, + [377] = {"reserved", (void *)nullptr}, + [378] = {"reserved", (void *)nullptr}, + [379] = {"reserved", (void *)nullptr}, + [380] = {"reserved", (void *)nullptr}, + [381] = {"reserved", (void *)nullptr}, + [382] = {"reserved", (void *)nullptr}, + [383] = {"reserved", (void *)nullptr}, + [384] = {"reserved", (void *)nullptr}, + [385] = {"reserved", (void *)nullptr}, + [386] = {"reserved", (void *)nullptr}, + [387] = {"reserved", (void *)nullptr}, + [388] = {"reserved", (void *)nullptr}, + [389] = {"reserved", (void *)nullptr}, + [390] = {"reserved", (void *)nullptr}, + [391] = {"reserved", (void *)nullptr}, + [392] = {"reserved", (void *)nullptr}, + [393] = {"reserved", (void *)nullptr}, + [394] = {"reserved", (void *)nullptr}, + [395] = {"reserved", (void *)nullptr}, + [396] = {"reserved", (void *)nullptr}, + [397] = {"reserved", (void *)nullptr}, + [398] = {"reserved", (void *)nullptr}, + [399] = {"reserved", (void *)nullptr}, + [400] = {"reserved", (void *)nullptr}, + [401] = {"reserved", (void *)nullptr}, + [402] = {"reserved", (void *)nullptr}, + [403] = {"reserved", (void *)nullptr}, + [404] = {"reserved", (void *)nullptr}, + [405] = {"reserved", (void *)nullptr}, + [406] = {"reserved", (void *)nullptr}, + [407] = {"reserved", (void *)nullptr}, + [408] = {"reserved", (void *)nullptr}, + [409] = {"reserved", (void *)nullptr}, + [410] = {"reserved", (void *)nullptr}, + [411] = {"reserved", (void *)nullptr}, + [412] = {"reserved", (void *)nullptr}, + [413] = {"reserved", (void *)nullptr}, + [414] = {"reserved", (void *)nullptr}, + [415] = {"reserved", (void *)nullptr}, + [416] = {"reserved", (void *)nullptr}, + [417] = {"reserved", (void *)nullptr}, + [418] = {"reserved", (void *)nullptr}, + [419] = {"reserved", (void *)nullptr}, + [420] = {"reserved", (void *)nullptr}, + [421] = {"reserved", (void *)nullptr}, + [422] = {"reserved", (void *)nullptr}, + [423] = {"reserved", (void *)nullptr}, + [__NR_pidfd_send_signal] = {"pidfd_send_signal", (void *)nullptr}, + [__NR_io_uring_setup] = {"io_uring_setup", (void *)nullptr}, + [__NR_io_uring_enter] = {"io_uring_enter", (void *)nullptr}, + [__NR_io_uring_register] = {"io_uring_register", (void *)nullptr}, + [__NR_open_tree] = {"open_tree", (void *)nullptr}, + [__NR_move_mount] = {"move_mount", (void *)nullptr}, + [__NR_fsopen] = {"fsopen", (void *)nullptr}, + [__NR_fsconfig] = {"fsconfig", (void *)nullptr}, + [__NR_fsmount] = {"fsmount", (void *)nullptr}, + [__NR_fspick] = {"fspick", (void *)nullptr}, + [__NR_pidfd_open] = {"pidfd_open", (void *)nullptr}, + [__NR_clone3] = {"clone3", (void *)nullptr}, + [__NR_close_range] = {"close_range", (void *)nullptr}, + [__NR_openat2] = {"openat2", (void *)nullptr}, + [__NR_pidfd_getfd] = {"pidfd_getfd", (void *)nullptr}, + [__NR_faccessat2] = {"faccessat2", (void *)nullptr}, + [__NR_process_madvise] = {"process_madvise", (void *)nullptr}, + [__NR_epoll_pwait2] = {"epoll_pwait2", (void *)nullptr}, + [__NR_mount_setattr] = {"mount_setattr", (void *)nullptr}, + [443] = {"reserved", (void *)nullptr}, + [__NR_landlock_create_ruleset] = {"landlock_create_ruleset", (void *)nullptr}, + [__NR_landlock_add_rule] = {"landlock_add_rule", (void *)nullptr}, + [__NR_landlock_restrict_self] = {"landlock_restrict_self", (void *)nullptr}, +}; + +uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame) +{ +#if defined(a64) + if (Frame->rax > sizeof(LinuxSyscallsTable) / sizeof(SyscallData)) + { + fixme("Syscall %d not implemented", + Frame->rax); + return -ENOSYS; + } + + SyscallData Syscall = LinuxSyscallsTable[Frame->rax]; + + long (*call)(long, ...) = r_cst(long (*)(long, ...), + Syscall.Handler); + + if (unlikely(!call)) + { + error("Syscall %s(%d) not implemented.", + Syscall.Name, Frame->rax); + return -ENOSYS; + } + + debug("[%d:\"%s\"]->( %#lx %#lx %#lx %#lx %#lx %#lx )", + Frame->rax, Syscall.Name, + Frame->rdi, Frame->rsi, Frame->rdx, + Frame->r10, Frame->r8, Frame->r9); + + return call(Frame->rdi, Frame->rsi, Frame->rdx, + Frame->r10, Frame->r8, Frame->r9); +#elif defined(a32) + return 0; +#elif defined(aa64) + return 0; +#endif +} diff --git a/SystemCalls/Linux/linux_syscalls.hpp b/SystemCalls/Linux/linux_syscalls.hpp new file mode 100644 index 0000000..7d81d7d --- /dev/null +++ b/SystemCalls/Linux/linux_syscalls.hpp @@ -0,0 +1,381 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_LINUX_SYSCALLS_H__ +#define __FENNIX_KERNEL_LINUX_SYSCALLS_H__ + +#include + +#define __NR_read 0 +#define __NR_write 1 +#define __NR_open 2 +#define __NR_close 3 +#define __NR_stat 4 +#define __NR_fstat 5 +#define __NR_lstat 6 +#define __NR_poll 7 +#define __NR_lseek 8 +#define __NR_mmap 9 +#define __NR_mprotect 10 +#define __NR_munmap 11 +#define __NR_brk 12 +#define __NR_rt_sigaction 13 +#define __NR_rt_sigprocmask 14 +#define __NR_rt_sigreturn 15 +#define __NR_ioctl 16 +#define __NR_pread64 17 +#define __NR_pwrite64 18 +#define __NR_readv 19 +#define __NR_writev 20 +#define __NR_access 21 +#define __NR_pipe 22 +#define __NR_select 23 +#define __NR_sched_yield 24 +#define __NR_mremap 25 +#define __NR_msync 26 +#define __NR_mincore 27 +#define __NR_madvise 28 +#define __NR_shmget 29 +#define __NR_shmat 30 +#define __NR_shmctl 31 +#define __NR_dup 32 +#define __NR_dup2 33 +#define __NR_pause 34 +#define __NR_nanosleep 35 +#define __NR_getitimer 36 +#define __NR_alarm 37 +#define __NR_setitimer 38 +#define __NR_getpid 39 +#define __NR_sendfile 40 +#define __NR_socket 41 +#define __NR_connect 42 +#define __NR_accept 43 +#define __NR_sendto 44 +#define __NR_recvfrom 45 +#define __NR_sendmsg 46 +#define __NR_recvmsg 47 +#define __NR_shutdown 48 +#define __NR_bind 49 +#define __NR_listen 50 +#define __NR_getsockname 51 +#define __NR_getpeername 52 +#define __NR_socketpair 53 +#define __NR_setsockopt 54 +#define __NR_getsockopt 55 +#define __NR_clone 56 +#define __NR_fork 57 +#define __NR_vfork 58 +#define __NR_execve 59 +#define __NR_exit 60 +#define __NR_wait4 61 +#define __NR_kill 62 +#define __NR_uname 63 +#define __NR_semget 64 +#define __NR_semop 65 +#define __NR_semctl 66 +#define __NR_shmdt 67 +#define __NR_msgget 68 +#define __NR_msgsnd 69 +#define __NR_msgrcv 70 +#define __NR_msgctl 71 +#define __NR_fcntl 72 +#define __NR_flock 73 +#define __NR_fsync 74 +#define __NR_fdatasync 75 +#define __NR_truncate 76 +#define __NR_ftruncate 77 +#define __NR_getdents 78 +#define __NR_getcwd 79 +#define __NR_chdir 80 +#define __NR_fchdir 81 +#define __NR_rename 82 +#define __NR_mkdir 83 +#define __NR_rmdir 84 +#define __NR_creat 85 +#define __NR_link 86 +#define __NR_unlink 87 +#define __NR_symlink 88 +#define __NR_readlink 89 +#define __NR_chmod 90 +#define __NR_fchmod 91 +#define __NR_chown 92 +#define __NR_fchown 93 +#define __NR_lchown 94 +#define __NR_umask 95 +#define __NR_gettimeofday 96 +#define __NR_getrlimit 97 +#define __NR_getrusage 98 +#define __NR_sysinfo 99 +#define __NR_times 100 +#define __NR_ptrace 101 +#define __NR_getuid 102 +#define __NR_syslog 103 +#define __NR_getgid 104 +#define __NR_setuid 105 +#define __NR_setgid 106 +#define __NR_geteuid 107 +#define __NR_getegid 108 +#define __NR_setpgid 109 +#define __NR_getppid 110 +#define __NR_getpgrp 111 +#define __NR_setsid 112 +#define __NR_setreuid 113 +#define __NR_setregid 114 +#define __NR_getgroups 115 +#define __NR_setgroups 116 +#define __NR_setresuid 117 +#define __NR_getresuid 118 +#define __NR_setresgid 119 +#define __NR_getresgid 120 +#define __NR_getpgid 121 +#define __NR_setfsuid 122 +#define __NR_setfsgid 123 +#define __NR_getsid 124 +#define __NR_capget 125 +#define __NR_capset 126 +#define __NR_rt_sigpending 127 +#define __NR_rt_sigtimedwait 128 +#define __NR_rt_sigqueueinfo 129 +#define __NR_rt_sigsuspend 130 +#define __NR_sigaltstack 131 +#define __NR_utime 132 +#define __NR_mknod 133 +#define __NR_uselib 134 +#define __NR_personality 135 +#define __NR_ustat 136 +#define __NR_statfs 137 +#define __NR_fstatfs 138 +#define __NR_sysfs 139 +#define __NR_getpriority 140 +#define __NR_setpriority 141 +#define __NR_sched_setparam 142 +#define __NR_sched_getparam 143 +#define __NR_sched_setscheduler 144 +#define __NR_sched_getscheduler 145 +#define __NR_sched_get_priority_max 146 +#define __NR_sched_get_priority_min 147 +#define __NR_sched_rr_get_interval 148 +#define __NR_mlock 149 +#define __NR_munlock 150 +#define __NR_mlockall 151 +#define __NR_munlockall 152 +#define __NR_vhangup 153 +#define __NR_modify_ldt 154 +#define __NR_pivot_root 155 +#define __NR__sysctl 156 +#define __NR_prctl 157 +#define __NR_arch_prctl 158 +#define __NR_adjtimex 159 +#define __NR_setrlimit 160 +#define __NR_chroot 161 +#define __NR_sync 162 +#define __NR_acct 163 +#define __NR_settimeofday 164 +#define __NR_mount 165 +#define __NR_umount2 166 +#define __NR_swapon 167 +#define __NR_swapoff 168 +#define __NR_reboot 169 +#define __NR_sethostname 170 +#define __NR_setdomainname 171 +#define __NR_iopl 172 +#define __NR_ioperm 173 +#define __NR_create_module 174 +#define __NR_init_module 175 +#define __NR_delete_module 176 +#define __NR_get_kernel_syms 177 +#define __NR_query_module 178 +#define __NR_quotactl 179 +#define __NR_nfsservctl 180 +#define __NR_getpmsg 181 +#define __NR_putpmsg 182 +#define __NR_afs_syscall 183 +#define __NR_tuxcall 184 +#define __NR_security 185 +#define __NR_gettid 186 +#define __NR_readahead 187 +#define __NR_setxattr 188 +#define __NR_lsetxattr 189 +#define __NR_fsetxattr 190 +#define __NR_getxattr 191 +#define __NR_lgetxattr 192 +#define __NR_fgetxattr 193 +#define __NR_listxattr 194 +#define __NR_llistxattr 195 +#define __NR_flistxattr 196 +#define __NR_removexattr 197 +#define __NR_lremovexattr 198 +#define __NR_fremovexattr 199 +#define __NR_tkill 200 +#define __NR_time 201 +#define __NR_futex 202 +#define __NR_sched_setaffinity 203 +#define __NR_sched_getaffinity 204 +#define __NR_set_thread_area 205 +#define __NR_io_setup 206 +#define __NR_io_destroy 207 +#define __NR_io_getevents 208 +#define __NR_io_submit 209 +#define __NR_io_cancel 210 +#define __NR_get_thread_area 211 +#define __NR_lookup_dcookie 212 +#define __NR_epoll_create 213 +#define __NR_epoll_ctl_old 214 +#define __NR_epoll_wait_old 215 +#define __NR_remap_file_pages 216 +#define __NR_getdents64 217 +#define __NR_set_tid_address 218 +#define __NR_restart_syscall 219 +#define __NR_semtimedop 220 +#define __NR_fadvise64 221 +#define __NR_timer_create 222 +#define __NR_timer_settime 223 +#define __NR_timer_gettime 224 +#define __NR_timer_getoverrun 225 +#define __NR_timer_delete 226 +#define __NR_clock_settime 227 +#define __NR_clock_gettime 228 +#define __NR_clock_getres 229 +#define __NR_clock_nanosleep 230 +#define __NR_exit_group 231 +#define __NR_epoll_wait 232 +#define __NR_epoll_ctl 233 +#define __NR_tgkill 234 +#define __NR_utimes 235 +#define __NR_vserver 236 +#define __NR_mbind 237 +#define __NR_set_mempolicy 238 +#define __NR_get_mempolicy 239 +#define __NR_mq_open 240 +#define __NR_mq_unlink 241 +#define __NR_mq_timedsend 242 +#define __NR_mq_timedreceive 243 +#define __NR_mq_notify 244 +#define __NR_mq_getsetattr 245 +#define __NR_kexec_load 246 +#define __NR_waitid 247 +#define __NR_add_key 248 +#define __NR_request_key 249 +#define __NR_keyctl 250 +#define __NR_ioprio_set 251 +#define __NR_ioprio_get 252 +#define __NR_inotify_init 253 +#define __NR_inotify_add_watch 254 +#define __NR_inotify_rm_watch 255 +#define __NR_migrate_pages 256 +#define __NR_openat 257 +#define __NR_mkdirat 258 +#define __NR_mknodat 259 +#define __NR_fchownat 260 +#define __NR_futimesat 261 +#define __NR_newfstatat 262 +#define __NR_unlinkat 263 +#define __NR_renameat 264 +#define __NR_linkat 265 +#define __NR_symlinkat 266 +#define __NR_readlinkat 267 +#define __NR_fchmodat 268 +#define __NR_faccessat 269 +#define __NR_pselect6 270 +#define __NR_ppoll 271 +#define __NR_unshare 272 +#define __NR_set_robust_list 273 +#define __NR_get_robust_list 274 +#define __NR_splice 275 +#define __NR_tee 276 +#define __NR_sync_file_range 277 +#define __NR_vmsplice 278 +#define __NR_move_pages 279 +#define __NR_utimensat 280 +#define __NR_epoll_pwait 281 +#define __NR_signalfd 282 +#define __NR_timerfd_create 283 +#define __NR_eventfd 284 +#define __NR_fallocate 285 +#define __NR_timerfd_settime 286 +#define __NR_timerfd_gettime 287 +#define __NR_accept4 288 +#define __NR_signalfd4 289 +#define __NR_eventfd2 290 +#define __NR_epoll_create1 291 +#define __NR_dup3 292 +#define __NR_pipe2 293 +#define __NR_inotify_init1 294 +#define __NR_preadv 295 +#define __NR_pwritev 296 +#define __NR_rt_tgsigqueueinfo 297 +#define __NR_perf_event_open 298 +#define __NR_recvmmsg 299 +#define __NR_fanotify_init 300 +#define __NR_fanotify_mark 301 +#define __NR_prlimit64 302 +#define __NR_name_to_handle_at 303 +#define __NR_open_by_handle_at 304 +#define __NR_clock_adjtime 305 +#define __NR_syncfs 306 +#define __NR_sendmmsg 307 +#define __NR_setns 308 +#define __NR_getcpu 309 +#define __NR_process_vm_readv 310 +#define __NR_process_vm_writev 311 +#define __NR_kcmp 312 +#define __NR_finit_module 313 +#define __NR_sched_setattr 314 +#define __NR_sched_getattr 315 +#define __NR_renameat2 316 +#define __NR_seccomp 317 +#define __NR_getrandom 318 +#define __NR_memfd_create 319 +#define __NR_kexec_file_load 320 +#define __NR_bpf 321 +#define __NR_execveat 322 +#define __NR_userfaultfd 323 +#define __NR_membarrier 324 +#define __NR_mlock2 325 +#define __NR_copy_file_range 326 +#define __NR_preadv2 327 +#define __NR_pwritev2 328 +#define __NR_pkey_mprotect 329 +#define __NR_pkey_alloc 330 +#define __NR_pkey_free 331 +#define __NR_statx 332 +#define __NR_io_pgetevents 333 +#define __NR_rseq 334 +#define __NR_pidfd_send_signal 424 +#define __NR_io_uring_setup 425 +#define __NR_io_uring_enter 426 +#define __NR_io_uring_register 427 +#define __NR_open_tree 428 +#define __NR_move_mount 429 +#define __NR_fsopen 430 +#define __NR_fsconfig 431 +#define __NR_fsmount 432 +#define __NR_fspick 433 +#define __NR_pidfd_open 434 +#define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 + +#endif // !__FENNIX_KERNEL_LINUX_SYSCALLS_H__ diff --git a/SystemCalls/Native.cpp b/SystemCalls/Native.cpp index f60ec1e..f8390af 100644 --- a/SystemCalls/Native.cpp +++ b/SystemCalls/Native.cpp @@ -27,318 +27,241 @@ #include "../kernel.h" #include "../ipc.h" -#define SysFrm SyscallsFrame +#if defined(a64) || defined(aa64) +static ssize_t ConvertErrno(ssize_t r) +{ + if (r >= 0) + return r; + return -errno; +} +#endif + +static int ConvertErrno(int r) +{ + if (r >= 0) + return r; + return -errno; +} + +struct SyscallData +{ + const char *Name; + void *Handler; + int RequiredID; +}; using InterProcessCommunication::IPC; using InterProcessCommunication::IPCID; -using Tasking::Token; -using Tasking::TTL; +using Tasking::PCB; +using Tasking::TCB; using Tasking::TaskStatus::Ready; using Tasking::TaskStatus::Terminated; -using Tasking::TTL::Trusted; -using Tasking::TTL::TrustedByKernel; -using Tasking::TTL::UnknownTrustLevel; -using Tasking::TTL::Untrusted; +using namespace Memory; -__noreturn static void sys_exit(SysFrm *, int code) +#define SysFrm SyscallsFrame + +#if defined(a64) +typedef long arch_t; +#elif defined(a32) +typedef int arch_t; +#endif + +__noreturn static void sys_exit(SysFrm *, int Code) { trace("Userspace thread %s(%d) exited with code %d (%#x)", - TaskManager->GetCurrentThread()->Name, - TaskManager->GetCurrentThread()->ID, code, - code < 0 ? -code : code); + thisThread->Name, + thisThread->ID, Code, + Code < 0 ? -Code : Code); - TaskManager->GetCurrentThread()->ExitCode = code; - TaskManager->GetCurrentThread()->Status = Terminated; - TaskManager->Schedule(); + thisThread->ExitCode = Code; + thisThread->Status = Terminated; + TaskManager->Yield(); __builtin_unreachable(); } -static int sys_print(SysFrm *, char Char, int Index) -{ - char ret = Display->Print(Char, Index, true); - if (!Config.BootAnimation && Index == 0) - Display->SetBuffer(Index); - return ret; -} - static uintptr_t sys_request_pages(SysFrm *, size_t Count) { - Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory; + MemMgr *MemMgr = thisThread->Memory; return (uintptr_t)MemMgr->RequestPages(Count + 1, true); } -static int sys_free_pages(SysFrm *, uintptr_t Address, size_t Count) +static int sys_free_pages(SysFrm *, uintptr_t Address, + size_t Count) { - Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory; + MemMgr *MemMgr = thisThread->Memory; MemMgr->FreePages((void *)Address, Count + 1); - return SYSCALL_OK; + return 0; } static int sys_detach_address(SysFrm *, uintptr_t Address) { - Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory; + MemMgr *MemMgr = thisThread->Memory; MemMgr->DetachAddress((void *)Address); - return SYSCALL_OK; + return 0; } static int sys_memory_map(SysFrm *, uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, - enum MemoryMapFlags Flags) + int Flags) { if (Flags > 7) /* (MAP_PRESENT | MAP_WRITABLE | MAP_USER) */ - return SYSCALL_INVALID_ARGUMENT; + return -EINVAL; - Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable; + PageTable *PageTable = thisProcess->PageTable; { - Memory::Virtual vmm = Memory::Virtual(PageTable); + Virtual vmm = Virtual(PageTable); vmm.Map((void *)VirtualAddress, (void *)PhysicalAddress, Size, Flags); } - return SYSCALL_OK; + return 0; } static int sys_memory_unmap(SysFrm *, uintptr_t VirtualAddress, size_t Size) { - Memory::PageTable *PageTable = TaskManager->GetCurrentProcess()->PageTable; + PageTable *PageTable = thisProcess->PageTable; { - Memory::Virtual vmm = Memory::Virtual(PageTable); + Virtual vmm = Virtual(PageTable); vmm.Unmap((void *)VirtualAddress, Size); } - return SYSCALL_OK; + return 0; } -static uintptr_t sys_kernelctl(SysFrm *, - enum KCtl Command, - uint64_t Arg1, uint64_t Arg2, - uint64_t Arg3, uint64_t Arg4) +static arch_t sys_kernelctl(SysFrm *, KCtl Command, + arch_t Arg1, arch_t Arg2, + arch_t Arg3, arch_t Arg4) { - switch (Command) - { - case KCTL_GET_PID: - return TaskManager->GetCurrentProcess()->ID; - case KCTL_GET_TID: - return TaskManager->GetCurrentThread()->ID; - case KCTL_GET_PAGE_SIZE: - return PAGE_SIZE; - case KCTL_IS_CRITICAL: - return TaskManager->GetCurrentThread()->Security.IsCritical; - case KCTL_REGISTER_ELF_LIB: - { - char *Identifier = (char *)Arg1; - const char *Path = (const char *)Arg2; - - if (!Identifier || !Path) - return SYSCALL_INVALID_ARGUMENT; - - std::string FullPath = Path; - int retries = 0; - RetryReadPath: - debug("KCTL_REGISTER_ELF_LIB: Trying to open %s", - FullPath.c_str()); - VirtualFileSystem::File f = vfs->Open(FullPath.c_str()); - - if (!f.IsOK()) - { - FullPath.clear(); - switch (retries) - { - case 0: - FullPath = "/lib/"; - break; - case 1: - FullPath = "/usr/lib/"; - break; - case 2: - FullPath = "/"; - break; - case 3: - { - VirtualFileSystem::Node *cwd = - TaskManager->GetCurrentProcess()->CurrentWorkingDirectory; - FullPath = vfs->GetPathFromNode(cwd).get(); - break; - } - default: - { - vfs->Close(f); - return SYSCALL_INVALID_ARGUMENT; - } - } - FullPath += Path; - vfs->Close(f); - retries++; - goto RetryReadPath; - } - - if (Execute::AddLibrary(Identifier, f)) - { - vfs->Close(f); - return SYSCALL_OK; - } - else - { - vfs->Close(f); - return SYSCALL_INTERNAL_ERROR; - } - } - case KCTL_GET_ELF_LIB_MEMORY_IMAGE: - { - char *Identifier = (char *)Arg1; - if (!Identifier) - return 0; - - Execute::SharedLibrary lib = Execute::GetLibrary(Identifier); - - if (!lib.MemoryImage) - { - debug("Failed to get library memory image %#lx", - (uintptr_t)lib.MemoryImage); - } - - debug("Returning memory image %#lx (%s)", - (uintptr_t)lib.MemoryImage, Identifier); - return (uintptr_t)lib.MemoryImage; - } - case KCTL_GET_ABSOLUTE_PATH: - { - char *Identifier = (char *)Arg1; - void *Buffer = (void *)Arg2; - size_t BufferSize = Arg3; - - if (!Identifier || !Buffer || !BufferSize) - return SYSCALL_INVALID_ARGUMENT; - - Execute::SharedLibrary lib = Execute::GetLibrary(Identifier); - - if (!lib.MemoryImage) - return SYSCALL_INTERNAL_ERROR; - - if (BufferSize < sizeof(lib.Path)) - return SYSCALL_INVALID_ARGUMENT; - - memcpy(Buffer, lib.Path, sizeof(lib.Path)); - return SYSCALL_OK; - } - default: - { - warn("KernelCTL: Unknown command: %lld", Command); - return SYSCALL_INVALID_ARGUMENT; - } - } - - UNUSED(Arg1); UNUSED(Arg2); UNUSED(Arg3); UNUSED(Arg4); -} -static uint64_t sys_file_open(SysFrm *, const char *Path, uint64_t Flags) -{ - function("%s, %#lx", Path, Flags); - VirtualFileSystem::Node *cwd = nullptr; - if (vfs->PathIsRelative(Path)) - cwd = TaskManager->GetCurrentProcess()->CurrentWorkingDirectory; - else - cwd = vfs->GetRootNode(); - - VirtualFileSystem::File KPObj = vfs->Open(Path, cwd); - if (!KPObj.IsOK()) + switch (Command) { - debug("Failed to open file %s (%d)", Path, KPObj.Status); - vfs->Close(KPObj); - return SYSCALL_INTERNAL_ERROR; - } - - Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory; - - constexpr size_t FileStructPages = - TO_PAGES(sizeof(VirtualFileSystem::File)); - - VirtualFileSystem::File *KernelPrivate = - (VirtualFileSystem::File *)MemMgr->RequestPages(FileStructPages); - *KernelPrivate = KPObj; - debug("Opened file %s (%d)", KPObj.Name, KPObj.Status); - return (uint64_t)KernelPrivate; - UNUSED(Flags); -} - -static int sys_file_close(SysFrm *, void *KernelPrivate) -{ - function("%#lx", KernelPrivate); - - if (KernelPrivate) + case KCTL_PRINT: { - VirtualFileSystem::File KPObj = *(VirtualFileSystem::File *)KernelPrivate; - debug("Closed file %s (%d)", KPObj.Name, KPObj.Status); - vfs->Close(KPObj); - Memory::MemMgr *MemMgr = TaskManager->GetCurrentThread()->Memory; - MemMgr->FreePages(KernelPrivate, - TO_PAGES(sizeof(VirtualFileSystem::File))); - return SYSCALL_OK; + SmartHeap sh(strlen((const char *)Arg1) + 1); + sh = Arg1; + KPrint(sh); + return 0; + } + case KCTL_GET_PAGE_SIZE: + return PAGE_SIZE; + case KCTL_IS_CRITICAL: + return thisThread->Security.IsCritical; + default: + { + warn("KernelCTL: Unknown command: %d", Command); + return -EINVAL; + } } - return SYSCALL_INVALID_ARGUMENT; } -static uint64_t sys_file_read(SysFrm *, void *KernelPrivate, - uint8_t *Buffer, uint64_t Size) +static int sys_file_open(SysFrm *, const char *Path, + int Flags, mode_t Mode) { - if (KernelPrivate == nullptr) - return 0; - - debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", - KernelPrivate, Buffer, Size); - - VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate; - return vfs->Read(*KPObj, Buffer, (size_t)Size); + function("%s, %d, %d", Path, Flags, Mode); + PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_open(Path, Flags, Mode)); } -static uint64_t sys_file_write(SysFrm *, void *KernelPrivate, - uint8_t *Buffer, uint64_t Size) +static int sys_file_close(SysFrm *, int FileDescriptor) { - if (KernelPrivate == nullptr) - return 0; - - debug("(KernelPrivate: %#lx, Offset: %#lx, Buffer: %#lx, Size: %#lx)", - KernelPrivate, Buffer, Size); - - VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate; - return vfs->Write(*KPObj, Buffer, (size_t)Size); + function("%d", FileDescriptor); + PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_close(FileDescriptor)); } -static off_t sys_file_seek(SysFrm *, void *KernelPrivate, +static uint64_t sys_file_read(SysFrm *, int FileDescriptor, + void *Buffer, size_t Count) +{ + function("%d, %p, %d", FileDescriptor, Buffer, Count); + PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_read(FileDescriptor, Buffer, Count)); +} + +static uint64_t sys_file_write(SysFrm *, int FileDescriptor, + const void *Buffer, size_t Count) +{ + function("%d, %p, %d", FileDescriptor, Buffer, Count); + PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_write(FileDescriptor, Buffer, Count)); +} + +static off_t sys_file_seek(SysFrm *, int FileDescriptor, off_t Offset, int Whence) { - if (KernelPrivate == nullptr) - return 0; - - debug("(KernelPrivate: %#lx, Offset: %#lx, Whence: %d)", - KernelPrivate, Offset, Whence); - - VirtualFileSystem::File *KPObj = (VirtualFileSystem::File *)KernelPrivate; - off_t ret = vfs->Seek(*KPObj, (off_t)Offset, (uint8_t)Whence); - debug("Seek %s %ld", KPObj->Name, ret); - return ret; + function("%d, %d, %d", FileDescriptor, Offset, Whence); + PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_lseek(FileDescriptor, Offset, Whence)); } -static int sys_file_status(SysFrm *) +static int sys_file_status(SysFrm *, int FileDescriptor, + struct stat *StatBuffer) { - stub; - return SYSCALL_NOT_IMPLEMENTED; + function("%d", FileDescriptor); + PCB *pcb = thisProcess; + VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors; + return ConvertErrno(fdt->_fstat(FileDescriptor, StatBuffer)); } static int sys_ipc(SysFrm *, enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size) { - InterProcessCommunication::IPC *ipc = TaskManager->GetCurrentProcess()->IPC; + InterProcessCommunication::IPC *ipc = thisProcess->IPC; return ipc->HandleSyscall(Command, Type, ID, Flags, Buffer, Size); } +static long sys_local_thread_state(SysFrm *, int Code, + unsigned long Address) +{ +#if defined(a64) || defined(aa64) + switch (Code) + { + case LTS_SET_GS: + { + wrmsr(CPU::x64::MSR_GS_BASE, Address); + return 0; + } + case LTS_GET_GS: + { + return rdmsr(CPU::x64::MSR_GS_BASE); + } + case LTS_SET_FS: + { + wrmsr(CPU::x64::MSR_FS_BASE, Address); + return 0; + } + case LTS_GET_FS: + { + return rdmsr(CPU::x64::MSR_FS_BASE); + } + case LTS_SET_CPUID: + { + fixme("TLS_SET_CPUID"); + return -ENOSYS; + } + case LTS_GET_CPUID: + { + fixme("TLS_GET_CPUID"); + return -ENOSYS; + } + default: + return -EINVAL; + } +#endif + return -ENOSYS; +} + static int sys_sleep(SysFrm *, uint64_t Milliseconds) { TaskManager->Sleep(Milliseconds, true); @@ -347,29 +270,31 @@ static int sys_sleep(SysFrm *, uint64_t Milliseconds) static int sys_fork(SysFrm *Frame) { - Tasking::PCB *Parent = TaskManager->GetCurrentThread()->Parent; - Tasking::TCB *Thread = TaskManager->GetCurrentThread(); +#ifdef a32 + return -ENOSYS; +#endif + PCB *Parent = thisThread->Parent; + TCB *Thread = thisThread; void *ProcSymTable = nullptr; if (Parent->ELFSymbolTable) ProcSymTable = Parent->ELFSymbolTable->GetImage(); - Tasking::PCB *NewProcess = + PCB *NewProcess = TaskManager->CreateProcess(Parent, Parent->Name, - Parent->Security.TrustLevel, + Parent->Security.ExecutionMode, ProcSymTable); if (!NewProcess) { error("Failed to create process for fork"); - return SYSCALL_ERROR; + return -EAGAIN; } - strncpy(NewProcess->Name, Parent->Name, sizeof(NewProcess->Name)); NewProcess->IPC->Fork(Parent->IPC); - Tasking::TCB *NewThread = + TCB *NewThread = TaskManager->CreateThread(NewProcess, 0, nullptr, @@ -379,25 +304,26 @@ static int sys_fork(SysFrm *Frame) Thread->Info.Compatibility, true); - strncpy(NewThread->Name, Thread->Name, sizeof(Thread->Name)); + NewThread->Rename(Thread->Name); if (!NewThread) { error("Failed to create thread for fork"); - return SYSCALL_ERROR; + return -EAGAIN; } static int RetChild = 0; static uint64_t ReturnAddress = 0; static uint64_t ChildStackPointer = 0; - TaskManager->Schedule(); + TaskManager->UpdateFrame(); if (RetChild--) { /* We can't just return 0; because the CPUData->SystemCallStack is no longer valid */ +#if defined(a64) || defined(aa64) asmv("movq %0, %%rcx\n" : : "r"(ReturnAddress)); @@ -411,6 +337,10 @@ static int sys_fork(SysFrm *Frame) asmv("swapgs\n"); /* Swap GS back to the user GS */ asmv("sti\n"); /* Enable interrupts */ asmv("sysretq\n"); /* Return to rcx address in user mode */ +#elif defined(a32) + UNUSED(ReturnAddress); + UNUSED(ChildStackPointer); +#endif } RetChild = 1; ReturnAddress = Frame->ReturnAddress; @@ -424,19 +354,15 @@ static int sys_fork(SysFrm *Frame) if (Thread->Security.IsCritical) NewThread->SetCritical(true); - Tasking::Security *Sec = TaskManager->GetSecurityManager(); - Sec->TrustToken(NewProcess->Security.UniqueToken, - (TTL)Sec->GetTokenTrustLevel(Parent->Security.UniqueToken)); - Sec->TrustToken(NewThread->Security.UniqueToken, - (TTL)Sec->GetTokenTrustLevel(Thread->Security.UniqueToken)); - #ifdef a86 NewThread->ShadowGSBase = Thread->ShadowGSBase; NewThread->GSBase = Thread->GSBase; NewThread->FSBase = Thread->FSBase; #endif - debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", Thread->Name, Thread->ID, NewThread->Name, NewThread->ID); + debug("Forked thread \"%s\"(%d) to \"%s\"(%d)", + Thread->Name, Thread->ID, + NewThread->Name, NewThread->ID); NewThread->Status = Ready; return (int)NewThread->ID; } @@ -444,118 +370,106 @@ static int sys_fork(SysFrm *Frame) static int sys_wait(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_kill(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_spawn(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_spawn_thread(SysFrm *, uint64_t InstructionPointer) { - Tasking::TCB *thread = - TaskManager->CreateThread(TaskManager->GetCurrentProcess(), - (Tasking::IP)InstructionPointer); + TCB *thread = + TaskManager->CreateThread(thisProcess, + Tasking::IP(InstructionPointer)); if (thread) return (int)thread->ID; - return SYSCALL_ERROR; + return -EAGAIN; } static int sys_get_thread_list_of_process(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_get_current_process(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_get_current_thread(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_get_current_process_id(SysFrm *) { - return (int)TaskManager->GetCurrentProcess()->ID; + return (int)thisProcess->ID; } static int sys_get_current_thread_id(SysFrm *) { - return (int)TaskManager->GetCurrentThread()->ID; + return (int)thisThread->ID; } static int sys_get_process_by_pid(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_get_thread_by_tid(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_kill_process(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_kill_thread(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_sys_reserved_create_process(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } static int sys_sys_reserved_create_thread(SysFrm *) { stub; - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } -struct SyscallData -{ - const char *Name; - void *Handler; - int TrustLevel; -}; - -static SyscallData NativeSyscallsTable[_MaxSyscall] = { +static SyscallData NativeSyscallsTable[sys_MaxSyscall] = { /** * * Basic syscalls * */ - [_Exit] = { + [sys_Exit] = { "Exit", (void *)sys_exit, - TrustedByKernel | Trusted | Untrusted | UnknownTrustLevel, - }, - [_Print] = { - "Print", - (void *)sys_print, - TrustedByKernel | Trusted, + UINT16_MAX, }, /** @@ -564,30 +478,30 @@ static SyscallData NativeSyscallsTable[_MaxSyscall] = { * */ - [_RequestPages] = { + [sys_RequestPages] = { "RequestPages", (void *)sys_request_pages, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_FreePages] = { + [sys_FreePages] = { "FreePages", (void *)sys_free_pages, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_DetachAddress] = { + [sys_DetachAddress] = { "DetachAddress", (void *)sys_detach_address, - TrustedByKernel | Trusted, + 99, }, - [_MemoryMap] = { + [sys_MemoryMap] = { "MemoryMap", (void *)sys_memory_map, - TrustedByKernel, + 99, }, - [_MemoryUnmap] = { + [sys_MemoryUnmap] = { "MemoryUnmap", (void *)sys_memory_unmap, - TrustedByKernel, + 99, }, /** @@ -596,10 +510,10 @@ static SyscallData NativeSyscallsTable[_MaxSyscall] = { * */ - [_KernelCTL] = { + [sys_KernelCTL] = { "KernelCTL", (void *)sys_kernelctl, - TrustedByKernel | Trusted | Untrusted, + 99, }, /** @@ -608,35 +522,35 @@ static SyscallData NativeSyscallsTable[_MaxSyscall] = { * */ - [_FileOpen] = { + [sys_FileOpen] = { "FileOpen", (void *)sys_file_open, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_FileClose] = { + [sys_FileClose] = { "FileClose", (void *)sys_file_close, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_FileRead] = { + [sys_FileRead] = { "FileRead", (void *)sys_file_read, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_FileWrite] = { + [sys_FileWrite] = { "FileWrite", (void *)sys_file_write, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_FileSeek] = { + [sys_FileSeek] = { "FileSeek", (void *)sys_file_seek, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_FileStatus] = { + [sys_FileStatus] = { "FileStatus", (void *)sys_file_status, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, /** @@ -645,92 +559,97 @@ static SyscallData NativeSyscallsTable[_MaxSyscall] = { * */ - [_IPC] = { + [sys_IPC] = { "IPC", (void *)sys_ipc, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_Sleep] = { + [sys_LocalThreadState] = { + "LocalThreadState", + (void *)sys_local_thread_state, + UINT16_MAX, + }, + [sys_Sleep] = { "Sleep", (void *)sys_sleep, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_Fork] = { + [sys_Fork] = { "Fork", (void *)sys_fork, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_Wait] = { + [sys_Wait] = { "Wait", (void *)sys_wait, 0, }, - [_Kill] = { + [sys_Kill] = { "Kill", (void *)sys_kill, 0, }, - [_Spawn] = { + [sys_Spawn] = { "Spawn", (void *)sys_spawn, 0, }, - [_SpawnThread] = { + [sys_SpawnThread] = { "SpawnThread", (void *)sys_spawn_thread, 0, }, - [_GetThreadListOfProcess] = { + [sys_GetThreadListOfProcess] = { "GetThreadListOfProcess", (void *)sys_get_thread_list_of_process, 0, }, - [_GetCurrentProcess] = { + [sys_GetCurrentProcess] = { "GetCurrentProcess", (void *)sys_get_current_process, 0, }, - [_GetCurrentThread] = { + [sys_GetCurrentThread] = { "GetCurrentThread", (void *)sys_get_current_thread, 0, }, - [_GetCurrentProcessID] = { + [sys_GetCurrentProcessID] = { "GetCurrentProcessID", (void *)sys_get_current_process_id, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_GetCurrentThreadID] = { + [sys_GetCurrentThreadID] = { "GetCurrentThreadID", (void *)sys_get_current_thread_id, - TrustedByKernel | Trusted | Untrusted, + UINT16_MAX, }, - [_GetProcessByPID] = { + [sys_GetProcessByPID] = { "GetProcessByPID", (void *)sys_get_process_by_pid, 0, }, - [_GetThreadByTID] = { + [sys_GetThreadByTID] = { "GetThreadByTID", (void *)sys_get_thread_by_tid, 0, }, - [_KillProcess] = { + [sys_KillProcess] = { "KillProcess", (void *)sys_kill_process, 0, }, - [_KillThread] = { + [sys_KillThread] = { "KillThread", (void *)sys_kill_thread, 0, }, - [_SysReservedCreateProcess] = { + [sys_SysReservedCreateProcess] = { "SysReservedCreateProcess", (void *)sys_sys_reserved_create_process, 0, }, - [_SysReservedCreateThread] = { + [sys_SysReservedCreateThread] = { "SysReservedCreateThread", (void *)sys_sys_reserved_create_thread, 0, @@ -740,10 +659,10 @@ static SyscallData NativeSyscallsTable[_MaxSyscall] = { uintptr_t HandleNativeSyscalls(SysFrm *Frame) { #if defined(a64) - if (unlikely(Frame->rax > _MaxSyscall)) + if (unlikely(Frame->rax > sys_MaxSyscall)) { fixme("Syscall %ld not implemented.", Frame->rax); - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; } SyscallData Syscall = NativeSyscallsTable[Frame->rax]; @@ -754,28 +673,20 @@ uintptr_t HandleNativeSyscalls(SysFrm *Frame) if (unlikely(!call)) { - error("Syscall %#lx not implemented.", Frame->rax); - return SYSCALL_NOT_IMPLEMENTED; + error("Syscall %s(%d) not implemented.", + Syscall.Name, Frame->rax); + return -ENOSYS; } - Token token = TaskManager->GetCurrentThread()->Security.UniqueToken; - Tasking::Security *Sec = TaskManager->GetSecurityManager(); - if (unlikely(!Sec->IsTokenTrusted(token, Syscall.TrustLevel))) + int euid = thisProcess->Security.Effective.UserID; + int egid = thisProcess->Security.Effective.GroupID; + int reqID = Syscall.RequiredID; + if (euid > reqID || egid > reqID) { - warn("Thread %s(%d) tried to access a system call \"%s\" with insufficient trust level", - TaskManager->GetCurrentThread()->Name, - TaskManager->GetCurrentThread()->ID, - Syscall.Name); - -#ifdef DEBUG - int TknTl = Sec->GetTokenTrustLevel(token); - debug("token=%#lx, trust=%d%d%d%d",token, - TknTl & TrustedByKernel ? 1 : 0, - TknTl & Trusted ? 1 : 0, - TknTl & Untrusted ? 1 : 0, - TknTl & UnknownTrustLevel ? 1 : 0); -#endif - return SYSCALL_ACCESS_DENIED; + warn("Process %s(%d) tried to access a system call \"%s\" with insufficient privileges.", + thisProcess->Name, thisProcess->ID, Syscall.Name); + debug("Required: %d; Effective u:%d, g:%d", reqID, euid, egid); + return -EPERM; } debug("[%d:\"%s\"]->( %#lx %#lx %#lx %#lx %#lx %#lx )", @@ -787,8 +698,8 @@ uintptr_t HandleNativeSyscalls(SysFrm *Frame) Frame->rdi, Frame->rsi, Frame->rdx, Frame->r10, Frame->r8, Frame->r9); #elif defined(a32) - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; #elif defined(aa64) - return SYSCALL_NOT_IMPLEMENTED; + return -ENOSYS; #endif } diff --git a/SystemCalls/Syscalls.cpp b/SystemCalls/Syscalls.cpp index 4901d81..6c69142 100644 --- a/SystemCalls/Syscalls.cpp +++ b/SystemCalls/Syscalls.cpp @@ -23,15 +23,19 @@ extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame) { - Tasking::TaskInfo *Ptinfo = &TaskManager->GetCurrentProcess()->Info; - Tasking::TaskInfo *Ttinfo = &TaskManager->GetCurrentThread()->Info; + Tasking::TaskInfo *Ptinfo = &thisProcess->Info; + Tasking::TaskInfo *Ttinfo = &thisThread->Info; uint64_t TempTimeCalc = TimeManager->GetCounter(); switch (Ttinfo->Compatibility) { case Tasking::TaskCompatibility::Native: { - uintptr_t ret = HandleNativeSyscalls(Frame); + uintptr_t ret = 0; + if (Config.UseLinuxSyscalls) + ret = HandleLinuxSyscalls(Frame); + else + ret = HandleNativeSyscalls(Frame); Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc; return ret; @@ -51,7 +55,7 @@ extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame) default: { error("Unknown compatibility mode! Killing thread..."); - TaskManager->KillThread(TaskManager->GetCurrentThread(), Tasking::KILL_SYSCALL); + TaskManager->KillThread(thisThread, Tasking::KILL_SYSCALL); break; } } diff --git a/Tasking/InterProcessCommunication.cpp b/Tasking/InterProcessCommunication.cpp index 45b52cb..e1d9784 100644 --- a/Tasking/InterProcessCommunication.cpp +++ b/Tasking/InterProcessCommunication.cpp @@ -40,6 +40,7 @@ namespace InterProcessCommunication IPCHandle *IPC::Create(IPCType Type, char UniqueToken[16]) { + UNUSED(Type); SmartLock(this->IPCLock); IPCHandle *Hnd = (IPCHandle *)mem->RequestPages(TO_PAGES(sizeof(IPCHandle) + 1)); @@ -57,17 +58,18 @@ namespace InterProcessCommunication IPCErrorCode IPC::Destroy(IPCID ID) { SmartLock(this->IPCLock); - for (size_t i = 0; i < Handles.size(); i++) + forItr(itr, Handles) { - if (Handles[i]->ID == ID) + if ((*itr)->ID == ID) { - vfs->Delete(Handles[i]->Node); - mem->FreePages(Handles[i], TO_PAGES(sizeof(IPCHandle) + 1)); - Handles.remove(i); + vfs->Delete((*itr)->Node); + mem->FreePages((*itr), TO_PAGES(sizeof(IPCHandle) + 1)); + Handles.erase(itr); debug("Destroyed IPC with ID %d", ID); return IPCSuccess; } } + debug("Failed to destroy IPC with ID %d", ID); return IPCIDNotFound; } @@ -201,7 +203,7 @@ namespace InterProcessCommunication warn("Interrupts are disabled. This may cause a kernel hang."); debug("Waiting for IPC %d (now %s)", ID, Hnd->Listening ? "listening" : "ready"); while (Hnd->Listening) - TaskManager->Schedule(); + TaskManager->Yield(); debug("IPC %d is ready", ID); return IPCSuccess; } diff --git a/Tasking/Process.cpp b/Tasking/Process.cpp new file mode 100644 index 0000000..56ccf4f --- /dev/null +++ b/Tasking/Process.cpp @@ -0,0 +1,220 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../kernel.h" + +#if defined(a64) +#include "../Architecture/amd64/cpu/apic.hpp" +#include "../Architecture/amd64/cpu/gdt.hpp" +#elif defined(a32) +#include "../Architecture/i386/cpu/apic.hpp" +#elif defined(aa64) +#endif + +// #define DEBUG_TASKING 1 + +#ifdef DEBUG_TASKING +#define tskdbg(m, ...) \ + debug(m, ##__VA_ARGS__); \ + __sync +#else +#define tskdbg(m, ...) +#endif + +using namespace InterProcessCommunication; +using namespace VirtualFileSystem; +using VirtualFileSystem::NodeFlags; + +namespace Tasking +{ + void PCB::Rename(const char *name) + { + assert(name != nullptr); + assert(strlen(name) > 0); + + trace("Renaming thread %s to %s", this->Name, name); + if (this->Name) + delete[] this->Name; + this->Name = new char[strlen(name) + 1]; + strcpy((char *)this->Name, name); + } + + void PCB::SetWorkingDirectory(VirtualFileSystem::Node *node) + { + debug("Setting working directory of process %s to %#lx (%s)", + this->Name, node, node->Name); + CurrentWorkingDirectory = node; + } + + PCB::PCB(Task *ctx, PCB *Parent, const char *Name, + TaskExecutionMode ExecutionMode, void *Image, + bool DoNotCreatePageTable, + uint16_t UserID, uint16_t GroupID) + { + assert(ctx != nullptr); + assert(ExecutionMode >= _ExecuteModeMin); + assert(ExecutionMode <= _ExecuteModeMax); + + this->ctx = ctx; + this->ID = ctx->NextPID++; + if (this->Name) + delete[] this->Name; + this->Name = new char[strlen(Name) + 1]; + strcpy((char *)this->Name, Name); + this->ExitCode = KILL_CRASH; + this->Security.ExecutionMode = ExecutionMode; + + if (Parent == nullptr) + this->Parent = ctx->GetCurrentProcess(); + else + this->Parent = Parent; + + if (this->Parent && + UserID == UINT16_MAX && + GroupID == UINT16_MAX) + { + UserID = this->Parent->Security.Real.UserID; + GroupID = this->Parent->Security.Real.GroupID; + } + + this->Security.Real.UserID = UserID; + this->Security.Real.GroupID = GroupID; + this->Security.Effective.UserID = UserID; + this->Security.Effective.GroupID = GroupID; + + char ProcFSName[16]; + sprintf(ProcFSName, "%d", this->ID); + this->ProcessDirectory = vfs->Create(ProcFSName, DIRECTORY, ProcFS); + this->memDirectory = vfs->Create("mem", DIRECTORY, this->ProcessDirectory); + this->FileDescriptors = new FileDescriptorTable(this); + this->IPC = new class IPC((void *)this); + + if (!DoNotCreatePageTable) + { + OwnPageTable = true; + switch (ExecutionMode) + { + case TaskExecutionMode::System: + fixme("Mode not supported."); + [[fallthrough]]; + case TaskExecutionMode::Kernel: + { + this->Security.IsCritical = true; +#if defined(a64) + this->PageTable = (Memory::PageTable *)CPU::x64::readcr3().raw; +#elif defined(a32) + this->PageTable = (Memory::PageTable *)CPU::x32::readcr3().raw; +#elif defined(aa64) +#endif + debug("Process %s(%d) has page table at %#lx", + this->Name, this->ID, this->PageTable); + break; + } + case TaskExecutionMode::User: + { +#if defined(a64) + this->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(sizeof(Memory::PageTable) + 1)); + memcpy(this->PageTable, + KernelPageTable, + sizeof(Memory::PageTable)); +#elif defined(a32) +#elif defined(aa64) +#endif + debug("Process %s(%d) has page table at %#lx", + this->Name, this->ID, this->PageTable); + break; + } + default: + assert(false); + } + } + + this->Memory = new Memory::MemMgr(this->PageTable, this->memDirectory); + + if (Image) + { + this->ELFSymbolTable = new SymbolResolver::Symbols((uintptr_t)Image); + } + else + { + debug("No image provided for process \"%s\"(%d)", + this->Name, this->ID); + } + + if (Parent) + Parent->Children.push_back(this); + + debug("Process page table: %#lx", this->PageTable); + debug("Created process \"%s\"(%d). Parent \"%s\"(%d)", + this->Name, this->ID, + Parent ? this->Parent->Name : "None", + Parent ? this->Parent->ID : 0); + + this->Info.SpawnTime = TimeManager->GetCounter(); + ctx->ProcessList.push_back(this); + } + + PCB::~PCB() + { + debug("Destroying process \"%s\"(%d)", + this->Name, this->ID); + + ctx->ProcessList.erase(std::find(ctx->ProcessList.begin(), + ctx->ProcessList.end(), + this)); + + if (this->ELFSymbolTable) + delete this->ELFSymbolTable; + + delete this->IPC; + delete this->FileDescriptors; + delete this->Memory; + delete[] this->Name; + + if (this->PageTable && OwnPageTable) + { + size_t PTPgs = TO_PAGES(sizeof(Memory::PageTable) + 1); + KernelAllocator.FreePages(this->PageTable, PTPgs); + } + + foreach (auto pcb in this->Children) + delete pcb; + + foreach (auto tcb in this->Threads) + delete tcb; + + vfs->Delete(this->ProcessDirectory, true); + + if (this->Parent) + { + std::vector &pChild = this->Parent->Children; + + pChild.erase(std::find(pChild.begin(), + pChild.end(), + this)); + } + } +} diff --git a/Tasking/Scheduler.cpp b/Tasking/Scheduler.cpp index 8ba140d..167dc90 100644 --- a/Tasking/Scheduler.cpp +++ b/Tasking/Scheduler.cpp @@ -34,8 +34,6 @@ #elif defined(aa64) #endif -NewLock(SchedulerLock); - /* FIXME: On screen task manager is corrupting the stack... */ // #define ON_SCREEN_SCHEDULER_TASK_MANAGER 1 @@ -127,14 +125,15 @@ namespace Tasking fnp_schedbg("%d processes", ProcessList.size()); #ifdef DEBUG_FIND_NEW_PROCESS foreach (auto process in ProcessList) - fnp_schedbg("Process %d %s", process->ID, process->Name); + fnp_schedbg("Process %d %s", process->ID, + process->Name); #endif foreach (auto process in ProcessList) { if (InvalidPCB(process)) continue; - switch (process->Status) + switch (process->Status.load()) { case TaskStatus::Ready: fnp_schedbg("Ready process (%s)%d", @@ -158,7 +157,7 @@ namespace Tasking if (InvalidTCB(thread)) continue; - if (thread->Status != TaskStatus::Ready) + if (thread->Status.load() != TaskStatus::Ready) continue; if (thread->Info.Affinity[CurrentCPU->ID] == false) @@ -177,17 +176,22 @@ namespace Tasking { CPUData *CurrentCPU = (CPUData *)CPUDataPointer; - for (size_t i = 0; i < CurrentCPU->CurrentProcess->Threads.size(); i++) + size_t ThreadsSize = CurrentCPU->CurrentProcess->Threads.size(); + + for (size_t i = 0; i < ThreadsSize; i++) { if (CurrentCPU->CurrentProcess->Threads[i] == CurrentCPU->CurrentThread.load()) { size_t TempIndex = i; RetryAnotherThread: + if (TempIndex + 1 >= ThreadsSize) + break; + TCB *nextThread = CurrentCPU->CurrentProcess->Threads[TempIndex + 1]; if (unlikely(InvalidTCB(nextThread))) { - if (TempIndex > CurrentCPU->CurrentProcess->Threads.size()) + if (TempIndex > ThreadsSize) break; TempIndex++; @@ -200,7 +204,7 @@ namespace Tasking CurrentCPU->CurrentProcess->Threads[i]->ID, nextThread->Name, nextThread->ID); - if (nextThread->Status != TaskStatus::Ready) + if (nextThread->Status.load() != TaskStatus::Ready) { gnat_schedbg("Thread %d is not ready", nextThread->ID); TempIndex++; @@ -213,7 +217,7 @@ namespace Tasking CurrentCPU->CurrentThread = nextThread; gnat_schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d", nextThread->ID, nextThread->Parent->Name, - CurrentCPU->CurrentProcess->Threads.size(), ProcessList.size()); + ThreadsSize, ProcessList.size()); return true; } #ifdef DEBUG @@ -253,7 +257,7 @@ namespace Tasking continue; } - if (process->Status != TaskStatus::Ready) + if (process->Status.load() != TaskStatus::Ready) { gnap_schedbg("Process %d is not ready", process->ID); continue; @@ -267,7 +271,7 @@ namespace Tasking continue; } - if (thread->Status != TaskStatus::Ready) + if (thread->Status.load() != TaskStatus::Ready) { gnap_schedbg("Thread %d is not ready", thread->ID); continue; @@ -299,7 +303,7 @@ namespace Tasking continue; } - if (process->Status != TaskStatus::Ready) + if (process->Status.load() != TaskStatus::Ready) { sspt_schedbg("Process %d is not ready", process->ID); continue; @@ -313,7 +317,7 @@ namespace Tasking continue; } - if (thread->Status != TaskStatus::Ready) + if (thread->Status.load() != TaskStatus::Ready) { sspt_schedbg("Thread %d is not ready", thread->ID); continue; @@ -339,14 +343,14 @@ namespace Tasking if (InvalidPCB(process)) continue; - if (process->Status == TaskStatus::Terminated || - process->Status == TaskStatus::Stopped) + if (process->Status.load() == TaskStatus::Terminated || + process->Status.load() == TaskStatus::Zombie) continue; bool AllThreadsSleeping = true; foreach (auto thread in process->Threads) { - if (thread->Status != TaskStatus::Sleeping) + if (thread->Status.load() != TaskStatus::Sleeping) { AllThreadsSleeping = false; break; @@ -354,9 +358,9 @@ namespace Tasking } if (AllThreadsSleeping) - process->Status = TaskStatus::Sleeping; - else if (process->Status == TaskStatus::Sleeping) - process->Status = TaskStatus::Ready; + process->Status.store(TaskStatus::Sleeping); + else if (process->Status.load() == TaskStatus::Sleeping) + process->Status.store(TaskStatus::Ready); } } @@ -367,8 +371,8 @@ namespace Tasking if (InvalidPCB(process)) continue; - if (process->Status == TaskStatus::Terminated || - process->Status == TaskStatus::Stopped) + if (process->Status.load() == TaskStatus::Terminated || + process->Status.load() == TaskStatus::Zombie) continue; foreach (auto thread in process->Threads) @@ -376,15 +380,15 @@ namespace Tasking if (InvalidTCB(thread)) continue; - if (thread->Status != TaskStatus::Sleeping) + if (thread->Status.load() != TaskStatus::Sleeping) continue; /* Check if the thread is ready to wake up. */ if (thread->Info.SleepUntil < TimeManager->GetCounter()) { - if (process->Status == TaskStatus::Sleeping) - process->Status = TaskStatus::Ready; - thread->Status = TaskStatus::Ready; + if (process->Status.load() == TaskStatus::Sleeping) + process->Status.store(TaskStatus::Ready); + thread->Status.store(TaskStatus::Ready); thread->Info.SleepUntil = 0; wut_schedbg("Thread \"%s\"(%d) woke up.", thread->Name, thread->ID); @@ -407,8 +411,8 @@ namespace Tasking "AAFF00", /* Ready */ "00AA00", /* Running */ "FFAA00", /* Sleeping */ - "FFAA00", /* Waiting */ - "FF0088", /* Stopped */ + "FFAA00", /* Blocked */ + "FF0088", /* Zombie */ "FF0000", /* Terminated */ }; @@ -526,10 +530,10 @@ namespace Tasking CurrentCPU->CurrentThread->GSBase = CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE); CurrentCPU->CurrentThread->FSBase = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE); - if (CurrentCPU->CurrentProcess->Status == TaskStatus::Running) - CurrentCPU->CurrentProcess->Status = TaskStatus::Ready; - if (CurrentCPU->CurrentThread->Status == TaskStatus::Running) - CurrentCPU->CurrentThread->Status = TaskStatus::Ready; + if (CurrentCPU->CurrentProcess->Status.load() == TaskStatus::Running) + CurrentCPU->CurrentProcess->Status.store(TaskStatus::Ready); + if (CurrentCPU->CurrentThread->Status.load() == TaskStatus::Running) + CurrentCPU->CurrentThread->Status.store(TaskStatus::Ready); this->UpdateProcessStatus(); schedbg("Passed UpdateProcessStatus"); @@ -537,6 +541,9 @@ namespace Tasking this->WakeUpThreads(); schedbg("Passed WakeUpThreads"); + if (this->SchedulerUpdateTrapFrame) + goto Success; + if (this->GetNextAvailableThread(CurrentCPU)) { #ifdef ON_SCREEN_SCHEDULER_TASK_MANAGER @@ -586,11 +593,16 @@ namespace Tasking CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID, CurrentCPU->ID); if (!ProcessNotChanged) - UpdateUsage(&CurrentCPU->CurrentProcess->Info, &CurrentCPU->CurrentProcess->Security, CurrentCPU->ID); - UpdateUsage(&CurrentCPU->CurrentThread->Info, &CurrentCPU->CurrentThread->Security, CurrentCPU->ID); + UpdateUsage(&CurrentCPU->CurrentProcess->Info, + CurrentCPU->CurrentProcess->Security.ExecutionMode, + CurrentCPU->ID); - CurrentCPU->CurrentProcess->Status = TaskStatus::Running; - CurrentCPU->CurrentThread->Status = TaskStatus::Running; + UpdateUsage(&CurrentCPU->CurrentThread->Info, + CurrentCPU->CurrentThread->Security.ExecutionMode, + CurrentCPU->ID); + + CurrentCPU->CurrentProcess->Status.store(TaskStatus::Running); + CurrentCPU->CurrentThread->Status.store(TaskStatus::Running); *Frame = CurrentCPU->CurrentThread->Registers; @@ -613,18 +625,18 @@ namespace Tasking OnScreenTaskManagerUpdate(); #endif - switch (CurrentCPU->CurrentProcess->Security.TrustLevel) + switch (CurrentCPU->CurrentProcess->Security.ExecutionMode) { - case TaskTrustLevel::System: - case TaskTrustLevel::Kernel: + case TaskExecutionMode::System: + case TaskExecutionMode::Kernel: // wrmsr(MSR_SHADOW_GS_BASE, (uint64_t)CurrentCPU->CurrentThread); break; - case TaskTrustLevel::User: + case TaskExecutionMode::User: // wrmsr(MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->gs); break; default: error("Unknown trust level %d.", - CurrentCPU->CurrentProcess->Security.TrustLevel); + CurrentCPU->CurrentProcess->Security.ExecutionMode); break; } @@ -663,7 +675,6 @@ namespace Tasking End: this->SchedulerTicks.store(TimeManager->GetCounter() - SchedTmpTicks); - __sync; /* TODO: Is this really needed? */ } SafeFunction NIF void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame) diff --git a/Tasking/Security.cpp b/Tasking/Security.cpp deleted file mode 100644 index dbed9e4..0000000 --- a/Tasking/Security.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#include - -#include -#include -#include - -namespace Tasking -{ - Token Security::CreateToken() - { - Token ret = 0; - Retry: - ret = (Token)Random::rand64(); - foreach (auto t in Tokens) - if (t.token == ret) - goto Retry; - - Tokens.push_back({ret, UnknownTrustLevel, 0, false}); - debug("Created token %#lx", ret); - return ret; - } - - bool Security::TrustToken(Token token, TTL TrustLevel) - { - foreach (auto &t in Tokens) - { - if (t.token == token) - { - t.TrustLevel = TrustLevel; - debug("Trusted token %#lx to level %d", token, t.TrustLevel); - return true; - } - } - warn("Failed to trust token %#lx", token); - return false; - } - - bool Security::UntrustToken(Token token) - { - foreach (auto &t in Tokens) - { - if (t.token == token) - { - t.TrustLevel = Untrusted; - debug("Untrusted token %#lx", token); - return true; - } - } - warn("Failed to untrust token %#lx", token); - return false; - } - - bool Security::AddTrustLevel(Token token, TTL TrustLevel) - { - foreach (auto &t in Tokens) - { - if (t.token == token) - { - t.TrustLevel |= TrustLevel; - debug("Added trust level %d to token %#lx", t.TrustLevel, token); - return true; - } - } - warn("Failed to add trust level %d to token %#lx", TrustLevel, token); - return false; - } - - bool Security::RemoveTrustLevel(Token token, TTL TrustLevel) - { - foreach (auto &t in Tokens) - { - if (t.token == token) - { - t.TrustLevel &= ~TrustLevel; - debug("Removed trust level %d from token %#lx", t.TrustLevel, token); - return true; - } - } - warn("Failed to remove trust level %d from token %#lx", TrustLevel, token); - return false; - } - - bool Security::DestroyToken(Token token) - { - fixme("DestroyToken->true"); - UNUSED(token); - return true; - } - - bool Security::IsTokenTrusted(Token token, TTL TrustLevel) - { - foreach (auto t in Tokens) - if (t.token == token) - { - if (t.TrustLevel == TrustLevel) - return true; - else - return false; - } - - warn("Failed to check trust level of token %#lx", token); - return false; - } - - bool Security::IsTokenTrusted(Token token, int TrustLevel) - { - foreach (auto t in Tokens) - if (t.token == token) - { - if (t.TrustLevel & TrustLevel) - return true; - else - return false; - } - - warn("Failed to check trust level of token %#lx", token); - return false; - } - - int Security::GetTokenTrustLevel(Token token) - { - foreach (auto t in Tokens) - if (t.token == token) - return t.TrustLevel; - - warn("Failed to get trust level of token %#lx", token); - return UnknownTrustLevel; - } - - Security::Security() {} - Security::~Security() { Tokens.clear(); } -} diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 17395d3..1e543a4 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -38,836 +38,410 @@ #ifdef DEBUG_TASKING #define tskdbg(m, ...) \ - debug(m, ##__VA_ARGS__); \ - __sync + debug(m, ##__VA_ARGS__); \ + __sync #else #define tskdbg(m, ...) #endif -NewLock(TaskingLock); - namespace Tasking { #if defined(a86) - __naked __used __no_stack_protector NIF void IdleProcessLoop() - { - asmv("IdleLoop:\n" - "hlt\n" - "jmp IdleLoop\n"); + __naked __used __no_stack_protector void IdleProcessLoop() + { + asmv("IdleLoop:\n" + "hlt\n" + "jmp IdleLoop\n"); #elif defined(aa64) - __used __no_stack_protector NIF void IdleProcessLoop() - { - asmv("IdleLoop:\n" - "wfe\n" - "b IdleLoop\n"); + __used __no_stack_protector void IdleProcessLoop() + { + asmv("IdleLoop:\n" + "wfe\n" + "b IdleLoop\n"); #endif - } + } - SafeFunction NIF bool Task::InvalidPCB(PCB *pcb) - { - if (!pcb) - return true; - if (pcb >= (PCB *)(UINTPTR_MAX - 0x1ffe)) /* Uninitialized pointers may have uintptr_t max value instead of nullptr. */ - return true; - if (pcb < (PCB *)(0x1000)) /* In this section of the memory is reserved by the kernel. */ - return true; - if (!Memory::Virtual().Check((void *)pcb)) /* Check if it's mapped. */ - return true; - return false; - } + SafeFunction bool Task::InvalidPCB(PCB *pcb) + { + if (!pcb) + return true; - SafeFunction NIF bool Task::InvalidTCB(TCB *tcb) - { - if (!tcb) - return true; - if (tcb >= (TCB *)(UINTPTR_MAX - 0x1ffe)) /* Uninitialized pointers may have uintptr_t max value instead of nullptr. */ - return true; - if (tcb < (TCB *)(0x1000)) /* In this section of the memory is reserved by the kernel. */ - return true; - if (!Memory::Virtual().Check((void *)tcb)) /* Check if it's mapped. */ - return true; - return false; - } + /* Uninitialized pointers may have uintptr_t max value instead of nullptr. */ + if (pcb >= (PCB *)(UINTPTR_MAX - 0x1ffe)) + return true; - SafeFunction NIF void Task::RemoveThread(TCB *Thread) - { - for (size_t i = 0; i < Thread->Parent->Threads.size(); i++) - if (Thread->Parent->Threads[i] == Thread) - { - trace("Thread \"%s\"(%d) removed from process \"%s\"(%d)", - Thread->Name, Thread->ID, Thread->Parent->Name, Thread->Parent->ID); - // Free memory - delete Thread->Stack, Thread->Stack = nullptr; - delete Thread->Memory, Thread->Memory = nullptr; - SecurityManager.DestroyToken(Thread->Security.UniqueToken); - delete Thread->Parent->Threads[i], Thread->Parent->Threads[i] = nullptr; - // Remove from the list - Thread->Parent->Threads.remove(i); - break; - } - } + /* In this section of the memory is reserved by the kernel. */ + if (pcb < (PCB *)(0x1000)) + return true; - SafeFunction NIF void Task::RemoveProcess(PCB *Process) - { - if (Process == nullptr) - return; + /* Check if it's mapped. */ + if (!Memory::Virtual().Check((void *)pcb)) + return true; - if (Process->Status == Terminated) - { - foreach (TCB *thread in Process->Threads) - RemoveThread(thread); + return false; + } - foreach (PCB *process in Process->Children) - RemoveProcess(process); + SafeFunction bool Task::InvalidTCB(TCB *tcb) + { + if (!tcb) + return true; - for (size_t i = 0; i < ProcessList.size(); i++) - { - if (ProcessList[i] == Process) - { - trace("Process \"%s\"(%d) removed from the list", Process->Name, Process->ID); - // Free memory - delete ProcessList[i]->IPC, ProcessList[i]->IPC = nullptr; - delete ProcessList[i]->ELFSymbolTable, ProcessList[i]->ELFSymbolTable = nullptr; - SecurityManager.DestroyToken(ProcessList[i]->Security.UniqueToken); - if (ProcessList[i]->Security.TrustLevel == TaskTrustLevel::User) - KernelAllocator.FreePages((void *)ProcessList[i]->PageTable, TO_PAGES(sizeof(Memory::PageTable) + 1)); + /* Uninitialized pointers may have uintptr_t max value instead of nullptr. */ + if (tcb >= (TCB *)(UINTPTR_MAX - 0x1ffe)) + return true; - // Remove the process from parent's children list - if (ProcessList[i]->Parent) - for (size_t j = 0; j < ProcessList[i]->Parent->Children.size(); j++) - { - if (ProcessList[i]->Parent->Children[j] == ProcessList[i]) - { - ProcessList[i]->Parent->Children.remove(j); - break; - } - } + /* In this section of the memory is reserved by the kernel. */ + if (tcb < (TCB *)(0x1000)) + return true; - // Delete process directory - vfs->Delete(ProcessList[i]->ProcessDirectory, true); + /* Check if it's mapped. */ + if (!Memory::Virtual().Check((void *)tcb)) + return true; - // Free memory - delete ProcessList[i], ProcessList[i] = nullptr; - // Remove from the list - ProcessList.remove(i); - break; - } - } - } - else - { - foreach (TCB *thread in Process->Threads) - if (!InvalidTCB(thread)) - if (thread->Status == Terminated) - RemoveThread(thread); - } - } + return false; + } - SafeFunction NIF void Task::UpdateUsage(TaskInfo *Info, TaskSecurity *Security, int Core) - { - uint64_t CurrentTime = TimeManager->GetCounter(); - uint64_t TimePassed = CurrentTime - Info->LastUpdateTime; - // Info->LastUpdateTime = CurrentTime; + SafeFunction void Task::RemoveThread(TCB *Thread) + { + foreach (TCB *tcb in Thread->Parent->Threads) + { + if (tcb == Thread) + { + debug("Thread \"%s\"(%d) removed from process \"%s\"(%d)", + Thread->Name, Thread->ID, Thread->Parent->Name, + Thread->Parent->ID); + delete tcb; + break; + } + } + } - if (Security->TrustLevel == TaskTrustLevel::User) - Info->UserTime += TimePassed; - else - Info->KernelTime += TimePassed; - } + SafeFunction void Task::RemoveProcess(PCB *Process) + { + if (InvalidPCB(Process)) + return; - void ThreadDoExit() - { - // TODO: How I can lock the scheduler without causing a deadlock? - CPUData *CPUData = GetCurrentCPU(); - CPUData->CurrentThread->Status = TaskStatus::Terminated; - debug("\"%s\"(%d) exited with code: %#lx", CPUData->CurrentThread->Name, CPUData->CurrentThread->ID, CPUData->CurrentThread->ExitCode); - CPU::Halt(true); - } + if (Process->Status == Terminated) + { + delete Process; + return; + } - PCB *Task::GetCurrentProcess() { return GetCurrentCPU()->CurrentProcess.load(); } - TCB *Task::GetCurrentThread() { return GetCurrentCPU()->CurrentThread.load(); } + foreach (TCB *thread in Process->Threads) + { + if (thread->Status == Terminated) + RemoveThread(thread); + } + } - PCB *Task::GetProcessByID(TID ID) - { - for (size_t i = 0; i < ProcessList.size(); i++) - if (ProcessList[i]->ID == ID) - return ProcessList[i]; - return nullptr; - } + SafeFunction void Task::UpdateUsage(TaskInfo *Info, TaskExecutionMode Mode, int Core) + { + UNUSED(Core); + uint64_t CurrentTime = TimeManager->GetCounter(); + uint64_t TimePassed = CurrentTime - Info->LastUpdateTime; + // Info->LastUpdateTime = CurrentTime; - TCB *Task::GetThreadByID(TID ID) - { - for (size_t i = 0; i < ProcessList.size(); i++) - for (size_t j = 0; j < ProcessList[i]->Threads.size(); j++) - if (ProcessList[i]->Threads[j]->ID == ID) - return ProcessList[i]->Threads[j]; - return nullptr; - } + if (Mode == TaskExecutionMode::User) + Info->UserTime += TimePassed; + else + Info->KernelTime += TimePassed; + } - void Task::WaitForProcess(PCB *pcb) - { - if (InvalidPCB(pcb)) - return; - if (pcb->Status == TaskStatus::UnknownStatus) - return; - debug("Waiting for process \"%s\"(%d)", pcb->Name, pcb->ID); - while (pcb->Status != TaskStatus::Terminated) - CPU::Pause(); - } + PCB *Task::GetCurrentProcess() + { + return GetCurrentCPU()->CurrentProcess.load(); + } - void Task::WaitForThread(TCB *tcb) - { - if (InvalidTCB(tcb)) - return; - if (tcb->Status == TaskStatus::UnknownStatus) - return; - debug("Waiting for thread \"%s\"(%d)", tcb->Name, tcb->ID); - while (tcb->Status != TaskStatus::Terminated) - CPU::Pause(); - } + TCB *Task::GetCurrentThread() + { + return GetCurrentCPU()->CurrentThread.load(); + } - void Task::WaitForProcessStatus(PCB *pcb, TaskStatus status) - { - if (InvalidPCB(pcb)) - return; - if (pcb->Status == TaskStatus::UnknownStatus) - return; - debug("Waiting for process \"%s\"(%d) to reach status: %d", pcb->Name, pcb->ID, status); - while (pcb->Status != status) - CPU::Pause(); - } + PCB *Task::GetProcessByID(TID ID) + { + SmartLock(TaskingLock); + foreach (auto p in ProcessList) + if (p->ID == ID) + return p; + return nullptr; + } - void Task::WaitForThreadStatus(TCB *tcb, TaskStatus status) - { - if (InvalidTCB(tcb)) - return; - if (tcb->Status == TaskStatus::UnknownStatus) - return; - debug("Waiting for thread \"%s\"(%d) to reach status: %d", tcb->Name, tcb->ID, status); - while (tcb->Status != status) - CPU::Pause(); - } + TCB *Task::GetThreadByID(TID ID) + { + SmartLock(TaskingLock); + foreach (auto p in ProcessList) + { + foreach (auto t in p->Threads) + if (t->ID == ID) + return t; + } + return nullptr; + } - void Task::Sleep(uint64_t Milliseconds, bool NoSwitch) - { - TCB *thread = this->GetCurrentThread(); - PCB *process = this->GetCurrentProcess(); + void Task::WaitForProcess(PCB *pcb) + { + if (InvalidPCB(pcb)) + return; - thread->Status = TaskStatus::Sleeping; - if (process->Threads.size() == 1) - process->Status = TaskStatus::Sleeping; + if (pcb->Status == TaskStatus::UnknownStatus) + return; - thread->Info.SleepUntil = - TimeManager->CalculateTarget(Milliseconds, - Time::Units::Milliseconds); + debug("Waiting for process \"%s\"(%d)", + pcb->Name, pcb->ID); - debug("Thread \"%s\"(%d) is going to sleep until %llu", - thread->Name, thread->ID, thread->Info.SleepUntil); + while (pcb->Status != TaskStatus::Terminated) + this->Yield(); + } - if (!NoSwitch) - this->Schedule(); - } + void Task::WaitForThread(TCB *tcb) + { + if (InvalidTCB(tcb)) + return; - void Task::SignalShutdown() - { - fixme("SignalShutdown()"); - // TODO: Implement this - // This should hang until all processes are terminated - } + if (tcb->Status == TaskStatus::UnknownStatus) + return; - void Task::CleanupProcessesThread() - { - while (true) - { - this->Sleep(1000); - foreach (auto process in ProcessList) - { - if (InvalidPCB(process)) - continue; + debug("Waiting for thread \"%s\"(%d)", + tcb->Name, tcb->ID); - RemoveProcess(process); - } - } - } + while (tcb->Status != TaskStatus::Terminated) + this->Yield(); + } - void Task::RevertProcessCreation(PCB *Process) - { - for (size_t i = 0; i < ProcessList.size(); i++) - { - if (ProcessList[i] == Process) - { - SecurityManager.DestroyToken(Process->Security.UniqueToken); - if (Process->Security.TrustLevel == TaskTrustLevel::User) - KernelAllocator.FreePages((void *)Process->PageTable, TO_PAGES(sizeof(Memory::PageTable) + 1)); + void Task::WaitForProcessStatus(PCB *pcb, TaskStatus status) + { + if (InvalidPCB(pcb)) + return; - if (Process->Parent) - for (size_t j = 0; j < Process->Parent->Children.size(); j++) - { - if (Process->Parent->Children[j] == Process) - { - Process->Parent->Children.remove(j); - break; - } - } + if (pcb->Status == TaskStatus::UnknownStatus) + return; - delete Process->IPC, Process->IPC = nullptr; - delete Process->ELFSymbolTable, Process->ELFSymbolTable = nullptr; - delete Process, Process = nullptr; - ProcessList.remove(i); - this->NextPID--; - break; - } - } - } + debug("Waiting for process \"%s\"(%d) to reach status: %d", + pcb->Name, pcb->ID, status); - void Task::RevertThreadCreation(TCB *Thread) - { - for (size_t j = 0; j < Thread->Parent->Threads.size(); j++) - { - if (Thread->Parent->Threads[j] == Thread) - { - Thread->Parent->Threads.remove(j); - break; - } - } + while (pcb->Status != status) + this->Yield(); + } - delete Thread->Stack, Thread->Stack = nullptr; - delete Thread->Memory, Thread->Memory = nullptr; - SecurityManager.DestroyToken(Thread->Security.UniqueToken); - delete Thread, Thread = nullptr; - this->NextTID--; - } + void Task::WaitForThreadStatus(TCB *tcb, TaskStatus status) + { + if (InvalidTCB(tcb)) + return; - __no_sanitize("undefined") TCB *Task::CreateThread(PCB *Parent, - IP EntryPoint, - const char **argv, - const char **envp, - const std::vector &auxv, - TaskArchitecture Architecture, - TaskCompatibility Compatibility, - bool ThreadNotReady) - { - SmartLock(TaskingLock); - TCB *Thread = new TCB; - if (Parent == nullptr) - { - Thread->Parent = this->GetCurrentProcess(); - if (Thread->Parent == nullptr) - { - error("Failed to get current process. Thread cannot be created."); - delete Thread; - return nullptr; - } - } - else - Thread->Parent = Parent; + if (tcb->Status == TaskStatus::UnknownStatus) + return; - if (InvalidPCB(Parent)) - { - error("Parent is invalid"); - delete Thread; - return nullptr; - } + debug("Waiting for thread \"%s\"(%d) to reach status: %d", + tcb->Name, tcb->ID, status); - Thread->ID = this->NextTID++; - strcpy(Thread->Name, Parent->Name); - Thread->EntryPoint = EntryPoint; - Thread->ExitCode = 0xdead; - if (ThreadNotReady) - Thread->Status = TaskStatus::Waiting; - else - Thread->Status = TaskStatus::Ready; - Thread->Memory = new Memory::MemMgr(Parent->PageTable, Parent->memDirectory); - Thread->FPU = (CPU::x64::FXState *)Thread->Memory->RequestPages(TO_PAGES(sizeof(CPU::x64::FXState) + 1)); - memset(Thread->FPU, 0, sizeof(CPU::x64::FXState)); + while (tcb->Status != status) + this->Yield(); + } - Thread->Security.TrustLevel = Parent->Security.TrustLevel; - Thread->Security.UniqueToken = SecurityManager.CreateToken(); + void Task::Sleep(uint64_t Milliseconds, bool NoSwitch) + { + TCB *thread = this->GetCurrentThread(); + PCB *process = this->GetCurrentProcess(); - // TODO: Is really a good idea to use the FPU in kernel mode? - Thread->FPU->mxcsr = 0b0001111110000000; - Thread->FPU->mxcsrmask = 0b1111111110111111; - Thread->FPU->fcw = 0b0000001100111111; + thread->Status = TaskStatus::Sleeping; - // CPU::x64::fxrstor(Thread->FPU); - // uint16_t FCW = 0b1100111111; - // asmv("fldcw %0" - // : - // : "m"(FCW) - // : "memory"); - // uint32_t MXCSR = 0b1111110000000; - // asmv("ldmxcsr %0" - // : - // : "m"(MXCSR) - // : "memory"); - // CPU::x64::fxsave(Thread->FPU); + { + SmartLock(TaskingLock); + if (process->Threads.size() == 1) + process->Status = TaskStatus::Sleeping; -#if defined(a64) - memset(&Thread->Registers, 0, sizeof(CPU::x64::TrapFrame)); // Just in case - Thread->Registers.rip = EntryPoint; -#elif defined(a32) -#elif defined(aa64) -#endif - switch (Parent->Security.TrustLevel) - { - case TaskTrustLevel::System: - warn("Trust level not supported."); - [[fallthrough]]; - case TaskTrustLevel::Kernel: - { - Thread->Security.IsCritical = true; - Thread->Stack = new Memory::StackGuard(false, Parent->PageTable); - Thread->SyscallStack = __UINTPTR_MAX__; - Thread->TempStack = __UINTPTR_MAX__; -#if defined(a64) - SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::TrustedByKernel); - Thread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE); - Thread->GSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); - Thread->FSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); - Thread->Registers.cs = GDT_KERNEL_CODE; - Thread->Registers.ss = GDT_KERNEL_DATA; - Thread->Registers.rflags.AlwaysOne = 1; - Thread->Registers.rflags.IF = 1; - Thread->Registers.rflags.ID = 1; - Thread->Registers.rsp = ((uintptr_t)Thread->Stack->GetStackTop()); - POKE(uintptr_t, Thread->Registers.rsp) = (uintptr_t)ThreadDoExit; -#elif defined(a32) -#elif defined(aa64) -#endif - break; - } - case TaskTrustLevel::User: - { - Thread->Stack = new Memory::StackGuard(true, Parent->PageTable); - Thread->SyscallStack = (uintptr_t)Thread->Memory->RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE; - Thread->TempStack = 0x0; -#if defined(a64) - SecurityManager.TrustToken(Thread->Security.UniqueToken, TTL::Untrusted); - Thread->ShadowGSBase = (uintptr_t)Thread; - Thread->GSBase = 0; - Thread->FSBase = 0; - Thread->Registers.cs = GDT_USER_CODE; - Thread->Registers.ss = GDT_USER_DATA; - Thread->Registers.rflags.AlwaysOne = 1; - Thread->Registers.rflags.IF = 1; - Thread->Registers.rflags.ID = 1; - /* We need to leave the libc's crt - to make a syscall when the Thread - is exited or we are going to get - GPF or PF exception. */ - -#pragma region - size_t ArgvSize = 0; - if (argv) - while (argv[ArgvSize] != nullptr) - ArgvSize++; - - size_t EnvpSize = 0; - if (envp) - while (envp[EnvpSize] != nullptr) - EnvpSize++; - - debug("ArgvSize: %d", ArgvSize); - debug("EnvpSize: %d", EnvpSize); - - /* https://articles.manugarg.com/aboutelfauxiliaryvectors.html */ - /* https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 */ - // rsp is the top of the stack - char *Stack = (char *)Thread->Stack->GetStackPhysicalTop(); - // Temporary stack pointer for strings - char *StackStrings = (char *)Stack; - char *StackStringsVirtual = (char *)Thread->Stack->GetStackTop(); - - // Store string pointers for later - uintptr_t *ArgvStrings = nullptr; - uintptr_t *EnvpStrings = nullptr; - if (ArgvSize > 0) - ArgvStrings = new uintptr_t[ArgvSize]; - if (EnvpSize > 0) - EnvpStrings = new uintptr_t[EnvpSize]; - - for (size_t i = 0; i < ArgvSize; i++) - { - // Subtract the length of the string and the null terminator - StackStrings -= strlen(argv[i]) + 1; - StackStringsVirtual -= strlen(argv[i]) + 1; - // Store the pointer to the string - ArgvStrings[i] = (uintptr_t)StackStringsVirtual; - // Copy the string to the stack - strcpy(StackStrings, argv[i]); - } - - for (size_t i = 0; i < EnvpSize; i++) - { - // Subtract the length of the string and the null terminator - StackStrings -= strlen(envp[i]) + 1; - StackStringsVirtual -= strlen(envp[i]) + 1; - // Store the pointer to the string - EnvpStrings[i] = (uintptr_t)StackStringsVirtual; - // Copy the string to the stack - strcpy(StackStrings, envp[i]); - } - - // Align the stack to 16 bytes - StackStrings -= (uintptr_t)StackStrings & 0xF; - // Set "Stack" to the new stack pointer - Stack = (char *)StackStrings; - // If argv and envp sizes are odd then we need to align the stack - Stack -= (ArgvSize + EnvpSize) % 2; - - // We need 8 bit pointers for the stack from here - uintptr_t *Stack64 = (uintptr_t *)Stack; - - // Store the null terminator - Stack64--; - *Stack64 = AT_NULL; - - // auxv_array is initialized with auxv elements. If the array is empty then we add a null terminator - std::vector auxv_array = auxv; - if (auxv_array.size() == 0) - auxv_array.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); - - // Store auxillary vector - foreach (AuxiliaryVector var in auxv_array) - { - // Subtract the size of the auxillary vector - Stack64 -= sizeof(Elf64_auxv_t) / sizeof(uintptr_t); - // Store the auxillary vector - POKE(Elf64_auxv_t, Stack64) = var.archaux; - // TODO: Store strings to the stack - } - - // Store the null terminator - Stack64--; - *Stack64 = AT_NULL; - - // Store EnvpStrings[] to the stack - Stack64 -= EnvpSize; // (1 Stack64 = 8 bits; Stack64 = 8 * EnvpSize) - for (size_t i = 0; i < EnvpSize; i++) - { - *(Stack64 + i) = (uintptr_t)EnvpStrings[i]; - debug("EnvpStrings[%d]: %#lx", i, EnvpStrings[i]); - } - - // Store the null terminator - Stack64--; - *Stack64 = AT_NULL; - - // Store ArgvStrings[] to the stack - Stack64 -= ArgvSize; // (1 Stack64 = 8 bits; Stack64 = 8 * ArgvSize) - for (size_t i = 0; i < ArgvSize; i++) - { - *(Stack64 + i) = (uintptr_t)ArgvStrings[i]; - debug("ArgvStrings[%d]: %#lx", i, ArgvStrings[i]); - } - - // Store the argc - Stack64--; - *Stack64 = ArgvSize; - - // Set "Stack" to the new stack pointer - Stack = (char *)Stack64; - - /* We need the virtual address but because we are in the kernel we can't use the process page table. - So we modify the physical address and store how much we need to subtract to get the virtual address for RSP. */ - uintptr_t SubtractStack = (uintptr_t)Thread->Stack->GetStackPhysicalTop() - (uintptr_t)Stack; - debug("SubtractStack: %#lx", SubtractStack); - - // Set the stack pointer to the new stack - Thread->Registers.rsp = ((uintptr_t)Thread->Stack->GetStackTop() - SubtractStack); - - if (ArgvSize > 0) - delete[] ArgvStrings; - if (EnvpSize > 0) - delete[] EnvpStrings; + thread->Info.SleepUntil = + TimeManager->CalculateTarget(Milliseconds, + Time::Units::Milliseconds); + } #ifdef DEBUG - DumpData("Stack Data", (void *)((uintptr_t)Thread->Stack->GetStackPhysicalTop() - (uintptr_t)SubtractStack), SubtractStack); + uint64_t TicksNow = TimeManager->GetCounter(); #endif + debug("Thread \"%s\"(%d) is going to sleep until %llu, current %llu, diff %llu", + thread->Name, thread->ID, thread->Info.SleepUntil, + TicksNow, thread->Info.SleepUntil - TicksNow); - Thread->Registers.rdi = (uintptr_t)ArgvSize; // argc - Thread->Registers.rsi = (uintptr_t)(Thread->Registers.rsp + 8); // argv - Thread->Registers.rcx = (uintptr_t)EnvpSize; // envc - Thread->Registers.rdx = (uintptr_t)(Thread->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp + if (!NoSwitch) + this->Yield(); + } -#pragma endregion + void Task::SignalShutdown() + { + fixme("SignalShutdown()"); + // TODO: Implement this + // This should hang until all processes are terminated + } -#elif defined(a32) -#elif defined(aa64) -#endif -#ifdef DEBUG_TASKING - DumpData(Thread->Name, Thread->Stack, STACK_SIZE); -#endif - break; - } - default: - { - error("Unknown elevation."); - delete Thread->Stack; - this->NextTID--; - delete Thread; - return nullptr; - } - } + void Task::CleanupProcessesThread() + { + thisThread->Rename("Tasking Cleanup"); + while (true) + { + this->Sleep(2000); + { + SmartLock(TaskingLock); + foreach (auto process in ProcessList) + { + if (InvalidPCB(process)) + continue; - Thread->Info = {}; - Thread->Info.SpawnTime = TimeManager->GetCounter(); - Thread->Info.Year = 0; - Thread->Info.Month = 0; - Thread->Info.Day = 0; - Thread->Info.Hour = 0; - Thread->Info.Minute = 0; - Thread->Info.Second = 0; - for (int i = 0; i < MAX_CPU; i++) - { - Thread->Info.Affinity[i] = true; - } - Thread->Info.Priority = TaskPriority::Normal; - Thread->Info.Architecture = Architecture; - Thread->Info.Compatibility = Compatibility; + RemoveProcess(process); + } + } + } + } -#ifdef DEBUG -#ifdef a64 - debug("Thread EntryPoint: %#lx => RIP: %#lx", Thread->EntryPoint, Thread->Registers.rip); - if (Parent->Security.TrustLevel == TaskTrustLevel::User) - debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.rsp); - else - debug("Thread stack region is %#lx-%#lx (K) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.rsp); -#elif defined(a32) - debug("Thread EntryPoint: %#lx => RIP: %#lx", Thread->EntryPoint, Thread->Registers.eip); - if (Parent->Security.TrustLevel == TaskTrustLevel::User) - debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.esp); - else - debug("Thread stack region is %#lx-%#lx (K) and rsp is %#lx", Thread->Stack->GetStackBottom(), Thread->Stack->GetStackTop(), Thread->Registers.esp); -#elif defined(aa64) -#endif - debug("Created thread \"%s\"(%d) in process \"%s\"(%d)", - Thread->Name, Thread->ID, - Thread->Parent->Name, Thread->Parent->ID); -#endif + __no_sanitize("undefined") + TCB *Task::CreateThread(PCB *Parent, + IP EntryPoint, + const char **argv, + const char **envp, + const std::vector &auxv, + TaskArchitecture Architecture, + TaskCompatibility Compatibility, + bool ThreadNotReady) + { + SmartLock(TaskingLock); + return new TCB(this, Parent, EntryPoint, + argv, envp, auxv, Architecture, + Compatibility, ThreadNotReady); + } - Parent->Threads.push_back(Thread); - return Thread; - } + PCB *Task::CreateProcess(PCB *Parent, + const char *Name, + TaskExecutionMode ExecutionMode, + void *Image, + bool DoNotCreatePageTable, + uint16_t UserID, + uint16_t GroupID) + { + SmartLock(TaskingLock); + return new PCB(this, Parent, Name, ExecutionMode, + Image, DoNotCreatePageTable, + UserID, GroupID); + } - PCB *Task::CreateProcess(PCB *Parent, - const char *Name, - TaskTrustLevel TrustLevel, void *Image, - bool DoNotCreatePageTable) - { - SmartLock(TaskingLock); - PCB *Process = new PCB; - Process->ID = NextPID++; - strcpy(Process->Name, Name); - if (Parent == nullptr) - Process->Parent = this->GetCurrentProcess(); - else - Process->Parent = Parent; - Process->ExitCode = 0xdead; - Process->Status = TaskStatus::Ready; - - Process->Security.TrustLevel = TrustLevel; - Process->Security.UniqueToken = SecurityManager.CreateToken(); - - char ProcFSName[16]; - sprintf(ProcFSName, "%d", Process->ID); - Process->ProcessDirectory = vfs->Create(ProcFSName, VirtualFileSystem::NodeFlags::DIRECTORY, ProcFS); - Process->memDirectory = vfs->Create("mem", VirtualFileSystem::NodeFlags::DIRECTORY, Process->ProcessDirectory); - Process->IPC = new InterProcessCommunication::IPC((void *)Process); - - switch (TrustLevel) - { - case TaskTrustLevel::System: - warn("Trust level not supported."); - [[fallthrough]]; - case TaskTrustLevel::Kernel: - { - Process->Security.IsCritical = true; - SecurityManager.TrustToken(Process->Security.UniqueToken, TTL::TrustedByKernel); + Task::Task(const IP EntryPoint) : Interrupts::Handler(16) /* IRQ16 */ + { #if defined(a64) - if (!DoNotCreatePageTable) - Process->PageTable = (Memory::PageTable *)CPU::x64::readcr3().raw; + // Map the IRQ16 to the first CPU. + ((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, CPU::x86::IRQ16 - CPU::x86::IRQ0, 1); #elif defined(a32) #elif defined(aa64) #endif - break; - } - case TaskTrustLevel::User: - { - SecurityManager.TrustToken(Process->Security.UniqueToken, TTL::Untrusted); -#if defined(a64) - if (!DoNotCreatePageTable) - { - Process->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(sizeof(Memory::PageTable) + 1)); - memcpy(Process->PageTable, (void *)KernelPageTable, sizeof(Memory::PageTable)); - } -#elif defined(a32) -#elif defined(aa64) -#endif - break; - } - default: - { - error("Unknown elevation."); - NextPID--; - delete Process; - return nullptr; - } - } - - Process->Info = {}; - Process->Info.SpawnTime = TimeManager->GetCounter(); - Process->Info.Year = 0; - Process->Info.Month = 0; - Process->Info.Day = 0; - Process->Info.Hour = 0; - Process->Info.Minute = 0; - Process->Info.Second = 0; - for (int i = 0; i < MAX_CPU; i++) - { - Process->Info.Affinity[i] = true; - } - Process->Info.Priority = TaskPriority::Normal; - - debug("Process page table: %#lx", Process->PageTable); - debug("Created process \"%s\"(%d). Parent \"%s\"(%d)", - Process->Name, Process->ID, - Parent ? Process->Parent->Name : "None", - Parent ? Process->Parent->ID : 0); - - if (Image) - { - // TODO: Check if it's ELF - Process->ELFSymbolTable = new SymbolResolver::Symbols((uintptr_t)Image); - } - else - { - debug("No image provided for process \"%s\"(%d)", Process->Name, Process->ID); - } - - if (Parent) - Parent->Children.push_back(Process); - ProcessList.push_back(Process); - return Process; - } - - Task::Task(const IP EntryPoint) : Interrupts::Handler(16) /* IRQ16 */ - { -#if defined(a64) - // Map the IRQ16 to the first CPU. - ((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, CPU::x86::IRQ16 - CPU::x86::IRQ0, 1); -#elif defined(a32) -#elif defined(aa64) -#endif - KPrint("Starting Tasking With Instruction Pointer: %p (\e666666%s\eCCCCCC)", EntryPoint, KernelSymbolTable->GetSymbolFromAddress(EntryPoint)); + KPrint("Starting Tasking With Instruction Pointer: %p (\e666666%s\eCCCCCC)", + EntryPoint, KernelSymbolTable->GetSymbolFromAddress(EntryPoint)); #if defined(a64) - TaskArchitecture Arch = TaskArchitecture::x64; + TaskArchitecture Arch = TaskArchitecture::x64; #elif defined(a32) - TaskArchitecture Arch = TaskArchitecture::x32; + TaskArchitecture Arch = TaskArchitecture::x32; #elif defined(aa64) - TaskArchitecture Arch = TaskArchitecture::ARM64; + TaskArchitecture Arch = TaskArchitecture::ARM64; #endif - PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel); - kproc->ELFSymbolTable = KernelSymbolTable; - TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, std::vector(), Arch); - kthrd->Rename("Main Thread"); - debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name); + PCB *kproc = CreateProcess(nullptr, "Kernel", TaskExecutionMode::Kernel); + kproc->ELFSymbolTable = KernelSymbolTable; + TCB *kthrd = CreateThread(kproc, EntryPoint, nullptr, nullptr, std::vector(), Arch); + kthrd->Rename("Main Thread"); + debug("Created Kernel Process: %s and Thread: %s", + kproc->Name, kthrd->Name); - bool MONITORSupported = false; - if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) - { - CPU::x86::AMD::CPUID0x00000001 cpuid; - cpuid.Get(); - MONITORSupported = cpuid.ECX.MONITOR; - } - else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) - { - CPU::x86::Intel::CPUID0x00000001 cpuid; - cpuid.Get(); - MONITORSupported = cpuid.ECX.MONITOR; - } + bool MONITORSupported = false; + if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) + { + CPU::x86::AMD::CPUID0x00000001 cpuid; + cpuid.Get(); + MONITORSupported = cpuid.ECX.MONITOR; + } + else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) + { + CPU::x86::Intel::CPUID0x00000001 cpuid; + cpuid.Get(); + MONITORSupported = cpuid.ECX.MONITOR; + } - if (MONITORSupported) - { - trace("CPU has MONITOR/MWAIT support."); - } + if (MONITORSupported) + { + trace("CPU has MONITOR/MWAIT support."); + } - if (!CPU::Interrupts(CPU::Check)) - { - error("Interrupts are not enabled."); - CPU::Interrupts(CPU::Enable); - } + if (!CPU::Interrupts(CPU::Check)) + { + error("Interrupts are not enabled."); + CPU::Interrupts(CPU::Enable); + } - IdleProcess = CreateProcess(nullptr, (char *)"Idle", TaskTrustLevel::Kernel); - IdleProcess->ELFSymbolTable = KernelSymbolTable; - for (int i = 0; i < SMP::CPUCores; i++) - { - IdleThread = CreateThread(IdleProcess, reinterpret_cast(IdleProcessLoop)); - char IdleName[16]; - sprintf(IdleName, "Idle Thread %d", i); - IdleThread->Rename(IdleName); - IdleThread->SetPriority(Idle); - for (int j = 0; j < MAX_CPU; j++) - IdleThread->Info.Affinity[j] = false; - IdleThread->Info.Affinity[i] = true; - } - debug("Tasking Started"); + IdleProcess = CreateProcess(nullptr, (char *)"Idle", TaskExecutionMode::Kernel); + IdleProcess->ELFSymbolTable = KernelSymbolTable; + for (int i = 0; i < SMP::CPUCores; i++) + { + IdleThread = CreateThread(IdleProcess, reinterpret_cast(IdleProcessLoop)); + char IdleName[16]; + sprintf(IdleName, "Idle Thread %d", i); + IdleThread->Rename(IdleName); + IdleThread->SetPriority(Idle); + for (int j = 0; j < MAX_CPU; j++) + IdleThread->Info.Affinity[j] = false; + IdleThread->Info.Affinity[i] = true; + } + debug("Tasking Started"); #if defined(a64) - ((APIC::Timer *)Interrupts::apicTimer[0])->OneShot(CPU::x86::IRQ16, 100); + ((APIC::Timer *)Interrupts::apicTimer[0])->OneShot(CPU::x86::IRQ16, 100); - /* FIXME: The kernel is not ready for multi-core tasking. */ - // for (int i = 1; i < SMP::CPUCores; i++) - // { - // ((APIC::Timer *)Interrupts::apicTimer[i])->OneShot(CPU::x86::IRQ16, 100); - // APIC::InterruptCommandRegisterLow icr; - // icr.Vector = CPU::x86::IRQ16; - // icr.Level = APIC::APICLevel::Assert; - // ((APIC::APIC *)Interrupts::apic[0])->IPI(i, icr); - // } + /* FIXME: The kernel is not ready for multi-core tasking. */ + // for (int i = 1; i < SMP::CPUCores; i++) + // { + // ((APIC::Timer *)Interrupts::apicTimer[i])->OneShot(CPU::x86::IRQ16, 100); + // APIC::InterruptCommandRegisterLow icr; + // icr.Vector = CPU::x86::IRQ16; + // icr.Level = APIC::APICLevel::Assert; + // ((APIC::APIC *)Interrupts::apic[0])->IPI(i, icr); + // } #elif defined(a32) #elif defined(aa64) #endif - } + } - Task::~Task() - { - debug("Destructor called"); - { - SmartLock(TaskingLock); - foreach (PCB *Process in ProcessList) - { - foreach (TCB *Thread in Process->Threads) - { - if (Thread == GetCurrentCPU()->CurrentThread.load() || - Thread == CleanupThread) - continue; - this->KillThread(Thread, KILL_SCHEDULER_DESTRUCTION); - } + Task::~Task() + { + debug("Destructor called"); + { + SmartLock(TaskingLock); + foreach (PCB *Process in ProcessList) + { + foreach (TCB *Thread in Process->Threads) + { + if (Thread == GetCurrentCPU()->CurrentThread.load() || + Thread == CleanupThread) + continue; + this->KillThread(Thread, KILL_SCHEDULER_DESTRUCTION); + } - if (Process == GetCurrentCPU()->CurrentProcess.load()) - continue; - this->KillProcess(Process, KILL_SCHEDULER_DESTRUCTION); - } - } + if (Process == GetCurrentCPU()->CurrentProcess.load()) + continue; + this->KillProcess(Process, KILL_SCHEDULER_DESTRUCTION); + } + } - while (ProcessList.size() > 0) - { - trace("Waiting for %d processes to terminate", ProcessList.size()); - int NotTerminated = 0; - foreach (PCB *Process in ProcessList) - { - debug("Process %s(%d) is still running (or waiting to be removed status %#lx)", Process->Name, Process->ID, Process->Status); - if (Process->Status == TaskStatus::Terminated) - continue; - NotTerminated++; - } - if (NotTerminated == 1) - break; - TaskingScheduler_OneShot(100); - } + while (ProcessList.size() > 0) + { + trace("Waiting for %d processes to terminate", ProcessList.size()); + int NotTerminated = 0; + foreach (PCB *Process in ProcessList) + { + debug("Process %s(%d) is still running (or waiting to be removed status %#lx)", + Process->Name, Process->ID, Process->Status); + if (Process->Status == TaskStatus::Terminated) + continue; + NotTerminated++; + } + if (NotTerminated == 1) + break; + TaskingScheduler_OneShot(100); + } - trace("Tasking stopped"); - } + debug("Tasking stopped"); + } } diff --git a/Tasking/Thread.cpp b/Tasking/Thread.cpp new file mode 100644 index 0000000..9b155e4 --- /dev/null +++ b/Tasking/Thread.cpp @@ -0,0 +1,460 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../kernel.h" + +#if defined(a64) +#include "../Architecture/amd64/cpu/apic.hpp" +#include "../Architecture/amd64/cpu/gdt.hpp" +#elif defined(a32) +#include "../Architecture/i386/cpu/apic.hpp" +#elif defined(aa64) +#endif + +// #define DEBUG_TASKING 1 + +#ifdef DEBUG_TASKING +#define tskdbg(m, ...) \ + debug(m, ##__VA_ARGS__); \ + __sync +#else +#define tskdbg(m, ...) +#endif + +void ThreadDoExit() +{ + CPUData *CPUData = GetCurrentCPU(); + Tasking::TCB *CurrentThread = CPUData->CurrentThread.load(); + CurrentThread->Status = Tasking::TaskStatus::Terminated; + + debug("\"%s\"(%d) exited with code: %#lx", + CurrentThread->Name, + CurrentThread->ID, + CurrentThread->ExitCode); + CPU::Halt(true); +} + +namespace Tasking +{ + void TCB::Rename(const char *name) + { + assert(name != nullptr); + assert(strlen(name) > 0); + + trace("Renaming thread %s to %s", this->Name, name); + if (this->Name) + delete[] this->Name; + this->Name = new char[strlen(name) + 1]; + strcpy((char *)this->Name, name); + } + + void TCB::SetPriority(TaskPriority priority) + { + assert(priority >= _PriorityMin); + // assert(priority <= _PriorityMax); + + trace("Setting priority of thread %s to %d", + this->Name, priority); + + Info.Priority = priority; + } + + void TCB::SetCritical(bool Critical) + { + trace("Setting criticality of thread %s to %s", + this->Name, Critical ? "true" : "false"); + + Security.IsCritical = Critical; + } + + void TCB::SetDebugMode(bool Enable) + { + trace("Setting debug mode of thread %s to %s", + this->Name, Enable ? "true" : "false"); + + Security.IsDebugEnabled = Enable; + } + + void TCB::SetKernelDebugMode(bool Enable) + { + trace("Setting kernel debug mode of thread %s to %s", + this->Name, Enable ? "true" : "false"); + + Security.IsKernelDebugEnabled = Enable; + } + + void TCB::SYSV_ABI_Call(uintptr_t Arg1, uintptr_t Arg2, + uintptr_t Arg3, uintptr_t Arg4, + uintptr_t Arg5, uintptr_t Arg6, + void *Function) + { +#if defined(a64) + this->Registers.rdi = Arg1; + this->Registers.rsi = Arg2; + this->Registers.rdx = Arg3; + this->Registers.rcx = Arg4; + this->Registers.r8 = Arg5; + this->Registers.r9 = Arg6; + if (Function != nullptr) + this->Registers.rip = (uint64_t)Function; +#else +#warning "SYSV ABI not implemented for this architecture" +#endif + } + + __no_sanitize("undefined") + TCB::TCB(Task *ctx, PCB *Parent, IP EntryPoint, + const char **argv, const char **envp, + const std::vector &auxv, + TaskArchitecture Architecture, + TaskCompatibility Compatibility, + bool ThreadNotReady) + { + assert(ctx != nullptr); + assert(Architecture >= _ArchitectureMin); + assert(Architecture <= _ArchitectureMax); + assert(Compatibility >= _CompatibilityMin); + assert(Compatibility <= _CompatibilityMax); + + if (Parent == nullptr) + { + this->Parent = ctx->GetCurrentProcess(); + assert(this->Parent != nullptr); + } + else + this->Parent = Parent; + + this->ctx = ctx; + this->ID = ctx->NextTID++; + + if (this->Name) + delete[] this->Name; + this->Name = new char[strlen(this->Parent->Name) + 1]; + strcpy((char *)this->Name, this->Parent->Name); + + this->EntryPoint = EntryPoint; + this->ExitCode = KILL_CRASH; + this->Info.Architecture = Architecture; + this->Info.Compatibility = Compatibility; + this->Security.ExecutionMode = + this->Parent->Security.ExecutionMode; + if (ThreadNotReady) + this->Status = TaskStatus::Zombie; + else + this->Status = TaskStatus::Ready; + this->Memory = new Memory::MemMgr(this->Parent->PageTable, + this->Parent->memDirectory); + std::size_t FXPgs = TO_PAGES(sizeof(CPU::x64::FXState) + 1); + this->FPU = (CPU::x64::FXState *)this->Memory->RequestPages(FXPgs); + memset(this->FPU, 0, sizeof(CPU::x64::FXState)); + + // TODO: Is really a good idea to use the FPU in kernel mode? + this->FPU->mxcsr = 0b0001111110000000; + this->FPU->mxcsrmask = 0b1111111110111111; + this->FPU->fcw = 0b0000001100111111; + + // CPU::x64::fxrstor(this->FPU); + // uint16_t FCW = 0b1100111111; + // asmv("fldcw %0" + // : + // : "m"(FCW) + // : "memory"); + // uint32_t MXCSR = 0b1111110000000; + // asmv("ldmxcsr %0" + // : + // : "m"(MXCSR) + // : "memory"); + // CPU::x64::fxsave(this->FPU); + +#if defined(a64) + this->Registers.rip = EntryPoint; +#elif defined(a32) + this->Registers.eip = EntryPoint; +#elif defined(aa64) + this->Registers.pc = EntryPoint; +#endif + + switch (this->Parent->Security.ExecutionMode) + { + case TaskExecutionMode::System: + fixme("System mode not supported."); + [[fallthrough]]; + case TaskExecutionMode::Kernel: + { + this->Security.IsCritical = true; + this->Stack = new Memory::StackGuard(false, + this->Parent->PageTable); + +#if defined(a64) + this->ShadowGSBase = + CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE); + this->GSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); + this->FSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); + this->Registers.cs = GDT_KERNEL_CODE; + this->Registers.ss = GDT_KERNEL_DATA; + this->Registers.rflags.AlwaysOne = 1; + this->Registers.rflags.IF = 1; + this->Registers.rflags.ID = 1; + this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop()); + POKE(uintptr_t, this->Registers.rsp) = (uintptr_t)ThreadDoExit; +#elif defined(a32) +#elif defined(aa64) +#endif + break; + } + case TaskExecutionMode::User: + { + this->Stack = new Memory::StackGuard(true, + this->Parent->PageTable); + + gsTCB *gsT = (gsTCB *)this->Memory->RequestPages(TO_PAGES(sizeof(gsTCB))); + + gsT->SyscallStack = + (uintptr_t)this->Memory->RequestPages(TO_PAGES(STACK_SIZE)) + + STACK_SIZE - 0x10; + + gsT->TempStack = 0x0; + gsT->t = this; +#if defined(a64) + this->ShadowGSBase = (uintptr_t)gsT; + this->GSBase = 0; + this->FSBase = 0; + this->Registers.cs = GDT_USER_CODE; + this->Registers.ss = GDT_USER_DATA; + this->Registers.rflags.AlwaysOne = 1; + this->Registers.rflags.IF = 1; + this->Registers.rflags.ID = 1; + /* We need to leave the libc's crt + to make a syscall when the Thread + is exited or we are going to get + GPF or PF exception. */ + +#pragma region + size_t ArgvSize = 0; + if (argv) + while (argv[ArgvSize] != nullptr) + ArgvSize++; + + size_t EnvpSize = 0; + if (envp) + while (envp[EnvpSize] != nullptr) + EnvpSize++; + + debug("ArgvSize: %d", ArgvSize); + debug("EnvpSize: %d", EnvpSize); + + /* https://articles.manugarg.com/aboutelfauxiliaryvectors.html */ + /* https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf#figure.3.9 */ + // rsp is the top of the stack + char *Stack = (char *)this->Stack->GetStackPhysicalTop(); + // Temporary stack pointer for strings + char *StackStrings = (char *)Stack; + char *StackStringsVirtual = (char *)this->Stack->GetStackTop(); + + // Store string pointers for later + uintptr_t *ArgvStrings = nullptr; + uintptr_t *EnvpStrings = nullptr; + if (ArgvSize > 0) + ArgvStrings = new uintptr_t[ArgvSize]; + if (EnvpSize > 0) + EnvpStrings = new uintptr_t[EnvpSize]; + + for (size_t i = 0; i < ArgvSize; i++) + { + // Subtract the length of the string and the null terminator + StackStrings -= strlen(argv[i]) + 1; + StackStringsVirtual -= strlen(argv[i]) + 1; + // Store the pointer to the string + ArgvStrings[i] = (uintptr_t)StackStringsVirtual; + // Copy the string to the stack + strcpy(StackStrings, argv[i]); + debug("argv[%d]: %s", i, argv[i]); + } + + for (size_t i = 0; i < EnvpSize; i++) + { + // Subtract the length of the string and the null terminator + StackStrings -= strlen(envp[i]) + 1; + StackStringsVirtual -= strlen(envp[i]) + 1; + // Store the pointer to the string + EnvpStrings[i] = (uintptr_t)StackStringsVirtual; + // Copy the string to the stack + strcpy(StackStrings, envp[i]); + debug("envp[%d]: %s", i, envp[i]); + } + + // Align the stack to 16 bytes + StackStrings -= (uintptr_t)StackStrings & 0xF; + // Set "Stack" to the new stack pointer + Stack = (char *)StackStrings; + // If argv and envp sizes are odd then we need to align the stack + Stack -= (ArgvSize + EnvpSize) % 2; + + // We need 8 bit pointers for the stack from here + uintptr_t *Stack64 = (uintptr_t *)Stack; + + // Store the null terminator + Stack64--; + *Stack64 = AT_NULL; + + // auxv_array is initialized with auxv elements. If the array is empty then we add a null terminator + std::vector auxv_array = auxv; + if (auxv_array.size() == 0) + auxv_array.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}}); + + // Store auxillary vector + foreach (AuxiliaryVector var in auxv_array) + { + // Subtract the size of the auxillary vector + Stack64 -= sizeof(Elf64_auxv_t) / sizeof(uintptr_t); + // Store the auxillary vector + POKE(Elf64_auxv_t, Stack64) = var.archaux; + // TODO: Store strings to the stack + } + + // Store the null terminator + Stack64--; + *Stack64 = AT_NULL; + + // Store EnvpStrings[] to the stack + Stack64 -= EnvpSize; // (1 Stack64 = 8 bits; Stack64 = 8 * EnvpSize) + for (size_t i = 0; i < EnvpSize; i++) + { + *(Stack64 + i) = (uintptr_t)EnvpStrings[i]; + debug("EnvpStrings[%d]: %#lx", + i, EnvpStrings[i]); + } + + // Store the null terminator + Stack64--; + *Stack64 = AT_NULL; + + // Store ArgvStrings[] to the stack + Stack64 -= ArgvSize; // (1 Stack64 = 8 bits; Stack64 = 8 * ArgvSize) + for (size_t i = 0; i < ArgvSize; i++) + { + *(Stack64 + i) = (uintptr_t)ArgvStrings[i]; + debug("ArgvStrings[%d]: %#lx", + i, ArgvStrings[i]); + } + + // Store the argc + Stack64--; + *Stack64 = ArgvSize; + + // Set "Stack" to the new stack pointer + Stack = (char *)Stack64; + + /* We need the virtual address but because we are in the kernel we can't use the process page table. + So we modify the physical address and store how much we need to subtract to get the virtual address for RSP. */ + uintptr_t SubtractStack = (uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)Stack; + debug("SubtractStack: %#lx", SubtractStack); + + // Set the stack pointer to the new stack + this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop() - SubtractStack); + + if (ArgvSize > 0) + delete[] ArgvStrings; + if (EnvpSize > 0) + delete[] EnvpStrings; + +#ifdef DEBUG + DumpData("Stack Data", (void *)((uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)SubtractStack), SubtractStack); +#endif + + this->Registers.rdi = (uintptr_t)ArgvSize; // argc + this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv + this->Registers.rcx = (uintptr_t)EnvpSize; // envc + this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp + +#pragma endregion + +#elif defined(a32) +#elif defined(aa64) +#endif +#ifdef DEBUG_TASKING + DumpData(this->Name, this->Stack, STACK_SIZE); +#endif + break; + } + default: + assert(false); + } + + this->Info.SpawnTime = TimeManager->GetCounter(); + +#ifdef DEBUG +#ifdef a64 + debug("Thread EntryPoint: %#lx => RIP: %#lx", + this->EntryPoint, this->Registers.rip); + if (this->Parent->Security.ExecutionMode == TaskExecutionMode::User) + debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", + this->Stack->GetStackBottom(), this->Stack->GetStackTop(), + this->Registers.rsp); + else + debug("Thread stack region is %#lx-%#lx (K) and rsp is %#lx", + this->Stack->GetStackBottom(), this->Stack->GetStackTop(), + this->Registers.rsp); +#elif defined(a32) + debug("Thread EntryPoint: %#lx => RIP: %#lx", + this->EntryPoint, this->Registers.eip); + if (Parent->Security.ExecutionMode == TaskExecutionMode::User) + debug("Thread stack region is %#lx-%#lx (U) and rsp is %#lx", + this->Stack->GetStackBottom(), this->Stack->GetStackTop(), + this->Registers.esp); + else + debug("Thread stack region is %#lx-%#lx (K) and rsp is %#lx", + this->Stack->GetStackBottom(), this->Stack->GetStackTop(), + this->Registers.esp); +#elif defined(aa64) +#endif + debug("Created thread \"%s\"(%d) in process \"%s\"(%d)", + this->Name, this->ID, this->Parent->Name, + this->Parent->ID); +#endif + + this->Parent->Threads.push_back(this); + + if (this->Parent->Threads.size() == 1 && + this->Parent->Status == Zombie && + ThreadNotReady == false) + { + this->Parent->Status = Ready; + } + } + + TCB::~TCB() + { + std::vector &Threads = this->Parent->Threads; + Threads.erase(std::find(Threads.begin(), + Threads.end(), + this)); + + delete[] this->Name; + delete this->Stack; + delete this->Memory; + } +} diff --git a/Tests/CPUID.cpp b/Tests/CPUID.cpp index c6c409b..289245e 100644 --- a/Tests/CPUID.cpp +++ b/Tests/CPUID.cpp @@ -25,131 +25,131 @@ extern bool DebuggerIsAttached; __constructor void TestCPUIDStructs() { - if (!DebuggerIsAttached) - return; + if (!DebuggerIsAttached) + return; - if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) - { - CPU::x86::AMD::CPUID0x00000000 cpuid0; - CPU::x86::AMD::CPUID0x00000001 cpuid1; - CPU::x86::AMD::CPUID0x00000005 cpuid5; - CPU::x86::AMD::CPUID0x00000006 cpuid6; - CPU::x86::AMD::CPUID0x00000007 cpuid7; - CPU::x86::AMD::CPUID0x0000000B_ECX_0 cpuidB_C_0; - CPU::x86::AMD::CPUID0x0000000B_ECX_1 cpuidB_C_1; - CPU::x86::AMD::CPUID0x0000000D_ECX_0 cpuidD_C_0; - CPU::x86::AMD::CPUID0x0000000D_ECX_1 cpuidD_C_1; - CPU::x86::AMD::CPUID0x0000000D_ECX_2 cpuidD_C_2; - CPU::x86::AMD::CPUID0x0000000D_ECX_11 cpuidD_C_11; - CPU::x86::AMD::CPUID0x0000000D_ECX_12 cpuidD_C_12; - CPU::x86::AMD::CPUID0x0000000D_ECX_3E cpuidD_C_3E; - CPU::x86::AMD::CPUID0x80000000 cpuid80000000; - CPU::x86::AMD::CPUID0x80000001 cpuid80000001; - CPU::x86::AMD::CPUID0x80000002 cpuid80000002; - CPU::x86::AMD::CPUID0x80000003 cpuid80000003; - CPU::x86::AMD::CPUID0x80000004 cpuid80000004; - CPU::x86::AMD::CPUID0x80000005 cpuid80000005; - CPU::x86::AMD::CPUID0x80000006 cpuid80000006; - CPU::x86::AMD::CPUID0x80000007 cpuid80000007; - CPU::x86::AMD::CPUID0x80000008 cpuid80000008; - CPU::x86::AMD::CPUID0x8000000A cpuid8000000A; - CPU::x86::AMD::CPUID0x80000019 cpuid80000019; - CPU::x86::AMD::CPUID0x8000001A cpuid8000001A; - CPU::x86::AMD::CPUID0x8000001B cpuid8000001B; - CPU::x86::AMD::CPUID0x8000001C cpuid8000001C; - CPU::x86::AMD::CPUID0x8000001D cpuid8000001D; - CPU::x86::AMD::CPUID0x8000001E cpuid8000001E; - CPU::x86::AMD::CPUID0x8000001F cpuid8000001F; - CPU::x86::AMD::CPUID0x80000020 cpuid80000020; - CPU::x86::AMD::CPUID0x80000021 cpuid80000021; - CPU::x86::AMD::CPUID0x80000022 cpuid80000022; - CPU::x86::AMD::CPUID0x80000023 cpuid80000023; - CPU::x86::AMD::CPUID0x80000026 cpuid80000026; + if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) + { + CPU::x86::AMD::CPUID0x00000000 cpuid0; + CPU::x86::AMD::CPUID0x00000001 cpuid1; + CPU::x86::AMD::CPUID0x00000005 cpuid5; + CPU::x86::AMD::CPUID0x00000006 cpuid6; + CPU::x86::AMD::CPUID0x00000007 cpuid7; + CPU::x86::AMD::CPUID0x0000000B_ECX_0 cpuidB_C_0; + CPU::x86::AMD::CPUID0x0000000B_ECX_1 cpuidB_C_1; + CPU::x86::AMD::CPUID0x0000000D_ECX_0 cpuidD_C_0; + CPU::x86::AMD::CPUID0x0000000D_ECX_1 cpuidD_C_1; + CPU::x86::AMD::CPUID0x0000000D_ECX_2 cpuidD_C_2; + CPU::x86::AMD::CPUID0x0000000D_ECX_11 cpuidD_C_11; + CPU::x86::AMD::CPUID0x0000000D_ECX_12 cpuidD_C_12; + CPU::x86::AMD::CPUID0x0000000D_ECX_3E cpuidD_C_3E; + CPU::x86::AMD::CPUID0x80000000 cpuid80000000; + CPU::x86::AMD::CPUID0x80000001 cpuid80000001; + CPU::x86::AMD::CPUID0x80000002 cpuid80000002; + CPU::x86::AMD::CPUID0x80000003 cpuid80000003; + CPU::x86::AMD::CPUID0x80000004 cpuid80000004; + CPU::x86::AMD::CPUID0x80000005 cpuid80000005; + CPU::x86::AMD::CPUID0x80000006 cpuid80000006; + CPU::x86::AMD::CPUID0x80000007 cpuid80000007; + CPU::x86::AMD::CPUID0x80000008 cpuid80000008; + CPU::x86::AMD::CPUID0x8000000A cpuid8000000A; + CPU::x86::AMD::CPUID0x80000019 cpuid80000019; + CPU::x86::AMD::CPUID0x8000001A cpuid8000001A; + CPU::x86::AMD::CPUID0x8000001B cpuid8000001B; + CPU::x86::AMD::CPUID0x8000001C cpuid8000001C; + CPU::x86::AMD::CPUID0x8000001D cpuid8000001D; + CPU::x86::AMD::CPUID0x8000001E cpuid8000001E; + CPU::x86::AMD::CPUID0x8000001F cpuid8000001F; + CPU::x86::AMD::CPUID0x80000020 cpuid80000020; + CPU::x86::AMD::CPUID0x80000021 cpuid80000021; + CPU::x86::AMD::CPUID0x80000022 cpuid80000022; + CPU::x86::AMD::CPUID0x80000023 cpuid80000023; + CPU::x86::AMD::CPUID0x80000026 cpuid80000026; - cpuid0.Get(); - cpuid1.Get(); - cpuid5.Get(); - cpuid6.Get(); - cpuid7.Get(); - cpuidB_C_0.Get(); - cpuidB_C_1.Get(); - cpuidD_C_0.Get(); - cpuidD_C_1.Get(); - cpuidD_C_2.Get(); - cpuidD_C_11.Get(); - cpuidD_C_12.Get(); - cpuidD_C_3E.Get(); - cpuid80000000.Get(); - cpuid80000001.Get(); - cpuid80000002.Get(); - cpuid80000003.Get(); - cpuid80000004.Get(); - cpuid80000005.Get(); - cpuid80000006.Get(); - cpuid80000007.Get(); - cpuid80000008.Get(); - cpuid8000000A.Get(); - cpuid80000019.Get(); - cpuid8000001A.Get(); - cpuid8000001B.Get(); - cpuid8000001C.Get(); - cpuid8000001D.Get(); - cpuid8000001E.Get(); - cpuid8000001F.Get(); - cpuid80000020.Get(); - cpuid80000021.Get(); - cpuid80000022.Get(); - cpuid80000023.Get(); - cpuid80000026.Get(); + cpuid0.Get(); + cpuid1.Get(); + cpuid5.Get(); + cpuid6.Get(); + cpuid7.Get(); + cpuidB_C_0.Get(); + cpuidB_C_1.Get(); + cpuidD_C_0.Get(); + cpuidD_C_1.Get(); + cpuidD_C_2.Get(); + cpuidD_C_11.Get(); + cpuidD_C_12.Get(); + cpuidD_C_3E.Get(); + cpuid80000000.Get(); + cpuid80000001.Get(); + cpuid80000002.Get(); + cpuid80000003.Get(); + cpuid80000004.Get(); + cpuid80000005.Get(); + cpuid80000006.Get(); + cpuid80000007.Get(); + cpuid80000008.Get(); + cpuid8000000A.Get(); + cpuid80000019.Get(); + cpuid8000001A.Get(); + cpuid8000001B.Get(); + cpuid8000001C.Get(); + cpuid8000001D.Get(); + cpuid8000001E.Get(); + cpuid8000001F.Get(); + cpuid80000020.Get(); + cpuid80000021.Get(); + cpuid80000022.Get(); + cpuid80000023.Get(); + cpuid80000026.Get(); - // asmv("int3"); - } - else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) - { - CPU::x86::Intel::CPUID0x00000000 cpuid0; - CPU::x86::Intel::CPUID0x00000001 cpuid1; - CPU::x86::Intel::CPUID0x00000002 cpuid2; - CPU::x86::Intel::CPUID0x00000003 cpuid3; - CPU::x86::Intel::CPUID0x00000004_1 cpuid4_1; - CPU::x86::Intel::CPUID0x00000005 cpuid5; - CPU::x86::Intel::CPUID0x00000006 cpuid6; - CPU::x86::Intel::CPUID0x00000007_0 cpuid7_0; - CPU::x86::Intel::CPUID0x00000007_1 cpuid7_1; - CPU::x86::Intel::CPUID0x0000000A cpuidA; - CPU::x86::Intel::CPUID0x00000015 cpuid15; - CPU::x86::Intel::CPUID0x00000016 cpuid16; - CPU::x86::Intel::CPUID0x80000000 cpuid80000000; - CPU::x86::Intel::CPUID0x80000001 cpuid80000001; - CPU::x86::Intel::CPUID0x80000002 cpuid80000002; - CPU::x86::Intel::CPUID0x80000003 cpuid80000003; - CPU::x86::Intel::CPUID0x80000004 cpuid80000004; - CPU::x86::Intel::CPUID0x80000006 cpuid80000006; - CPU::x86::Intel::CPUID0x80000008 cpuid80000008; - CPU::x86::Intel::CPUID0x8000000A cpuid8000000A; + // asmv("int3"); + } + else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) + { + CPU::x86::Intel::CPUID0x00000000 cpuid0; + CPU::x86::Intel::CPUID0x00000001 cpuid1; + CPU::x86::Intel::CPUID0x00000002 cpuid2; + CPU::x86::Intel::CPUID0x00000003 cpuid3; + CPU::x86::Intel::CPUID0x00000004_1 cpuid4_1; + CPU::x86::Intel::CPUID0x00000005 cpuid5; + CPU::x86::Intel::CPUID0x00000006 cpuid6; + CPU::x86::Intel::CPUID0x00000007_0 cpuid7_0; + CPU::x86::Intel::CPUID0x00000007_1 cpuid7_1; + CPU::x86::Intel::CPUID0x0000000A cpuidA; + CPU::x86::Intel::CPUID0x00000015 cpuid15; + CPU::x86::Intel::CPUID0x00000016 cpuid16; + CPU::x86::Intel::CPUID0x80000000 cpuid80000000; + CPU::x86::Intel::CPUID0x80000001 cpuid80000001; + CPU::x86::Intel::CPUID0x80000002 cpuid80000002; + CPU::x86::Intel::CPUID0x80000003 cpuid80000003; + CPU::x86::Intel::CPUID0x80000004 cpuid80000004; + CPU::x86::Intel::CPUID0x80000006 cpuid80000006; + CPU::x86::Intel::CPUID0x80000008 cpuid80000008; + CPU::x86::Intel::CPUID0x8000000A cpuid8000000A; - cpuid0.Get(); - cpuid1.Get(); - cpuid2.Get(); - cpuid3.Get(); - cpuid4_1.Get(); - cpuid5.Get(); - cpuid6.Get(); - cpuid7_0.Get(); - cpuid7_1.Get(); - cpuidA.Get(); - cpuid15.Get(); - cpuid16.Get(); - cpuid80000000.Get(); - cpuid80000001.Get(); - cpuid80000002.Get(); - cpuid80000003.Get(); - cpuid80000004.Get(); - cpuid80000006.Get(); - cpuid80000008.Get(); - cpuid8000000A.Get(); + cpuid0.Get(); + cpuid1.Get(); + cpuid2.Get(); + cpuid3.Get(); + cpuid4_1.Get(); + cpuid5.Get(); + cpuid6.Get(); + cpuid7_0.Get(); + cpuid7_1.Get(); + cpuidA.Get(); + cpuid15.Get(); + cpuid16.Get(); + cpuid80000000.Get(); + cpuid80000001.Get(); + cpuid80000002.Get(); + cpuid80000003.Get(); + cpuid80000004.Get(); + cpuid80000006.Get(); + cpuid80000008.Get(); + cpuid8000000A.Get(); - // asmv("int3"); - } + // asmv("int3"); + } } #endif // DEBUG diff --git a/Tests/Marco.cpp b/Tests/Marco.cpp index 138dc65..089e9fa 100644 --- a/Tests/Marco.cpp +++ b/Tests/Marco.cpp @@ -22,6 +22,16 @@ #include #include +#include +#include "../syscalls.h" + +void TestSeekMacros() /* static assert, no constructor needed */ +{ + static_assert(SYSCALL_SEEK_SET == SEEK_SET); + static_assert(SYSCALL_SEEK_CUR == SEEK_CUR); + static_assert(SYSCALL_SEEK_END == SEEK_END); +} + __constructor void TestMacros() { { diff --git a/Tests/MemoryAllocation.cpp b/Tests/MemoryAllocation.cpp index 12ff434..f60abc1 100644 --- a/Tests/MemoryAllocation.cpp +++ b/Tests/MemoryAllocation.cpp @@ -18,8 +18,8 @@ #ifdef DEBUG #include -#include #include +#include /* Originally from: https://github.com/EnderIce2/FennixProject/blob/main/kernel/test.cpp */ @@ -28,20 +28,20 @@ class test_mem_new_delete { public: - test_mem_new_delete(); - ~test_mem_new_delete(); + test_mem_new_delete(); + ~test_mem_new_delete(); }; test_mem_new_delete::test_mem_new_delete() { - for (char i = 0; i < 2; i++) - ; + for (char i = 0; i < 2; i++) + ; } test_mem_new_delete::~test_mem_new_delete() { - for (char i = 0; i < 2; i++) - ; + for (char i = 0; i < 2; i++) + ; } extern bool EnableExternalMemoryTracer; @@ -50,204 +50,212 @@ extern bool DebuggerIsAttached; void TestMemoryAllocation() { #ifdef a32 - return; /* Not really for now. */ + return; /* Not ready for now. */ #endif - if (EnableExternalMemoryTracer || DebuggerIsAttached) - { - debug("The test is disabled when the external memory tracer or a debugger is enabled."); - return; - } + if (EnableExternalMemoryTracer || DebuggerIsAttached) + { + debug("The test is disabled when the external memory tracer or a debugger is enabled."); + return; + } - void *tmpAlloc1 = kmalloc(176); - void *tmpAlloc2 = kmalloc(511); - void *tmpAlloc3 = kmalloc(1027); - void *tmpAlloc4 = kmalloc(1569); - for (int repeat = 0; repeat < 4; repeat++) - { - debug("---------------[TEST %d]---------------\n", repeat); + void *tmpAlloc1 = kmalloc(176); + void *tmpAlloc2 = kmalloc(511); + void *tmpAlloc3 = kmalloc(1027); + void *tmpAlloc4 = kmalloc(1569); + for (int repeat = 0; repeat < 4; repeat++) + { + debug("---------------[TEST %d]---------------\n", repeat); - debug("Single Page Request Test"); - { - uint64_t prq1 = (uint64_t)KernelAllocator.RequestPage(); - KernelAllocator.FreePage((void *)prq1); + debug("Single Page Request Test"); + { + uint64_t prq1 = (uint64_t)KernelAllocator.RequestPage(); + KernelAllocator.FreePage((void *)prq1); - for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) - KernelAllocator.FreePage(KernelAllocator.RequestPage()); + for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) + KernelAllocator.FreePage(KernelAllocator.RequestPage()); - uint64_t prq2 = (uint64_t)KernelAllocator.RequestPage(); - KernelAllocator.FreePage((void *)prq2); + uint64_t prq2 = (uint64_t)KernelAllocator.RequestPage(); + KernelAllocator.FreePage((void *)prq2); - debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); - assert(prq1 == prq2); - } + debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); + assert(prq1 == prq2); + } - debug("Multiple Page Request Test"); - { - uint64_t prq1 = (uint64_t)KernelAllocator.RequestPages(10); - KernelAllocator.FreePages((void *)prq1, 10); + debug("Multiple Page Request Test"); + { + uint64_t prq1 = (uint64_t)KernelAllocator.RequestPages(10); + KernelAllocator.FreePages((void *)prq1, 10); - for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) - KernelAllocator.FreePages(KernelAllocator.RequestPages(20), 20); + for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) + KernelAllocator.FreePages(KernelAllocator.RequestPages(20), 20); - uint64_t prq2 = (uint64_t)KernelAllocator.RequestPages(10); - KernelAllocator.FreePages((void *)prq2, 10); + uint64_t prq2 = (uint64_t)KernelAllocator.RequestPages(10); + KernelAllocator.FreePages((void *)prq2, 10); - debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); - assert(prq1 == prq2); - } + debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); + assert(prq1 == prq2); + } - debug("Multiple Fixed Malloc Test"); - { - uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq1); + debug("Multiple Fixed Malloc Test"); + { + uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq1); - for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) - kfree(kmalloc(0x10000)); + for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) + { + kfree(kmalloc(0x10000)); + kfree(kmalloc(0x1000)); + kfree(kmalloc(0x100)); + kfree(kmalloc(0x10)); + kfree(kmalloc(0x1)); + } - uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq2); + uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq2); - debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); - assert(prq1 == prq2); - } + debug(" Result:\t\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); + assert(prq1 == prq2); + } - debug("Multiple Dynamic Malloc Test"); - { - uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq1); + debug("Multiple Dynamic Malloc Test"); + { + uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq1); - for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) - kfree(kmalloc(i)); + for (size_t i = 1; i < MEMTEST_ITERATIONS; i++) + kfree(kmalloc(i)); - uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq2); + uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq2); - debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); - assert(prq1 == prq2); - } + debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); + assert(prq1 == prq2); + } - debug("New/Delete Test"); - { - uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq1); + debug("New/Delete Test"); + { + uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq1); - for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) - { - test_mem_new_delete *t = new test_mem_new_delete(); - delete t; - } + for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) + { + test_mem_new_delete *t = new test_mem_new_delete(); + delete t; + } - uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq2); + uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq2); - debug(" Result: \t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); - assert(prq1 == prq2); - } + debug(" Result: \t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); + assert(prq1 == prq2); + } - debug("New/Delete Fixed Array Test"); - { - uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq1); + debug("New/Delete Fixed Array Test"); + { + uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq1); - for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) - { - char *t = new char[128]; - delete[] t; - } + for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) + { + char *t = new char[128]; + delete[] t; + } - uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq2); + uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq2); - debug(" Result: \t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); - assert(prq1 == prq2); - } + debug(" Result: \t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); + assert(prq1 == prq2); + } - debug("New/Delete Dynamic Array Test"); - { - uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq1); + debug("New/Delete Dynamic Array Test"); + { + uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq1); - for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) - { - if (i == 0) - continue; - char *t = new char[i]; - delete[] t; - } + for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) + { + if (i == 0) + continue; + char *t = new char[i]; + delete[] t; + } - uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq2); + uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq2); - debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); - assert(prq1 == prq2); - } + debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); + assert(prq1 == prq2); + } - debug("calloc Test"); - { - uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq1); + debug("calloc Test"); + { + uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq1); - for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) - { - char *t = (char *)kcalloc(128, 1); - kfree(t); - } + for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) + { + char *t = (char *)kcalloc(128, 1); + kfree(t); + } - uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq2); + uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq2); - debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); - assert(prq1 == prq2); - } + debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); + assert(prq1 == prq2); + } - debug("realloc Test"); - { - uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq1); + debug("realloc Test"); + { + uintptr_t prq1 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq1); - for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) - { - char *t = (char *)kmalloc(128); - t = (char *)krealloc(t, 256); - kfree(t); - } + for (size_t i = 0; i < MEMTEST_ITERATIONS; i++) + { + char *t = (char *)kmalloc(128); + t = (char *)krealloc(t, 256); + kfree(t); + } - uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); - kfree((void *)prq2); + uintptr_t prq2 = (uintptr_t)kmalloc(0x1000); + kfree((void *)prq2); - debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); - assert(prq1 == prq2); - } - } + debug(" Result:\t1-[%#lx]; 2-[%#lx]", (void *)prq1, (void *)prq2); + assert(prq1 == prq2); + } + } - kfree(tmpAlloc1); - kfree(tmpAlloc2); - kfree(tmpAlloc3); - kfree(tmpAlloc4); + kfree(tmpAlloc1); + kfree(tmpAlloc2); + kfree(tmpAlloc3); + kfree(tmpAlloc4); - debug("Memory Stress Test"); - for (size_t i = 0; i < 0x1000; i++) - kfree(kmalloc(i)); + debug("Memory Stress Test"); + for (size_t i = 1; i < 0x1000; i++) + kfree(kmalloc(i)); - debug("Invalid Usage Test"); - kfree(tmpAlloc1); - kfree(tmpAlloc2); - kfree(tmpAlloc3); - kfree(tmpAlloc4); + debug("Invalid Usage Test"); + kfree(tmpAlloc1); + kfree(tmpAlloc2); + kfree(tmpAlloc3); + kfree(tmpAlloc4); - void *InvMlc = kmalloc(0); - assert(InvMlc == nullptr); - krealloc(InvMlc, 0); - assert(InvMlc == nullptr); - kcalloc(0, 0); - assert(InvMlc == nullptr); - kcalloc(1, 0); - assert(InvMlc == nullptr); - kcalloc(0, 1); - assert(InvMlc == nullptr); - kfree(InvMlc); + /* Allocation functions have assertions to check for invalid usage */ - debug("Memory Test Complete"); + // void *InvMlc = kmalloc(0); + // assert(InvMlc == nullptr); + // krealloc(InvMlc, 0); + // assert(InvMlc == nullptr); + // kcalloc(0, 0); + // assert(InvMlc == nullptr); + // kcalloc(1, 0); + // assert(InvMlc == nullptr); + // kcalloc(0, 1); + // assert(InvMlc == nullptr); + // kfree(InvMlc); + + debug("Memory Test Complete"); } #endif // DEBUG diff --git a/Tests/MemoryOperations.cpp b/Tests/MemoryOperations.cpp index 3cf5b6f..e487cbd 100644 --- a/Tests/MemoryOperations.cpp +++ b/Tests/MemoryOperations.cpp @@ -23,118 +23,125 @@ extern bool EnableExternalMemoryTracer; extern bool DebuggerIsAttached; +extern Memory::MemoryAllocatorType AllocatorType; __constructor void TestMemoryOperations() { - if (EnableExternalMemoryTracer || DebuggerIsAttached) - { - debug("The test is disabled when the external memory tracer or a debugger is enabled."); - return; - } + if (EnableExternalMemoryTracer || DebuggerIsAttached) + { + debug("The test is disabled when the external memory tracer or a debugger is enabled."); + return; + } - int arr1[5] = {1, 2, 3, 4, 5}; - int arr2[5] = {0, 0, 0, 0, 0}; - char str1[] = "Hello"; - char str2[] = "World"; + if (AllocatorType == Memory::MemoryAllocatorType::Pages) + { + debug("The test is disabled when the allocator is set to pages."); + return; + } - memcpy_unsafe(arr2, arr1, sizeof(arr1)); - debug("memcpy: arr2[0]=%d, arr2[1]=%d, arr2[2]=%d, arr2[3]=%d, arr2[4]=%d", - arr2[0], arr2[1], arr2[2], arr2[3], arr2[4]); - if (memcmp(arr1, arr2, sizeof(arr1)) != 0) - { - error("memcpy failed!"); - inf_loop; - } + int arr1[5] = {1, 2, 3, 4, 5}; + int arr2[5] = {0, 0, 0, 0, 0}; + char str1[] = "Hello"; + char str2[] = "World"; - memset_unsafe(arr2, 0, sizeof(arr2)); - debug("memset: arr2[0]=%d, arr2[1]=%d, arr2[2]=%d, arr2[3]=%d, arr2[4]=%d", - arr2[0], arr2[1], arr2[2], arr2[3], arr2[4]); - if (memcmp(arr1, arr2, sizeof(arr1)) == 0) - { - error("memset failed!"); - inf_loop; - } + memcpy_unsafe(arr2, arr1, sizeof(arr1)); + debug("memcpy: arr2[0]=%d, arr2[1]=%d, arr2[2]=%d, arr2[3]=%d, arr2[4]=%d", + arr2[0], arr2[1], arr2[2], arr2[3], arr2[4]); + if (memcmp(arr1, arr2, sizeof(arr1)) != 0) + { + error("memcpy failed!"); + inf_loop; + } - memmove_unsafe(str1 + 3, str1, strlen(str1) + 1); - debug("memmove: str1=%s", str1); - if (strcmp(str1, "HelHello") != 0) - { - error("memmove failed!"); - inf_loop; - } + memset_unsafe(arr2, 0, sizeof(arr2)); + debug("memset: arr2[0]=%d, arr2[1]=%d, arr2[2]=%d, arr2[3]=%d, arr2[4]=%d", + arr2[0], arr2[1], arr2[2], arr2[3], arr2[4]); + if (memcmp(arr1, arr2, sizeof(arr1)) == 0) + { + error("memset failed!"); + inf_loop; + } - char carr[512]; - char carrTo[16]; + memmove_unsafe(str1 + 3, str1, strlen(str1) + 1); + debug("memmove: str1=%s", str1); + if (strcmp(str1, "HelHello") != 0) + { + error("memmove failed!"); + inf_loop; + } - for (size_t i = 0; i < 512; i++) - { - for (size_t i = 0; i < 16; i++) - carrTo[i] = 'a'; + char carr[512]; + char carrTo[16]; - for (size_t i = 0; i < 512; i += 16) - memcpy_unsafe(carr + i, carrTo, 16); + for (size_t i = 0; i < 512; i++) + { + for (size_t i = 0; i < 16; i++) + carrTo[i] = 'a'; - for (size_t i = 0; i < 512; i++) - { - if (carr[i] != 'a') - { - error("memcpy failed!"); - while (1) - ; - } - } + for (size_t i = 0; i < 512; i += 16) + memcpy_unsafe(carr + i, carrTo, 16); - { - char carrFull[512]; - for (size_t i = 0; i < 512; i++) - carrFull[i] = 'b'; + for (size_t i = 0; i < 512; i++) + { + if (carr[i] != 'a') + { + error("memcpy failed!"); + while (1) + ; + } + } - memcpy_unsafe(carr, carrFull, 512); + { + char carrFull[512]; + for (size_t i = 0; i < 512; i++) + carrFull[i] = 'b'; - for (size_t i = 0; i < 512; i++) - { - if (carr[i] != 'b') - { - error("memcpy failed!"); - while (1) - ; - } - } - } - } + memcpy_unsafe(carr, carrFull, 512); - for (size_t i = 0; i < 512; i++) - { - for (size_t i = 0; i < 512; i += 16) - memset_unsafe(carr + i, 'c', 16); + for (size_t i = 0; i < 512; i++) + { + if (carr[i] != 'b') + { + error("memcpy failed!"); + while (1) + ; + } + } + } + } - for (size_t i = 0; i < 512; i++) - { - if (carr[i] != 'c') - { - error("memcpy failed!"); - while (1) - ; - } - } - } + for (size_t i = 0; i < 512; i++) + { + for (size_t i = 0; i < 512; i += 16) + memset_unsafe(carr + i, 'c', 16); - for (size_t i = 0; i < 512; i++) - { - memset_unsafe(carr, 'd', 512); + for (size_t i = 0; i < 512; i++) + { + if (carr[i] != 'c') + { + error("memcpy failed!"); + while (1) + ; + } + } + } - for (size_t i = 0; i < 512; i++) - { - if (carr[i] != 'd') - { - error("memset failed!"); - while (1) - ; - } - } - } + for (size_t i = 0; i < 512; i++) + { + memset_unsafe(carr, 'd', 512); - debug("Memory operations test passed"); + for (size_t i = 0; i < 512; i++) + { + if (carr[i] != 'd') + { + error("memset failed!"); + while (1) + ; + } + } + } + + debug("Memory operations test passed"); } #endif diff --git a/Tests/RandomNumberGenerator.cpp b/Tests/RandomNumberGenerator.cpp index 72372b0..0f6eb13 100644 --- a/Tests/RandomNumberGenerator.cpp +++ b/Tests/RandomNumberGenerator.cpp @@ -23,46 +23,46 @@ __constructor void TestRandom() { - int RDRANDFlag = 0; - if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) - { - CPU::x86::AMD::CPUID0x00000001 cpuid; - cpuid.Get(); - RDRANDFlag = cpuid.ECX.RDRAND; - } - else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) - { - CPU::x86::Intel::CPUID0x00000001 cpuid; - cpuid.Get(); - RDRANDFlag = cpuid.ECX.RDRAND; - } + int RDRANDFlag = 0; + if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) + { + CPU::x86::AMD::CPUID0x00000001 cpuid; + cpuid.Get(); + RDRANDFlag = cpuid.ECX.RDRAND; + } + else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) + { + CPU::x86::Intel::CPUID0x00000001 cpuid; + cpuid.Get(); + RDRANDFlag = cpuid.ECX.RDRAND; + } - if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0) - RDRANDFlag = 0; + if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0) + RDRANDFlag = 0; #if defined(a86) - if (RDRANDFlag) - { - uintptr_t RDSEEDValue = 0; - asmv("1: rdseed %0; jnc 1b" - : "=r"(RDSEEDValue)); - debug("RDSEED: %ld", RDSEEDValue); - } + if (RDRANDFlag) + { + uintptr_t RDSEEDValue = 0; + asmv("1: rdseed %0; jnc 1b" + : "=r"(RDSEEDValue)); + debug("RDSEED: %ld", RDSEEDValue); + } #endif - Random::ChangeSeed(0xdeadbeef); - uint16_t Seeds16[16]; - uint32_t Seeds32[16]; - uint64_t Seeds64[16]; - for (short i = 0; i < 16; i++) - { - Seeds16[i] = Random::rand16(); - Seeds32[i] = Random::rand32(); - Seeds64[i] = Random::rand64(); - } - debug("Random 16: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld", Seeds16[0], Seeds16[1], Seeds16[2], Seeds16[3], Seeds16[4], Seeds16[5], Seeds16[6], Seeds16[7], Seeds16[8], Seeds16[9], Seeds16[10], Seeds16[11], Seeds16[12], Seeds16[13], Seeds16[14], Seeds16[15]); - debug("Random 32: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld", Seeds32[0], Seeds32[1], Seeds32[2], Seeds32[3], Seeds32[4], Seeds32[5], Seeds32[6], Seeds32[7], Seeds32[8], Seeds32[9], Seeds32[10], Seeds32[11], Seeds32[12], Seeds32[13], Seeds32[14], Seeds32[15]); - debug("Random 64: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld", Seeds64[0], Seeds64[1], Seeds64[2], Seeds64[3], Seeds64[4], Seeds64[5], Seeds64[6], Seeds64[7], Seeds64[8], Seeds64[9], Seeds64[10], Seeds64[11], Seeds64[12], Seeds64[13], Seeds64[14], Seeds64[15]); + Random::ChangeSeed(0xdeadbeef); + uint16_t Seeds16[16]; + uint32_t Seeds32[16]; + uint64_t Seeds64[16]; + for (short i = 0; i < 16; i++) + { + Seeds16[i] = Random::rand16(); + Seeds32[i] = Random::rand32(); + Seeds64[i] = Random::rand64(); + } + debug("Random 16: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld", Seeds16[0], Seeds16[1], Seeds16[2], Seeds16[3], Seeds16[4], Seeds16[5], Seeds16[6], Seeds16[7], Seeds16[8], Seeds16[9], Seeds16[10], Seeds16[11], Seeds16[12], Seeds16[13], Seeds16[14], Seeds16[15]); + debug("Random 32: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld", Seeds32[0], Seeds32[1], Seeds32[2], Seeds32[3], Seeds32[4], Seeds32[5], Seeds32[6], Seeds32[7], Seeds32[8], Seeds32[9], Seeds32[10], Seeds32[11], Seeds32[12], Seeds32[13], Seeds32[14], Seeds32[15]); + debug("Random 64: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld", Seeds64[0], Seeds64[1], Seeds64[2], Seeds64[3], Seeds64[4], Seeds64[5], Seeds64[6], Seeds64[7], Seeds64[8], Seeds64[9], Seeds64[10], Seeds64[11], Seeds64[12], Seeds64[13], Seeds64[14], Seeds64[15]); } #endif // DEBUG diff --git a/Tests/String.cpp b/Tests/String.cpp index 6f646e9..ac8560e 100644 --- a/Tests/String.cpp +++ b/Tests/String.cpp @@ -18,102 +18,136 @@ #ifdef DEBUG #include +#include #include void TestString() { - std::string hw("Hello, world!"); - debug("String length: %d", hw.length()); - debug("String capacity: %d", hw.capacity()); - debug("String data: %s", hw.c_str()); - if (hw == "Hello, world!" && hw != "World, hello!") - debug("String comparison works!"); - else - { - error("String comparison doesn't work! \"%s\"", hw.c_str()); - inf_loop; - } + char *sanity_alloc = (char *)kmalloc(1024); + for (int i = 0; i < 1024; i++) + sanity_alloc[i] = 'A'; + std::string hw("Hello, world!"); - std::string hi("Hi"); - char chi[3]; - chi[0] = hi[0]; - chi[1] = hi[1]; - chi[2] = '\0'; - if (strcmp(chi, "Hi") == 0) - debug("String indexing works!"); - else - { - error("String indexing doesn't work! \"%s\" \"%s\"", chi, hi.c_str()); - inf_loop; - } + for (int i = 0; i < 1024; i++) + if (sanity_alloc[i] != 'A') + { + error("Sanity check failed! %d", i); + inf_loop; + } - hi << " there!"; - if (hi == "Hi there!") - debug("String concatenation works!"); - else - { - error("String concatenation doesn't work! \"%s\"", hi.c_str()); - inf_loop; - } + debug("String length: %d", hw.length()); + debug("String capacity: %d", hw.capacity()); + debug("String data: %s", hw.c_str()); + if (hw == "Hello, world!" && hw != "World, hello!") + debug("String comparison works!"); + else + { + error("String comparison doesn't work! \"%s\"", hw.c_str()); + inf_loop; + } - hi << " " << hw; - if (hi == "Hi there! Hello, world!") - debug("String concatenation works!"); - else - { - error("String concatenation doesn't work! \"%s\"", hi.c_str()); - inf_loop; - } + for (int i = 0; i < 1024; i++) + if (sanity_alloc[i] != 'A') + { + error("Sanity check failed! %d", i); + inf_loop; + } - std::string eq0("Hello, world!"); - std::string eq1("Hello, world!"); - std::string eq2("World, hello!"); + kfree(sanity_alloc); - if (eq0 == eq1) - debug("String equality works!"); - else - { - error("String equality doesn't work! \"%s\" \"%s\"", eq0.c_str(), eq1.c_str()); - inf_loop; - } + std::string hi("Hi"); + char chi[3]; + chi[0] = hi[0]; + chi[1] = hi[1]; + chi[2] = '\0'; + if (strcmp(chi, "Hi") == 0) + debug("String indexing works!"); + else + { + error("String indexing doesn't work! \"%s\" \"%s\"", chi, hi.c_str()); + inf_loop; + } - if (eq0 != eq2) - debug("String inequality works!"); - else - { - error("String inequality doesn't work! \"%s\" \"%s\"", eq0.c_str(), eq2.c_str()); - inf_loop; - } + sanity_alloc = (char *)kmalloc(1024); + for (int i = 0; i < 1024; i++) + sanity_alloc[i] = 'A'; - char chw[14]; - int i = 0; - foreach (auto c in hw) - { - chw[i] = c; - i++; - } - chw[i] = '\0'; + hi << " there!"; + if (hi == "Hi there!") + debug("String concatenation works!"); + else + { + error("String concatenation doesn't work! \"%s\"", hi.c_str()); + inf_loop; + } - if (strcmp(chw, "Hello, world!") == 0) - debug("String iteration works!"); - else - { - error("String iteration doesn't work! \"%s\" \"%s\" %d", chw, hw.c_str(), i); - inf_loop; - } + hi << " " << hw; + if (hi == "Hi there! Hello, world!") + debug("String concatenation works!"); + else + { + error("String concatenation doesn't work! \"%s\"", hi.c_str()); + inf_loop; + } - std::string a("Hello"); - std::string b("World"); - std::string c; - c = a + ", " + b + "!"; + std::string eq0("Hello, world!"); + std::string eq1("Hello, world!"); + std::string eq2("World, hello!"); - if (c == "Hello, World!") - debug("String addition works!"); - else - { - error("String addition doesn't work! \"%s\"", c.c_str()); - inf_loop; - } + if (eq0 == eq1) + debug("String equality works!"); + else + { + error("String equality doesn't work! \"%s\" \"%s\"", eq0.c_str(), eq1.c_str()); + inf_loop; + } + + if (eq0 != eq2) + debug("String inequality works!"); + else + { + error("String inequality doesn't work! \"%s\" \"%s\"", eq0.c_str(), eq2.c_str()); + inf_loop; + } + + char chw[14]; + int i = 0; + foreach (auto c in hw) + { + chw[i] = c; + i++; + } + chw[i] = '\0'; + + if (strcmp(chw, "Hello, world!") == 0) + debug("String iteration works!"); + else + { + error("String iteration doesn't work! \"%s\" \"%s\" %d", chw, hw.c_str(), i); + inf_loop; + } + + std::string a("Hello"); + std::string b("World"); + std::string c; + c = a + ", " + b + "!"; + + if (c == "Hello, World!") + debug("String addition works!"); + else + { + error("String addition doesn't work! \"%s\"", c.c_str()); + inf_loop; + } + + for (int i = 0; i < 1024; i++) + if (sanity_alloc[i] != 'A') + { + error("Sanity check failed! %d", i); + inf_loop; + } + + kfree(sanity_alloc); } #endif // DEBUG diff --git a/Tests/TypeSize.cpp b/Tests/TypeSize.cpp index ab24ba3..63a81b2 100644 --- a/Tests/TypeSize.cpp +++ b/Tests/TypeSize.cpp @@ -21,103 +21,103 @@ __constructor void TestTypeSize() { - debug("--- INT TYPES ---"); - debug("sizeof(__INT8_TYPE__) = %lld", sizeof(__INT8_TYPE__)); - debug("sizeof(__INT16_TYPE__) = %lld", sizeof(__INT16_TYPE__)); - debug("sizeof(__INT32_TYPE__) = %lld", sizeof(__INT32_TYPE__)); - debug("sizeof(__INT64_TYPE__) = %lld", sizeof(__INT64_TYPE__)); + debug("--- INT TYPES ---"); + debug("sizeof(__INT8_TYPE__) = %lld", sizeof(__INT8_TYPE__)); + debug("sizeof(__INT16_TYPE__) = %lld", sizeof(__INT16_TYPE__)); + debug("sizeof(__INT32_TYPE__) = %lld", sizeof(__INT32_TYPE__)); + debug("sizeof(__INT64_TYPE__) = %lld", sizeof(__INT64_TYPE__)); - debug("-- UINT TYPES ---"); - debug("sizeof(__UINT8_TYPE__) = %lld", sizeof(__INT8_TYPE__)); - debug("sizeof(__UINT16_TYPE__) = %lld", sizeof(__INT16_TYPE__)); - debug("sizeof(__UINT32_TYPE__) = %lld", sizeof(__INT32_TYPE__)); - debug("sizeof(__UINT64_TYPE__) = %lld", sizeof(__INT64_TYPE__)); + debug("-- UINT TYPES ---"); + debug("sizeof(__UINT8_TYPE__) = %lld", sizeof(__INT8_TYPE__)); + debug("sizeof(__UINT16_TYPE__) = %lld", sizeof(__INT16_TYPE__)); + debug("sizeof(__UINT32_TYPE__) = %lld", sizeof(__INT32_TYPE__)); + debug("sizeof(__UINT64_TYPE__) = %lld", sizeof(__INT64_TYPE__)); - debug("--- INT LEAST TYPES ---"); - debug("sizeof(__INT_LEAST8_TYPE__) = %lld", sizeof(__INT_LEAST8_TYPE__)); - debug("sizeof(__INT_LEAST16_TYPE__) = %lld", sizeof(__INT_LEAST16_TYPE__)); - debug("sizeof(__INT_LEAST32_TYPE__) = %lld", sizeof(__INT_LEAST32_TYPE__)); - debug("sizeof(__INT_LEAST64_TYPE__) = %lld", sizeof(__INT_LEAST64_TYPE__)); + debug("--- INT LEAST TYPES ---"); + debug("sizeof(__INT_LEAST8_TYPE__) = %lld", sizeof(__INT_LEAST8_TYPE__)); + debug("sizeof(__INT_LEAST16_TYPE__) = %lld", sizeof(__INT_LEAST16_TYPE__)); + debug("sizeof(__INT_LEAST32_TYPE__) = %lld", sizeof(__INT_LEAST32_TYPE__)); + debug("sizeof(__INT_LEAST64_TYPE__) = %lld", sizeof(__INT_LEAST64_TYPE__)); - debug("--- UINT LEAST TYPES ---"); - debug("sizeof(__UINT_LEAST8_TYPE__) = %lld", sizeof(__UINT_LEAST8_TYPE__)); - debug("sizeof(__UINT_LEAST16_TYPE__) = %lld", sizeof(__UINT_LEAST16_TYPE__)); - debug("sizeof(__UINT_LEAST32_TYPE__) = %lld", sizeof(__UINT_LEAST32_TYPE__)); - debug("sizeof(__UINT_LEAST64_TYPE__) = %lld", sizeof(__UINT_LEAST64_TYPE__)); + debug("--- UINT LEAST TYPES ---"); + debug("sizeof(__UINT_LEAST8_TYPE__) = %lld", sizeof(__UINT_LEAST8_TYPE__)); + debug("sizeof(__UINT_LEAST16_TYPE__) = %lld", sizeof(__UINT_LEAST16_TYPE__)); + debug("sizeof(__UINT_LEAST32_TYPE__) = %lld", sizeof(__UINT_LEAST32_TYPE__)); + debug("sizeof(__UINT_LEAST64_TYPE__) = %lld", sizeof(__UINT_LEAST64_TYPE__)); - debug("--- INT FAST TYPES ---"); - debug("sizeof(__INT_FAST8_TYPE__) = %lld", sizeof(__INT_FAST8_TYPE__)); - debug("sizeof(__INT_FAST16_TYPE__) = %lld", sizeof(__INT_FAST16_TYPE__)); - debug("sizeof(__INT_FAST32_TYPE__) = %lld", sizeof(__INT_FAST32_TYPE__)); - debug("sizeof(__INT_FAST64_TYPE__) = %lld", sizeof(__INT_FAST64_TYPE__)); + debug("--- INT FAST TYPES ---"); + debug("sizeof(__INT_FAST8_TYPE__) = %lld", sizeof(__INT_FAST8_TYPE__)); + debug("sizeof(__INT_FAST16_TYPE__) = %lld", sizeof(__INT_FAST16_TYPE__)); + debug("sizeof(__INT_FAST32_TYPE__) = %lld", sizeof(__INT_FAST32_TYPE__)); + debug("sizeof(__INT_FAST64_TYPE__) = %lld", sizeof(__INT_FAST64_TYPE__)); - debug("--- UINT FAST TYPES ---"); - debug("sizeof(__UINT_FAST8_TYPE__) = %lld", sizeof(__UINT_FAST8_TYPE__)); - debug("sizeof(__UINT_FAST16_TYPE__) = %lld", sizeof(__UINT_FAST16_TYPE__)); - debug("sizeof(__UINT_FAST32_TYPE__) = %lld", sizeof(__UINT_FAST32_TYPE__)); - debug("sizeof(__UINT_FAST64_TYPE__) = %lld", sizeof(__UINT_FAST64_TYPE__)); + debug("--- UINT FAST TYPES ---"); + debug("sizeof(__UINT_FAST8_TYPE__) = %lld", sizeof(__UINT_FAST8_TYPE__)); + debug("sizeof(__UINT_FAST16_TYPE__) = %lld", sizeof(__UINT_FAST16_TYPE__)); + debug("sizeof(__UINT_FAST32_TYPE__) = %lld", sizeof(__UINT_FAST32_TYPE__)); + debug("sizeof(__UINT_FAST64_TYPE__) = %lld", sizeof(__UINT_FAST64_TYPE__)); - debug("--- INTPTR TYPES ---"); - debug("sizeof(__INTPTR_TYPE__) = %lld", sizeof(__INTPTR_TYPE__)); - debug("sizeof(__UINTPTR_TYPE__) = %lld", sizeof(__UINTPTR_TYPE__)); + debug("--- INTPTR TYPES ---"); + debug("sizeof(__INTPTR_TYPE__) = %lld", sizeof(__INTPTR_TYPE__)); + debug("sizeof(__UINTPTR_TYPE__) = %lld", sizeof(__UINTPTR_TYPE__)); - debug("--- OTHER TYPES ---"); - debug("sizeof(__PTRDIFF_TYPE__) = %lld", sizeof(__PTRDIFF_TYPE__)); - debug("sizeof(__SIZE_TYPE__) = %lld", sizeof(__SIZE_TYPE__)); - debug("sizeof(__WCHAR_TYPE__) = %lld", sizeof(__WCHAR_TYPE__)); - debug("sizeof(__WINT_TYPE__) = %lld", sizeof(__WINT_TYPE__)); - debug("sizeof(__SIG_ATOMIC_TYPE__) = %lld", sizeof(__SIG_ATOMIC_TYPE__)); + debug("--- OTHER TYPES ---"); + debug("sizeof(__PTRDIFF_TYPE__) = %lld", sizeof(__PTRDIFF_TYPE__)); + debug("sizeof(__SIZE_TYPE__) = %lld", sizeof(__SIZE_TYPE__)); + debug("sizeof(__WCHAR_TYPE__) = %lld", sizeof(__WCHAR_TYPE__)); + debug("sizeof(__WINT_TYPE__) = %lld", sizeof(__WINT_TYPE__)); + debug("sizeof(__SIG_ATOMIC_TYPE__) = %lld", sizeof(__SIG_ATOMIC_TYPE__)); - debug("--- INTX MAX TYPES ---"); - debug("__INT8_MAX__ = %#llx", __INT8_MAX__); - debug("__INT16_MAX__ = %#llx", __INT16_MAX__); - debug("__INT32_MAX__ = %#llx", __INT32_MAX__); - debug("__INT64_MAX__ = %#llx", __INT64_MAX__); + debug("--- INTX MAX TYPES ---"); + debug("__INT8_MAX__ = %#llx", __INT8_MAX__); + debug("__INT16_MAX__ = %#llx", __INT16_MAX__); + debug("__INT32_MAX__ = %#llx", __INT32_MAX__); + debug("__INT64_MAX__ = %#llx", __INT64_MAX__); - debug("--- UINTX MAX TYPES ---"); - debug("__UINT8_MAX__ = %#llx", __UINT8_MAX__); - debug("__UINT16_MAX__ = %#llx", __UINT16_MAX__); - debug("__UINT32_MAX__ = %#llx", __UINT32_MAX__); - debug("__UINT64_MAX__ = %#llx", __UINT64_MAX__); + debug("--- UINTX MAX TYPES ---"); + debug("__UINT8_MAX__ = %#llx", __UINT8_MAX__); + debug("__UINT16_MAX__ = %#llx", __UINT16_MAX__); + debug("__UINT32_MAX__ = %#llx", __UINT32_MAX__); + debug("__UINT64_MAX__ = %#llx", __UINT64_MAX__); - // debug("--- INTMAX TYPES ---"); - // debug("__INTMAX_TYPE__ = %#llx", __INTMAX_TYPE__); - // debug("__UINTMAX_TYPE__ = %#llx", __UINTMAX_TYPE__); + // debug("--- INTMAX TYPES ---"); + // debug("__INTMAX_TYPE__ = %#llx", __INTMAX_TYPE__); + // debug("__UINTMAX_TYPE__ = %#llx", __UINTMAX_TYPE__); - debug("--- INTLEASTX MAX ---"); - debug("__INT_LEAST8_MAX__ = %#llx", __INT_LEAST8_MAX__); - debug("__INT_LEAST16_MAX__ = %#llx", __INT_LEAST16_MAX__); - debug("__INT_LEAST32_MAX__ = %#llx", __INT_LEAST32_MAX__); - debug("__INT_LEAST64_MAX__ = %#llx", __INT_LEAST64_MAX__); + debug("--- INTLEASTX MAX ---"); + debug("__INT_LEAST8_MAX__ = %#llx", __INT_LEAST8_MAX__); + debug("__INT_LEAST16_MAX__ = %#llx", __INT_LEAST16_MAX__); + debug("__INT_LEAST32_MAX__ = %#llx", __INT_LEAST32_MAX__); + debug("__INT_LEAST64_MAX__ = %#llx", __INT_LEAST64_MAX__); - debug("--- UINTLEASTX MAX ---"); - debug("__UINT_LEAST8_MAX__ = %#llx", __UINT_LEAST8_MAX__); - debug("__UINT_LEAST16_MAX__ = %#llx", __UINT_LEAST16_MAX__); + debug("--- UINTLEASTX MAX ---"); + debug("__UINT_LEAST8_MAX__ = %#llx", __UINT_LEAST8_MAX__); + debug("__UINT_LEAST16_MAX__ = %#llx", __UINT_LEAST16_MAX__); - debug("--- INTFASTX MAX ---"); - debug("__INT_FAST8_MAX__ = %#llx", __INT_FAST8_MAX__); - debug("__INT_FAST16_MAX__ = %#llx", __INT_FAST16_MAX__); - debug("__INT_FAST32_MAX__ = %#llx", __INT_FAST32_MAX__); - debug("__INT_FAST64_MAX__ = %#llx", __INT_FAST64_MAX__); + debug("--- INTFASTX MAX ---"); + debug("__INT_FAST8_MAX__ = %#llx", __INT_FAST8_MAX__); + debug("__INT_FAST16_MAX__ = %#llx", __INT_FAST16_MAX__); + debug("__INT_FAST32_MAX__ = %#llx", __INT_FAST32_MAX__); + debug("__INT_FAST64_MAX__ = %#llx", __INT_FAST64_MAX__); - debug("--- UINTFASTX MAX ---"); - debug("__UINT_FAST8_MAX__ = %#llx", __UINT_FAST8_MAX__); - debug("__UINT_FAST16_MAX__ = %#llx", __UINT_FAST16_MAX__); - debug("__UINT_FAST32_MAX__ = %#llx", __UINT_FAST32_MAX__); - debug("__UINT_FAST64_MAX__ = %#llx", __UINT_FAST64_MAX__); + debug("--- UINTFASTX MAX ---"); + debug("__UINT_FAST8_MAX__ = %#llx", __UINT_FAST8_MAX__); + debug("__UINT_FAST16_MAX__ = %#llx", __UINT_FAST16_MAX__); + debug("__UINT_FAST32_MAX__ = %#llx", __UINT_FAST32_MAX__); + debug("__UINT_FAST64_MAX__ = %#llx", __UINT_FAST64_MAX__); - debug("--- INTPTR MAX ---"); - debug("__INTPTR_MAX__ = %#llx", __INTPTR_MAX__); - debug("__UINTPTR_MAX__ = %#llx", __UINTPTR_MAX__); + debug("--- INTPTR MAX ---"); + debug("__INTPTR_MAX__ = %#llx", __INTPTR_MAX__); + debug("__UINTPTR_MAX__ = %#llx", __UINTPTR_MAX__); - debug("--- OTHER MAX ---"); - debug("__PTRDIFF_MAX__ = %#llx", __PTRDIFF_MAX__); - debug("__SIZE_MAX__ = %#llx", __SIZE_MAX__); - debug("__WCHAR_MAX__ = %#llx", __WCHAR_MAX__); - debug("__WINT_MAX__ = %#llx", __WINT_MAX__); - debug("__SIG_ATOMIC_MAX__ = %#llx", __SIG_ATOMIC_MAX__); - debug("__INTMAX_MAX__ = %#llx", __INTMAX_MAX__); - debug("__UINTMAX_MAX__ = %#llx", __UINTMAX_MAX__); + debug("--- OTHER MAX ---"); + debug("__PTRDIFF_MAX__ = %#llx", __PTRDIFF_MAX__); + debug("__SIZE_MAX__ = %#llx", __SIZE_MAX__); + debug("__WCHAR_MAX__ = %#llx", __WCHAR_MAX__); + debug("__WINT_MAX__ = %#llx", __WINT_MAX__); + debug("__SIG_ATOMIC_MAX__ = %#llx", __SIG_ATOMIC_MAX__); + debug("__INTMAX_MAX__ = %#llx", __INTMAX_MAX__); + debug("__UINTMAX_MAX__ = %#llx", __UINTMAX_MAX__); } #endif // DEBUG diff --git a/Tests/std.cpp b/Tests/std.cpp index 6b0c0e9..7ce2777 100644 --- a/Tests/std.cpp +++ b/Tests/std.cpp @@ -19,18 +19,51 @@ #include #include +#include -__constructor void Test_std() +void Test_std() { - std::atomic_int a = 0; - a++; - assert(a == 1); + std::atomic_int a = 0; + a++; + assert(a == 1); - int b = a.exchange(2); - assert(b == 1); - assert(a == 2); + int b = a.exchange(2); + assert(b == 1); + assert(a == 2); - debug("std: OK"); + /* ---------------------------- */ + + std::vector intVector; + intVector.push_back(10); + intVector.push_back(20); + intVector.push_back(30); + assert(intVector.size() == 3); + + assert(intVector[0] == 10); + assert(intVector[1] == 20); + assert(intVector[2] == 30); + + intVector.pop_back(); + assert(intVector.size() == 2); + + intVector.clear(); + assert(intVector.empty()); + + intVector.push_back(1); + intVector.push_back(1); + intVector.push_back(1); + intVector.push_back(1); + intVector.push_back(1); + + intVector.erase(intVector.end() - 1); + assert(intVector.size() == 4); + debug("0: %#lx", intVector[0]); + debug("1: %#lx", intVector[1]); + debug("2: %#lx", intVector[2]); + debug("3: %#lx", intVector[3]); + debug("4: %#lx", intVector[4]); + + debug("std: OK"); } #endif // DEBUG diff --git a/Tests/t.h b/Tests/t.h index e6f841c..9525b5c 100644 --- a/Tests/t.h +++ b/Tests/t.h @@ -22,8 +22,8 @@ #include void TestString(); +void Test_std(); void TestMemoryAllocation(); -EXTERNC void TestSyscalls(); #endif // DEBUG #endif // !__FENNIX_KERNEL_non_constructor_tests_H__ diff --git a/Virtualization/IsVirtualizedEnvironment.cpp b/Virtualization/IsVirtualizedEnvironment.cpp new file mode 100644 index 0000000..1371edc --- /dev/null +++ b/Virtualization/IsVirtualizedEnvironment.cpp @@ -0,0 +1,203 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include + +#include +#include + +#if defined(a64) +#include "../Architecture/amd64/acpi.hpp" +#elif defined(a32) +#include "../Architecture/i386/acpi.hpp" +#elif defined(aa64) +#endif + +#include "../kernel.h" + +bool DetectByHypervisor() +{ + const char *Hypervisor = CPU::Hypervisor(); + if (strcmp(Hypervisor, x86_CPUID_VENDOR_VMWARE) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_XENHVM) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_MICROSOFT_HV) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_MICROSOFT_XTA) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_PARALLELS) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_KVM) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_VIRTUALBOX) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_TCG) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_BHYVE) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_ACRN) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_QNX) == 0) + goto Yes; + else if (strcmp(Hypervisor, x86_CPUID_VENDOR_APPLE) == 0) + goto Yes; + return false; + +Yes: + debug("Hypervisor: %s", Hypervisor); + return true; +} + +bool IsVMwareBackdoorAvailable() +{ + struct + { + union + { + uint32_t ax; + uint32_t magic; + }; + union + { + uint32_t bx; + size_t size; + }; + union + { + uint32_t cx; + uint16_t command; + }; + union + { + uint32_t dx; + uint16_t port; + }; + uint32_t si; + uint32_t di; + } cmd{}; + +#define VMWARE_MAGIC 0x564D5868 /* hXMV */ +#define VMWARE_PORT 0x5658 +#define CMD_GETVERSION 0xA + + cmd.bx = ~VMWARE_MAGIC; + cmd.command = CMD_GETVERSION; + cmd.magic = VMWARE_MAGIC; + cmd.port = VMWARE_PORT; + + asmv("in %%dx, %0" + : "+a"(cmd.ax), + "+b"(cmd.bx), + "+c"(cmd.cx), + "+d"(cmd.dx), + "+S"(cmd.si), + "+D"(cmd.di)); + + if (cmd.bx != VMWARE_MAGIC || cmd.ax == 0xFFFFFFFF) + return false; + + debug("VMware backdoor version: %d.%d.%d", + cmd.ax >> 16, + (cmd.ax >> 8) & 0xFF, + cmd.ax & 0xFF); + + return true; +} + +bool DetectByCPUID() +{ + bool IsVM = false; + if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) + { + CPU::x86::Intel::CPUID0x00000001 cpuid00000001; + cpuid00000001.Get(); + + if (cpuid00000001.ECX.Hypervisor == 1) + { + debug("Intel: Hypervisor: %d", + cpuid00000001.ECX.Hypervisor); + IsVM = true; + } + } + else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) + { + CPU::x86::AMD::CPUID0x00000001 cpuid00000001; + cpuid00000001.Get(); + + if (cpuid00000001.ECX.Hypervisor == 1) + { + debug("AMD: Hypervisor: %d", + cpuid00000001.ECX.Hypervisor); + IsVM = true; + } + } + return IsVM; +} + +bool DetectByHPET() +{ + void *acpi = PowerManager->GetACPI(); + if (!acpi) + return false; + + void *hpet = ((ACPI::ACPI *)acpi)->HPET; + if (!hpet) + return false; + + ACPI::ACPI::HPETHeader *HPET = (ACPI::ACPI::HPETHeader *)hpet; + + if (strstr((const char *)HPET->Header.OEMID, "BOCHS BXPC") != NULL) + goto Yes; + + if (strstr((const char *)HPET->Header.OEMID, "VBOX") != NULL) + goto Yes; + + if (strstr((const char *)HPET->Header.OEMID, "VMWAREVMW") != NULL) + goto Yes; + + return false; + +Yes: + debug("HPET: %s", HPET->Header.OEMID); + return true; +} + +bool IsVirtualizedEnvironment() +{ + bool IsVM = false; + + debug("Detecting virtualized environment..."); + + if (DetectByHypervisor()) + IsVM = true; + + if (IsVMwareBackdoorAvailable()) + IsVM = true; + + if (DetectByCPUID()) + IsVM = true; + + if (DetectByHPET()) + IsVM = true; + + /* TODO: Add more detection methods */ + + debug("Virtualized environment: %s", + IsVM ? "Yes" : "No"); + return IsVM; +} diff --git a/include/bitmap.hpp b/include/bitmap.hpp index 62249a9..d8f38b6 100644 --- a/include/bitmap.hpp +++ b/include/bitmap.hpp @@ -23,11 +23,12 @@ class Bitmap { public: - size_t Size; - uint8_t *Buffer; - bool operator[](uint64_t index); - bool Set(uint64_t index, bool value); - bool Get(uint64_t index); + size_t Size; + uint8_t *Buffer; + bool Set(uint64_t index, bool value); + bool Get(uint64_t index); + + bool operator[](uint64_t index); }; #endif // !__FENNIX_KERNEL_BITMAP_H__ diff --git a/include/cpu.hpp b/include/cpu.hpp index a56c174..fcea0ad 100644 --- a/include/cpu.hpp +++ b/include/cpu.hpp @@ -37,878 +37,888 @@ */ namespace CPU { - /** - * @brief Enum for CPU::Interrupts() function. - */ - enum InterruptsType - { - /** - * @brief Check if interrupts are enabled. - */ - Check, - /** - * @brief Enable interrupts. - */ - Enable, - /** - * @brief Disable interrupts. - */ - Disable - }; + /** + * @brief Enum for CPU::Interrupts() function. + */ + enum InterruptsType + { + /** + * @brief Check if interrupts are enabled. + */ + Check, + /** + * @brief Enable interrupts. + */ + Enable, + /** + * @brief Disable interrupts. + */ + Disable + }; - enum x86SIMDType - { - SIMD_NONE = (1 << 0), + enum x86SIMDType + { + SIMD_NONE = (1 << 0), - SIMD_SSE = (1 << 1), - SIMD_SSE2 = (1 << 2), - SIMD_SSE3 = (1 << 3), - SIMD_SSSE3 = (1 << 4), - SIMD_SSE41 = (1 << 5), - SIMD_SSE42 = (1 << 6), + SIMD_SSE = (1 << 1), + SIMD_SSE2 = (1 << 2), + SIMD_SSE3 = (1 << 3), + SIMD_SSSE3 = (1 << 4), + SIMD_SSE41 = (1 << 5), + SIMD_SSE42 = (1 << 6), - SIMD_AVX = (1 << 7), - SIMD_AVX2 = (1 << 8), - SIMD_AVX512 = (1 << 9), + SIMD_AVX = (1 << 7), + SIMD_AVX2 = (1 << 8), + SIMD_AVX512 = (1 << 9), - SIMD_AVX512F = (1 << 10), - SIMD_AVX512CD = (1 << 11), - SIMD_AVX512ER = (1 << 12), - SIMD_AVX512PF = (1 << 13), + SIMD_AVX512F = (1 << 10), + SIMD_AVX512CD = (1 << 11), + SIMD_AVX512ER = (1 << 12), + SIMD_AVX512PF = (1 << 13), - SIMD_AVX512VL = (1 << 14), - SIMD_AVX512DQ = (1 << 16), - SIMD_AVX512BW = (1 << 15), + SIMD_AVX512VL = (1 << 14), + SIMD_AVX512DQ = (1 << 16), + SIMD_AVX512BW = (1 << 15), - SIMD_AVX512IFMA = (1 << 17), - SIMD_AVX512VBMI = (1 << 18), + SIMD_AVX512IFMA = (1 << 17), + SIMD_AVX512VBMI = (1 << 18), - SIMD_AVX5124VNNIW = (1 << 19), - SIMD_AVX5124FMAPS = (1 << 20), + SIMD_AVX5124VNNIW = (1 << 19), + SIMD_AVX5124FMAPS = (1 << 20), - SIMD_AVX512VPOPCNTDQ = (1 << 21), + SIMD_AVX512VPOPCNTDQ = (1 << 21), - SIMD_AVX512VNNI = (1 << 22), - SIMD_AVX512VBMI2 = (1 << 23), - SIMD_AVX512BITALG = (1 << 24), + SIMD_AVX512VNNI = (1 << 22), + SIMD_AVX512VBMI2 = (1 << 23), + SIMD_AVX512BITALG = (1 << 24), - SIMD_AVX512VP2INTERSECT = (1 << 25), + SIMD_AVX512VP2INTERSECT = (1 << 25), - SIMD_AVX512GFNI = (1 << 26), - SIMD_AVX512VPCLMULQDQ = (1 << 27), - SIMD_AVX512VAES = (1 << 28), - }; + SIMD_AVX512GFNI = (1 << 26), + SIMD_AVX512VPCLMULQDQ = (1 << 27), + SIMD_AVX512VAES = (1 << 28), + }; - /** - * @brief Get CPU vendor identifier. - * - * @return char* CPU Vendor ID. - */ - char *Vendor(); + /** + * @brief Get CPU vendor identifier. + * + * @return CPU Vendor ID. + */ + const char *Vendor(); - /** - * @brief Get CPU name. - * - * @return char* CPU Name. - */ - char *Name(); + /** + * @brief Get CPU name. + * + * @return CPU Name. + */ + const char *Name(); - /** - * @brief Get CPU hypervisor vendor. - * - * @return char* Hypervisor vendor. - */ - char *Hypervisor(); + /** + * @brief Get CPU hypervisor vendor. + * + * @return Hypervisor vendor. + */ + const char *Hypervisor(); - /** - * @brief Check SIMD support. It will return the highest supported SIMD type. - * - * @return x86SIMDType flags. - */ - uint64_t CheckSIMD(); + /** + * @brief Check SIMD support. It will return the highest supported SIMD type. + * + * @return x86SIMDType flags. + */ + uint64_t CheckSIMD(); - /** - * @brief Check SIMD support. - * - * @param Type SIMD type. - * @return true if supported. - * @return false if not supported. - */ - bool CheckSIMD(x86SIMDType Type); + /** + * @brief Check SIMD support. + * + * @param Type SIMD type. + * @return true if supported. + * @return false if not supported. + */ + bool CheckSIMD(x86SIMDType Type); - /** - * @brief Pause the CPU - */ - SafeFunction static inline void Pause(bool Loop = false) - { - do - { + /** + * @brief Pause the CPU + */ + SafeFunction static inline void Pause(bool Loop = false) + { + do + { #if defined(a86) - asmv("pause"); + asmv("pause"); #elif defined(aa64) - asmv("yield"); + asmv("yield"); #endif - } while (Loop); - } + } while (Loop); + } - /** - * @brief Stop the CPU (infinite loop) - */ + /** + * @brief Stop the CPU (infinite loop) + */ #if defined(a86) - SafeFunction __noreturn __naked __used inline void Stop() - { - asmv("CPUStopLoop:\n" - "cli\n" - "hlt\n" - "jmp CPUStopLoop"); + SafeFunction __noreturn __naked __used inline void Stop() + { + asmv("CPUStopLoop:\n" + "cli\n" + "hlt\n" + "jmp CPUStopLoop"); #elif defined(aa64) // annoying warning: "‘noreturn’ function does return" and "‘naked’ attribute directive ignored" - SafeFunction __used inline void Stop() - { - asmv("CPUStopLoop:\n" - "msr daifset, #2\n" // Disable IRQs (bit 1 of the DAIF register) - "wfi\n" // Wait for Interrupt (puts the processor in low-power state until an interrupt occurs) - "b CPUStopLoop"); // Branch to the beginning of the loop + SafeFunction __used inline void Stop() + { + asmv("CPUStopLoop:\n" + "msr daifset, #2\n" // Disable IRQs (bit 1 of the DAIF register) + "wfi\n" // Wait for Interrupt (puts the processor in low-power state until an interrupt occurs) + "b CPUStopLoop"); // Branch to the beginning of the loop #endif - } + } - /** - * @brief Halt the CPU - */ - SafeFunction static inline void Halt(bool Loop = false) - { - do - { + /** + * @brief Halt the CPU + */ + SafeFunction static inline void Halt(bool Loop = false) + { + do + { #if defined(a86) - asmv("hlt"); + asmv("hlt"); #elif defined(aa64) - asmv("wfe"); + asmv("wfe"); #endif - } while (Loop); - } + } while (Loop); + } - /** - * @brief Check if interrupts are enabled - * - * @return true If InterruptsType::Check and interrupts are enabled, or if other InterruptsType were executed successfully - * @return false If InterruptsType::Check and interrupts are disabled, or if other InterruptsType failed - */ - bool Interrupts(InterruptsType Type = Check); + /** + * @brief Check if interrupts are enabled + * + * @return true If InterruptsType::Check and interrupts are enabled, or if other InterruptsType were executed successfully + * @return false If InterruptsType::Check and interrupts are disabled, or if other InterruptsType failed + */ + bool Interrupts(InterruptsType Type = Check); - /** - * @brief Get/Set the CPU's page table - * - * @param PT The new page table, if empty, the current page table will be returned - * @return void* The current page table - */ - void *PageTable(void *PT = nullptr); + /** + * @brief Get/Set the CPU's page table + * + * @param PT The new page table, if empty, the current page table will be returned + * @return void* The current page table + */ + void *PageTable(void *PT = nullptr); - /** @brief To be used only once. */ - void InitializeFeatures(long Core); + /** @brief To be used only once. */ + void InitializeFeatures(long Core); - /** @brief Get CPU counter value. */ - uintptr_t Counter(); + /** @brief Get CPU counter value. */ + uintptr_t Counter(); - namespace x32 - { - typedef union - { - struct - { - /** @brief Carry Flag */ - uint32_t CF : 1; - /** @brief Reserved */ - uint32_t AlwaysOne : 1; - /** @brief Parity Flag */ - uint32_t PF : 1; - /** @brief Reserved */ - uint32_t Reserved0 : 1; - /** @brief Auxiliary Carry Flag */ - uint32_t AF : 1; - /** @brief Reserved */ - uint32_t Reserved1 : 1; - /** @brief Zero Flag */ - uint32_t ZF : 1; - /** @brief Sign Flag */ - uint32_t SF : 1; - /** @brief Trap Flag */ - uint32_t TF : 1; - /** @brief Interrupt Enable Flag */ - uint32_t IF : 1; - /** @brief Direction Flag */ - uint32_t DF : 1; - /** @brief Overflow Flag */ - uint32_t OF : 1; - /** @brief I/O Privilege Level */ - uint32_t IOPL : 2; - /** @brief Nested Task */ - uint32_t NT : 1; - /** @brief Reserved */ - uint32_t Reserved2 : 1; - /** @brief Resume Flag */ - uint32_t RF : 1; - /** @brief Virtual 8086 Mode */ - uint32_t VM : 1; - /** @brief Alignment Check */ - uint32_t AC : 1; - /** @brief Virtual Interrupt Flag */ - uint32_t VIF : 1; - /** @brief Virtual Interrupt Pending */ - uint32_t VIP : 1; - /** @brief ID Flag */ - uint32_t ID : 1; - }; - uint32_t raw; - } EFLAGS; + namespace x32 + { + typedef union + { + struct + { + /** @brief Carry Flag */ + uint32_t CF : 1; + /** @brief Reserved */ + uint32_t AlwaysOne : 1; + /** @brief Parity Flag */ + uint32_t PF : 1; + /** @brief Reserved */ + uint32_t Reserved0 : 1; + /** @brief Auxiliary Carry Flag */ + uint32_t AF : 1; + /** @brief Reserved */ + uint32_t Reserved1 : 1; + /** @brief Zero Flag */ + uint32_t ZF : 1; + /** @brief Sign Flag */ + uint32_t SF : 1; + /** @brief Trap Flag */ + uint32_t TF : 1; + /** @brief Interrupt Enable Flag */ + uint32_t IF : 1; + /** @brief Direction Flag */ + uint32_t DF : 1; + /** @brief Overflow Flag */ + uint32_t OF : 1; + /** @brief I/O Privilege Level */ + uint32_t IOPL : 2; + /** @brief Nested Task */ + uint32_t NT : 1; + /** @brief Reserved */ + uint32_t Reserved2 : 1; + /** @brief Resume Flag */ + uint32_t RF : 1; + /** @brief Virtual 8086 Mode */ + uint32_t VM : 1; + /** @brief Alignment Check */ + uint32_t AC : 1; + /** @brief Virtual Interrupt Flag */ + uint32_t VIF : 1; + /** @brief Virtual Interrupt Pending */ + uint32_t VIP : 1; + /** @brief ID Flag */ + uint32_t ID : 1; + }; + uint32_t raw; + } EFLAGS; - typedef struct TrapFrame - { - // uint32_t ebp; // Base Pointer (meant for stack frames) - // uint32_t edi; // Destination index for string operations - // uint32_t esi; // Source index for string operations - // uint32_t edx; // Data (commonly extends the A register) - // uint32_t ecx; // Counter - // uint32_t ebx; // Base - // uint32_t eax; // Accumulator + typedef struct TrapFrame + { + // uint32_t ebp; // Base Pointer (meant for stack frames) + // uint32_t edi; // Destination index for string operations + // uint32_t esi; // Source index for string operations + // uint32_t edx; // Data (commonly extends the A register) + // uint32_t ecx; // Counter + // uint32_t ebx; // Base + // uint32_t eax; // Accumulator - uint32_t edi; // Destination index for string operations - uint32_t esi; // Source index for string operations - uint32_t ebp; // Base Pointer (meant for stack frames) - uint32_t esp; // Stack Pointer - uint32_t ebx; // Base - uint32_t edx; // Data (commonly extends the A register) - uint32_t ecx; // Counter - uint32_t eax; // Accumulator + uint32_t edi; // Destination index for string operations + uint32_t esi; // Source index for string operations + uint32_t ebp; // Base Pointer (meant for stack frames) + uint32_t esp; // Stack Pointer + uint32_t ebx; // Base + uint32_t edx; // Data (commonly extends the A register) + uint32_t ecx; // Counter + uint32_t eax; // Accumulator - uint32_t InterruptNumber; // Interrupt Number - uint32_t ErrorCode; // Error code + uint32_t InterruptNumber; // Interrupt Number + uint32_t ErrorCode; // Error code - uint32_t eip; // Instruction Pointer - uint32_t cs; // Code Segment - EFLAGS eflags; // Register Flags - // uint32_t esp; // Stack Pointer - uint32_t ss; // Stack Segment - } TrapFrame; + uint32_t eip; // Instruction Pointer + uint32_t cs; // Code Segment + EFLAGS eflags; // Register Flags + // uint32_t esp; // Stack Pointer + uint32_t ss; // Stack Segment + } TrapFrame; - typedef union DR6 - { - struct - { - /** @brief Breakpoint #0 Condition Detected */ - uint64_t B0 : 1; - /** @brief Breakpoint #1 Condition Detected */ - uint64_t B1 : 1; - /** @brief Breakpoint #2 Condition Detected */ - uint64_t B2 : 1; - /** @brief Breakpoint #3 Condition Detected */ - uint64_t B3 : 1; - /** @brief Reserved */ - uint64_t Reserved0 : 8; - /** @brief Reserved */ - uint64_t Reserved1 : 1; - /** @brief Breakpoint Debug Access Detected */ - uint64_t BD : 1; - /** @brief Breakpoint Single Step */ - uint64_t BS : 1; - /** @brief Breakpoint Task Switch */ - uint64_t BT : 1; - /** @brief Reserved */ - uint64_t Reserved2 : 15; - }; - uint64_t raw; - } DR6; + typedef union DR6 + { + struct + { + /** @brief Breakpoint #0 Condition Detected */ + uint64_t B0 : 1; + /** @brief Breakpoint #1 Condition Detected */ + uint64_t B1 : 1; + /** @brief Breakpoint #2 Condition Detected */ + uint64_t B2 : 1; + /** @brief Breakpoint #3 Condition Detected */ + uint64_t B3 : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 8; + /** @brief Reserved */ + uint64_t Reserved1 : 1; + /** @brief Breakpoint Debug Access Detected */ + uint64_t BD : 1; + /** @brief Breakpoint Single Step */ + uint64_t BS : 1; + /** @brief Breakpoint Task Switch */ + uint64_t BT : 1; + /** @brief Reserved */ + uint64_t Reserved2 : 15; + }; + uint64_t raw; + } DR6; - typedef union DR7 - { - struct - { - /** @brief Local Exact Breakpoint #0 Enabled */ - uint32_t L0 : 1; - /** @brief Global Exact Breakpoint #0 Enabled */ - uint32_t G0 : 1; - /** @brief Local Exact Breakpoint #1 Enabled */ - uint32_t L1 : 1; - /** @brief Global Exact Breakpoint #1 Enabled */ - uint32_t G1 : 1; - /** @brief Local Exact Breakpoint #2 Enabled */ - uint32_t L2 : 1; - /** @brief Global Exact Breakpoint #2 Enabled */ - uint32_t G2 : 1; - /** @brief Local Exact Breakpoint #3 Enabled */ - uint32_t L3 : 1; - /** @brief Global Exact Breakpoint #3 Enabled */ - uint32_t G3 : 1; - /** @brief Local Exact Breakpoint Enabled */ - uint32_t LE : 1; - /** @brief Global Exact Breakpoint Enabled */ - uint32_t GE : 1; - /** @brief Reserved */ - uint32_t Reserved0 : 1; - /** @brief Reserved */ - uint32_t Reserved1 : 2; - /** @brief General Detect Enabled */ - uint32_t GD : 1; - /** @brief Reserved */ - uint32_t Reserved2 : 2; - /** @brief Type of Transaction(s) to Trap */ - uint32_t RW0 : 2; - /** @brief Length of Breakpoint #0 */ - uint32_t LEN0 : 2; - /** @brief Type of Transaction(s) to Trap */ - uint32_t RW1 : 2; - /** @brief Length of Breakpoint #1 */ - uint32_t LEN1 : 2; - /** @brief Type of Transaction(s) to Trap */ - uint32_t RW2 : 2; - /** @brief Length of Breakpoint #2 */ - uint32_t LEN2 : 2; - /** @brief Type of Transaction(s) to Trap */ - uint32_t RW3 : 2; - /** @brief Length of Breakpoint #3 */ - uint32_t LEN3 : 2; - }; - uint32_t raw; - } DR7; + typedef union DR7 + { + struct + { + /** @brief Local Exact Breakpoint #0 Enabled */ + uint32_t L0 : 1; + /** @brief Global Exact Breakpoint #0 Enabled */ + uint32_t G0 : 1; + /** @brief Local Exact Breakpoint #1 Enabled */ + uint32_t L1 : 1; + /** @brief Global Exact Breakpoint #1 Enabled */ + uint32_t G1 : 1; + /** @brief Local Exact Breakpoint #2 Enabled */ + uint32_t L2 : 1; + /** @brief Global Exact Breakpoint #2 Enabled */ + uint32_t G2 : 1; + /** @brief Local Exact Breakpoint #3 Enabled */ + uint32_t L3 : 1; + /** @brief Global Exact Breakpoint #3 Enabled */ + uint32_t G3 : 1; + /** @brief Local Exact Breakpoint Enabled */ + uint32_t LE : 1; + /** @brief Global Exact Breakpoint Enabled */ + uint32_t GE : 1; + /** @brief Reserved */ + uint32_t Reserved0 : 1; + /** @brief Reserved */ + uint32_t Reserved1 : 2; + /** @brief General Detect Enabled */ + uint32_t GD : 1; + /** @brief Reserved */ + uint32_t Reserved2 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint32_t RW0 : 2; + /** @brief Length of Breakpoint #0 */ + uint32_t LEN0 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint32_t RW1 : 2; + /** @brief Length of Breakpoint #1 */ + uint32_t LEN1 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint32_t RW2 : 2; + /** @brief Length of Breakpoint #2 */ + uint32_t LEN2 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint32_t RW3 : 2; + /** @brief Length of Breakpoint #3 */ + uint32_t LEN3 : 2; + }; + uint32_t raw; + } DR7; - struct FXState - { - /** @brief FPU control word */ - uint16_t fcw; - /** @brief FPU status word */ - uint16_t fsw; - /** @brief FPU tag words */ - uint8_t ftw; - /** @brief Reserved (zero) */ - uint8_t Reserved; - /** @brief FPU opcode */ - uint16_t fop; - /** @brief PFU instruction pointer */ - uint64_t rip; - /** @brief FPU data pointer */ - uint64_t rdp; - /** @brief SSE control register */ - uint32_t mxcsr; - /** @brief SSE control register mask */ - uint32_t mxcsrmask; - /** @brief FPU registers (last 6 bytes reserved) */ - uint8_t st[8][16]; - /** @brief XMM registers */ - uint8_t xmm[16][16]; - } __packed; + struct FXState + { + /** @brief FPU control word */ + uint16_t fcw; + /** @brief FPU status word */ + uint16_t fsw; + /** @brief FPU tag words */ + uint8_t ftw; + /** @brief Reserved (zero) */ + uint8_t Reserved; + /** @brief FPU opcode */ + uint16_t fop; + /** @brief PFU instruction pointer */ + uint64_t rip; + /** @brief FPU data pointer */ + uint64_t rdp; + /** @brief SSE control register */ + uint32_t mxcsr; + /** @brief SSE control register mask */ + uint32_t mxcsrmask; + /** @brief FPU registers (last 6 bytes reserved) */ + uint8_t st[8][16]; + /** @brief XMM registers */ + uint8_t xmm[16][16]; + } __packed; - /** - * @brief CPUID - * - * @param Function Leaf - * @param eax EAX - * @param ebx EBX - * @param ecx ECX - * @param edx EDX - */ - static inline void cpuid(uint32_t Function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) - { + /** + * @brief CPUID + * + * @param Function Leaf + * @param eax EAX + * @param ebx EBX + * @param ecx ECX + * @param edx EDX + */ + static inline void cpuid(uint32_t Function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) + { #ifdef a32 - asmv("cpuid" - : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) - : "a"(Function)); + asmv("cpuid" + : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) + : "a"(Function)); #else - UNUSED(Function); - UNUSED(eax); - UNUSED(ebx); - UNUSED(ecx); - UNUSED(edx); + UNUSED(Function); + UNUSED(eax); + UNUSED(ebx); + UNUSED(ecx); + UNUSED(edx); #endif - } + } - SafeFunction static inline void lgdt(void *gdt) - { + SafeFunction static inline void lgdt(void *gdt) + { #ifdef a32 - asmv("lgdt (%0)" - : - : "r"(gdt)); -#endif - } - - SafeFunction static inline void lidt(void *idt) - { -#ifdef a32 - asmv("lidt (%0)" - : - : "r"(idt)); -#endif - } - - SafeFunction static inline void ltr(uint16_t Segment) - { -#ifdef a32 - asmv("ltr %0" - : - : "r"(Segment)); -#endif - } - - SafeFunction static inline void invlpg(void *Address) - { -#ifdef a32 - asmv("invlpg (%0)" - : - : "r"(Address) - : "memory"); + asmv("lgdt (%0)" + : + : "r"(gdt)); #else - UNUSED(Address); + UNUSED(gdt); #endif - } + } - SafeFunction static inline void fxsave(void *FXSaveArea) - { + SafeFunction static inline void lidt(void *idt) + { #ifdef a32 - if (!FXSaveArea) - return; - - asmv("fxsave (%0)" - : - : "r"(FXSaveArea) - : "memory"); + asmv("lidt (%0)" + : + : "r"(idt)); +#else + UNUSED(idt); #endif - } + } - SafeFunction static inline void fxrstor(void *FXRstorArea) - { + SafeFunction static inline void ltr(uint16_t Segment) + { #ifdef a32 - if (!FXRstorArea) - return; - - asmv("fxrstor (%0)" - : - : "r"(FXRstorArea) - : "memory"); + asmv("ltr %0" + : + : "r"(Segment)); +#else + UNUSED(Segment); #endif - } - } + } - namespace x64 - { - /** - * @brief MSR_APIC_BASE structure - * @see MSR_APIC_BASE - */ - typedef union - { - struct - { - /** @brief Reserved */ - uint32_t Reserved0 : 8; - /** - * @brief BSP Flag - * @details If the BSP flag is set to 1, the processor is the bootstrap processor. - */ - uint32_t BSP : 1; - /** @brief Reserved */ - uint32_t Reserved1 : 1; - /** @brief Enable x2APIC mode */ - uint32_t EXTD : 1; - /** @brief APIC Global Enable */ - uint32_t EN : 1; - /** @brief APIC Base Low Address */ - uint32_t ApicBaseLo : 20; - /** @brief APIC Base High Address */ - uint32_t ApicBaseHi : 32; - }; - uint64_t raw; - } __packed APIC_BASE; + SafeFunction static inline void invlpg(void *Address) + { +#ifdef a32 + asmv("invlpg (%0)" + : + : "r"(Address) + : "memory"); +#else + UNUSED(Address); +#endif + } - typedef union - { - struct - { - /** @brief Carry Flag */ - uint64_t CF : 1; - /** @brief Reserved */ - uint64_t AlwaysOne : 1; - /** @brief Parity Flag */ - uint64_t PF : 1; - /** @brief Reserved */ - uint64_t Reserved0 : 1; - /** @brief Auxiliary Carry Flag */ - uint64_t AF : 1; - /** @brief Reserved */ - uint64_t Reserved1 : 1; - /** @brief Zero Flag */ - uint64_t ZF : 1; - /** @brief Sign Flag */ - uint64_t SF : 1; - /** @brief Trap Flag */ - uint64_t TF : 1; - /** @brief Interrupt Enable Flag */ - uint64_t IF : 1; - /** @brief Direction Flag */ - uint64_t DF : 1; - /** @brief Overflow Flag */ - uint64_t OF : 1; - /** @brief I/O Privilege Level */ - uint64_t IOPL : 2; - /** @brief Nested Task */ - uint64_t NT : 1; - /** @brief Reserved */ - uint64_t Reserved2 : 1; - /** @brief Resume Flag */ - uint64_t RF : 1; - /** @brief Virtual 8086 Mode */ - uint64_t VM : 1; - /** @brief Alignment Check */ - uint64_t AC : 1; - /** @brief Virtual Interrupt Flag */ - uint64_t VIF : 1; - /** @brief Virtual Interrupt Pending */ - uint64_t VIP : 1; - /** @brief ID Flag (Allow using CPUID instruction) */ - uint64_t ID : 1; - /** @brief Reserved */ - uint64_t Reserved3 : 10; - }; - uint64_t raw; - } RFLAGS; + SafeFunction static inline void fxsave(void *FXSaveArea) + { +#ifdef a32 + if (!FXSaveArea) + return; - typedef struct TrapFrame - { - uint64_t r15; // General purpose - uint64_t r14; // General purpose - uint64_t r13; // General purpose - uint64_t r12; // General purpose - uint64_t r11; // General purpose - uint64_t r10; // General purpose - uint64_t r9; // General purpose - uint64_t r8; // General purpose + asmv("fxsave (%0)" + : + : "r"(FXSaveArea) + : "memory"); +#else + UNUSED(FXSaveArea); +#endif + } - uint64_t rbp; // Base Pointer (meant for stack frames) - uint64_t rdi; // Destination index for string operations - uint64_t rsi; // Source index for string operations - uint64_t rdx; // Data (commonly extends the A register) - uint64_t rcx; // Counter - uint64_t rbx; // Base - uint64_t rax; // Accumulator + SafeFunction static inline void fxrstor(void *FXRstorArea) + { +#ifdef a32 + if (!FXRstorArea) + return; - uint64_t InterruptNumber; // Interrupt Number - uint64_t ErrorCode; // Error code + asmv("fxrstor (%0)" + : + : "r"(FXRstorArea) + : "memory"); +#else + UNUSED(FXRstorArea); +#endif + } + } - uint64_t rip; // Instruction Pointer - uint64_t cs; // Code Segment - RFLAGS rflags; // Register Flags - uint64_t rsp; // Stack Pointer - uint64_t ss; // Stack Segment - } TrapFrame; + namespace x64 + { + /** + * @brief MSR_APIC_BASE structure + * @see MSR_APIC_BASE + */ + typedef union + { + struct + { + /** @brief Reserved */ + uint32_t Reserved0 : 8; + /** + * @brief BSP Flag + * @details If the BSP flag is set to 1, the processor is the bootstrap processor. + */ + uint32_t BSP : 1; + /** @brief Reserved */ + uint32_t Reserved1 : 1; + /** @brief Enable x2APIC mode */ + uint32_t EXTD : 1; + /** @brief APIC Global Enable */ + uint32_t EN : 1; + /** @brief APIC Base Low Address */ + uint32_t ApicBaseLo : 20; + /** @brief APIC Base High Address */ + uint32_t ApicBaseHi : 32; + }; + uint64_t raw; + } __packed APIC_BASE; - typedef union EFER - { - struct - { - /** @brief Enable syscall & sysret instructions in 64-bit mode. */ - uint64_t SCE : 1; - /** @brief Reserved */ - uint64_t Reserved0 : 7; - /** @brief Enable long mode. */ - uint64_t LME : 1; - /** @brief Reserved */ - uint64_t Reserved1 : 1; - /** @brief Indicates long. */ - uint64_t LMA : 1; - /** @brief Enable No-Execute Bit */ - uint64_t NXE : 1; - /** @brief Enable Secure Virtual Machine */ - uint64_t SVME : 1; - /** @brief Enable Long Mode Segment Limit */ - uint64_t LMSLE : 1; - /** @brief Enable Fast FXSAVE/FXRSTOR */ - uint64_t FFXSR : 1; - /** @brief Enable Translation Cache Extension */ - uint64_t TCE : 1; - /** @brief Reserved */ - uint64_t Reserved2 : 32; - }; - uint64_t raw; - } __packed EFER; + typedef union + { + struct + { + /** @brief Carry Flag */ + uint64_t CF : 1; + /** @brief Reserved */ + uint64_t AlwaysOne : 1; + /** @brief Parity Flag */ + uint64_t PF : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 1; + /** @brief Auxiliary Carry Flag */ + uint64_t AF : 1; + /** @brief Reserved */ + uint64_t Reserved1 : 1; + /** @brief Zero Flag */ + uint64_t ZF : 1; + /** @brief Sign Flag */ + uint64_t SF : 1; + /** @brief Trap Flag */ + uint64_t TF : 1; + /** @brief Interrupt Enable Flag */ + uint64_t IF : 1; + /** @brief Direction Flag */ + uint64_t DF : 1; + /** @brief Overflow Flag */ + uint64_t OF : 1; + /** @brief I/O Privilege Level */ + uint64_t IOPL : 2; + /** @brief Nested Task */ + uint64_t NT : 1; + /** @brief Reserved */ + uint64_t Reserved2 : 1; + /** @brief Resume Flag */ + uint64_t RF : 1; + /** @brief Virtual 8086 Mode */ + uint64_t VM : 1; + /** @brief Alignment Check */ + uint64_t AC : 1; + /** @brief Virtual Interrupt Flag */ + uint64_t VIF : 1; + /** @brief Virtual Interrupt Pending */ + uint64_t VIP : 1; + /** @brief ID Flag (Allow using CPUID instruction) */ + uint64_t ID : 1; + /** @brief Reserved */ + uint64_t Reserved3 : 10; + }; + uint64_t raw; + } RFLAGS; - typedef union DR6 - { - struct - { - /** @brief Breakpoint #0 Condition Detected */ - uint64_t B0 : 1; - /** @brief Breakpoint #1 Condition Detected */ - uint64_t B1 : 1; - /** @brief Breakpoint #2 Condition Detected */ - uint64_t B2 : 1; - /** @brief Breakpoint #3 Condition Detected */ - uint64_t B3 : 1; - /** @brief Reserved */ - uint64_t Reserved0 : 8; - /** @brief Reserved */ - uint64_t Reserved1 : 1; - /** @brief Breakpoint Debug Access Detected */ - uint64_t BD : 1; - /** @brief Breakpoint Single Step */ - uint64_t BS : 1; - /** @brief Breakpoint Task Switch */ - uint64_t BT : 1; - /** @brief Reserved */ - uint64_t Reserved2 : 15; - /** @brief Reserved */ - uint64_t Reserved3 : 32; - }; - uint64_t raw; - } DR6; + typedef struct TrapFrame + { + uint64_t r15; // General purpose + uint64_t r14; // General purpose + uint64_t r13; // General purpose + uint64_t r12; // General purpose + uint64_t r11; // General purpose + uint64_t r10; // General purpose + uint64_t r9; // General purpose + uint64_t r8; // General purpose - typedef union DR7 - { - struct - { - /** @brief Local Exact Breakpoint #0 Enabled */ - uint64_t L0 : 1; - /** @brief Global Exact Breakpoint #0 Enabled */ - uint64_t G0 : 1; - /** @brief Local Exact Breakpoint #1 Enabled */ - uint64_t L1 : 1; - /** @brief Global Exact Breakpoint #1 Enabled */ - uint64_t G1 : 1; - /** @brief Local Exact Breakpoint #2 Enabled */ - uint64_t L2 : 1; - /** @brief Global Exact Breakpoint #2 Enabled */ - uint64_t G2 : 1; - /** @brief Local Exact Breakpoint #3 Enabled */ - uint64_t L3 : 1; - /** @brief Global Exact Breakpoint #3 Enabled */ - uint64_t G3 : 1; - /** @brief Local Exact Breakpoint Enabled */ - uint64_t LE : 1; - /** @brief Global Exact Breakpoint Enabled */ - uint64_t GE : 1; - /** @brief Reserved */ - uint64_t Reserved0 : 1; - /** @brief Reserved */ - uint64_t Reserved1 : 2; - /** @brief General Detect Enabled */ - uint64_t GD : 1; - /** @brief Reserved */ - uint64_t Reserved2 : 2; - /** @brief Type of Transaction(s) to Trap */ - uint64_t RW0 : 2; - /** @brief Length of Breakpoint #0 */ - uint64_t LEN0 : 2; - /** @brief Type of Transaction(s) to Trap */ - uint64_t RW1 : 2; - /** @brief Length of Breakpoint #1 */ - uint64_t LEN1 : 2; - /** @brief Type of Transaction(s) to Trap */ - uint64_t RW2 : 2; - /** @brief Length of Breakpoint #2 */ - uint64_t LEN2 : 2; - /** @brief Type of Transaction(s) to Trap */ - uint64_t RW3 : 2; - /** @brief Length of Breakpoint #3 */ - uint64_t LEN3 : 2; - /** @brief Reserved */ - uint64_t Reserved3 : 32; - }; - uint64_t raw; - } DR7; + uint64_t rbp; // Base Pointer (meant for stack frames) + uint64_t rdi; // Destination index for string operations + uint64_t rsi; // Source index for string operations + uint64_t rdx; // Data (commonly extends the A register) + uint64_t rcx; // Counter + uint64_t rbx; // Base + uint64_t rax; // Accumulator - typedef union PageFaultErrorCode - { - struct - { - /** @brief When set, the page fault was caused by a page-protection violation. When not set, it was caused by a non-present page. */ - uint64_t P : 1; - /** @brief When set, the page fault was caused by a write access. When not set, it was caused by a read access. */ - uint64_t W : 1; - /** @brief When set, the page fault was caused while CPL = 3. This does not necessarily mean that the page fault was a privilege violation. */ - uint64_t U : 1; - /** @brief When set, one or more page directory entries contain reserved bits which are set to 1. This only applies when the PSE or PAE flags in CR4 are set to 1. */ - uint64_t R : 1; - /** @brief When set, the page fault was caused by an instruction fetch. This only applies when the No-Execute bit is supported and enabled. */ - uint64_t I : 1; - /** @brief When set, the page fault was caused by a protection-key violation. The PKRU register (for user-mode accesses) or PKRS MSR (for supervisor-mode accesses) specifies the protection key rights. */ - uint64_t PK : 1; - /** @brief When set, the page fault was caused by a shadow stack access. */ - uint64_t SS : 1; - /** @brief Reserved */ - uint64_t Reserved0 : 8; - /** @brief When set, the fault was due to an SGX violation. The fault is unrelated to ordinary paging. */ - uint64_t SGX : 1; - /** @brief Reserved */ - uint64_t Reserved1 : 16; - }; - uint64_t raw; - } PageFaultErrorCode; + uint64_t InterruptNumber; // Interrupt Number + uint64_t ErrorCode; // Error code - // ! TODO: UNTESTED! - typedef union SelectorErrorCode - { - struct - { - /** @brief When set, the exception originated externally to the processor. */ - uint64_t External : 1; - /** @brief IDT/GDT/LDT Table - * @details 0b00 - The Selector Index references a descriptor in the GDT. - * @details 0b01 - The Selector Index references a descriptor in the IDT. - * @details 0b10 - The Selector Index references a descriptor in the LDT. - * @details 0b11 - The Selector Index references a descriptor in the IDT. - */ - uint64_t Table : 2; - /** @brief The index in the GDT, IDT or LDT. */ - uint64_t Idx : 13; - /** @brief Reserved */ - uint64_t Reserved : 16; - }; - uint64_t raw; - } SelectorErrorCode; + uint64_t rip; // Instruction Pointer + uint64_t cs; // Code Segment + RFLAGS rflags; // Register Flags + uint64_t rsp; // Stack Pointer + uint64_t ss; // Stack Segment + } TrapFrame; - struct FXState - { - /** @brief FPU control word */ - uint16_t fcw; - /** @brief FPU status word */ - uint16_t fsw; - /** @brief FPU tag words */ - uint8_t ftw; - /** @brief Reserved (zero) */ - uint8_t Reserved; - /** @brief FPU opcode */ - uint16_t fop; - /** @brief PFU instruction pointer */ - uint64_t rip; - /** @brief FPU data pointer */ - uint64_t rdp; - /** @brief SSE control register */ - uint32_t mxcsr; - /** @brief SSE control register mask */ - uint32_t mxcsrmask; - /** @brief FPU registers (last 6 bytes reserved) */ - uint8_t st[8][16]; - /** @brief XMM registers */ - uint8_t xmm[16][16]; - } __packed; + typedef union EFER + { + struct + { + /** @brief Enable syscall & sysret instructions in 64-bit mode. */ + uint64_t SCE : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 7; + /** @brief Enable long mode. */ + uint64_t LME : 1; + /** @brief Reserved */ + uint64_t Reserved1 : 1; + /** @brief Indicates long. */ + uint64_t LMA : 1; + /** @brief Enable No-Execute Bit */ + uint64_t NXE : 1; + /** @brief Enable Secure Virtual Machine */ + uint64_t SVME : 1; + /** @brief Enable Long Mode Segment Limit */ + uint64_t LMSLE : 1; + /** @brief Enable Fast FXSAVE/FXRSTOR */ + uint64_t FFXSR : 1; + /** @brief Enable Translation Cache Extension */ + uint64_t TCE : 1; + /** @brief Reserved */ + uint64_t Reserved2 : 32; + }; + uint64_t raw; + } __packed EFER; - SafeFunction static inline void lgdt(void *gdt) - { + typedef union DR6 + { + struct + { + /** @brief Breakpoint #0 Condition Detected */ + uint64_t B0 : 1; + /** @brief Breakpoint #1 Condition Detected */ + uint64_t B1 : 1; + /** @brief Breakpoint #2 Condition Detected */ + uint64_t B2 : 1; + /** @brief Breakpoint #3 Condition Detected */ + uint64_t B3 : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 8; + /** @brief Reserved */ + uint64_t Reserved1 : 1; + /** @brief Breakpoint Debug Access Detected */ + uint64_t BD : 1; + /** @brief Breakpoint Single Step */ + uint64_t BS : 1; + /** @brief Breakpoint Task Switch */ + uint64_t BT : 1; + /** @brief Reserved */ + uint64_t Reserved2 : 15; + /** @brief Reserved */ + uint64_t Reserved3 : 32; + }; + uint64_t raw; + } DR6; + + typedef union DR7 + { + struct + { + /** @brief Local Exact Breakpoint #0 Enabled */ + uint64_t L0 : 1; + /** @brief Global Exact Breakpoint #0 Enabled */ + uint64_t G0 : 1; + /** @brief Local Exact Breakpoint #1 Enabled */ + uint64_t L1 : 1; + /** @brief Global Exact Breakpoint #1 Enabled */ + uint64_t G1 : 1; + /** @brief Local Exact Breakpoint #2 Enabled */ + uint64_t L2 : 1; + /** @brief Global Exact Breakpoint #2 Enabled */ + uint64_t G2 : 1; + /** @brief Local Exact Breakpoint #3 Enabled */ + uint64_t L3 : 1; + /** @brief Global Exact Breakpoint #3 Enabled */ + uint64_t G3 : 1; + /** @brief Local Exact Breakpoint Enabled */ + uint64_t LE : 1; + /** @brief Global Exact Breakpoint Enabled */ + uint64_t GE : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 1; + /** @brief Reserved */ + uint64_t Reserved1 : 2; + /** @brief General Detect Enabled */ + uint64_t GD : 1; + /** @brief Reserved */ + uint64_t Reserved2 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint64_t RW0 : 2; + /** @brief Length of Breakpoint #0 */ + uint64_t LEN0 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint64_t RW1 : 2; + /** @brief Length of Breakpoint #1 */ + uint64_t LEN1 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint64_t RW2 : 2; + /** @brief Length of Breakpoint #2 */ + uint64_t LEN2 : 2; + /** @brief Type of Transaction(s) to Trap */ + uint64_t RW3 : 2; + /** @brief Length of Breakpoint #3 */ + uint64_t LEN3 : 2; + /** @brief Reserved */ + uint64_t Reserved3 : 32; + }; + uint64_t raw; + } DR7; + + typedef union PageFaultErrorCode + { + struct + { + /** @brief When set, the page fault was caused by a page-protection violation. When not set, it was caused by a non-present page. */ + uint64_t P : 1; + /** @brief When set, the page fault was caused by a write access. When not set, it was caused by a read access. */ + uint64_t W : 1; + /** @brief When set, the page fault was caused while CPL = 3. This does not necessarily mean that the page fault was a privilege violation. */ + uint64_t U : 1; + /** @brief When set, one or more page directory entries contain reserved bits which are set to 1. This only applies when the PSE or PAE flags in CR4 are set to 1. */ + uint64_t R : 1; + /** @brief When set, the page fault was caused by an instruction fetch. This only applies when the No-Execute bit is supported and enabled. */ + uint64_t I : 1; + /** @brief When set, the page fault was caused by a protection-key violation. The PKRU register (for user-mode accesses) or PKRS MSR (for supervisor-mode accesses) specifies the protection key rights. */ + uint64_t PK : 1; + /** @brief When set, the page fault was caused by a shadow stack access. */ + uint64_t SS : 1; + /** @brief Reserved */ + uint64_t Reserved0 : 8; + /** @brief When set, the fault was due to an SGX violation. The fault is unrelated to ordinary paging. */ + uint64_t SGX : 1; + /** @brief Reserved */ + uint64_t Reserved1 : 16; + }; + uint64_t raw; + } PageFaultErrorCode; + + // ! TODO: UNTESTED! + typedef union SelectorErrorCode + { + struct + { + /** @brief When set, the exception originated externally to the processor. */ + uint64_t External : 1; + /** @brief IDT/GDT/LDT Table + * @details 0b00 - The Selector Index references a descriptor in the GDT. + * @details 0b01 - The Selector Index references a descriptor in the IDT. + * @details 0b10 - The Selector Index references a descriptor in the LDT. + * @details 0b11 - The Selector Index references a descriptor in the IDT. + */ + uint64_t Table : 2; + /** @brief The index in the GDT, IDT or LDT. */ + uint64_t Idx : 13; + /** @brief Reserved */ + uint64_t Reserved : 16; + }; + uint64_t raw; + } SelectorErrorCode; + + struct FXState + { + /** @brief FPU control word */ + uint16_t fcw; + /** @brief FPU status word */ + uint16_t fsw; + /** @brief FPU tag words */ + uint8_t ftw; + /** @brief Reserved (zero) */ + uint8_t Reserved; + /** @brief FPU opcode */ + uint16_t fop; + /** @brief PFU instruction pointer */ + uint64_t rip; + /** @brief FPU data pointer */ + uint64_t rdp; + /** @brief SSE control register */ + uint32_t mxcsr; + /** @brief SSE control register mask */ + uint32_t mxcsrmask; + /** @brief FPU registers (last 6 bytes reserved) */ + uint8_t st[8][16]; + /** @brief XMM registers */ + uint8_t xmm[16][16]; + } __packed; + + SafeFunction static inline void lgdt(void *gdt) + { #ifdef a64 - asmv("lgdt (%0)" - : - : "r"(gdt)); + asmv("lgdt (%0)" + : + : "r"(gdt)); #endif - } + } - SafeFunction static inline void lidt(void *idt) - { + SafeFunction static inline void lidt(void *idt) + { #ifdef a64 - asmv("lidt (%0)" - : - : "r"(idt)); + asmv("lidt (%0)" + : + : "r"(idt)); #endif - } + } - SafeFunction static inline void ltr(uint16_t Segment) - { + SafeFunction static inline void ltr(uint16_t Segment) + { #ifdef a64 - asmv("ltr %0" - : - : "r"(Segment)); + asmv("ltr %0" + : + : "r"(Segment)); #endif - } + } - SafeFunction static inline void invlpg(void *Address) - { + SafeFunction static inline void invlpg(void *Address) + { #ifdef a64 - asmv("invlpg (%0)" - : - : "r"(Address) - : "memory"); + asmv("invlpg (%0)" + : + : "r"(Address) + : "memory"); #endif - } + } - /** - * @brief CPUID - * - * @param Function Leaf - * @param eax EAX - * @param ebx EBX - * @param ecx ECX - * @param edx EDX - */ - SafeFunction static inline void cpuid(uint32_t Function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) - { + /** + * @brief CPUID + * + * @param Function Leaf + * @param eax EAX + * @param ebx EBX + * @param ecx ECX + * @param edx EDX + */ + SafeFunction static inline void cpuid(uint32_t Function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) + { #ifdef a64 - asmv("cpuid" - : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) - : "a"(Function)); + asmv("cpuid" + : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) + : "a"(Function)); #endif - } + } - /** - * @brief Get the highest leaf function supported by CPUID - * - * @example if (GetHighestLeaf() < 0x15) { error("CPU doesn't support leaf 0x15!"); } - * - * @return uint32_t - */ - SafeFunction static inline uint32_t GetHighestLeaf() - { - uint32_t eax, ebx, ecx, edx; - cpuid(0x0, &eax, &ebx, &ecx, &edx); - return eax; - } + /** + * @brief Get the highest leaf function supported by CPUID + * + * @example if (GetHighestLeaf() < 0x15) { error("CPU doesn't support leaf 0x15!"); } + * + * @return uint32_t + */ + SafeFunction static inline uint32_t GetHighestLeaf() + { + uint32_t eax, ebx, ecx, edx; + cpuid(0x0, &eax, &ebx, &ecx, &edx); + return eax; + } - SafeFunction static inline void fxsave(void *FXSaveArea) - { + SafeFunction static inline void fxsave(void *FXSaveArea) + { #ifdef a64 - if (!FXSaveArea || FXSaveArea >= (char *)0xfffffffffffff000) - return; + if (!FXSaveArea || FXSaveArea >= (char *)0xfffffffffffff000) + return; - asmv("fxsaveq (%0)" - : - : "r"(FXSaveArea) - : "memory"); + asmv("fxsaveq (%0)" + : + : "r"(FXSaveArea) + : "memory"); #endif - } + } - SafeFunction static inline void fxrstor(void *FXRstorArea) - { + SafeFunction static inline void fxrstor(void *FXRstorArea) + { #ifdef a64 - if (!FXRstorArea || FXRstorArea >= (char *)0xfffffffffffff000) - return; + if (!FXRstorArea || FXRstorArea >= (char *)0xfffffffffffff000) + return; - asmv("fxrstorq (%0)" - : - : "r"(FXRstorArea) - : "memory"); + asmv("fxrstorq (%0)" + : + : "r"(FXRstorArea) + : "memory"); #endif - } - } + } + } - namespace aarch64 - { - typedef struct TrapFrame - { - uint64_t x19; // General purpose - uint64_t x20; // General purpose - uint64_t x21; // General purpose - uint64_t x22; // General purpose - uint64_t x23; // General purpose - uint64_t x24; // General purpose - uint64_t x25; // General purpose - uint64_t x26; // General purpose + namespace aarch64 + { + typedef struct TrapFrame + { + uint64_t x19; // General purpose + uint64_t x20; // General purpose + uint64_t x21; // General purpose + uint64_t x22; // General purpose + uint64_t x23; // General purpose + uint64_t x24; // General purpose + uint64_t x25; // General purpose + uint64_t x26; // General purpose - uint64_t x27; // Stack frame pointer - uint64_t x28; // Link register - uint64_t x29; // Frame pointer - uint64_t x30; // Program counter + uint64_t x27; // Stack frame pointer + uint64_t x28; // Link register + uint64_t x29; // Frame pointer + uint64_t x30; // Program counter - uint64_t sp_el0; // Stack pointer - uint64_t elr_el1; // Exception Link Register - uint64_t spsr_el1; // Saved Program Status Register - uint64_t ErrorCode /* esr_el1 */; // Exception Syndrome Register + uint64_t sp_el0; // Stack pointer + uint64_t elr_el1; // Exception Link Register + uint64_t spsr_el1; // Saved Program Status Register + uint64_t ErrorCode /* esr_el1 */; // Exception Syndrome Register - uint64_t InterruptNumber /* iar_el1 */; // Interrupt Acknowledge Register - } TrapFrame; - } + uint64_t InterruptNumber /* iar_el1 */; // Interrupt Acknowledge Register + } TrapFrame; + } } #endif // !__FENNIX_KERNEL_CPU_H__ diff --git a/include/cpu/x86/cpuid_amd.hpp b/include/cpu/x86/cpuid_amd.hpp index 164573a..14ffaa4 100644 --- a/include/cpu/x86/cpuid_amd.hpp +++ b/include/cpu/x86/cpuid_amd.hpp @@ -30,2130 +30,2226 @@ typedef uint64_t cpuid_t; namespace CPU { - namespace x86 - { - /** @brief EXPERIMENTAL IMPLEMENTATION */ - namespace AMD - { - /** @brief Basic CPU information */ - struct CPUID0x00000000 - { - __always_inline inline void Get() - { + namespace x86 + { + /** @brief EXPERIMENTAL IMPLEMENTATION */ + namespace AMD + { + /** @brief Basic CPU information */ + struct CPUID0x00000000 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x0)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x0)); #endif // a64 || a32 - } + } - /** @brief Largest Standard Function Number */ - union - { - struct - { - uint32_t LFuncStd : 32; - }; - cpuid_t raw; - } EAX; + /** @brief Largest Standard Function Number */ + union + { + struct + { + uint32_t LFuncStd : 32; + }; + cpuid_t raw; + } EAX; - /** @brief Processor Vendor */ - union - { - struct - { - char Vendor[4]; - }; - cpuid_t raw; - } EBX; + /** @brief Processor Vendor */ + union + { + struct + { + char Vendor[4]; + }; + cpuid_t raw; + } EBX; - /** @brief Processor Vendor */ - union - { - struct - { - char Vendor[4]; - }; - cpuid_t raw; - } ECX; + /** @brief Processor Vendor */ + union + { + struct + { + char Vendor[4]; + }; + cpuid_t raw; + } ECX; - /** @brief Processor Vendor */ - union - { - struct - { - char Vendor[4]; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Processor Vendor */ + union + { + struct + { + char Vendor[4]; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Additional CPU information */ - struct CPUID0x00000001 - { - __always_inline inline void Get() - { + /** @brief Additional CPU information */ + struct CPUID0x00000001 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x1)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x1)); #endif // a64 || a32 - } + } - /** @brief Family, Model, Stepping Identifiers */ - union - { - /* "This function is an identical copy of CPUID Fn8000_0001_EAX." */ - struct - { - uint32_t Stepping : 4; - uint32_t BaseModel : 4; - uint32_t BaseFamily : 4; - uint32_t Reserved0 : 4; - uint32_t ExtModel : 4; - uint32_t ExtFamily : 8; - uint32_t Reserved1 : 4; - }; - cpuid_t raw; - } EAX; + /** @brief Family, Model, Stepping Identifiers */ + union + { + /* "This function is an identical copy of CPUID Fn8000_0001_EAX." */ + struct + { + uint32_t Stepping : 4; + uint32_t BaseModel : 4; + uint32_t BaseFamily : 4; + uint32_t Reserved0 : 4; + uint32_t ExtModel : 4; + uint32_t ExtFamily : 8; + uint32_t Reserved1 : 4; + }; + cpuid_t raw; + } EAX; - /** @brief LocalApicId, LogicalProcessorCount, CLFlush */ - union - { - struct - { - uint32_t BrandId : 8; - uint32_t CLFlush : 8; - uint32_t LogicalProcessorCount : 8; - uint32_t LocalApicId : 8; - }; - cpuid_t raw; - } EBX; + /** @brief LocalApicId, LogicalProcessorCount, CLFlush */ + union + { + struct + { + uint32_t BrandId : 8; + uint32_t CLFlush : 8; + uint32_t LogicalProcessorCount : 8; + uint32_t LocalApicId : 8; + }; + cpuid_t raw; + } EBX; - /** @brief Feature Identifiers */ - union - { - struct - { - uint32_t SSE3 : 1; - uint32_t PCLMULQDQ : 1; - uint32_t Reserved0 : 1; - uint32_t MONITOR : 1; - uint32_t Reserved1 : 5; - uint32_t SSSE3 : 1; - uint32_t Reserved2 : 2; - uint32_t FMA : 1; - uint32_t CMPXCHG16B : 1; - uint32_t Reserved3 : 5; - uint32_t SSE41 : 1; - uint32_t SSE42 : 1; - uint32_t x2APIC : 1; - uint32_t MOVBE : 1; - uint32_t POPCNT : 1; - uint32_t Reserved4 : 1; - uint32_t AES : 1; - uint32_t XSAVE : 1; - uint32_t OSXSAVE : 1; - uint32_t AVX : 1; - uint32_t F16C : 1; - uint32_t RDRAND : 1; + /** @brief Feature Identifiers */ + union + { + struct + { + uint32_t SSE3 : 1; + uint32_t PCLMULQDQ : 1; + uint32_t Reserved0 : 1; + uint32_t MONITOR : 1; + uint32_t Reserved1 : 5; + uint32_t SSSE3 : 1; + uint32_t Reserved2 : 2; + uint32_t FMA : 1; + uint32_t CMPXCHG16B : 1; + uint32_t Reserved3 : 5; + uint32_t SSE41 : 1; + uint32_t SSE42 : 1; + uint32_t x2APIC : 1; + uint32_t MOVBE : 1; + uint32_t POPCNT : 1; + uint32_t Reserved4 : 1; + uint32_t AES : 1; + uint32_t XSAVE : 1; + uint32_t OSXSAVE : 1; + uint32_t AVX : 1; + uint32_t F16C : 1; + uint32_t RDRAND : 1; - /** - * @brief Reserved for use by hypervisor to indicate guest status. - */ - uint32_t Hypervisor : 1; - }; - cpuid_t raw; - } ECX; + /** + * @brief Reserved for use by hypervisor to indicate guest status. + */ + uint32_t Hypervisor : 1; + }; + cpuid_t raw; + } ECX; - /** @brief Feature Identifiers */ - union - { - struct - { - uint32_t FPU : 1; - uint32_t VME : 1; - uint32_t DE : 1; - uint32_t PSE : 1; - uint32_t TSC : 1; - uint32_t MSR : 1; - uint32_t PAE : 1; - uint32_t MCE : 1; - uint32_t CMPXCHG8B : 1; - uint32_t APIC : 1; - uint32_t Reserved0 : 1; - uint32_t SysEnterSysExit : 1; - uint32_t MTRR : 1; - uint32_t PGE : 1; - uint32_t MCA : 1; - uint32_t CMOV : 1; - uint32_t PAT : 1; - uint32_t PSE36 : 1; - uint32_t Reserved1 : 1; - uint32_t CLFSH : 1; - uint32_t Reserved2 : 3; - uint32_t MMX : 1; - uint32_t FXSR : 1; - uint32_t SSE : 1; - uint32_t SSE2 : 1; - uint32_t Reserved3 : 1; - uint32_t HTT : 1; - uint32_t Reserved4 : 3; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Feature Identifiers */ + union + { + struct + { + uint32_t FPU : 1; + uint32_t VME : 1; + uint32_t DE : 1; + uint32_t PSE : 1; + uint32_t TSC : 1; + uint32_t MSR : 1; + uint32_t PAE : 1; + uint32_t MCE : 1; + uint32_t CMPXCHG8B : 1; + uint32_t APIC : 1; + uint32_t Reserved0 : 1; + uint32_t SysEnterSysExit : 1; + uint32_t MTRR : 1; + uint32_t PGE : 1; + uint32_t MCA : 1; + uint32_t CMOV : 1; + uint32_t PAT : 1; + uint32_t PSE36 : 1; + uint32_t Reserved1 : 1; + uint32_t CLFSH : 1; + uint32_t Reserved2 : 3; + uint32_t MMX : 1; + uint32_t FXSR : 1; + uint32_t SSE : 1; + uint32_t SSE2 : 1; + uint32_t Reserved3 : 1; + uint32_t HTT : 1; + uint32_t Reserved4 : 3; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Monitor and MWait Features */ - struct CPUID0x00000005 - { - __always_inline inline void Get() - { + /** @brief Monitor and MWait Features */ + struct CPUID0x00000005 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x5)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x5)); #endif // a64 || a32 - } + } - /** @brief Monitor/MWait */ - union - { - struct - { - uint32_t MonLineSizeMin : 16; - uint32_t Reserved0 : 16; - }; - cpuid_t raw; - } EAX; + /** @brief Monitor/MWait */ + union + { + struct + { + uint32_t MonLineSizeMin : 16; + uint32_t Reserved0 : 16; + }; + cpuid_t raw; + } EAX; - /** @brief Monitor/MWait */ - union - { - struct - { - uint32_t MonLineSizeMax : 16; - uint32_t Reserved0 : 16; - }; - cpuid_t raw; - } EBX; + /** @brief Monitor/MWait */ + union + { + struct + { + uint32_t MonLineSizeMax : 16; + uint32_t Reserved0 : 16; + }; + cpuid_t raw; + } EBX; - /** @brief Monitor/MWait */ - union - { - struct - { - uint32_t EMX : 1; - uint32_t IBE : 1; - uint32_t Reserved0 : 30; - }; - cpuid_t raw; - } ECX; + /** @brief Monitor/MWait */ + union + { + struct + { + uint32_t EMX : 1; + uint32_t IBE : 1; + uint32_t Reserved0 : 30; + }; + cpuid_t raw; + } ECX; - /** @brief Reserved */ - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Reserved */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Power Management Related Features */ - struct CPUID0x00000006 - { - __always_inline inline void Get() - { + /** @brief Power Management Related Features */ + struct CPUID0x00000006 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x6)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x6)); #endif // a64 || a32 - } + } - /** @brief Local APIC Timer Invariance */ - union - { - struct - { - uint32_t Reserved0 : 2; - uint32_t ARAT : 1; - uint32_t Reserved1 : 29; - }; - cpuid_t raw; - } EAX; + /** @brief Local APIC Timer Invariance */ + union + { + struct + { + uint32_t Reserved0 : 2; + uint32_t ARAT : 1; + uint32_t Reserved1 : 29; + }; + cpuid_t raw; + } EAX; - /** @brief Reserved */ - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EBX; + /** @brief Reserved */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EBX; - /** @brief Effective Processor Frequency Interface */ - union - { - struct - { - uint32_t EffFreq : 1; - uint32_t Reserved0 : 31; - }; - cpuid_t raw; - } ECX; + /** @brief Effective Processor Frequency Interface */ + union + { + struct + { + uint32_t EffFreq : 1; + uint32_t Reserved0 : 31; + }; + cpuid_t raw; + } ECX; - /** @brief Reserved */ - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Reserved */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Structured Extended Feature Identifiers */ - struct CPUID0x00000007 - { - __always_inline inline void Get() - { + /** @brief Structured Extended Feature Identifiers */ + struct CPUID0x00000007 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x7)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x7)); #endif // a64 || a32 - } + } - /** @brief Structured Extended Feature Identifiers */ - union - { - struct - { - uint32_t MaxSubFn : 32; - }; - cpuid_t raw; - } EAX; + /** @brief Structured Extended Feature Identifiers */ + union + { + struct + { + uint32_t MaxSubFn : 32; + }; + cpuid_t raw; + } EAX; - /** @brief Structured Extended Feature Identifiers */ - union - { - struct - { - uint32_t FSGSBASE : 1; - uint32_t Reserved0 : 2; - uint32_t BMI1 : 1; - uint32_t Reserved1 : 1; - uint32_t AVX2 : 1; - uint32_t Reserved2 : 1; - uint32_t SMEP : 1; - uint32_t BMI2 : 1; - uint32_t Reserved3 : 1; - uint32_t INVPCID : 1; - uint32_t Reserved4 : 1; - uint32_t PQM : 1; - uint32_t Reserved5 : 2; - uint32_t PQE : 1; - uint32_t Reserved6 : 2; - uint32_t RDSEED : 1; - uint32_t ADX : 1; - uint32_t SMAP : 1; - uint32_t Reserved7 : 1; - uint32_t RDPID : 1; - uint32_t CLFLUSHOPT : 1; - uint32_t CLWB : 1; - uint32_t Reserved8 : 4; - uint32_t SHA : 1; - uint32_t Reserved9 : 2; - }; - cpuid_t raw; - } EBX; + /** @brief Structured Extended Feature Identifiers */ + union + { + struct + { + uint32_t FSGSBASE : 1; + uint32_t Reserved0 : 2; + uint32_t BMI1 : 1; + uint32_t Reserved1 : 1; + uint32_t AVX2 : 1; + uint32_t Reserved2 : 1; + uint32_t SMEP : 1; + uint32_t BMI2 : 1; + uint32_t Reserved3 : 1; + uint32_t INVPCID : 1; + uint32_t Reserved4 : 1; + uint32_t PQM : 1; + uint32_t Reserved5 : 2; + uint32_t PQE : 1; + uint32_t Reserved6 : 2; + uint32_t RDSEED : 1; + uint32_t ADX : 1; + uint32_t SMAP : 1; + uint32_t Reserved7 : 1; + uint32_t RDPID : 1; + uint32_t CLFLUSHOPT : 1; + uint32_t CLWB : 1; + uint32_t Reserved8 : 4; + uint32_t SHA : 1; + uint32_t Reserved9 : 2; + }; + cpuid_t raw; + } EBX; - /** @brief Structured Extended Feature Identifiers */ - union - { - struct - { - uint32_t Reserved0 : 2; - uint32_t UMIP : 1; - uint32_t PKU : 1; - uint32_t OSPKE : 1; - uint32_t Reserved1 : 2; - uint32_t CET_SS : 1; - uint32_t Reserved2 : 1; - uint32_t VAES : 1; - uint32_t VPCLMULQDQ : 1; - uint32_t Reserved3 : 5; - uint32_t LA57 : 1; - uint32_t Reserved4 : 15; - }; - cpuid_t raw; - } ECX; + /** @brief Structured Extended Feature Identifiers */ + union + { + struct + { + uint32_t Reserved0 : 2; + uint32_t UMIP : 1; + uint32_t PKU : 1; + uint32_t OSPKE : 1; + uint32_t Reserved1 : 2; + uint32_t CET_SS : 1; + uint32_t Reserved2 : 1; + uint32_t VAES : 1; + uint32_t VPCLMULQDQ : 1; + uint32_t Reserved3 : 5; + uint32_t LA57 : 1; + uint32_t Reserved4 : 15; + }; + cpuid_t raw; + } ECX; - /** @brief Structured Extended Feature Identifiers */ - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Structured Extended Feature Identifiers */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Thread Level - Extended Topology Enumeration */ - struct CPUID0x0000000B_ECX_0 - { - __always_inline inline void Get() - { + /** @brief Thread Level - Extended Topology Enumeration */ + struct CPUID0x0000000B_ECX_0 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0xB), "c"(0x0)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0xB), "c"(0x0)); #endif // a64 || a32 - } + } - /** @brief Extended Topology Enumeration */ - union - { - struct - { - uint32_t ThreadMaskWidth : 5; - uint32_t Reserved0 : 27; - }; - cpuid_t raw; - } EAX; + /** @brief Extended Topology Enumeration */ + union + { + struct + { + uint32_t ThreadMaskWidth : 5; + uint32_t Reserved0 : 27; + }; + cpuid_t raw; + } EAX; - /** @brief Extended Topology Enumeration */ - union - { - struct - { - uint32_t NumberOfThreadsInACore : 5; /* No field name */ - uint32_t Reserved0 : 27; - }; - cpuid_t raw; - } EBX; + /** @brief Extended Topology Enumeration */ + union + { + struct + { + uint32_t NumberOfThreadsInACore : 5; /* No field name */ + uint32_t Reserved0 : 27; + }; + cpuid_t raw; + } EBX; - /** @brief Extended Topology Enumeration */ - union - { - struct - { - uint32_t ECXInputValue : 8; - uint32_t LevelNumber : 8; - uint32_t Reserved0 : 16; - }; - cpuid_t raw; - } ECX; + /** @brief Extended Topology Enumeration */ + union + { + struct + { + uint32_t ECXInputValue : 8; + uint32_t LevelNumber : 8; + uint32_t Reserved0 : 16; + }; + cpuid_t raw; + } ECX; - /** @brief Extended Topology Enumeration */ - union - { - struct - { - uint32_t x2APID_ID : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Extended Topology Enumeration */ + union + { + struct + { + uint32_t x2APID_ID : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Core Level - Extended Topology Enumeration */ - struct CPUID0x0000000B_ECX_1 - { - __always_inline inline void Get() - { + /** @brief Core Level - Extended Topology Enumeration */ + struct CPUID0x0000000B_ECX_1 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0xB), "c"(0x1)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0xB), "c"(0x1)); #endif // a64 || a32 - } + } - /** @brief Extended Topology Enumeration */ - union - { - struct - { - uint32_t CoreMaskWidth : 5; - uint32_t Reserved0 : 27; - }; - cpuid_t raw; - } EAX; + /** @brief Extended Topology Enumeration */ + union + { + struct + { + uint32_t CoreMaskWidth : 5; + uint32_t Reserved0 : 27; + }; + cpuid_t raw; + } EAX; - /** @brief Extended Topology Enumeration */ - union - { - struct - { - uint32_t NumberOfLogicalCoresInSocket : 5; /* No field name */ - uint32_t Reserved0 : 27; - }; - cpuid_t raw; - } EBX; + /** @brief Extended Topology Enumeration */ + union + { + struct + { + uint32_t NumberOfLogicalCoresInSocket : 5; /* No field name */ + uint32_t Reserved0 : 27; + }; + cpuid_t raw; + } EBX; - /** @brief Extended Topology Enumeration */ - union - { - struct - { - uint32_t ECXInputValue : 8; - uint32_t LevelNumber : 8; - uint32_t Reserved0 : 16; - }; - cpuid_t raw; - } ECX; + /** @brief Extended Topology Enumeration */ + union + { + struct + { + uint32_t ECXInputValue : 8; + uint32_t LevelNumber : 8; + uint32_t Reserved0 : 16; + }; + cpuid_t raw; + } ECX; - /** @brief Extended Topology Enumeration */ - union - { - struct - { - uint32_t x2APID_ID : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Extended Topology Enumeration */ + union + { + struct + { + uint32_t x2APID_ID : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Processor Extended State Enumeration */ - struct CPUID0x0000000D_ECX_0 - { - __always_inline inline void Get() - { + /** @brief Processor Extended State Enumeration */ + struct CPUID0x0000000D_ECX_0 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0xD), "c"(0x0)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0xD), "c"(0x0)); #endif // a64 || a32 - } + } - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t XFeatureSupportedMask : 32; - }; - cpuid_t raw; - } EAX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t XFeatureSupportedMask : 32; + }; + cpuid_t raw; + } EAX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t XFeatureEnabledSizeMax : 32; - }; - cpuid_t raw; - } EBX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t XFeatureEnabledSizeMax : 32; + }; + cpuid_t raw; + } EBX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t XFeatureSupportedSizeMax : 32; - }; - cpuid_t raw; - } ECX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t XFeatureSupportedSizeMax : 32; + }; + cpuid_t raw; + } ECX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t XFeatureSupportedMask : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t XFeatureSupportedMask : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Processor Extended State Enumeration */ - struct CPUID0x0000000D_ECX_1 - { - __always_inline inline void Get() - { + /** @brief Processor Extended State Enumeration */ + struct CPUID0x0000000D_ECX_1 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0xD), "c"(0x1)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0xD), "c"(0x1)); #endif // a64 || a32 - } + } - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t XSAVEOPT : 1; - uint32_t XSAVEC : 1; - uint32_t XGETBV : 1; - uint32_t XSAVES : 1; - uint32_t Reserved0 : 28; - }; - cpuid_t raw; - } EAX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t XSAVEOPT : 1; + uint32_t XSAVEC : 1; + uint32_t XGETBV : 1; + uint32_t XSAVES : 1; + uint32_t Reserved0 : 28; + }; + cpuid_t raw; + } EAX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - /** - * @brief The value returned on EBX represents the - * fixed size of the save area (240h) plus the - * state size of each enabled extended feature: - * EBX = 0240h - * + ((XCR0[AVX] == 1) ? 0000_0100h : 0) - * + ((XCR0[MPK] == 1) ? 0000_0008h : 0) - * + ((XSS[CET_U] == 1) ? 0000_0010h : 0) - * + ((XSS[CET_S] == 1) ? 0000_0018h : 0) - */ - uint32_t ebx : 32; - }; - cpuid_t raw; - } EBX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + /** + * @brief The value returned on EBX represents the + * fixed size of the save area (240h) plus the + * state size of each enabled extended feature: + * EBX = 0240h + * + ((XCR0[AVX] == 1) ? 0000_0100h : 0) + * + ((XCR0[MPK] == 1) ? 0000_0008h : 0) + * + ((XSS[CET_U] == 1) ? 0000_0010h : 0) + * + ((XSS[CET_S] == 1) ? 0000_0018h : 0) + */ + uint32_t ebx : 32; + }; + cpuid_t raw; + } EBX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t Reserved0 : 11; - uint32_t CET_U : 1; - uint32_t CET_S : 1; - uint32_t Reserved1 : 19; - }; - cpuid_t raw; - } ECX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t Reserved0 : 11; + uint32_t CET_U : 1; + uint32_t CET_S : 1; + uint32_t Reserved1 : 19; + }; + cpuid_t raw; + } ECX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Processor Extended State Enumeration */ - struct CPUID0x0000000D_ECX_2 - { - __always_inline inline void Get() - { + /** @brief Processor Extended State Enumeration */ + struct CPUID0x0000000D_ECX_2 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0xD), "c"(0x2)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0xD), "c"(0x2)); #endif // a64 || a32 - } + } - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t YmmSaveStateSize : 32; - }; - cpuid_t raw; - } EAX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t YmmSaveStateSize : 32; + }; + cpuid_t raw; + } EAX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t YmmSaveStateOffset : 32; - }; - cpuid_t raw; - } EBX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t YmmSaveStateOffset : 32; + }; + cpuid_t raw; + } EBX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } ECX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } ECX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Processor Extended State Emulation */ - struct CPUID0x0000000D_ECX_11 - { - __always_inline inline void Get() - { + /** @brief Processor Extended State Emulation */ + struct CPUID0x0000000D_ECX_11 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0xD), "c"(0x11)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0xD), "c"(0x11)); #endif // a64 || a32 - } + } - /** @brief Processor Extended State Emulation */ - union - { - struct - { - uint32_t CetSupervisorSize : 32; - }; - cpuid_t raw; - } EAX; + /** @brief Processor Extended State Emulation */ + union + { + struct + { + uint32_t CetSupervisorSize : 32; + }; + cpuid_t raw; + } EAX; - /** @brief Processor Extended State Emulation */ - union - { - struct - { - uint32_t CetSupervisorOffset : 32; - }; - cpuid_t raw; - } EBX; + /** @brief Processor Extended State Emulation */ + union + { + struct + { + uint32_t CetSupervisorOffset : 32; + }; + cpuid_t raw; + } EBX; - /** @brief Processor Extended State Emulation */ - union - { - struct - { - uint32_t Reserved : 31; - uint32_t US : 1; - }; - cpuid_t raw; - } ECX; + /** @brief Processor Extended State Emulation */ + union + { + struct + { + uint32_t Reserved : 31; + uint32_t US : 1; + }; + cpuid_t raw; + } ECX; - /** @brief Processor Extended State Emulation */ - union - { - struct - { - uint32_t Unused : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Processor Extended State Emulation */ + union + { + struct + { + uint32_t Unused : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Processor Extended State Emulation */ - struct CPUID0x0000000D_ECX_12 - { - __always_inline inline void Get() - { + /** @brief Processor Extended State Emulation */ + struct CPUID0x0000000D_ECX_12 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0xD), "c"(0x12)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0xD), "c"(0x12)); #endif // a64 || a32 - } + } - /** @brief Processor Extended State Emulation */ - union - { - struct - { - uint32_t CetSupervisorSize : 32; - }; - cpuid_t raw; - } EAX; + /** @brief Processor Extended State Emulation */ + union + { + struct + { + uint32_t CetSupervisorSize : 32; + }; + cpuid_t raw; + } EAX; - /** @brief Processor Extended State Emulation */ - union - { - struct - { - uint32_t CetSupervisorOffset : 32; - }; - cpuid_t raw; - } EBX; + /** @brief Processor Extended State Emulation */ + union + { + struct + { + uint32_t CetSupervisorOffset : 32; + }; + cpuid_t raw; + } EBX; - /** @brief Processor Extended State Emulation */ - union - { - struct - { - uint32_t Reserved : 31; - uint32_t US : 1; - }; - cpuid_t raw; - } ECX; + /** @brief Processor Extended State Emulation */ + union + { + struct + { + uint32_t Reserved : 31; + uint32_t US : 1; + }; + cpuid_t raw; + } ECX; - /** @brief Processor Extended State Emulation */ - union - { - struct - { - uint32_t Unused : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Processor Extended State Emulation */ + union + { + struct + { + uint32_t Unused : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Processor Extended State Enumeration */ - struct CPUID0x0000000D_ECX_3E - { - __always_inline inline void Get() - { + /** @brief Processor Extended State Enumeration */ + struct CPUID0x0000000D_ECX_3E + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0xD), "c"(0x3E)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0xD), "c"(0x3E)); #endif // a64 || a32 - } + } - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t LwpSaveStateSize : 32; - }; - cpuid_t raw; - } EAX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t LwpSaveStateSize : 32; + }; + cpuid_t raw; + } EAX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t LwpSaveStateOffset : 32; - }; - cpuid_t raw; - } EBX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t LwpSaveStateOffset : 32; + }; + cpuid_t raw; + } EBX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } ECX; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } ECX; - /** @brief Processor Extended State Enumeration */ - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Processor Extended State Enumeration */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Maximum Extended Function Number and Vendor String */ - struct CPUID0x80000000 - { - __always_inline inline void Get() - { + /** @brief Maximum Extended Function Number and Vendor String */ + struct CPUID0x80000000 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000000)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000000)); #endif // a64 || a32 - } + } - /** @brief Largest Extended Function Number */ - union - { - struct - { - uint32_t LFuncExt : 32; - }; - cpuid_t raw; - } EAX; + /** @brief Largest Extended Function Number */ + union + { + struct + { + uint32_t LFuncExt : 32; + }; + cpuid_t raw; + } EAX; - /** @brief Processor Vendor */ - union - { - struct - { - char Vendor[4]; - }; - cpuid_t raw; - } EBX; + /** @brief Processor Vendor */ + union + { + struct + { + char Vendor[4]; + }; + cpuid_t raw; + } EBX; - /** @brief Processor Vendor */ - union - { - struct - { - char Vendor[4]; - }; - cpuid_t raw; - } ECX; + /** @brief Processor Vendor */ + union + { + struct + { + char Vendor[4]; + }; + cpuid_t raw; + } ECX; - /** @brief Processor Vendor */ - union - { - struct - { - char Vendor[4]; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Processor Vendor */ + union + { + struct + { + char Vendor[4]; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Extended Processor and Processor Feature Identifiers */ - struct CPUID0x80000001 - { - __always_inline inline void Get() - { + /** @brief Extended Processor and Processor Feature Identifiers */ + struct CPUID0x80000001 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000001)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000001)); #endif // a64 || a32 - } + } - /** @brief AMD Family, Model, Stepping */ - union - { - /* "This function is an identical copy of CPUID Fn0000_0001_EAX." */ - struct - { - uint32_t Stepping : 4; - uint32_t BaseModel : 4; - uint32_t BaseFamily : 4; - uint32_t Reserved0 : 4; - uint32_t ExtendedModel : 4; - uint32_t ExtendedFamily : 8; - uint32_t Reserved1 : 4; - }; - cpuid_t raw; - } EAX; + /** @brief AMD Family, Model, Stepping */ + union + { + /* "This function is an identical copy of CPUID Fn0000_0001_EAX." */ + struct + { + uint32_t Stepping : 4; + uint32_t BaseModel : 4; + uint32_t BaseFamily : 4; + uint32_t Reserved0 : 4; + uint32_t ExtendedModel : 4; + uint32_t ExtendedFamily : 8; + uint32_t Reserved1 : 4; + }; + cpuid_t raw; + } EAX; - /** @brief BrandId Identifier */ - union - { - struct - { - uint32_t BrandId : 16; - uint32_t Reserved0 : 12; - uint32_t PkgType : 4; - }; - cpuid_t raw; - } EBX; + /** @brief BrandId Identifier */ + union + { + struct + { + uint32_t BrandId : 16; + uint32_t Reserved0 : 12; + uint32_t PkgType : 4; + }; + cpuid_t raw; + } EBX; - /** @brief Feature Identifiers */ - union - { - struct - { - uint32_t LahfSahf : 1; - uint32_t CmpLegacy : 1; - uint32_t SVM : 1; - uint32_t ExtApicSpace : 1; - uint32_t AltMovCr8 : 1; - uint32_t ABM : 1; - uint32_t SSE4A : 1; - uint32_t MisAlignSse : 1; - uint32_t ThreeDNowPrefetch : 1; - uint32_t OSVW : 1; - uint32_t IBS : 1; - uint32_t XOP : 1; - uint32_t SKINIT : 1; - uint32_t WDT : 1; - uint32_t Reserved0 : 1; - uint32_t LWP : 1; - uint32_t FMA4 : 1; - uint32_t TCE : 1; - uint32_t Reserved1 : 3; - uint32_t TBM : 1; - uint32_t TopologyExtensions : 1; - uint32_t PerfCtrExtCore : 1; - uint32_t PerfCtrExtNB : 1; - uint32_t Reserved2 : 1; - uint32_t DataBkptExt : 1; - uint32_t PerfTsc : 1; - uint32_t PerfCtrExtLLC : 1; - uint32_t MONITORX : 1; - uint32_t AddrMaskExt : 1; - uint32_t Reserved3 : 1; - }; - cpuid_t raw; - } ECX; + /** @brief Feature Identifiers */ + union + { + struct + { + uint32_t LahfSahf : 1; + uint32_t CmpLegacy : 1; + uint32_t SVM : 1; + uint32_t ExtApicSpace : 1; + uint32_t AltMovCr8 : 1; + uint32_t ABM : 1; + uint32_t SSE4A : 1; + uint32_t MisAlignSse : 1; + uint32_t ThreeDNowPrefetch : 1; + uint32_t OSVW : 1; + uint32_t IBS : 1; + uint32_t XOP : 1; + uint32_t SKINIT : 1; + uint32_t WDT : 1; + uint32_t Reserved0 : 1; + uint32_t LWP : 1; + uint32_t FMA4 : 1; + uint32_t TCE : 1; + uint32_t Reserved1 : 3; + uint32_t TBM : 1; + uint32_t TopologyExtensions : 1; + uint32_t PerfCtrExtCore : 1; + uint32_t PerfCtrExtNB : 1; + uint32_t Reserved2 : 1; + uint32_t DataBkptExt : 1; + uint32_t PerfTsc : 1; + uint32_t PerfCtrExtLLC : 1; + uint32_t MONITORX : 1; + uint32_t AddrMaskExt : 1; + uint32_t Reserved3 : 1; + }; + cpuid_t raw; + } ECX; - /** @brief Feature Identifiers */ - union - { - struct - { - uint32_t FPU : 1; - uint32_t VME : 1; - uint32_t DE : 1; - uint32_t PSE : 1; - uint32_t TSC : 1; - uint32_t MSR : 1; - uint32_t PAE : 1; - uint32_t MCE : 1; - uint32_t CMPXCHG8B : 1; - uint32_t APIC : 1; - uint32_t Reserved0 : 1; - uint32_t SysCallSysRet : 1; - uint32_t MTRR : 1; - uint32_t PGE : 1; - uint32_t MCA : 1; - uint32_t CMOV : 1; - uint32_t PAT : 1; - uint32_t PSE36 : 1; - uint32_t Reserved1 : 2; - uint32_t NX : 1; - uint32_t Reserved2 : 1; - uint32_t MmxExt : 1; - uint32_t MMX : 1; - uint32_t FXSR : 1; - uint32_t FFXSR : 1; - uint32_t Page1GB : 1; - uint32_t RDTSCP : 1; - uint32_t Reserved3 : 1; - uint32_t LM : 1; - uint32_t ThreeDNowExtended : 1; - uint32_t ThreeDNow : 1; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Feature Identifiers */ + union + { + struct + { + uint32_t FPU : 1; + uint32_t VME : 1; + uint32_t DE : 1; + uint32_t PSE : 1; + uint32_t TSC : 1; + uint32_t MSR : 1; + uint32_t PAE : 1; + uint32_t MCE : 1; + uint32_t CMPXCHG8B : 1; + uint32_t APIC : 1; + uint32_t Reserved0 : 1; + uint32_t SysCallSysRet : 1; + uint32_t MTRR : 1; + uint32_t PGE : 1; + uint32_t MCA : 1; + uint32_t CMOV : 1; + uint32_t PAT : 1; + uint32_t PSE36 : 1; + uint32_t Reserved1 : 2; + uint32_t NX : 1; + uint32_t Reserved2 : 1; + uint32_t MmxExt : 1; + uint32_t MMX : 1; + uint32_t FXSR : 1; + uint32_t FFXSR : 1; + uint32_t Page1GB : 1; + uint32_t RDTSCP : 1; + uint32_t Reserved3 : 1; + uint32_t LM : 1; + uint32_t ThreeDNowExtended : 1; + uint32_t ThreeDNow : 1; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Extended Processor Name String */ - struct CPUID0x80000002 - { - __always_inline inline void Get() - { + /** @brief Extended Processor Name String */ + struct CPUID0x80000002 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000002)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000002)); #endif // a64 || a32 - } + } - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Extended Processor Name String */ - struct CPUID0x80000003 - { - __always_inline inline void Get() - { + /** @brief Extended Processor Name String */ + struct CPUID0x80000003 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000003)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000003)); #endif // a64 || a32 - } + } - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Extended Processor Name String */ - struct CPUID0x80000004 - { - __always_inline inline void Get() - { + /** @brief Extended Processor Name String */ + struct CPUID0x80000004 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000004)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000004)); #endif // a64 || a32 - } + } - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EDX; + }; - /** @brief L1 Cache and TLB Information */ - struct CPUID0x80000005 - { - __always_inline inline void Get() - { + /** @brief L1 Cache and TLB Information */ + struct CPUID0x80000005 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000005)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000005)); #endif // a64 || a32 - } + } - /** @brief L1 TLB 2M/4M Information */ - union - { - struct - { - uint32_t L1ITlb2and4MSize : 8; - uint32_t L1ITlb2and4MAssoc : 8; - uint32_t L1DTlb2and4MSize : 8; - uint32_t L1DTlb2and4MAssoc : 8; - }; - cpuid_t raw; - } EAX; + /** @brief L1 TLB 2M/4M Information */ + union + { + struct + { + uint32_t L1ITlb2and4MSize : 8; + uint32_t L1ITlb2and4MAssoc : 8; + uint32_t L1DTlb2and4MSize : 8; + uint32_t L1DTlb2and4MAssoc : 8; + }; + cpuid_t raw; + } EAX; - /** @brief L1 TLB 4K Information */ - union - { - struct - { - uint32_t L1ITlb4KSize : 8; - uint32_t L1ITlb4KAssoc : 8; - uint32_t L1DTlb4KSize : 8; - uint32_t L1DTlb4KAssoc : 8; - }; - cpuid_t raw; - } EBX; + /** @brief L1 TLB 4K Information */ + union + { + struct + { + uint32_t L1ITlb4KSize : 8; + uint32_t L1ITlb4KAssoc : 8; + uint32_t L1DTlb4KSize : 8; + uint32_t L1DTlb4KAssoc : 8; + }; + cpuid_t raw; + } EBX; - /** @brief L1 Data Cache Information */ - union - { - struct - { - uint32_t L1DcLineSize : 8; - uint32_t L1DcLinesPerTag : 8; - uint32_t L1DcAssoc : 8; - uint32_t L1DcSize : 8; - }; - cpuid_t raw; - } ECX; + /** @brief L1 Data Cache Information */ + union + { + struct + { + uint32_t L1DcLineSize : 8; + uint32_t L1DcLinesPerTag : 8; + uint32_t L1DcAssoc : 8; + uint32_t L1DcSize : 8; + }; + cpuid_t raw; + } ECX; - /** @brief L1 Instruction Cache Information */ - union - { - struct - { - uint32_t L1IcLineSize : 8; - uint32_t L1IcLinesPerTag : 8; - uint32_t L1IcAssoc : 8; - uint32_t L1IcSize : 8; - }; - cpuid_t raw; - } EDX; - }; + /** @brief L1 Instruction Cache Information */ + union + { + struct + { + uint32_t L1IcLineSize : 8; + uint32_t L1IcLinesPerTag : 8; + uint32_t L1IcAssoc : 8; + uint32_t L1IcSize : 8; + }; + cpuid_t raw; + } EDX; + }; - /** @brief L2 Cache and TLB and L3 Cache Information */ - struct CPUID0x80000006 - { - __always_inline inline void Get() - { + /** @brief L2 Cache and TLB and L3 Cache Information */ + struct CPUID0x80000006 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000006)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000006)); #endif // a64 || a32 - } + } - /** @brief L2 TLB 2M/4M Information */ - union - { - struct - { - uint32_t L2ITlb2and4MSize : 12; - uint32_t L2ITlb2and4MAssoc : 4; - uint32_t L2DTlb2and4MSize : 12; - uint32_t L2DTlb2and4MAssoc : 4; - }; - cpuid_t raw; - } EAX; + /** @brief L2 TLB 2M/4M Information */ + union + { + struct + { + uint32_t L2ITlb2and4MSize : 12; + uint32_t L2ITlb2and4MAssoc : 4; + uint32_t L2DTlb2and4MSize : 12; + uint32_t L2DTlb2and4MAssoc : 4; + }; + cpuid_t raw; + } EAX; - /** @brief L2 TLB 4K Information */ - union - { - struct - { - uint32_t L2ITlb4KSize : 12; - uint32_t L2ITlb4KAssoc : 4; - uint32_t L2DTlb4KSize : 12; - uint32_t L2DTlb4KAssoc : 4; - }; - cpuid_t raw; - } EBX; + /** @brief L2 TLB 4K Information */ + union + { + struct + { + uint32_t L2ITlb4KSize : 12; + uint32_t L2ITlb4KAssoc : 4; + uint32_t L2DTlb4KSize : 12; + uint32_t L2DTlb4KAssoc : 4; + }; + cpuid_t raw; + } EBX; - /** @brief L2 Cache Information */ - union - { - struct - { - uint32_t L2LineSize : 8; - uint32_t L2LinesPerTag : 4; - uint32_t L2Assoc : 4; - uint32_t L2Size : 16; - }; - cpuid_t raw; - } ECX; + /** @brief L2 Cache Information */ + union + { + struct + { + uint32_t L2LineSize : 8; + uint32_t L2LinesPerTag : 4; + uint32_t L2Assoc : 4; + uint32_t L2Size : 16; + }; + cpuid_t raw; + } ECX; - /** @brief L3 Cache Information */ - union - { - struct - { - uint32_t L3LineSize : 8; - uint32_t L3LinesPerTag : 4; - uint32_t L3Assoc : 4; - uint32_t Reserved0 : 2; - uint32_t L3Size : 14; - }; - cpuid_t raw; - } EDX; - }; + /** @brief L3 Cache Information */ + union + { + struct + { + uint32_t L3LineSize : 8; + uint32_t L3LinesPerTag : 4; + uint32_t L3Assoc : 4; + uint32_t Reserved0 : 2; + uint32_t L3Size : 14; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Processor Power Management and RAS Capabilities */ - struct CPUID0x80000007 - { - __always_inline inline void Get() - { + /** @brief Processor Power Management and RAS Capabilities */ + struct CPUID0x80000007 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000007)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000007)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EAX; - /** @brief RAS Capabilities */ - union - { - struct - { - uint32_t McaOverflowRecov : 1; - uint32_t SUCCOR : 1; - uint32_t HWA : 1; - uint32_t ScalableMca : 1; - uint32_t Reserved0 : 28; - }; - cpuid_t raw; - } EBX; + /** @brief RAS Capabilities */ + union + { + struct + { + uint32_t McaOverflowRecov : 1; + uint32_t SUCCOR : 1; + uint32_t HWA : 1; + uint32_t ScalableMca : 1; + uint32_t Reserved0 : 28; + }; + cpuid_t raw; + } EBX; - /** @brief Processor Power Monitoring Interface */ - union - { - struct - { - uint32_t CpuPwrSampleTimeRatio : 32; - }; - cpuid_t raw; - } ECX; + /** @brief Processor Power Monitoring Interface */ + union + { + struct + { + uint32_t CpuPwrSampleTimeRatio : 32; + }; + cpuid_t raw; + } ECX; - /** @brief Advanced Power Management Features */ - union - { - struct - { - uint32_t TS : 1; - uint32_t FID : 1; - uint32_t VID : 1; - uint32_t TTP : 1; - uint32_t TM : 1; - uint32_t Reserved0 : 1; - uint32_t OneHundredMHzSteps : 1; - uint32_t HwPstate : 1; - uint32_t TscInvariant : 1; - uint32_t CPB : 1; - uint32_t EffFreqRO : 1; - uint32_t ProcFeedbackInterface : 1; - uint32_t ProcPowerReporting : 1; - uint32_t Reserved1 : 19; - }; - cpuid_t raw; - } EDX; - }; + /** @brief Advanced Power Management Features */ + union + { + struct + { + uint32_t TS : 1; + uint32_t FID : 1; + uint32_t VID : 1; + uint32_t TTP : 1; + uint32_t TM : 1; + uint32_t Reserved0 : 1; + uint32_t OneHundredMHzSteps : 1; + uint32_t HwPstate : 1; + uint32_t TscInvariant : 1; + uint32_t CPB : 1; + uint32_t EffFreqRO : 1; + uint32_t ProcFeedbackInterface : 1; + uint32_t ProcPowerReporting : 1; + uint32_t Reserved1 : 19; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Processor Capacity Parameters and Extended Feature Identification */ - struct CPUID0x80000008 - { - __always_inline inline void Get() - { + /** @brief Processor Capacity Parameters and Extended Feature Identification */ + struct CPUID0x80000008 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000008)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000008)); #endif // a64 || a32 - } + } - /** @brief Long Mode Size Identifiers */ - union - { - struct - { - uint32_t PhysAddrSize : 8; - uint32_t LinAddrSize : 8; - uint32_t GuestPhysAddrSize : 8; - uint32_t Reserved0 : 8; - }; - cpuid_t raw; - } EAX; + /** @brief Long Mode Size Identifiers */ + union + { + struct + { + uint32_t PhysAddrSize : 8; + uint32_t LinAddrSize : 8; + uint32_t GuestPhysAddrSize : 8; + uint32_t Reserved0 : 8; + }; + cpuid_t raw; + } EAX; - /** @brief Extended Feature Identifiers */ - union - { - struct - { - uint32_t CLZERO : 1; - uint32_t InstRetCntMsr : 1; - uint32_t RstrFpErrPtrs : 1; - uint32_t INVLPGB : 1; - uint32_t RDPRU : 1; - uint32_t Reserved0 : 3; - uint32_t MCOMMIT : 1; - uint32_t WBNOINVD : 1; - uint32_t Reserved1 : 2; - uint32_t IBPB : 1; - uint32_t INT_WBINVD : 1; - uint32_t IBRS : 1; - uint32_t STIBP : 1; - uint32_t IbrsAlwaysOn : 1; - uint32_t StibpAlwaysOn : 1; - uint32_t IbrsPreferred : 1; - uint32_t IbrsSameMode : 1; - uint32_t EferLmsleUnsupported : 1; - uint32_t INVLPGBnestedPages : 1; - uint32_t Reserved2 : 2; - uint32_t SSBD : 1; - uint32_t SsbdVirtSpecCtrl : 1; - uint32_t SsbdNotRequired : 1; - uint32_t Reserved3 : 1; - uint32_t PSFD : 1; - uint32_t BTC_NO : 1; - uint32_t Reserved4 : 2; - }; - cpuid_t raw; - } EBX; + /** @brief Extended Feature Identifiers */ + union + { + struct + { + uint32_t CLZERO : 1; + uint32_t InstRetCntMsr : 1; + uint32_t RstrFpErrPtrs : 1; + uint32_t INVLPGB : 1; + uint32_t RDPRU : 1; + uint32_t Reserved0 : 3; + uint32_t MCOMMIT : 1; + uint32_t WBNOINVD : 1; + uint32_t Reserved1 : 2; + uint32_t IBPB : 1; + uint32_t INT_WBINVD : 1; + uint32_t IBRS : 1; + uint32_t STIBP : 1; + uint32_t IbrsAlwaysOn : 1; + uint32_t StibpAlwaysOn : 1; + uint32_t IbrsPreferred : 1; + uint32_t IbrsSameMode : 1; + uint32_t EferLmsleUnsupported : 1; + uint32_t INVLPGBnestedPages : 1; + uint32_t Reserved2 : 2; + uint32_t SSBD : 1; + uint32_t SsbdVirtSpecCtrl : 1; + uint32_t SsbdNotRequired : 1; + uint32_t Reserved3 : 1; + uint32_t PSFD : 1; + uint32_t BTC_NO : 1; + uint32_t Reserved4 : 2; + }; + cpuid_t raw; + } EBX; - /** @brief Size Identifiers */ - union - { - struct - { - uint32_t NT : 8; - uint32_t Reserved0 : 4; - uint32_t ApicIdSize : 4; - uint32_t PerfTscSize : 2; - uint32_t Reserved1 : 14; - }; - cpuid_t raw; - } ECX; + /** @brief Size Identifiers */ + union + { + struct + { + uint32_t NT : 8; + uint32_t Reserved0 : 4; + uint32_t ApicIdSize : 4; + uint32_t PerfTscSize : 2; + uint32_t Reserved1 : 14; + }; + cpuid_t raw; + } ECX; - /** @brief RDPRU Register Identifier Range */ - union - { - struct - { - uint32_t InvlpgbCountMax : 16; - uint32_t MaxRdpruID : 16; - }; - cpuid_t raw; - } EDX; - }; + /** @brief RDPRU Register Identifier Range */ + union + { + struct + { + uint32_t InvlpgbCountMax : 16; + uint32_t MaxRdpruID : 16; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x8000000A - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x8000000A + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x8000000A)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x8000000A)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t SvmRev : 8; + uint32_t Reserved : 24; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t NASID : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t NP : 1; + uint32_t LbrVirt : 1; + uint32_t SVML : 1; + uint32_t NRIPS : 1; + uint32_t TscRateMsr : 1; + uint32_t VmcbClean : 1; + uint32_t FlushByAsid : 1; + uint32_t DecodeAssists : 1; + uint32_t Reserved0 : 2; + uint32_t PauseFilter : 1; + uint32_t Reserved1 : 1; + uint32_t PauseFilterThreshold : 1; + uint32_t AVIC : 1; + uint32_t Reserved2 : 1; + uint32_t VMSAVEvirt : 1; + uint32_t VGIF : 1; + uint32_t GMET : 1; + uint32_t x2AVIC : 1; + uint32_t SSSCheck : 1; + uint32_t SpecCtrl : 1; + uint32_t ROGPT : 1; + uint32_t Reserved3 : 1; + uint32_t HOST_MCE_OVERRIDE : 1; + uint32_t TlbiCtl : 1; + uint32_t VNMI : 1; + uint32_t IbsVirt : 1; + uint32_t Reserved4 : 4; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x80000019 - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x80000019 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000019)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000019)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x8000001A - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x8000001A + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x8000001A)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x8000001A)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x8000001B - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x8000001B + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x8000001B)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x8000001B)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x8000001C - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x8000001C + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x8000001C)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x8000001C)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x8000001D - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x8000001D + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x8000001D)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x8000001D)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x8000001E - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x8000001E + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x8000001E)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x8000001E)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x8000001F - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x8000001F + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x8000001F)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x8000001F)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x80000020 - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x80000020 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000020)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000020)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x80000021 - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x80000021 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000021)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000021)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x80000022 - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x80000022 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000022)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000022)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x80000023 - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x80000023 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000023)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000023)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief TODO */ - struct CPUID0x80000026 - { - __always_inline inline void Get() - { + /** @brief TODO */ + struct CPUID0x80000026 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000026)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000026)); #endif // a64 || a32 - } + } - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EAX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EAX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EBX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EBX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } ECX; + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } ECX; - /** @brief */ - union - { - struct - { - uint32_t todo : 32; - }; - cpuid_t raw; - } EDX; - }; - } - } + /** @brief */ + union + { + struct + { + uint32_t todo : 32; + }; + cpuid_t raw; + } EDX; + }; + + /** + * AMD Easter Egg + * + * AMD K6: "NexGen‍erationAMD" + * AMD K8: "IT'S HAMMER TIME" + * AMD JAGUAR: "HELLO KITTY! ^-^" + * + * @note This cpuid is not found on AMD's manual + */ + struct CPUID0x8FFFFFFF + { + __always_inline inline void Get() + { +#if defined(a86) + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x8FFFFFFF)); +#endif // a64 || a32 + } + + /** + * String + */ + union + { + struct + { + char String[4]; + }; + cpuid_t raw; + } EAX; + + /** + * String + */ + union + { + struct + { + char String[4]; + }; + cpuid_t raw; + } EBX; + + /** + * String + */ + union + { + struct + { + char String[4]; + }; + cpuid_t raw; + } ECX; + + /** + * String + */ + union + { + struct + { + char String[4]; + }; + cpuid_t raw; + } EDX; + }; + } + } } #endif // !__FENNIX_KERNEL_CPU_x86_CPUID_AMD_H__ diff --git a/include/cpu/x86/cpuid_intel.hpp b/include/cpu/x86/cpuid_intel.hpp index 26ab2f9..daab964 100644 --- a/include/cpu/x86/cpuid_intel.hpp +++ b/include/cpu/x86/cpuid_intel.hpp @@ -30,1402 +30,1402 @@ typedef uint64_t cpuid_t; namespace CPU { - namespace x86 - { - /** @brief EXPERIMENTAL IMPLEMENTATION */ - namespace Intel - { - /** @brief Basic CPU information */ - struct CPUID0x00000000 - { - __always_inline inline void Get() - { + namespace x86 + { + /** @brief EXPERIMENTAL IMPLEMENTATION */ + namespace Intel + { + /** @brief Basic CPU information */ + struct CPUID0x00000000 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x0)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x0)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t HighestFunctionSupported : 32; - }; - cpuid_t raw; - } EAX; - union - { - struct - { - char Vendor[4]; - }; - cpuid_t raw; - } EBX; - union - { - struct - { - char Vendor[4]; - }; - cpuid_t raw; - } ECX; - union - { - struct - { - char Vendor[4]; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + uint32_t HighestFunctionSupported : 32; + }; + cpuid_t raw; + } EAX; + union + { + struct + { + char Vendor[4]; + }; + cpuid_t raw; + } EBX; + union + { + struct + { + char Vendor[4]; + }; + cpuid_t raw; + } ECX; + union + { + struct + { + char Vendor[4]; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Additional CPU information */ - struct CPUID0x00000001 - { - __always_inline inline void Get() - { + /** @brief Additional CPU information */ + struct CPUID0x00000001 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x1)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x1)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t Stepping : 4; - uint32_t Model : 4; - uint32_t Family : 4; - /** - * @brief Processor Type - * - * 00: Original OEM Processor - * 01: Intel OverDrive Processor - * 10: Dual processor - * 11: Intel reserved - */ - uint32_t ProcessorType : 2; - uint32_t Reserved0 : 2; - uint32_t ExtendedModel : 4; - uint32_t ExtendedFamily : 8; - uint32_t Reserved1 : 4; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t Stepping : 4; + uint32_t Model : 4; + uint32_t Family : 4; + /** + * @brief Processor Type + * + * 00: Original OEM Processor + * 01: Intel OverDrive Processor + * 10: Dual processor + * 11: Intel reserved + */ + uint32_t ProcessorType : 2; + uint32_t Reserved0 : 2; + uint32_t ExtendedModel : 4; + uint32_t ExtendedFamily : 8; + uint32_t Reserved1 : 4; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t BrandIndex : 8; - uint32_t CLFLUSHLineSize : 8; - uint32_t LogicalProcessorsPerPackage : 8; - uint32_t DefaultAPICID : 8; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t BrandIndex : 8; + uint32_t CLFLUSHLineSize : 8; + uint32_t LogicalProcessorsPerPackage : 8; + uint32_t DefaultAPICID : 8; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t SSE3 : 1; - uint32_t PCLMULDQ : 1; - uint32_t DTES64 : 1; - uint32_t MONITOR : 1; - uint32_t DS_CPL : 1; - uint32_t VMX : 1; - uint32_t SMX : 1; - uint32_t EIST : 1; - uint32_t TM2 : 1; - uint32_t SSSE3 : 1; - uint32_t CNXT_ID : 1; - uint32_t Reserved0 : 1; - uint32_t FMA : 1; - uint32_t CX16 : 1; - uint32_t xTPR : 1; - uint32_t PDCM : 1; - uint32_t Reserved1 : 1; - uint32_t PCID : 1; - uint32_t DCA : 1; - uint32_t SSE4_1 : 1; - uint32_t SSE4_2 : 1; - uint32_t x2APIC : 1; - uint32_t MOVBE : 1; - uint32_t POPCNT : 1; - uint32_t TSC_DEADLINE : 1; - uint32_t AES : 1; - uint32_t XSAVE : 1; - uint32_t OSXSAVE : 1; - uint32_t AVX : 1; - uint32_t F16C : 1; - uint32_t RDRAND : 1; - /** - * @note Not sure if this is correct - * Intel documentation says it's "Not Used; Always returns 0." - */ - uint32_t Hypervisor : 1; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t SSE3 : 1; + uint32_t PCLMULDQ : 1; + uint32_t DTES64 : 1; + uint32_t MONITOR : 1; + uint32_t DS_CPL : 1; + uint32_t VMX : 1; + uint32_t SMX : 1; + uint32_t EIST : 1; + uint32_t TM2 : 1; + uint32_t SSSE3 : 1; + uint32_t CNXT_ID : 1; + uint32_t Reserved0 : 1; + uint32_t FMA : 1; + uint32_t CX16 : 1; + uint32_t xTPR : 1; + uint32_t PDCM : 1; + uint32_t Reserved1 : 1; + uint32_t PCID : 1; + uint32_t DCA : 1; + uint32_t SSE4_1 : 1; + uint32_t SSE4_2 : 1; + uint32_t x2APIC : 1; + uint32_t MOVBE : 1; + uint32_t POPCNT : 1; + uint32_t TSC_DEADLINE : 1; + uint32_t AES : 1; + uint32_t XSAVE : 1; + uint32_t OSXSAVE : 1; + uint32_t AVX : 1; + uint32_t F16C : 1; + uint32_t RDRAND : 1; + /** + * @note Not sure if this is correct + * Intel documentation says it's "Not Used; Always returns 0." + */ + uint32_t Hypervisor : 1; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t FPU : 1; - uint32_t VME : 1; - uint32_t DE : 1; - uint32_t PSE : 1; - uint32_t TSC : 1; - uint32_t MSR : 1; - uint32_t PAE : 1; - uint32_t MCE : 1; - uint32_t CX8 : 1; - uint32_t APIC : 1; - uint32_t Reserved0 : 1; - uint32_t SEP : 1; - uint32_t MTRR : 1; - uint32_t PGE : 1; - uint32_t MCA : 1; - uint32_t CMOV : 1; - uint32_t PAT : 1; - uint32_t PSE36 : 1; - uint32_t PSN : 1; - uint32_t CLFSH : 1; - uint32_t Reserved1 : 1; - uint32_t DS : 1; - uint32_t ACPI : 1; - uint32_t MMX : 1; - uint32_t FXSR : 1; - uint32_t SSE : 1; - uint32_t SSE2 : 1; - uint32_t SS : 1; - uint32_t HTT : 1; - uint32_t TM : 1; - uint32_t Reserved2 : 1; - uint32_t PBE : 1; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + uint32_t FPU : 1; + uint32_t VME : 1; + uint32_t DE : 1; + uint32_t PSE : 1; + uint32_t TSC : 1; + uint32_t MSR : 1; + uint32_t PAE : 1; + uint32_t MCE : 1; + uint32_t CX8 : 1; + uint32_t APIC : 1; + uint32_t Reserved0 : 1; + uint32_t SEP : 1; + uint32_t MTRR : 1; + uint32_t PGE : 1; + uint32_t MCA : 1; + uint32_t CMOV : 1; + uint32_t PAT : 1; + uint32_t PSE36 : 1; + uint32_t PSN : 1; + uint32_t CLFSH : 1; + uint32_t Reserved1 : 1; + uint32_t DS : 1; + uint32_t ACPI : 1; + uint32_t MMX : 1; + uint32_t FXSR : 1; + uint32_t SSE : 1; + uint32_t SSE2 : 1; + uint32_t SS : 1; + uint32_t HTT : 1; + uint32_t TM : 1; + uint32_t Reserved2 : 1; + uint32_t PBE : 1; + }; + cpuid_t raw; + } EDX; + }; - /** @brief CPU cache and TLB */ /* FIXME TODO */ - struct CPUID0x00000002 - { - __always_inline inline void Get() - { + /** @brief CPU cache and TLB */ /* FIXME TODO */ + struct CPUID0x00000002 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x2)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x2)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t CacheLineSize : 8; - uint32_t CacheLinesPerTag : 8; - uint32_t Associativity : 8; - uint32_t CacheSize : 8; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t CacheLineSize : 8; + uint32_t CacheLinesPerTag : 8; + uint32_t Associativity : 8; + uint32_t CacheSize : 8; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t CacheLineSize : 8; - uint32_t CacheLinesPerTag : 8; - uint32_t Associativity : 8; - uint32_t CacheSize : 8; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t CacheLineSize : 8; + uint32_t CacheLinesPerTag : 8; + uint32_t Associativity : 8; + uint32_t CacheSize : 8; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t CacheLineSize : 8; - uint32_t CacheLinesPerTag : 8; - uint32_t Associativity : 8; - uint32_t CacheSize : 8; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t CacheLineSize : 8; + uint32_t CacheLinesPerTag : 8; + uint32_t Associativity : 8; + uint32_t CacheSize : 8; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t CacheLineSize : 8; - uint32_t CacheLinesPerTag : 8; - uint32_t Associativity : 8; - uint32_t CacheSize : 8; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + uint32_t CacheLineSize : 8; + uint32_t CacheLinesPerTag : 8; + uint32_t Associativity : 8; + uint32_t CacheSize : 8; + }; + cpuid_t raw; + } EDX; + }; - /** @brief CPU serial number */ - struct CPUID0x00000003 - { - __always_inline inline void Get() - { + /** @brief CPU serial number */ + struct CPUID0x00000003 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x3)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x3)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t ProcessorSerialNumber : 32; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t ProcessorSerialNumber : 32; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t ProcessorSerialNumber : 32; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + uint32_t ProcessorSerialNumber : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Cache information */ - struct CPUID0x00000004_1 - { - __always_inline inline void Get() - { + /** @brief Cache information */ + struct CPUID0x00000004_1 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x4), "c"(0x1)); /* FIXME */ + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x4), "c"(0x1)); /* FIXME */ #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t Type : 5; - uint32_t Level : 3; - uint32_t SelfInitializing : 1; - uint32_t FullyAssociative : 1; - uint32_t Reserved : 4; - uint32_t MaxAddressableIdsForLogicalProcessors : 12; - uint32_t CoresPerPackage : 6; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t Type : 5; + uint32_t Level : 3; + uint32_t SelfInitializing : 1; + uint32_t FullyAssociative : 1; + uint32_t Reserved : 4; + uint32_t MaxAddressableIdsForLogicalProcessors : 12; + uint32_t CoresPerPackage : 6; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t SystemCoherencyLineSize : 12; - uint32_t PhysicalLinePartitions : 10; - uint32_t WaysOfAssociativity : 10; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t SystemCoherencyLineSize : 12; + uint32_t PhysicalLinePartitions : 10; + uint32_t WaysOfAssociativity : 10; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief MONITOR information */ - struct CPUID0x00000005 - { - __always_inline inline void Get() - { + /** @brief MONITOR information */ + struct CPUID0x00000005 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x5)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x5)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t SmallestMonitorLineSize : 16; - uint32_t Reserved : 16; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t SmallestMonitorLineSize : 16; + uint32_t Reserved : 16; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t LargestMonitorLineSize : 16; - uint32_t Reserved : 16; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t LargestMonitorLineSize : 16; + uint32_t Reserved : 16; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t MWAITEnumerationSupported : 1; - uint32_t InterruptsAsBreakEvent : 1; - uint32_t Reserved : 30; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t MWAITEnumerationSupported : 1; + uint32_t InterruptsAsBreakEvent : 1; + uint32_t Reserved : 30; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t C0 : 4; - uint32_t C1 : 4; - uint32_t C2 : 4; - uint32_t C3 : 4; - uint32_t C4 : 4; - uint32_t Reserved : 12; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + uint32_t C0 : 4; + uint32_t C1 : 4; + uint32_t C2 : 4; + uint32_t C3 : 4; + uint32_t C4 : 4; + uint32_t Reserved : 12; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Thermal and power management information */ - struct CPUID0x00000006 - { - __always_inline inline void Get() - { + /** @brief Thermal and power management information */ + struct CPUID0x00000006 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x6)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x6)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t SensorSupported : 1; - uint32_t Reserved : 31; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t SensorSupported : 1; + uint32_t Reserved : 31; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t InterruptThreshold : 4; - uint32_t Reserved : 26; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t InterruptThreshold : 4; + uint32_t Reserved : 26; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t ACNT_MCNT : 1; - uint32_t Reserved : 31; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t ACNT_MCNT : 1; + uint32_t Reserved : 31; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Extended feature flags enumeration */ - struct CPUID0x00000007_0 - { - __always_inline inline void Get() - { + /** @brief Extended feature flags enumeration */ + struct CPUID0x00000007_0 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x7), "c"(0x0)); /* FIXME */ + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x7), "c"(0x0)); /* FIXME */ #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - /** @brief Access to base of fs and gs */ - uint32_t FSGSBase : 1; - /** @brief IA32_TSC_ADJUST MSR */ - uint32_t IA32TSCAdjust : 1; - /** @brief Software Guard Extensions */ - uint32_t SGX : 1; - /** @brief Bit Manipulation Instruction Set 1 */ - uint32_t BMI1 : 1; - /** @brief TSX Hardware Lock Elision */ - uint32_t HLE : 1; - /** @brief Advanced Vector Extensions 2 */ - uint32_t AVX2 : 1; - /** @brief FDP_EXCPTN_ONLY */ - uint32_t FDPExcptonOnly : 1; - /** @brief Supervisor Mode Execution Protection */ - uint32_t SMEP : 1; - /** @brief Bit Manipulation Instruction Set 2 */ - uint32_t BMI2 : 1; - /** @brief Enhanced REP MOVSB/STOSB */ - uint32_t ERMS : 1; - /** @brief INVPCID */ - uint32_t INVPCID : 1; - /** @brief RTM */ - uint32_t RTM : 1; - /** @brief Intel Resource Director Monitoring */ - uint32_t RDT_M : 1; - /** @brief Deprecates FPU CS and DS values */ - uint32_t DeprecatesFPU : 1; - /** @brief Intel Memory Protection Extensions */ - uint32_t MPX : 1; - /** @brief Intel Resource Director Allocation */ - uint32_t RDT_A : 1; - /** @brief AVX-512 Foundation */ - uint32_t AVX512F : 1; - /** @brief AVX-512 Doubleword and Quadword Instructions */ - uint32_t AVX512DQ : 1; - /** @brief RDSEED */ - uint32_t RDSEED : 1; - /** @brief Intel Multi-Precision Add-Carry Instruction Extensions */ - uint32_t ADX : 1; - /** @brief Supervisor Mode Access Prevention */ - uint32_t SMAP : 1; - /** @brief AVX-512 Integer Fused Multiply-Add Instructions */ - uint32_t AVX512IFMA : 1; - /** @brief Reserved */ - uint32_t Reserved : 1; - /** @brief CLFLUSHOPT */ - uint32_t CLFLUSHOPT : 1; - /** @brief CLWB */ - uint32_t CLWB : 1; - /** @brief Intel Processor Trace */ - uint32_t IntelProcessorTrace : 1; - /** @brief AVX-512 Prefetch Instructions */ - uint32_t AVX512PF : 1; - /** @brief AVX-512 Exponential and Reciprocal Instructions */ - uint32_t AVX512ER : 1; - /** @brief AVX-512 Conflict Detection Instructions */ - uint32_t AVX512CD : 1; - /** @brief SHA Extensions */ - uint32_t SHA : 1; - /** @brief AVX-512 Byte and Word Instructions */ - uint32_t AVX512BW : 1; - /** @brief AVX-512 Vector Length Extensions */ - uint32_t AVX512VL : 1; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + /** @brief Access to base of fs and gs */ + uint32_t FSGSBase : 1; + /** @brief IA32_TSC_ADJUST MSR */ + uint32_t IA32TSCAdjust : 1; + /** @brief Software Guard Extensions */ + uint32_t SGX : 1; + /** @brief Bit Manipulation Instruction Set 1 */ + uint32_t BMI1 : 1; + /** @brief TSX Hardware Lock Elision */ + uint32_t HLE : 1; + /** @brief Advanced Vector Extensions 2 */ + uint32_t AVX2 : 1; + /** @brief FDP_EXCPTN_ONLY */ + uint32_t FDPExcptonOnly : 1; + /** @brief Supervisor Mode Execution Protection */ + uint32_t SMEP : 1; + /** @brief Bit Manipulation Instruction Set 2 */ + uint32_t BMI2 : 1; + /** @brief Enhanced REP MOVSB/STOSB */ + uint32_t ERMS : 1; + /** @brief INVPCID */ + uint32_t INVPCID : 1; + /** @brief RTM */ + uint32_t RTM : 1; + /** @brief Intel Resource Director Monitoring */ + uint32_t RDT_M : 1; + /** @brief Deprecates FPU CS and DS values */ + uint32_t DeprecatesFPU : 1; + /** @brief Intel Memory Protection Extensions */ + uint32_t MPX : 1; + /** @brief Intel Resource Director Allocation */ + uint32_t RDT_A : 1; + /** @brief AVX-512 Foundation */ + uint32_t AVX512F : 1; + /** @brief AVX-512 Doubleword and Quadword Instructions */ + uint32_t AVX512DQ : 1; + /** @brief RDSEED */ + uint32_t RDSEED : 1; + /** @brief Intel Multi-Precision Add-Carry Instruction Extensions */ + uint32_t ADX : 1; + /** @brief Supervisor Mode Access Prevention */ + uint32_t SMAP : 1; + /** @brief AVX-512 Integer Fused Multiply-Add Instructions */ + uint32_t AVX512IFMA : 1; + /** @brief Reserved */ + uint32_t Reserved : 1; + /** @brief CLFLUSHOPT */ + uint32_t CLFLUSHOPT : 1; + /** @brief CLWB */ + uint32_t CLWB : 1; + /** @brief Intel Processor Trace */ + uint32_t IntelProcessorTrace : 1; + /** @brief AVX-512 Prefetch Instructions */ + uint32_t AVX512PF : 1; + /** @brief AVX-512 Exponential and Reciprocal Instructions */ + uint32_t AVX512ER : 1; + /** @brief AVX-512 Conflict Detection Instructions */ + uint32_t AVX512CD : 1; + /** @brief SHA Extensions */ + uint32_t SHA : 1; + /** @brief AVX-512 Byte and Word Instructions */ + uint32_t AVX512BW : 1; + /** @brief AVX-512 Vector Length Extensions */ + uint32_t AVX512VL : 1; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - /** @brief PREFETCHWT1 */ - uint32_t PREFETCHWT1 : 1; - /** @brief AVX-512 Vector Bit Manipulation Instructions */ - uint32_t AVX512VBMI : 1; - /** @brief User Mode Instruction Prevention */ - uint32_t UMIP : 1; - /** @brief Memory Protection Keys for User-mode pages */ - uint32_t PKU : 1; - /** @brief PKU enabled by OS */ - uint32_t OSPKE : 1; - /** @brief Timed pause and user-level monitor/wait */ - uint32_t WaitPKG : 1; - /** @brief AVX-512 Vector Bit Manipulation Instructions 2 */ - uint32_t AVX512VBMI2 : 1; - /** @brief Control flow enforcement (CET) shadow stack */ - uint32_t CET_SS : 1; - /** @brief Galois Field instructions */ - uint32_t GFNI : 1; - /** @brief Vector AES instruction set (VEX-256/EVEX) */ - uint32_t VAES : 1; - /** @brief CLMUL instruction set (VEX-256/EVEX) */ - uint32_t VPCLMULQDQ : 1; - /** @brief AVX-512 Vector Neural Network Instructions */ - uint32_t AVX512VNNI : 1; - /** @brief AVX-512 Bit Algorithms Instructions */ - uint32_t AVX512BITALG : 1; - /** @brief IA32_TME related MSRs */ - uint32_t TME : 1; - /** @brief AVX-512 Vector Population Count Double and Quad-word */ - uint32_t AVX512VPOPCNTDQ : 1; - /** @brief Reserved */ - uint32_t Reserved0 : 1; - /** @brief 5-level paging (57 address bits) */ - uint32_t LA57 : 1; - /** @brief The value of userspace MPX Address-Width Adjust used by the BNDLDX and BNDSTX Intel MPX instructions in 64-bit mode */ - uint32_t MAWAU : 5; - /** @brief Read Processor ID and IA32_TSC_AUX */ - uint32_t RDPID : 1; - /** @brief Key Locker */ - uint32_t KL : 1; - /** @brief BUS_LOCK_DETECT */ - uint32_t BusLockDetect : 1; - /** @brief Cache line demote */ - uint32_t CLDEMOTE : 1; - /** @brief Reserved */ - uint32_t Reserved1 : 1; - /** @brief MOVDIRI */ - uint32_t MOVDIRI : 1; - /** @brief MOVDIR64B */ - uint32_t MOVDIR64B : 1; - /** @brief SGX Launch Configuration */ - uint32_t SGX_LC : 1; - /** @brief Protection Keys for Supervisor-mode pages */ - uint32_t PKS : 1; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + /** @brief PREFETCHWT1 */ + uint32_t PREFETCHWT1 : 1; + /** @brief AVX-512 Vector Bit Manipulation Instructions */ + uint32_t AVX512VBMI : 1; + /** @brief User Mode Instruction Prevention */ + uint32_t UMIP : 1; + /** @brief Memory Protection Keys for User-mode pages */ + uint32_t PKU : 1; + /** @brief PKU enabled by OS */ + uint32_t OSPKE : 1; + /** @brief Timed pause and user-level monitor/wait */ + uint32_t WaitPKG : 1; + /** @brief AVX-512 Vector Bit Manipulation Instructions 2 */ + uint32_t AVX512VBMI2 : 1; + /** @brief Control flow enforcement (CET) shadow stack */ + uint32_t CET_SS : 1; + /** @brief Galois Field instructions */ + uint32_t GFNI : 1; + /** @brief Vector AES instruction set (VEX-256/EVEX) */ + uint32_t VAES : 1; + /** @brief CLMUL instruction set (VEX-256/EVEX) */ + uint32_t VPCLMULQDQ : 1; + /** @brief AVX-512 Vector Neural Network Instructions */ + uint32_t AVX512VNNI : 1; + /** @brief AVX-512 Bit Algorithms Instructions */ + uint32_t AVX512BITALG : 1; + /** @brief IA32_TME related MSRs */ + uint32_t TME : 1; + /** @brief AVX-512 Vector Population Count Double and Quad-word */ + uint32_t AVX512VPOPCNTDQ : 1; + /** @brief Reserved */ + uint32_t Reserved0 : 1; + /** @brief 5-level paging (57 address bits) */ + uint32_t LA57 : 1; + /** @brief The value of userspace MPX Address-Width Adjust used by the BNDLDX and BNDSTX Intel MPX instructions in 64-bit mode */ + uint32_t MAWAU : 5; + /** @brief Read Processor ID and IA32_TSC_AUX */ + uint32_t RDPID : 1; + /** @brief Key Locker */ + uint32_t KL : 1; + /** @brief BUS_LOCK_DETECT */ + uint32_t BusLockDetect : 1; + /** @brief Cache line demote */ + uint32_t CLDEMOTE : 1; + /** @brief Reserved */ + uint32_t Reserved1 : 1; + /** @brief MOVDIRI */ + uint32_t MOVDIRI : 1; + /** @brief MOVDIR64B */ + uint32_t MOVDIR64B : 1; + /** @brief SGX Launch Configuration */ + uint32_t SGX_LC : 1; + /** @brief Protection Keys for Supervisor-mode pages */ + uint32_t PKS : 1; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - /** @brief Reserved */ - uint32_t Reserved0 : 2; - /** @brief AVX-512 4-register Neural Network Instructions */ - uint32_t AVX512_4VNNIW : 1; - /** @brief AVX-512 4-register Multiply Accumulation Single Precision */ - uint32_t AVX512_4FMAPS : 1; - /** @brief Fast Short REP MOVSB/STOSB */ - uint32_t FSRM : 1; - /** @brief User Inter-Processor Interrupts */ - uint32_t UINTR : 1; - /** @brief Reserved */ - uint32_t Reserved1 : 2; - /** @brief AVX-512 VP2INTERSECT Doubleword and Quadword Instructions */ - uint32_t AVX512_VP2INTERSECT : 1; - /** @brief Special Register Buffer Data Sampling Mitigations */ - uint32_t SRBDS_CTRL : 1; - /** @brief VERW instruction clears CPU buffers */ - uint32_t MC_CLEAR : 1; - /** @brief All TSX transactions are aborted */ - uint32_t TSX_FORCE_ABORT : 1; - /** @brief Reserved */ - uint32_t Reserved2 : 1; - /** @brief TSX_FORCE_ABORT MSR is available */ - uint32_t TsxForceAbortMsr : 1; - /** @brief SERIALIZE */ - uint32_t SERIALIZE : 1; - /** @brief Mixture of CPU types in processor topology */ - uint32_t HYBRID : 1; - /** @brief TSXLDTRK */ - uint32_t TSXLDTRK : 1; - /** @brief Reserved */ - uint32_t Reserved3 : 1; - /** @brief Platform configuration for Memory Encryption Technologies Instrctuions */ - uint32_t PCONFIG : 1; - /** @brief Architectural Last Branch Records */ - uint32_t LBR : 1; - /** @brief Control flow enforcement (CET) indirect branch tracking */ - uint32_t CET_IBT : 1; - /** @brief Reserved */ - uint32_t Reserved4 : 1; - /** @brief Tile computation on bfloat16 numbers */ - uint32_t AMX_BF16 : 1; - /** @brief AVX512-FP16 half-precision floating-point instructions */ - uint32_t AVX512_FP16 : 1; - /** @brief Tile architecture */ - uint32_t AMX_TILE : 1; - /** @brief Tile computation on 8-bit integers */ - uint32_t AMX_INT8 : 1; - /** @brief Speculation Control, part of Indirect Branch Control (IBC): - Indirect Branch Restricted Speculation (IBRS) and - Indirect Branch Prediction Barrier (IBPB) */ - uint32_t SPEC_CTRL : 1; - /** @brief Single Thread Indirect Branch Predictor, part of IBC */ - uint32_t STIBP : 1; - /** @brief IA32_FLUSH_CMD MSR */ - uint32_t L1D_FLUSH : 1; - /** @brief IA32_ARCH_CAPABILITIES (lists speculative side channel mitigations */ - uint32_t ArchCapabilities : 1; - /** @brief IA32_CORE_CAPABILITIES MSR (lists model-specific core capabilities) */ - uint32_t CoreCapabilities : 1; - /** @brief Speculative Store Bypass Disable, as mitigation for Speculative Store Bypass (IA32_SPEC_CTRL) */ - uint32_t SSBD : 1; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + /** @brief Reserved */ + uint32_t Reserved0 : 2; + /** @brief AVX-512 4-register Neural Network Instructions */ + uint32_t AVX512_4VNNIW : 1; + /** @brief AVX-512 4-register Multiply Accumulation Single Precision */ + uint32_t AVX512_4FMAPS : 1; + /** @brief Fast Short REP MOVSB/STOSB */ + uint32_t FSRM : 1; + /** @brief User Inter-Processor Interrupts */ + uint32_t UINTR : 1; + /** @brief Reserved */ + uint32_t Reserved1 : 2; + /** @brief AVX-512 VP2INTERSECT Doubleword and Quadword Instructions */ + uint32_t AVX512_VP2INTERSECT : 1; + /** @brief Special Register Buffer Data Sampling Mitigations */ + uint32_t SRBDS_CTRL : 1; + /** @brief VERW instruction clears CPU buffers */ + uint32_t MC_CLEAR : 1; + /** @brief All TSX transactions are aborted */ + uint32_t TSX_FORCE_ABORT : 1; + /** @brief Reserved */ + uint32_t Reserved2 : 1; + /** @brief TSX_FORCE_ABORT MSR is available */ + uint32_t TsxForceAbortMsr : 1; + /** @brief SERIALIZE */ + uint32_t SERIALIZE : 1; + /** @brief Mixture of CPU types in processor topology */ + uint32_t HYBRID : 1; + /** @brief TSXLDTRK */ + uint32_t TSXLDTRK : 1; + /** @brief Reserved */ + uint32_t Reserved3 : 1; + /** @brief Platform configuration for Memory Encryption Technologies Instrctuions */ + uint32_t PCONFIG : 1; + /** @brief Architectural Last Branch Records */ + uint32_t LBR : 1; + /** @brief Control flow enforcement (CET) indirect branch tracking */ + uint32_t CET_IBT : 1; + /** @brief Reserved */ + uint32_t Reserved4 : 1; + /** @brief Tile computation on bfloat16 numbers */ + uint32_t AMX_BF16 : 1; + /** @brief AVX512-FP16 half-precision floating-point instructions */ + uint32_t AVX512_FP16 : 1; + /** @brief Tile architecture */ + uint32_t AMX_TILE : 1; + /** @brief Tile computation on 8-bit integers */ + uint32_t AMX_INT8 : 1; + /** @brief Speculation Control, part of Indirect Branch Control (IBC): + Indirect Branch Restricted Speculation (IBRS) and + Indirect Branch Prediction Barrier (IBPB) */ + uint32_t SPEC_CTRL : 1; + /** @brief Single Thread Indirect Branch Predictor, part of IBC */ + uint32_t STIBP : 1; + /** @brief IA32_FLUSH_CMD MSR */ + uint32_t L1D_FLUSH : 1; + /** @brief IA32_ARCH_CAPABILITIES (lists speculative side channel mitigations */ + uint32_t ArchCapabilities : 1; + /** @brief IA32_CORE_CAPABILITIES MSR (lists model-specific core capabilities) */ + uint32_t CoreCapabilities : 1; + /** @brief Speculative Store Bypass Disable, as mitigation for Speculative Store Bypass (IA32_SPEC_CTRL) */ + uint32_t SSBD : 1; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Extended feature flags enumeration */ - struct CPUID0x00000007_1 - { - __always_inline inline void Get() - { + /** @brief Extended feature flags enumeration */ + struct CPUID0x00000007_1 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x7), "c"(0x1)); /* FIXME */ + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x7), "c"(0x1)); /* FIXME */ #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t Reserved0 : 3; - /** @brief RAO-INT */ - uint32_t RAO_INT : 1; - /** @brief AVX Vector Neural Network Instructions (XNNI) (VEX encoded) */ - uint32_t AVX_VNNI : 1; - /** @brief AVX-512 instructions for bfloat16 numbers */ - uint32_t AVX512_BF16 : 1; - /** @brief Reserved */ - uint32_t Reserved1 : 1; - /** @brief CMPccXADD */ - uint32_t CMPCCXADD : 1; - /** @brief Architectural Performance Monitoring Extended Leaf (EAX=23h) */ - uint32_t ARCHPERFMONEXT : 1; - /** @brief Reserved */ - uint32_t Reserved2 : 1; - /** @brief Fast zero-length MOVSB */ - uint32_t FAST_ZERO_REP_MOVSB : 1; - /** @brief Fast zero-length STOSB */ - uint32_t FAST_SHORT_REP_STOSB : 1; - /** @brief Fast zero-length CMPSB and SCASB */ - uint32_t FAST_SHORT_REP_CMPSB_SCASB : 1; - /** @brief Reserved */ - uint32_t Reserved3 : 4; - /** @brief Flexible Return and Event Delivery */ - uint32_t FRED : 1; - /** @brief LKGS Instruction */ - uint32_t LKGS : 1; - /** @brief WRMSRNS instruction */ - uint32_t WRMSRNS : 1; - /** @brief Reserved */ - uint32_t Reserved4 : 1; - /** @brief AMX instructions for FP16 numbers */ - uint32_t AMX_FP16 : 1; - /** @brief HRESET instruction, IA32_HRESET_ENABLE MSR, and Processor History Reset Leaf (EAX=20h) */ - uint32_t HRESET : 1; - /** @brief AVX IFMA instructions */ - uint32_t AVX_IFMA : 1; - /** @brief Reserved */ - uint32_t Reserved5 : 2; - /** @brief Linear Address Masking */ - uint32_t LAM : 1; - /** @brief RDMSRLIST and WRMSRLIST instructions, and the IA32_BARRIER MSR */ - uint32_t MSRLIST : 1; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t Reserved0 : 3; + /** @brief RAO-INT */ + uint32_t RAO_INT : 1; + /** @brief AVX Vector Neural Network Instructions (XNNI) (VEX encoded) */ + uint32_t AVX_VNNI : 1; + /** @brief AVX-512 instructions for bfloat16 numbers */ + uint32_t AVX512_BF16 : 1; + /** @brief Reserved */ + uint32_t Reserved1 : 1; + /** @brief CMPccXADD */ + uint32_t CMPCCXADD : 1; + /** @brief Architectural Performance Monitoring Extended Leaf (EAX=23h) */ + uint32_t ARCHPERFMONEXT : 1; + /** @brief Reserved */ + uint32_t Reserved2 : 1; + /** @brief Fast zero-length MOVSB */ + uint32_t FAST_ZERO_REP_MOVSB : 1; + /** @brief Fast zero-length STOSB */ + uint32_t FAST_SHORT_REP_STOSB : 1; + /** @brief Fast zero-length CMPSB and SCASB */ + uint32_t FAST_SHORT_REP_CMPSB_SCASB : 1; + /** @brief Reserved */ + uint32_t Reserved3 : 4; + /** @brief Flexible Return and Event Delivery */ + uint32_t FRED : 1; + /** @brief LKGS Instruction */ + uint32_t LKGS : 1; + /** @brief WRMSRNS instruction */ + uint32_t WRMSRNS : 1; + /** @brief Reserved */ + uint32_t Reserved4 : 1; + /** @brief AMX instructions for FP16 numbers */ + uint32_t AMX_FP16 : 1; + /** @brief HRESET instruction, IA32_HRESET_ENABLE MSR, and Processor History Reset Leaf (EAX=20h) */ + uint32_t HRESET : 1; + /** @brief AVX IFMA instructions */ + uint32_t AVX_IFMA : 1; + /** @brief Reserved */ + uint32_t Reserved5 : 2; + /** @brief Linear Address Masking */ + uint32_t LAM : 1; + /** @brief RDMSRLIST and WRMSRLIST instructions, and the IA32_BARRIER MSR */ + uint32_t MSRLIST : 1; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - /** @brief IA32_PPIN and IA32_PPIN_CTL MSRs */ - uint32_t PPIN : 1; - /** @brief Reserved */ - uint32_t Reserved : 31; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + /** @brief IA32_PPIN and IA32_PPIN_CTL MSRs */ + uint32_t PPIN : 1; + /** @brief Reserved */ + uint32_t Reserved : 31; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - /** @brief Reserved */ - uint32_t Reserved : 32; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + /** @brief Reserved */ + uint32_t Reserved : 32; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - /** @brief Reserved */ - uint32_t Reserved0 : 4; - /** @brief AVX VNNI INT8 instructions */ - uint32_t AVX_VNNI_INT8 : 1; - /** @brief AVX NE CONVERT instructions */ - uint32_t AVX_NE_CONVERT : 1; - /** @brief Reserved */ - uint32_t Reserved1 : 8; - /** @brief PREFETCHIT0 and PREFETCHIT1 instructions */ - uint32_t PREFETCHIT : 1; - /** @brief Reserved */ - uint32_t Reserved2 : 17; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + /** @brief Reserved */ + uint32_t Reserved0 : 4; + /** @brief AVX VNNI INT8 instructions */ + uint32_t AVX_VNNI_INT8 : 1; + /** @brief AVX NE CONVERT instructions */ + uint32_t AVX_NE_CONVERT : 1; + /** @brief Reserved */ + uint32_t Reserved1 : 8; + /** @brief PREFETCHIT0 and PREFETCHIT1 instructions */ + uint32_t PREFETCHIT : 1; + /** @brief Reserved */ + uint32_t Reserved2 : 17; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Performance monitors */ - struct CPUID0x0000000A - { - __always_inline inline void Get() - { + /** @brief Performance monitors */ + struct CPUID0x0000000A + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0xA)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0xA)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t VersionID : 8; - uint32_t NumberCounters : 8; - uint32_t BitWidthOfCounters : 8; - uint32_t LengthOfEBXBitVector : 8; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t VersionID : 8; + uint32_t NumberCounters : 8; + uint32_t BitWidthOfCounters : 8; + uint32_t LengthOfEBXBitVector : 8; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t CoreCycles : 1; - uint32_t InstructionsRetired : 1; - uint32_t ReferenceCycles : 1; - uint32_t CacheReferences : 1; - uint32_t CacheMisses : 1; - uint32_t BranchInstructionsRetired : 1; - uint32_t BranchMissesRetired : 1; - uint32_t Reserved : 25; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t CoreCycles : 1; + uint32_t InstructionsRetired : 1; + uint32_t ReferenceCycles : 1; + uint32_t CacheReferences : 1; + uint32_t CacheMisses : 1; + uint32_t BranchInstructionsRetired : 1; + uint32_t BranchMissesRetired : 1; + uint32_t Reserved : 25; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t FixedFunctionCounters : 5; - uint32_t CounterWidth : 8; - uint32_t Reserved : 19; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t FixedFunctionCounters : 5; + uint32_t CounterWidth : 8; + uint32_t Reserved : 19; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Get CPU frequency information */ - struct CPUID0x00000015 - { - __always_inline inline void Get() - { + /** @brief Get CPU frequency information */ + struct CPUID0x00000015 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x15)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x15)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t VersionID : 8; - uint32_t NumberCounters : 8; - uint32_t BitWidthOfCounters : 8; - uint32_t LengthOfEBXBitVector : 8; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t VersionID : 8; + uint32_t NumberCounters : 8; + uint32_t BitWidthOfCounters : 8; + uint32_t LengthOfEBXBitVector : 8; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t CoreCycles : 1; - uint32_t InstructionsRetired : 1; - uint32_t ReferenceCycles : 1; - uint32_t CacheReferences : 1; - uint32_t CacheMisses : 1; - uint32_t BranchInstructionsRetired : 1; - uint32_t BranchMissesRetired : 1; - uint32_t Reserved : 25; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t CoreCycles : 1; + uint32_t InstructionsRetired : 1; + uint32_t ReferenceCycles : 1; + uint32_t CacheReferences : 1; + uint32_t CacheMisses : 1; + uint32_t BranchInstructionsRetired : 1; + uint32_t BranchMissesRetired : 1; + uint32_t Reserved : 25; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t FixedFunctionCounters : 5; - uint32_t CounterWidth : 8; - uint32_t Reserved : 19; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t FixedFunctionCounters : 5; + uint32_t CounterWidth : 8; + uint32_t Reserved : 19; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Get CPU frequency information */ - struct CPUID0x00000016 - { - __always_inline inline void Get() - { + /** @brief Get CPU frequency information */ + struct CPUID0x00000016 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x16)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x16)); #endif // a64 || a32 - } + } - union - { - struct - { - /** - * @brief Denominator of the TSC frequency - * - * @note TSC frequency = core crystal clock frequency * EBX/EAX - */ - uint32_t Denominator : 31; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + /** + * @brief Denominator of the TSC frequency + * + * @note TSC frequency = core crystal clock frequency * EBX/EAX + */ + uint32_t Denominator : 31; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - /** - * @brief Numerator of the TSC frequency - * - * @note TSC frequency = core crystal clock frequency * EBX/EAX - */ - uint32_t Numerator : 31; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + /** + * @brief Numerator of the TSC frequency + * + * @note TSC frequency = core crystal clock frequency * EBX/EAX + */ + uint32_t Numerator : 31; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - /** @brief Core crystal clock frequency in Hz */ - uint32_t CoreCrystalClock : 31; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + /** @brief Core crystal clock frequency in Hz */ + uint32_t CoreCrystalClock : 31; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - /** @brief Reserved */ - uint32_t Reserved : 31; - }; - cpuid_t raw; - } EDX; - }; + union + { + struct + { + /** @brief Reserved */ + uint32_t Reserved : 31; + }; + cpuid_t raw; + } EDX; + }; - /** @brief Extended CPU information */ - struct CPUID0x80000000 - { - __always_inline inline void Get() - { + /** @brief Extended CPU information */ + struct CPUID0x80000000 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000000)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000000)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t HighestExtendedFunctionSupported : 32; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t HighestExtendedFunctionSupported : 32; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - cpuid_t raw; - }; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + cpuid_t raw; + }; - /** @brief Extended CPU information */ - struct CPUID0x80000001 - { - __always_inline inline void Get() - { + /** @brief Extended CPU information */ + struct CPUID0x80000001 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000001)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000001)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t Unknown : 32; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t Unknown : 32; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t LAHF_SAHF : 1; - uint32_t Reserved : 31; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t LAHF_SAHF : 1; + uint32_t Reserved : 31; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t Reserved0 : 11; - uint32_t SYSCALL : 1; - uint32_t Reserved1 : 8; - uint32_t ExecuteDisable : 1; - uint32_t Reserved2 : 8; - uint32_t EMT64T : 1; - uint32_t Reserved3 : 2; - }; - cpuid_t raw; - } EDX; - cpuid_t raw; - }; + union + { + struct + { + uint32_t Reserved0 : 11; + uint32_t SYSCALL : 1; + uint32_t Reserved1 : 8; + uint32_t ExecuteDisable : 1; + uint32_t Reserved2 : 8; + uint32_t EMT64T : 1; + uint32_t Reserved3 : 2; + }; + cpuid_t raw; + } EDX; + cpuid_t raw; + }; - /** @brief CPU brand string */ - struct CPUID0x80000002 - { - __always_inline inline void Get() - { + /** @brief CPU brand string */ + struct CPUID0x80000002 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000002)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000002)); #endif // a64 || a32 - } + } - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EDX; - cpuid_t raw; - }; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EDX; + cpuid_t raw; + }; - /** @brief CPU brand string */ - struct CPUID0x80000003 - { - __always_inline inline void Get() - { + /** @brief CPU brand string */ + struct CPUID0x80000003 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000003)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000003)); #endif // a64 || a32 - } + } - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EDX; - cpuid_t raw; - }; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EDX; + cpuid_t raw; + }; - /** @brief CPU brand string */ - struct CPUID0x80000004 - { - __always_inline inline void Get() - { + /** @brief CPU brand string */ + struct CPUID0x80000004 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000004)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000004)); #endif // a64 || a32 - } + } - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - char Brand[4]; - }; - cpuid_t raw; - } EDX; - cpuid_t raw; - }; + union + { + struct + { + char Brand[4]; + }; + cpuid_t raw; + } EDX; + cpuid_t raw; + }; - /** @brief CPU cache line information */ - struct CPUID0x80000006 - { - __always_inline inline void Get() - { + /** @brief CPU cache line information */ + struct CPUID0x80000006 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000006)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000006)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t InstructionCount : 12; - uint32_t InstructionAssociativity : 4; - uint32_t DataCount : 12; - uint32_t DataAssociativity : 4; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t InstructionCount : 12; + uint32_t InstructionAssociativity : 4; + uint32_t DataCount : 12; + uint32_t DataAssociativity : 4; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t InstructionCount : 12; - uint32_t InstructionAssociativity : 4; - uint32_t DataCount : 12; - uint32_t DataAssociativity : 4; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t InstructionCount : 12; + uint32_t InstructionAssociativity : 4; + uint32_t DataCount : 12; + uint32_t DataAssociativity : 4; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t LineSize : 8; - uint32_t LinePerTag : 4; - uint32_t Associativity : 4; - uint32_t CacheSize : 16; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t LineSize : 8; + uint32_t LinePerTag : 4; + uint32_t Associativity : 4; + uint32_t CacheSize : 16; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - cpuid_t raw; - }; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + cpuid_t raw; + }; - /** @brief Virtual and physical memory size */ - struct CPUID0x80000008 - { - __always_inline inline void Get() - { + /** @brief Virtual and physical memory size */ + struct CPUID0x80000008 + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x80000008)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x80000008)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t PhysicalAddressBits : 8; - uint32_t LinearAddressBits : 8; - uint32_t Reserved : 16; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t PhysicalAddressBits : 8; + uint32_t LinearAddressBits : 8; + uint32_t Reserved : 16; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - cpuid_t raw; - }; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + cpuid_t raw; + }; - /** @brief Secure virtual machine parameters */ - struct CPUID0x8000000A - { - __always_inline inline void Get() - { + /** @brief Secure virtual machine parameters */ + struct CPUID0x8000000A + { + __always_inline inline void Get() + { #if defined(a86) - asmv("cpuid" - : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) - : "a"(0x8000000A)); + asmv("cpuid" + : "=a"(EAX.raw), "=b"(EBX.raw), "=c"(ECX.raw), "=d"(EDX.raw) + : "a"(0x8000000A)); #endif // a64 || a32 - } + } - union - { - struct - { - uint32_t SVMRevision : 8; - uint32_t Reserved : 24; - }; - cpuid_t raw; - } EAX; + union + { + struct + { + uint32_t SVMRevision : 8; + uint32_t Reserved : 24; + }; + cpuid_t raw; + } EAX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EBX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EBX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } ECX; + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } ECX; - union - { - struct - { - uint32_t Reserved : 32; - }; - cpuid_t raw; - } EDX; - cpuid_t raw; - }; - } - } + union + { + struct + { + uint32_t Reserved : 32; + }; + cpuid_t raw; + } EDX; + cpuid_t raw; + }; + } + } } #endif // !__FENNIX_KERNEL_CPU_x86_CPUID_INTEL_H__ diff --git a/include/elf.h b/include/elf.h index 1886dc3..230b9cb 100644 --- a/include/elf.h +++ b/include/elf.h @@ -230,7 +230,9 @@ enum SegmentTypes PT_SUNWSTACK = 0x6ffffffa, PT_HISUNW = 0x6fffffff, PT_LOPROC = 0x70000000, - PT_HIPROC = 0x7fffffff + PT_HIPROC = 0x7fffffff, + PT_GNU_EH_FRAME = 0x6474e550, + PT_GNU_STACK = 0x6474e551, }; enum DynamicArrayTags @@ -718,6 +720,13 @@ struct Elf64_Dyn } d_un; }; +typedef struct +{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + typedef struct { Elf64_Addr r_offset; @@ -725,4 +734,34 @@ typedef struct Elf64_Sxword r_addend; } Elf64_Rela; +#if defined(a64) || defined(aa64) +typedef Elf64_Addr Elf_Addr; +typedef Elf64_Half Elf_Half; +typedef Elf64_Off Elf_Off; +typedef Elf64_Sword Elf_Sword; +typedef Elf64_Word Elf_Word; + +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Phdr Elf_Phdr; +typedef Elf64_Rel Elf_Rel; +typedef Elf64_Sym Elf_Sym; +typedef Elf64_Dyn Elf_Dyn; +typedef Elf64_Rela Elf_Rela; +#elif defined(a32) +typedef Elf32_Addr Elf_Addr; +typedef Elf32_Half Elf_Half; +typedef Elf32_Off Elf_Off; +typedef Elf32_Sword Elf_Sword; +typedef Elf32_Word Elf_Word; + +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Phdr Elf_Phdr; +typedef Elf32_Rel Elf_Rel; +typedef Elf32_Sym Elf_Sym; +typedef Elf32_Dyn Elf_Dyn; +typedef Elf32_Rela Elf_Rela; +#endif + #endif // !__FENNIX_KERNEL_ELF_H__ diff --git a/include/exec.hpp b/include/exec.hpp index caeb0bc..0347fe6 100644 --- a/include/exec.hpp +++ b/include/exec.hpp @@ -23,12 +23,13 @@ #include #include #include +#include #include #include namespace Execute { - enum BinaryType + enum BinaryType : int { BinTypeInvalid, BinTypeFex, @@ -39,28 +40,6 @@ namespace Execute BinTypeUnknown }; - enum ExStatus - { - Unknown, - OK, - Unsupported, - GenericError, - LoadingProcedureFailed, - InvalidFile, - InvalidFileFormat, - InvalidFileHeader, - InvalidFileData, - InvalidFileEntryPoint, - InvalidFilePath - }; - - struct SpawnData - { - ExStatus Status; - Tasking::PCB *Process; - Tasking::TCB *Thread; - }; - struct SharedLibrary { char Identifier[64]; @@ -72,25 +51,6 @@ namespace Execute size_t Length; }; - struct ELFBaseLoad - { - bool Success; - bool Interpreter; - SpawnData sd; - Tasking::IP InstructionPointer; - - std::vector NeededLibraries; - void *MemoryImage; - void *VirtualMemoryImage; - - /* This should be deleted after copying the allocated pages to the thread - Intended to be used only inside BaseLoad.cpp */ - Memory::MemMgr *TmpMem; - - /* Same as above, for BaseLoad.cpp only */ - std::vector auxv; - }; - struct MmImage { void *Physical; @@ -100,46 +60,46 @@ namespace Execute class ELFObject { private: - ELFBaseLoad BaseLoadInfo{}; + bool IsElfValid; + const char **ELFargv; + const char **ELFenvp; + std::vector Elfauxv; + Tasking::IP ip; - ELFBaseLoad LoadExec_x86_32(VirtualFileSystem::File &ElfFile, - Tasking::PCB *TargetProcess); + void LoadExec_x86_32(int fd, + Tasking::PCB *TargetProcess); - ELFBaseLoad LoadExec_x86_64(VirtualFileSystem::File &ElfFile, - Tasking::PCB *TargetProcess); + void LoadExec_x86_64(int fd, + Tasking::PCB *TargetProcess); - ELFBaseLoad LoadDyn_x86_32(VirtualFileSystem::File &ElfFile, - Tasking::PCB *TargetProcess, - bool IsLibrary); + void LoadDyn_x86_32(int fd, + Tasking::PCB *TargetProcess); - ELFBaseLoad LoadDyn_x86_64(VirtualFileSystem::File &ElfFile, - Tasking::PCB *TargetProcess, - bool IsLibrary); + void LoadDyn_x86_64(int fd, + Tasking::PCB *TargetProcess); + + bool LoadInterpreter(int fd, + Tasking::PCB *TargetProcess); public: - ELFBaseLoad GetBaseLoadInfo() { return BaseLoadInfo; } - bool IsValid() { return BaseLoadInfo.Success; } + decltype(IsElfValid) &IsValid = IsElfValid; + decltype(ip) &InstructionPointer = ip; + decltype(ELFargv) &argv = ELFargv; + decltype(ELFenvp) &envp = ELFenvp; + decltype(Elfauxv) &auxv = Elfauxv; ELFObject(char *AbsolutePath, Tasking::PCB *TargetProcess, - bool IsLibrary = false); + const char **argv, + const char **envp); ~ELFObject(); }; - /* Full binary size. */ - BinaryType GetBinaryType(void *Image); + BinaryType GetBinaryType(const char *Path); - BinaryType GetBinaryType(char *Path); - - SpawnData Spawn(char *Path, const char **argv, const char **envp); - - ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp, - Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native); - - void ELFInterpreterIPCThread(Tasking::PCB *TargetProcess, - std::string *TargetPath, - void *MemoryImage, - std::vector *NeededLibraries); + int Spawn(char *Path, const char **argv, const char **envp, + Tasking::PCB *Parent = nullptr, + Tasking::TaskCompatibility Compatibility = Tasking::TaskCompatibility::Native); bool ELFIs64(void *Header); Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header); @@ -147,44 +107,17 @@ namespace Execute char *GetELFStringTable(Elf64_Ehdr *Header); char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset); Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name); - Elf64_Sym ELFLookupSymbol(VirtualFileSystem::File &ElfFile, const char *Name); + Elf64_Sym ELFLookupSymbol(int fd, const char *Name); uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index); - std::vector ELFGetSymbolType_x86_64(VirtualFileSystem::File &ElfFile, SegmentTypes Tag); - std::vector ELFGetSymbolType_x86_32(VirtualFileSystem::File &ElfFile, SegmentTypes Tag); + std::vector ELFGetSymbolType_x86_64(int fd, SegmentTypes Tag); + std::vector ELFGetSymbolType_x86_32(int fd, SegmentTypes Tag); - std::vector ELFGetSections_x86_64(VirtualFileSystem::File &ElfFile, const char *SectionName); - std::vector ELFGetSections_x86_32(VirtualFileSystem::File &ElfFile, const char *SectionName); + std::vector ELFGetSections_x86_64(int fd, const char *SectionName); + std::vector ELFGetSections_x86_32(int fd, const char *SectionName); - std::vector ELFGetDynamicTag_x86_64(VirtualFileSystem::File &ElfFile, DynamicArrayTags Tag); - std::vector ELFGetDynamicTag_x86_32(VirtualFileSystem::File &ElfFile, DynamicArrayTags Tag); - - void CopyLOADSegments(VirtualFileSystem::File &ElfFile, uintptr_t HdrsBase, uintptr_t PhysicalBase); - void GetBaseAndSize(VirtualFileSystem::File &ElfFile, uintptr_t &Base, size_t &Size); - - /** - * @brief Create a ELF Memory Image - * - * @param mem The memory manager to use - * @param vmm Memory::Virtual object to use - * @param ElfFile The ELF File - * @param Length Length of @p ElfFile - * @return The Memory Image (Physical and Virtual) - */ - MmImage ELFCreateMemoryImage(Memory::MemMgr *mem, - Memory::Virtual &vmm, - VirtualFileSystem::File &ElfFile, - size_t Length); - - uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, - Memory::Virtual &vmm, - const char *Interpreter); - - void LibraryManagerService(); - bool AddLibrary(char *Identifier, - VirtualFileSystem::File &ExFile, - const Memory::Virtual &vmm = Memory::Virtual()); - SharedLibrary GetLibrary(char *Identifier); + std::vector ELFGetDynamicTag_x86_64(int fd, DynamicArrayTags Tag); + std::vector ELFGetDynamicTag_x86_32(int fd, DynamicArrayTags Tag); } #endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__ diff --git a/include/filesystem.hpp b/include/filesystem.hpp index 9c8c6dc..0d1e340 100644 --- a/include/filesystem.hpp +++ b/include/filesystem.hpp @@ -19,203 +19,389 @@ #define __FENNIX_KERNEL_FILESYSTEM_H__ #include -#include -#include -namespace VirtualFileSystem -{ +#include +#include +#include +#include +#include +#include + #define FILENAME_LENGTH 256 +#define PATH_MAX 256 #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 - struct Node; +#define S_IXOTH 0001 +#define S_IWOTH 0002 +#define S_IROTH 0004 +#define S_IRWXO 0007 +#define S_IXGRP 0010 +#define S_IWGRP 0020 +#define S_IRGRP 0040 +#define S_IRWXG 0070 +#define S_IXUSR 0100 +#define S_IWUSR 0200 +#define S_IRUSR 0400 +#define S_IRWXU 0700 - typedef size_t (*OperationMount)(const char *, unsigned long, const void *); - typedef size_t (*OperationUmount)(int); - typedef size_t (*OperationRead)(Node *node, size_t Size, uint8_t *Buffer); - typedef size_t (*OperationWrite)(Node *node, size_t Size, uint8_t *Buffer); - typedef void (*OperationOpen)(Node *node, uint8_t Mode, uint8_t Flags); - typedef void (*OperationClose)(Node *node); - typedef size_t (*OperationSync)(void); - typedef void (*OperationCreate)(Node *node, char *Name, uint16_t NameLength); - typedef void (*OperationMkdir)(Node *node, char *Name, uint16_t NameLength); - typedef size_t (*OperationSeek)(Node *node, size_t Offset, uint8_t Whence); +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 +#define O_EXCL 0200 +#define O_TRUNC 01000 +#define O_APPEND 02000 +#define O_CLOEXEC 02000000 -#define MountFSFunction(name) size_t name(const char *unknown0, unsigned long unknown1, const uint8_t *unknown2) -#define UMountFSFunction(name) size_t name(int unknown0) +#define S_IFIFO 0010000 +#define S_IFCHR 0020000 +#define S_IFDIR 0040000 +#define S_IFBLK 0060000 +#define S_IFREG 0100000 +#define S_IFLNK 0120000 +#define S_IFSOCK 0140000 -#define ReadFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Size, uint8_t *Buffer) -#define WriteFSFunction(name) size_t name(VirtualFileSystem::Node *node, size_t Size, uint8_t *Buffer) -#define OpenFSFunction(name) void name(VirtualFileSystem::Node *node, uint8_t Mode, uint8_t Flags) -#define CloseFSFunction(name) void name(VirtualFileSystem::Node *node) -#define SyncFSFunction(name) size_t name(void) -#define CreateFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength) -#define MkdirFSFunction(name) void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength) -#define SeekFSFunction(name) off_t name(VirtualFileSystem::Node *node, off_t Offset, uint8_t Whence) +#define S_IFMT 0170000 - enum FileStatus - { - OK, - NotFound, - NotEmpty, - NotSupported, - AccessDenied, - Timeout, - SectorNotFound, - PartiallyCompleted, +#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) +#define S_ISCHR(mode) (((mode)&S_IFMT) == S_IFCHR) +#define S_ISBLK(mode) (((mode)&S_IFMT) == S_IFBLK) +#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG) +#define S_ISFIFO(mode) (((mode)&S_IFMT) == S_IFIFO) +#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK) +#define S_ISSOCK(mode) (((mode)&S_IFMT) == S_IFSOCK) - InvalidName, - InvalidParameter, - InvalidHandle, - InvalidPath, - InvalidDevice, - InvalidOperator, - InvalidNode, +struct stat +{ + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; - FileExists, - FileIsADirectory, - FileIsInvalid, + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; + blksize_t st_blksize; + blkcnt_t st_blocks; + mode_t st_attr; +}; - DirectoryNotEmpty, - NotADirectory, +struct stat64 +{ + dev_t st_dev; + ino64_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off64_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; + blksize_t st_blksize; + blkcnt64_t st_blocks; + mode_t st_attr; +}; - UnknownFileStatusError - }; +static inline int ConvertFileFlags(const char *Mode) +{ + int Flags = 0; - enum NodeFlags - { - NODE_FLAG_ERROR = 0x0, - FILE = 0x01, - DIRECTORY = 0x02, - CHARDEVICE = 0x03, - BLOCKDEVICE = 0x04, - PIPE = 0x05, - SYMLINK = 0x06, - MOUNTPOINT = 0x08 - }; + if (strchr(Mode, '+')) + Flags |= O_RDWR; + else if (*Mode == 'r') + Flags |= O_RDONLY; + else + Flags |= O_WRONLY; - struct FileSystemOperations - { - char Name[FILENAME_LENGTH]; - OperationMount Mount = nullptr; - OperationUmount Umount = nullptr; - OperationRead Read = nullptr; - OperationWrite Write = nullptr; - OperationOpen Open = nullptr; - OperationClose Close = nullptr; - OperationCreate Create = nullptr; - OperationMkdir MakeDirectory = nullptr; - OperationSeek Seek = nullptr; - }; + if (strchr(Mode, 'x')) + Flags |= O_EXCL; - struct Node - { - char Name[FILENAME_LENGTH]; - uint64_t IndexNode = 0; - uint64_t Mask = 0; - uint64_t Mode = 0; - NodeFlags Flags = NodeFlags::NODE_FLAG_ERROR; - uint64_t UserIdentifier = 0, GroupIdentifier = 0; - uintptr_t Address = 0; - size_t Length = 0; - off_t Offset = 0; - Node *Parent = nullptr; - FileSystemOperations *Operator = nullptr; - /* For root node: - 0 - root "/" - 1 - etc - ... - */ - std::vector Children; - }; + if (strchr(Mode, 'e')) + Flags |= O_CLOEXEC; - struct File - { - char Name[FILENAME_LENGTH]; - FileStatus Status; - bool IsOK() - { - return Status == FileStatus::OK; - } + if (*Mode != 'r') + Flags |= O_CREAT; - size_t GetLength() - { - return node->Length; - } + if (*Mode == 'w') + Flags |= O_TRUNC; - std::vector GetChildren() - { - return node->Children; - } + if (*Mode == 'a') + Flags |= O_APPEND; - NodeFlags GetFlags() - { - return node->Flags; - } - - /** @brief Special cases only. */ - Node *GetNode() - { - return node; - } - - private: - Node *node; - off_t ContextOffset; - - friend class Virtual; - }; - - /* Manage / etc.. */ - class Virtual - { - private: - Node *FileSystemRoot = nullptr; - - public: - std::shared_ptr GetPathFromNode(Node *node); - Node *GetNodeFromPath(const char *Path, Node *Parent = nullptr); - - /** - * @brief Convert a Node to a File - * - * @param node Node to convert - * @return Converted node - */ - File ConvertNodeToFILE(Node *node); - - bool PathIsRelative(const char *Path); - - Node *GetParent(const char *Path, Node *Parent); - Node *GetRootNode() { return FileSystemRoot; } - - Node *AddNewChild(const char *Name, Node *Parent); - Node *GetChild(const char *Name, Node *Parent); - FileStatus RemoveChild(const char *Name, Node *Parent); - - std::shared_ptr NormalizePath(const char *Path, Node *Parent = nullptr); - bool PathExists(const char *Path, Node *Parent = nullptr); - Node *CreateRoot(const char *RootName, FileSystemOperations *Operator); - Node *Create(const char *Path, NodeFlags Flag, Node *Parent = nullptr); - - FileStatus Delete(const char *Path, bool Recursive = false, Node *Parent = nullptr); - FileStatus Delete(Node *Path, bool Recursive = false, Node *Parent = nullptr); - - File Mount(const char *Path, FileSystemOperations *Operator); - FileStatus Unmount(File &File); - - size_t Read(File &File, uint8_t *Buffer, size_t Size); - size_t Write(File &File, uint8_t *Buffer, size_t Size); - off_t Seek(File &File, off_t Offset, uint8_t Whence); - - File Open(const char *Path, Node *Parent = nullptr); - FileStatus Close(File &File); - - Virtual(); - ~Virtual(); - }; + return Flags; } +namespace VirtualFileSystem +{ + struct Node; + + typedef std::size_t (*OperationRead)(Node *node, std::size_t Size, uint8_t *Buffer, off_t &RefOffset); + typedef std::size_t (*OperationWrite)(Node *node, std::size_t Size, uint8_t *Buffer, off_t &RefOffset); + typedef void (*OperationCreate)(Node *node, char *Name, uint16_t NameLength, off_t &RefOffset); + typedef void (*OperationMkdir)(Node *node, char *Name, uint16_t NameLength, off_t &RefOffset); + typedef std::size_t (*OperationSeek)(Node *node, std::size_t Offset, int Whence, off_t &RefOffset); + +#define ReadFSFunction(name) \ + std::size_t name(VirtualFileSystem::Node *node, std::size_t Size, uint8_t *Buffer, off_t &RefOffset) +#define WriteFSFunction(name) \ + std::size_t name(VirtualFileSystem::Node *node, std::size_t Size, uint8_t *Buffer, off_t &RefOffset) +#define CreateFSFunction(name) \ + void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength, off_t &RefOffset) +#define MkdirFSFunction(name) \ + void name(VirtualFileSystem::Node *node, char *Name, uint16_t NameLength, off_t &RefOffset) +#define SeekFSFunction(name) \ + off_t name(VirtualFileSystem::Node *node, off_t Offset, uint8_t Whence, off_t &RefOffset) + + enum NodeFlags + { + NODE_FLAG_ERROR = 0x0, + FILE = S_IFREG, + DIRECTORY = S_IFDIR, + CHARDEVICE = S_IFCHR, + BLOCKDEVICE = S_IFBLK, + PIPE = S_IFIFO, + SYMLINK = S_IFLNK, + MOUNTPOINT = S_IFDIR + }; + + struct FileSystemOperations + { + /** + * Name of the filesystem operations + * + * @note Mandatory + */ + char Name[FILENAME_LENGTH]; + + /** + * Pointer to the read function + * + * @note Mandatory + */ + OperationRead Read = nullptr; + + /** + * Pointer to the write function + * + * @note Mandatory + */ + OperationWrite Write = nullptr; + + /** + * Pointer to the create function + * + * @note Optional + */ + OperationCreate Create = nullptr; + + /** + * Pointer to the mkdir function + * + * @note Optional + */ + OperationMkdir MakeDirectory = nullptr; + + /** + * Pointer to the seek function + * + * @note Optional + */ + OperationSeek Seek = nullptr; + }; + +#define RefNode VirtualFileSystem::ReferenceNode + + class ReferenceNode + { + private: + std::atomic_int64_t Offset = 0; + off_t FileSize = 0; + NewLock(RefNodeLock); + Node *node; + RefNode *SymlinkTo; + + public: + decltype(FileSize) &Length = FileSize; + Node *GetNode() const { return node; } + std::string AbsolutePath; + + size_t Read(uint8_t *Buffer, size_t Size); + size_t Write(uint8_t *Buffer, size_t Size); + off_t Seek(off_t Offset, int Whence); + + ReferenceNode(Node *node); + ~ReferenceNode(); + + friend class Virtual; + friend class FileDescriptorTable; + }; + + class Node + { + private: + NewLock(NodeLock); + + public: + class Virtual *FileSystem = nullptr; + ino_t IndexNode = 0; + const char *Name; + const char *Symlink; + Node *SymlinkTarget = nullptr; + mode_t Mode = 0; + NodeFlags Flags = NodeFlags::NODE_FLAG_ERROR; + uid_t UserIdentifier = 0; + gid_t GroupIdentifier = 0; + uintptr_t Address = 0; + off_t Length = 0; + Node *Parent = nullptr; + FileSystemOperations *Operator = nullptr; + /* For root node: + 0 - root "/" + 1 - etc + ... + */ + std::vector Children; + + /** + * References to this node (open files, etc..) + */ + std::vector References; + + /** + * Create a new reference to this node + * @return Pointer to the new reference + */ + ReferenceNode *CreateReference(); + + /** + * Remove a reference to this node + * @param Reference Pointer to the reference to remove + */ + void RemoveReference(ReferenceNode *Reference); + + Node() {} + ~Node() {} + }; + + class Virtual + { + private: + Node *FileSystemRoot = nullptr; + NewLock(VirtualLock); + + /** + * @note This function is NOT thread safe + */ + Node *AddNewChild(const char *Name, Node *Parent); + + /** + * @note This function is NOT thread safe + */ + Node *GetChild(const char *Name, Node *Parent); + + /** + * @note This function is NOT thread safe + */ + int RemoveChild(const char *Name, Node *Parent); + + /** + * @note This function is NOT thread safe + */ + Node *GetParent(const char *Path, Node *Parent); + + /** + * @note This function is NOT thread safe + */ + Node *GetNodeFromPath_Unsafe(const char *Path, Node *Parent = nullptr); + + public: + std::string GetPathFromNode(Node *node); + Node *GetNodeFromPath(const char *Path, Node *Parent = nullptr); + + bool PathIsRelative(const char *Path); + + Node *GetRootNode() { return FileSystemRoot; } + + std::string NormalizePath(const char *Path, Node *Parent = nullptr); + bool PathExists(const char *Path, Node *Parent = nullptr); + Node *CreateRoot(const char *RootName, FileSystemOperations *Operator); + Node *Create(const char *Path, NodeFlags Flag, Node *Parent = nullptr); + + int Delete(const char *Path, bool Recursive = false, Node *Parent = nullptr); + int Delete(Node *Path, bool Recursive = false, Node *Parent = nullptr); + + Node *Mount(const char *Path, FileSystemOperations *Operator); + int Unmount(Node *File); + + /** + * Open a file + * @param Path The path to the file, relative or absolute. The buffer shouldn't be modified while the function is running. + * @param Parent Pointer to the parent node, if nullptr, the root node will be used. + * @return A pointer to the VirtualFileSystem::ReferenceNode, or nullptr if the file doesn't exist. + */ + RefNode *Open(const char *Path, Node *Parent = nullptr); + + Virtual(); + ~Virtual(); + }; + + class FileDescriptorTable + { + public: + struct FileDescriptor + { + RefNode *Handle{}; + mode_t Mode = 0; + int Flags = 0; + int Descriptor = -1; + }; + + private: + std::vector FileDescriptors; + VirtualFileSystem::Node *fdDir = nullptr; + + FileDescriptor GetFileDescriptor(int FileDescriptor); + int ProbeMode(mode_t Mode, int Flags); + int AddFileDescriptor(const char *AbsolutePath, mode_t Mode, int Flags); + int RemoveFileDescriptor(int FileDescriptor); + int GetFreeFileDescriptor(); + + public: + std::string GetAbsolutePath(int FileDescriptor); + std::vector &GetFileDescriptors() { return FileDescriptors; } + + int _open(const char *pathname, int flags, mode_t mode); + int _creat(const char *pathname, mode_t mode); + ssize_t _read(int fd, void *buf, size_t count); + ssize_t _write(int fd, const void *buf, size_t count); + int _close(int fd); + off_t _lseek(int fd, off_t offset, int whence); + int _stat(const char *pathname, struct stat *statbuf); + int _fstat(int fd, struct stat *statbuf); + int _lstat(const char *pathname, struct stat *statbuf); + + FileDescriptorTable(void *Owner); + ~FileDescriptorTable(); + }; +} + +int fopen(const char *pathname, const char *mode); +int creat(const char *pathname, mode_t mode); +ssize_t fread(int fd, void *buf, size_t count); +ssize_t fwrite(int fd, const void *buf, size_t count); +int fclose(int fd); +off_t lseek(int fd, off_t offset, int whence); +int stat(const char *pathname, struct stat *statbuf); +int fstat(int fd, struct stat *statbuf); +int lstat(const char *pathname, struct stat *statbuf); + #endif // !__FENNIX_KERNEL_FILESYSTEM_H__ diff --git a/include/gui.hpp b/include/gui.hpp deleted file mode 100644 index 9f6b422..0000000 --- a/include/gui.hpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#ifndef __FENNIX_KERNEL_GUI_H__ -#define __FENNIX_KERNEL_GUI_H__ - -#include -#include -#include -#include -#include - -namespace GraphicalUserInterface -{ - typedef uintptr_t Handle; - - struct MouseData - { - size_t X; - size_t Y; - size_t Z; - bool Left; - bool Right; - bool Middle; - }; - - struct ScreenBitmap - { - size_t Width; - size_t Height; - size_t Size; - size_t Pitch; - uint64_t BitsPerPixel; - uint8_t *Data; - }; - - struct Rect - { - int64_t Left; - int64_t Top; - size_t Width; - size_t Height; - - bool Contains(int64_t X, int64_t Y) - { - return (X >= Left && - X <= Left + (int64_t)Width && - Y >= Top && - Y <= Top + (int64_t)Height); - } - - bool Contains(Rect rect) - { - return (rect.Left >= Left && - rect.Left + rect.Width <= Left + Width && - rect.Top >= Top && - rect.Top + rect.Height <= Top + Height); - } - }; - - enum CursorType - { - Visible = 0, - Hidden, - Arrow, - Hand, - Wait, - IBeam, - ResizeHorizontal, - ResizeVertical, - ResizeDiagonalLeft, - ResizeDiagonalRight, - ResizeAll, - Cross, - Help, - No, - AppStarting, - }; - - struct Event - { - struct - { - size_t Width; - size_t Height; - } Resize; - - struct - { - size_t X; - size_t Y; - bool Left; - bool Right; - bool Middle; - } MouseDown; - - struct - { - size_t X; - size_t Y; - bool Left; - bool Right; - bool Middle; - } MouseUp; - - struct - { - size_t X; - size_t Y; - bool Left; - bool Right; - bool Middle; - } MouseMove; - }; - - /* - virtual void OnMouseMove(Event *e) {} - virtual void OnMouseClick(Event *e) {} - virtual void OnMouseDoubleClick(Event *e) {} - virtual void OnMouseDown(Event *e) {} - virtual void OnMouseUp(Event *e) {} - virtual void OnMouseWheel(Event *e) {} - virtual void OnMouseEnter(Event *e) {} - virtual void OnMouseLeave(Event *e) {} - virtual void OnMouseHover(Event *e) {} - virtual void OnMouseDrag(Event *e) {} - virtual void OnMouseDragStart(Event *e) {} - virtual void OnMouseDragEnd(Event *e) {} - virtual void OnMouseDragEnter(Event *e) {} - virtual void OnMouseDragLeave(Event *e) {} - virtual void OnMouseDragHover(Event *e) {} - virtual void OnMouseDragDrop(Event *e) {} - virtual void OnMouseDragDropEnter(Event *e) {} - virtual void OnMouseDragDropLeave(Event *e) {} - virtual void OnMouseDragDropHover(Event *e) {} - virtual void OnMouseDragDropEnd(Event *e) {} - virtual void OnMouseDragDropStart(Event *e) {} - virtual void OnMouseDragDropCancel(Event *e) {} - virtual void OnMouseDragDropComplete(Event *e) {} - virtual void OnMouseDragDropAbort(Event *e) {} - - virtual void OnKeyDown(Event *e) {} - virtual void OnKeyUp(Event *e) {} - virtual void OnKeyPress(Event *e) {} - - virtual void OnFocusEnter(Event *e) {} - virtual void OnFocusLeave(Event *e) {} - virtual void OnFocusHover(Event *e) {} - - virtual void OnResize(Event *e) {} - virtual void OnMinimize(Event *e) {} - virtual void OnMaximize(Event *e) {} - virtual void OnMove(Event *e) {} - virtual void OnShow(Event *e) {} - virtual void OnHide(Event *e) {} - virtual void OnClose(Event *e) {} - virtual void OnDestroy(Event *e) {} - - virtual void OnPaint(Event *e) {} - virtual void OnPaintBackground(Event *e) {} - virtual void OnPaintForeground(Event *e) {} - virtual void OnPaintOverlay(Event *e) {} - virtual void OnPaintAll(Event *e) {} - virtual void OnPaintChildren(Event *e) {} - virtual void OnPaintChildrenBackground(Event *e) {} - virtual void OnPaintChildrenForeground(Event *e) {} - virtual void OnPaintChildrenBorder(Event *e) {} - virtual void OnPaintChildrenShadow(Event *e) {} - virtual void OnPaintChildrenOverlay(Event *e) {} - virtual void OnPaintChildrenAll(Event *e) {} - */ - - void SetPixel(ScreenBitmap *Bitmap, size_t X, size_t Y, uint32_t Color); - void DrawOverBitmap(ScreenBitmap *DestinationBitmap, - ScreenBitmap *SourceBitmap, - int64_t Top, - int64_t Left, - bool IgnoreZero = true); - void PutRect(ScreenBitmap *Bitmap, Rect rect, uint32_t Color); - void PutBorder(ScreenBitmap *Bitmap, Rect rect, uint32_t Color); - uint32_t BlendColors(uint32_t c1, uint32_t c2, float t); - void PutBorderWithShadow(ScreenBitmap *Bitmap, Rect rect, uint32_t Color); - void DrawShadow(ScreenBitmap *Bitmap, Rect rect); - void PaintChar(Video::Font *font, ScreenBitmap *Bitmap, char c, uint32_t Color, int64_t *CharCursorX, int64_t *CharCursorY); - void DrawString(ScreenBitmap *Bitmap, Rect rect, const char *Text, uint32_t Color); - - class WidgetCollection - { - private: - Memory::MemMgr *mem; - ScreenBitmap *Buffer; - Video::Font *CurrentFont; - void *ParentWindow; - bool NeedRedraw; - - struct HandleMeta - { - char Type[4]; - }; - - struct LabelObject - { - HandleMeta Handle; - Rect rect; - char Text[512]; - uint32_t Color; - int64_t CharCursorX, CharCursorY; - }; - - struct PanelObject - { - HandleMeta Handle; - Rect rect; - uint32_t Color; - uint32_t BorderColor; - uint32_t ShadowColor; - bool Shadow; - }; - - struct ButtonObject - { - HandleMeta Handle; - Rect rect; - char Text[512]; - uint32_t Color; - uint32_t HoverColor; - uint32_t PressedColor; - uint32_t BorderColor; - uint32_t ShadowColor; - int64_t CharCursorX, CharCursorY; - bool Shadow; - bool Hover; - bool Pressed; - uintptr_t OnClick; - }; - - std::vector Labels; - std::vector Panels; - std::vector Buttons; - - public: - void ReplaceFont(Video::Font *NewFont) - { - delete this->CurrentFont; - this->CurrentFont = NewFont; - } - - Handle CreatePanel(Rect rect, uint32_t Color); - Handle CreateButton(Rect rect, const char *Text, uintptr_t OnClick = (uintptr_t) nullptr); - Handle CreateLabel(Rect rect, const char *Text); - Handle CreateTextBox(Rect rect, const char *Text); - Handle CreateCheckBox(Rect rect, const char *Text); - Handle CreateRadioButton(Rect rect, const char *Text); - Handle CreateComboBox(Rect rect, const char *Text); - Handle CreateListBox(Rect rect, const char *Text); - Handle CreateProgressBar(Rect rect, const char *Text); - Handle CreateContextMenu(Rect rect, const char *Text); - - void SetText(Handle handle, const char *Text); - - WidgetCollection(void /* Window */ *ParentWindow); - ~WidgetCollection(); - - void OnMouseMove(Event *e); - void OnMouseClick(Event *e); - void OnMouseDoubleClick(Event *e); - void OnMouseDown(Event *e); - void OnMouseUp(Event *e); - void OnMouseWheel(Event *e); - void OnMouseEnter(Event *e); - void OnMouseLeave(Event *e); - void OnMouseHover(Event *e); - void OnMouseDrag(Event *e); - void OnMouseDragStart(Event *e); - void OnMouseDragEnd(Event *e); - - void OnKeyDown(Event *e); - void OnKeyUp(Event *e); - void OnKeyPress(Event *e); - - void OnShow(Event *e); - void OnHide(Event *e); - void OnDestroy(Event *e); - - void OnPaint(Event *e); - void OnPaintBackground(Event *e); - void OnPaintForeground(Event *e); - }; - - class Window - { - private: - Memory::MemMgr *mem; - ScreenBitmap *Buffer; - Rect Position; - Rect LastPosition; - char Title[256]; - std::vector Widgets; - void *ParentGUI; - - bool Maximized; - bool Minimized; - - public: - bool IsMaximized() { return Maximized; } - bool IsMinimized() { return Minimized; } - ScreenBitmap *GetBuffer() { return Buffer; } - Rect GetPosition() { return Position; } - Rect *GetPositionPtr() { return &Position; } - const char *GetTitle() { return (const char *)Title; } - void SetTitle(const char *Title) { strcpy(this->Title, Title); } - void AddWidget(WidgetCollection *widget); - - Window(void *ParentGUI, Rect rect, const char *Title); - ~Window(); - - void OnMouseMove(Event *e); - void OnMouseClick(Event *e); - void OnMouseDoubleClick(Event *e); - void OnMouseDown(Event *e); - void OnMouseUp(Event *e); - void OnMouseWheel(Event *e); - void OnMouseEnter(Event *e); - void OnMouseLeave(Event *e); - void OnMouseHover(Event *e); - void OnMouseDrag(Event *e); - void OnMouseDragStart(Event *e); - void OnMouseDragEnd(Event *e); - - void OnKeyDown(Event *e); - void OnKeyUp(Event *e); - void OnKeyPress(Event *e); - - void OnFocusEnter(Event *e); - void OnFocusLeave(Event *e); - void OnFocusHover(Event *e); - - void OnResize(Event *e); - void OnMinimize(Event *e); - void OnMaximize(Event *e); - void OnMove(Event *e); - void OnShow(Event *e); - void OnHide(Event *e); - void OnClose(Event *e); - void OnDestroy(Event *e); - - void OnPaint(Event *e); - void OnPaintBackground(Event *e); - void OnPaintForeground(Event *e); - void OnPaintOverlay(Event *e); - void OnPaintAll(Event *e); - void OnPaintChildren(Event *e); - void OnPaintChildrenBackground(Event *e); - void OnPaintChildrenForeground(Event *e); - void OnPaintChildrenBorder(Event *e); - void OnPaintChildrenShadow(Event *e); - void OnPaintChildrenOverlay(Event *e); - void OnPaintChildrenAll(Event *e); - }; - - class GUI - { - private: - MouseData MouseArray[256]; - Memory::MemMgr *mem; - Video::Font *CurrentFont; - Rect Desktop; - ScreenBitmap *BackBuffer; - ScreenBitmap *DesktopBuffer; - ScreenBitmap *OverlayBuffer; - ScreenBitmap *CursorBuffer; - std::vector Widgets; - std::vector Windows; - CursorType Cursor = CursorType::Arrow; - CursorType LastCursor = CursorType::Arrow; - bool CursorVisible = true; - bool IsRunning = false; - - bool DesktopBufferRepaint = true; - bool OverlayBufferRepaint = true; - bool OverlayFullRepaint = true; - bool CursorBufferRepaint = true; - - void FetchInputs(); - void PaintDesktop(); - void PaintWidgets(); - void PaintWindows(); - void PaintCursor(); - - public: - void SetCursorType(CursorType Type = CursorType::Visible) { this->Cursor = Type; } - void Loop(); - void AddWindow(Window *window); - void AddWidget(WidgetCollection *widget); - GUI(); - ~GUI(); - }; -} - -#endif // !__FENNIX_KERNEL_GUI_H__ diff --git a/include/io.h b/include/io.h index 39a2730..e6bfc30 100644 --- a/include/io.h +++ b/include/io.h @@ -26,204 +26,204 @@ extern "C" { #endif - static inline uint8_t inportb(uint16_t Port) - { - uint8_t Result; - asm("in %%dx, %%al" - : "=a"(Result) - : "d"(Port)); - return Result; - } + static inline uint8_t inportb(uint16_t Port) + { + uint8_t Result; + asm("in %%dx, %%al" + : "=a"(Result) + : "d"(Port)); + return Result; + } - static inline uint16_t inportw(uint16_t Port) - { - uint16_t Result; - asm("in %%dx, %%ax" - : "=a"(Result) - : "d"(Port)); - return Result; - } + static inline uint16_t inportw(uint16_t Port) + { + uint16_t Result; + asm("in %%dx, %%ax" + : "=a"(Result) + : "d"(Port)); + return Result; + } - static inline uint32_t inportl(uint16_t Port) - { - uint32_t Result; - asmv("inl %1, %0" - : "=a"(Result) - : "dN"(Port)); - return Result; - } + static inline uint32_t inportl(uint16_t Port) + { + uint32_t Result; + asmv("inl %1, %0" + : "=a"(Result) + : "dN"(Port)); + return Result; + } - static inline void outportb(uint16_t Port, uint8_t Data) - { - asmv("out %%al, %%dx" - : - : "a"(Data), "d"(Port)); - } + static inline void outportb(uint16_t Port, uint8_t Data) + { + asmv("out %%al, %%dx" + : + : "a"(Data), "d"(Port)); + } - static inline void outportw(uint16_t Port, uint16_t Data) - { - asmv("out %%ax, %%dx" - : - : "a"(Data), "d"(Port)); - } + static inline void outportw(uint16_t Port, uint16_t Data) + { + asmv("out %%ax, %%dx" + : + : "a"(Data), "d"(Port)); + } - static inline void outportl(uint16_t Port, uint32_t Data) - { - asmv("outl %1, %0" - : - : "dN"(Port), "a"(Data)); - } + static inline void outportl(uint16_t Port, uint32_t Data) + { + asmv("outl %1, %0" + : + : "dN"(Port), "a"(Data)); + } - static inline uint8_t mmioin8(uint64_t Address) - { - asmv("" :: - : "memory"); - uint8_t Result = *(volatile uint8_t *)(uintptr_t)Address; - asmv("" :: - : "memory"); - return Result; - } + static inline uint8_t mmioin8(uint64_t Address) + { + asmv("" :: + : "memory"); + uint8_t Result = *(volatile uint8_t *)(uintptr_t)Address; + asmv("" :: + : "memory"); + return Result; + } - static inline uint16_t mmioin16(uint64_t Address) - { - asmv("" :: - : "memory"); - uint16_t Result = *(volatile uint16_t *)(uintptr_t)Address; - asmv("" :: - : "memory"); - return Result; - } + static inline uint16_t mmioin16(uint64_t Address) + { + asmv("" :: + : "memory"); + uint16_t Result = *(volatile uint16_t *)(uintptr_t)Address; + asmv("" :: + : "memory"); + return Result; + } - static inline uint32_t mmioin32(uint64_t Address) - { - asmv("" :: - : "memory"); - uint32_t Result = *(volatile uint32_t *)(uintptr_t)Address; - asmv("" :: - : "memory"); - return Result; - } + static inline uint32_t mmioin32(uint64_t Address) + { + asmv("" :: + : "memory"); + uint32_t Result = *(volatile uint32_t *)(uintptr_t)Address; + asmv("" :: + : "memory"); + return Result; + } - static inline uint64_t mmioin64(uint64_t Address) - { - asmv("" :: - : "memory"); - uint64_t Result = *(volatile uint64_t *)(uintptr_t)Address; - asmv("" :: - : "memory"); - return Result; - } + static inline uint64_t mmioin64(uint64_t Address) + { + asmv("" :: + : "memory"); + uint64_t Result = *(volatile uint64_t *)(uintptr_t)Address; + asmv("" :: + : "memory"); + return Result; + } - static inline void mmioout8(uint64_t Address, uint8_t Data) - { - asmv("" :: - : "memory"); - *(volatile uint8_t *)Address = Data; - asmv("" :: - : "memory"); - } + static inline void mmioout8(uint64_t Address, uint8_t Data) + { + asmv("" :: + : "memory"); + *(volatile uint8_t *)Address = Data; + asmv("" :: + : "memory"); + } - static inline void mmioout16(uint64_t Address, uint16_t Data) - { - asmv("" :: - : "memory"); - *(volatile uint16_t *)Address = Data; - asmv("" :: - : "memory"); - } + static inline void mmioout16(uint64_t Address, uint16_t Data) + { + asmv("" :: + : "memory"); + *(volatile uint16_t *)Address = Data; + asmv("" :: + : "memory"); + } - static inline void mmioout32(uint64_t Address, uint32_t Data) - { - asmv("" :: - : "memory"); - *(volatile uint32_t *)Address = Data; - asmv("" :: - : "memory"); - } + static inline void mmioout32(uint64_t Address, uint32_t Data) + { + asmv("" :: + : "memory"); + *(volatile uint32_t *)Address = Data; + asmv("" :: + : "memory"); + } - static inline void mmioout64(uint64_t Address, uint64_t Data) - { - asmv("" :: - : "memory"); - *(volatile uint64_t *)Address = Data; - asmv("" :: - : "memory"); - } + static inline void mmioout64(uint64_t Address, uint64_t Data) + { + asmv("" :: + : "memory"); + *(volatile uint64_t *)Address = Data; + asmv("" :: + : "memory"); + } - static inline void mmoutb(void *Address, uint8_t Value) - { - asmv("mov %1, %0" - : "=m"((*(uint8_t *)(Address))) - : "r"(Value) - : "memory"); - } + static inline void mmoutb(void *Address, uint8_t Value) + { + asmv("mov %1, %0" + : "=m"((*(uint8_t *)(Address))) + : "r"(Value) + : "memory"); + } - static inline void mmoutw(void *Address, uint16_t Value) - { - asmv("mov %1, %0" - : "=m"((*(uint16_t *)(Address))) - : "r"(Value) - : "memory"); - } + static inline void mmoutw(void *Address, uint16_t Value) + { + asmv("mov %1, %0" + : "=m"((*(uint16_t *)(Address))) + : "r"(Value) + : "memory"); + } - static inline void mmoutl(void *Address, uint32_t Value) - { - asmv("mov %1, %0" - : "=m"((*(uint32_t *)(Address))) - : "r"(Value) - : "memory"); - } + static inline void mmoutl(void *Address, uint32_t Value) + { + asmv("mov %1, %0" + : "=m"((*(uint32_t *)(Address))) + : "r"(Value) + : "memory"); + } #if defined(a64) - static inline void mmoutq(void *Address, uint64_t Value) - { - asmv("mov %1, %0" - : "=m"((*(uint64_t *)(Address))) - : "r"(Value) - : "memory"); - } + static inline void mmoutq(void *Address, uint64_t Value) + { + asmv("mov %1, %0" + : "=m"((*(uint64_t *)(Address))) + : "r"(Value) + : "memory"); + } #endif - static inline uint8_t mminb(void *Address) - { - uint8_t Result; - asmv("mov %1, %0" - : "=r"(Result) - : "m"((*(uint8_t *)(Address))) - : "memory"); - return Result; - } + static inline uint8_t mminb(void *Address) + { + uint8_t Result; + asmv("mov %1, %0" + : "=r"(Result) + : "m"((*(uint8_t *)(Address))) + : "memory"); + return Result; + } - static inline uint16_t mminw(void *Address) - { - uint16_t Result; - asmv("mov %1, %0" - : "=r"(Result) - : "m"((*(uint16_t *)(Address))) - : "memory"); - return Result; - } + static inline uint16_t mminw(void *Address) + { + uint16_t Result; + asmv("mov %1, %0" + : "=r"(Result) + : "m"((*(uint16_t *)(Address))) + : "memory"); + return Result; + } - static inline uint32_t mminl(void *Address) - { - uint32_t Result; - asmv("mov %1, %0" - : "=r"(Result) - : "m"((*(uint32_t *)(Address))) - : "memory"); - return Result; - } + static inline uint32_t mminl(void *Address) + { + uint32_t Result; + asmv("mov %1, %0" + : "=r"(Result) + : "m"((*(uint32_t *)(Address))) + : "memory"); + return Result; + } #if defined(a64) - static inline uint64_t mminq(void *Address) - { - uint64_t Result; - asmv("mov %1, %0" - : "=r"(Result) - : "m"((*(uint64_t *)(Address))) - : "memory"); - return Result; - } + static inline uint64_t mminq(void *Address) + { + uint64_t Result; + asmv("mov %1, %0" + : "=r"(Result) + : "m"((*(uint64_t *)(Address))) + : "memory"); + return Result; + } #endif #ifdef __cplusplus } diff --git a/include/kconfig.hpp b/include/kconfig.hpp index 6afcd2e..5a7a3f5 100644 --- a/include/kconfig.hpp +++ b/include/kconfig.hpp @@ -21,12 +21,19 @@ #include #include +enum KCSchedType +{ + Mono = 0, + Multi = 1, +}; + struct KernelConfig { Memory::MemoryAllocatorType AllocatorType; bool SchedulerType; char DriverDirectory[256]; char InitPath[256]; + bool UseLinuxSyscalls; bool InterruptsOnCrash; int Cores; int IOAPICInterruptCore; diff --git a/include/kshell.hpp b/include/kshell.hpp index 97b7495..31ea0e4 100644 --- a/include/kshell.hpp +++ b/include/kshell.hpp @@ -20,6 +20,6 @@ #include -void StartKernelShell(); +void KShellThread(); #endif // !__FENNIX_KERNEL_KERNEL_SHELL_H__ diff --git a/include/lock.hpp b/include/lock.hpp index ddd5617..710cc20 100644 --- a/include/lock.hpp +++ b/include/lock.hpp @@ -39,121 +39,158 @@ size_t GetLocksCount(); class LockClass { public: - struct SpinLockData - { - std::atomic_uint64_t LockData = 0x0; - std::atomic CurrentHolder = "(nul)"; - std::atomic AttemptingToGet = "(nul)"; - std::atomic_uintptr_t StackPointerHolder = 0; - std::atomic_uintptr_t StackPointerAttempt = 0; - std::atomic_size_t Count = 0; - std::atomic_long Core = 0; - }; + struct SpinLockData + { + std::atomic_uint64_t LockData = 0x0; + std::atomic CurrentHolder = "(nul)"; + std::atomic AttemptingToGet = "(nul)"; + std::atomic_uintptr_t StackPointerHolder = 0; + std::atomic_uintptr_t StackPointerAttempt = 0; + std::atomic_size_t Count = 0; + std::atomic_long Core = 0; + }; private: - SpinLockData LockData; - std::atomic_bool IsLocked = false; - std::atomic_ulong DeadLocks = 0; + SpinLockData LockData; + std::atomic_bool IsLocked = false; + std::atomic_ulong DeadLocks = 0; - void DeadLock(SpinLockData Lock); - void TimeoutDeadLock(SpinLockData Lock, uint64_t Timeout); + void DeadLock(SpinLockData &Lock); + void TimeoutDeadLock(SpinLockData &Lock, uint64_t Timeout); + void Yield(); public: - SpinLockData *GetLockData() { return &LockData; } - int Lock(const char *FunctionName); - int Unlock(); + SpinLockData *GetLockData() { return &LockData; } + int Lock(const char *FunctionName); + int Unlock(); - int TimeoutLock(const char *FunctionName, uint64_t Timeout); + int TimeoutLock(const char *FunctionName, uint64_t Timeout); }; /** @brief Please use this macro to create a new smart lock. */ class SmartLockClass { private: - LockClass *LockPointer = nullptr; + LockClass *LockPointer = nullptr; public: - SmartLockClass(LockClass &Lock, const char *FunctionName) - { - this->LockPointer = &Lock; - this->LockPointer->Lock(FunctionName); - } - ~SmartLockClass() { this->LockPointer->Unlock(); } + SmartLockClass(LockClass &Lock, const char *FunctionName) + { + this->LockPointer = &Lock; + this->LockPointer->Lock(FunctionName); + } + ~SmartLockClass() { this->LockPointer->Unlock(); } }; class SmartTimeoutLockClass { private: - LockClass *LockPointer = nullptr; + LockClass *LockPointer = nullptr; public: - SmartTimeoutLockClass(LockClass &Lock, const char *FunctionName, uint64_t Timeout) - { - this->LockPointer = &Lock; - this->LockPointer->TimeoutLock(FunctionName, Timeout); - } - ~SmartTimeoutLockClass() { this->LockPointer->Unlock(); } + SmartTimeoutLockClass(LockClass &Lock, + const char *FunctionName, + uint64_t Timeout) + { + this->LockPointer = &Lock; + this->LockPointer->TimeoutLock(FunctionName, Timeout); + } + ~SmartTimeoutLockClass() + { + this->LockPointer->Unlock(); + } }; -/** @brief Please use this macro to create a new smart critical section lock. */ class SmartLockCriticalSectionClass { private: - LockClass *LockPointer = nullptr; - bool InterruptsEnabled = false; + LockClass *LockPointer = nullptr; + bool InterruptsEnabled = false; public: - SmartLockCriticalSectionClass(LockClass &Lock, const char *FunctionName) - { - if (CPU::Interrupts(CPU::Check)) - InterruptsEnabled = true; - CPU::Interrupts(CPU::Disable); - this->LockPointer = &Lock; - this->LockPointer->Lock(FunctionName); - } - ~SmartLockCriticalSectionClass() - { - this->LockPointer->Unlock(); - if (InterruptsEnabled) - CPU::Interrupts(CPU::Enable); - } + SmartLockCriticalSectionClass(LockClass &Lock, + const char *FunctionName) + { + if (CPU::Interrupts(CPU::Check)) + InterruptsEnabled = true; + CPU::Interrupts(CPU::Disable); + this->LockPointer = &Lock; + this->LockPointer->Lock(FunctionName); + } + ~SmartLockCriticalSectionClass() + { + this->LockPointer->Unlock(); + if (InterruptsEnabled) + CPU::Interrupts(CPU::Enable); + } }; -/** @brief Please use this macro to create a new critical section. */ class SmartCriticalSectionClass { private: - bool InterruptsEnabled = false; + bool InterruptsEnabled = false; public: - bool IsInterruptsEnabled() { return InterruptsEnabled; } + bool IsInterruptsEnabled() + { + return InterruptsEnabled; + } - SmartCriticalSectionClass() - { - if (CPU::Interrupts(CPU::Check)) - InterruptsEnabled = true; - CPU::Interrupts(CPU::Disable); - } - ~SmartCriticalSectionClass() - { - if (InterruptsEnabled) - CPU::Interrupts(CPU::Enable); - } + SmartCriticalSectionClass() + { + if (CPU::Interrupts(CPU::Check)) + InterruptsEnabled = true; + CPU::Interrupts(CPU::Disable); + } + ~SmartCriticalSectionClass() + { + if (InterruptsEnabled) + CPU::Interrupts(CPU::Enable); + } }; -/** @brief Create a new lock (can be used with SmartCriticalSection). */ +/** + * Create a new lock + * + * @note Can be used with SmartCriticalSection + */ #define NewLock(Name) LockClass Name -/** @brief Simple lock that is automatically released when the scope ends. */ -#define SmartLock(LockClassName) SmartLockClass CONCAT(lock##_, __COUNTER__)(LockClassName, __FUNCTION__) +/** + * Simple lock that is automatically released + * when the scope ends. + */ +#define SmartLock(LockClassName) \ + SmartLockClass \ + CONCAT(lock##_, __COUNTER__)(LockClassName, \ + __FUNCTION__) -/** @brief Simple lock with timeout that is automatically released when the scope ends. */ -#define SmartTimeoutLock(LockClassName, Timeout) SmartTimeoutLockClass CONCAT(lock##_, __COUNTER__)(LockClassName, __FUNCTION__, Timeout) +/** + * Simple lock with timeout that is automatically + * released when the scope ends. + */ +#define SmartTimeoutLock(LockClassName, Timeout) \ + SmartTimeoutLockClass \ + CONCAT(lock##_, __COUNTER__)(LockClassName, \ + __FUNCTION__, \ + Timeout) -/** @brief Simple critical section that is automatically released when the scope ends and interrupts are restored if they were enabled. */ -#define SmartCriticalSection(LockClassName) SmartLockCriticalSectionClass CONCAT(lock##_, __COUNTER__)(LockClassName, __FUNCTION__) +/** + * Simple critical section that is + * automatically released when the scope ends + * and interrupts are restored if they + * were enabled. + */ +#define SmartCriticalSection(LockClassName) \ + SmartLockCriticalSectionClass \ + CONCAT(lock##_, \ + __COUNTER__)(LockClassName, \ + __FUNCTION__) -/** @brief Automatically disable interrupts and restore them when the scope ends. */ +/** + * Automatically disable interrupts and + * restore them when the scope ends. + */ #define CriticalSection SmartCriticalSectionClass #endif // __cplusplus diff --git a/include/memory.hpp b/include/memory.hpp index 4e5d00b..e94f962 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #endif // __cplusplus #include @@ -38,33 +39,25 @@ extern uintptr_t _kernel_rodata_start, _kernel_rodata_end; extern uintptr_t _kernel_bss_start, _kernel_bss_end; // kilobyte -#define TO_KB(d) ((d) / 1024) +#define TO_KiB(d) ((d) / 1024) // megabyte -#define TO_MB(d) ((d) / 1024 / 1024) +#define TO_MiB(d) ((d) / 1024 / 1024) // gigabyte -#define TO_GB(d) ((d) / 1024 / 1024 / 1024) +#define TO_GiB(d) ((d) / 1024 / 1024 / 1024) // terabyte -#define TO_TB(d) ((d) / 1024 / 1024 / 1024 / 1024) +#define TO_TiB(d) ((d) / 1024 / 1024 / 1024 / 1024) // petabyte -#define TO_PB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024) +#define TO_PiB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024) // exobyte -#define TO_EB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024 / 1024) -// zettabyte -#define TO_ZB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024) -// yottabyte -#define TO_YB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024) -// brontobyte -#define TO_BB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024) -// geopbyte -#define TO_GPB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024 / 1024) +#define TO_EiB(d) ((d) / 1024 / 1024 / 1024 / 1024 / 1024 / 1024) -#define PAGE_SIZE 0x1000 // 4KB -#define PAGE_SIZE_4K PAGE_SIZE // 4KB -#define PAGE_SIZE_2M 0x200000 // 2MB -#define PAGE_SIZE_4M 0x400000 // 4MB +#define PAGE_SIZE 0x1000 // 4KB +#define PAGE_SIZE_4K PAGE_SIZE // 4KB +#define PAGE_SIZE_2M 0x200000 // 2MB +#define PAGE_SIZE_4M 0x400000 // 4MB #define PAGE_SIZE_1G 0x40000000 // 1GB -#define STACK_SIZE 0x4000 // 16kb +#define STACK_SIZE 0x4000 // 16kb #define USER_STACK_SIZE 0x2000 // 8kb // To pages @@ -88,1001 +81,1025 @@ extern uintptr_t _kernel_bss_start, _kernel_bss_end; namespace Memory { - enum MemoryAllocatorType - { - None, - Pages, - XallocV1, - liballoc11 - }; + enum MemoryAllocatorType + { + None, + Pages, + XallocV1, + liballoc11 + }; - /** - * @brief https://wiki.osdev.org/images/4/41/64-bit_page_tables1.png - * @brief https://wiki.osdev.org/images/6/6b/64-bit_page_tables2.png - */ - enum PTFlag - { - /** @brief Present */ - P = 1 << 0, + /** + * @brief https://wiki.osdev.org/images/4/41/64-bit_page_tables1.png + * @brief https://wiki.osdev.org/images/6/6b/64-bit_page_tables2.png + */ + enum PTFlag + { + /** @brief Present */ + P = 1 << 0, - /** @brief Read/Write */ - RW = 1 << 1, + /** @brief Read/Write */ + RW = 1 << 1, - /** @brief User/Supervisor */ - US = 1 << 2, + /** @brief User/Supervisor */ + US = 1 << 2, - /** @brief Write-Through */ - PWT = 1 << 3, + /** @brief Write-Through */ + PWT = 1 << 3, - /** @brief Cache Disable */ - PCD = 1 << 4, + /** @brief Cache Disable */ + PCD = 1 << 4, - /** @brief Accessed */ - A = 1 << 5, + /** @brief Accessed */ + A = 1 << 5, - /** @brief Dirty */ - D = 1 << 6, + /** @brief Dirty */ + D = 1 << 6, - /** @brief Page Size */ - PS = 1 << 7, + /** @brief Page Size */ + PS = 1 << 7, - /** @brief Global */ - G = 1 << 8, + /** @brief Global */ + G = 1 << 8, - /** @brief Available 0 */ - AVL0 = 1 << 9, + /** @brief Available 0 */ + AVL0 = 1 << 9, - /** @brief Available 1 */ - AVL1 = 1 << 10, + /** @brief Available 1 */ + AVL1 = 1 << 10, - /** @brief Available 2 */ - AVL2 = 1 << 11, + /** @brief Available 2 */ + AVL2 = 1 << 11, - /** @brief Page Attribute Table */ - PAT = 1 << 12, + /** @brief Page Attribute Table */ + PAT = 1 << 12, - /** @brief Available 3 */ - AVL3 = (uint64_t)1 << 52, + /** @brief Available 3 */ + AVL3 = (uint64_t)1 << 52, - /** @brief Available 4 */ - AVL4 = (uint64_t)1 << 53, + /** @brief Available 4 */ + AVL4 = (uint64_t)1 << 53, - /** @brief Available 5 */ - AVL5 = (uint64_t)1 << 54, + /** @brief Available 5 */ + AVL5 = (uint64_t)1 << 54, - /** @brief Available 6 */ - AVL6 = (uint64_t)1 << 55, + /** @brief Available 6 */ + AVL6 = (uint64_t)1 << 55, - /** @brief Available 7 */ - AVL7 = (uint64_t)1 << 56, + /** @brief Available 7 */ + AVL7 = (uint64_t)1 << 56, - /** @brief Available 8 */ - AVL8 = (uint64_t)1 << 57, + /** @brief Available 8 */ + AVL8 = (uint64_t)1 << 57, - /** @brief Available 9 */ - AVL9 = (uint64_t)1 << 58, + /** @brief Available 9 */ + AVL9 = (uint64_t)1 << 58, - /** @brief Protection Key 0 */ - PK0 = (uint64_t)1 << 59, + /** @brief Protection Key 0 */ + PK0 = (uint64_t)1 << 59, - /** @brief Protection Key 1 */ - PK1 = (uint64_t)1 << 60, + /** @brief Protection Key 1 */ + PK1 = (uint64_t)1 << 60, - /** @brief Protection Key 2 */ - PK2 = (uint64_t)1 << 61, + /** @brief Protection Key 2 */ + PK2 = (uint64_t)1 << 61, - /** @brief Protection Key 3 */ - PK3 = (uint64_t)1 << 62, + /** @brief Protection Key 3 */ + PK3 = (uint64_t)1 << 62, - /** @brief Execute Disable */ - XD = (uint64_t)1 << 63 - }; + /** @brief Execute Disable */ + XD = (uint64_t)1 << 63 + }; - union __packed PageTableEntry - { - struct - { + union __packed PageTableEntry + { + struct + { #if defined(a64) - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Dirty : 1; // 6 - uintptr_t PageAttributeTable : 1; // 7 - uintptr_t Global : 1; // 8 - uintptr_t Available0 : 1; // 9 - uintptr_t Available1 : 1; // 10 - uintptr_t Available2 : 1; // 11 - uintptr_t Address : 40; // 12-51 - uintptr_t Available3 : 1; // 52 - uintptr_t Available4 : 1; // 53 - uintptr_t Available5 : 1; // 54 - uintptr_t Available6 : 1; // 55 - uintptr_t Available7 : 1; // 56 - uintptr_t Available8 : 1; // 57 - uintptr_t Available9 : 1; // 58 - uintptr_t ProtectionKey : 4; // 59-62 - uintptr_t ExecuteDisable : 1; // 63 + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Dirty : 1; // 6 + uintptr_t PageAttributeTable : 1; // 7 + uintptr_t Global : 1; // 8 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 + uintptr_t Address : 40; // 12-51 + uintptr_t Available3 : 1; // 52 + uintptr_t Available4 : 1; // 53 + uintptr_t Available5 : 1; // 54 + uintptr_t Available6 : 1; // 55 + uintptr_t Available7 : 1; // 56 + uintptr_t Available8 : 1; // 57 + uintptr_t Available9 : 1; // 58 + uintptr_t ProtectionKey : 4; // 59-62 + uintptr_t ExecuteDisable : 1; // 63 #elif defined(a32) - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Dirty : 1; // 6 - uintptr_t PageAttributeTable : 1; // 7 - uintptr_t Global : 1; // 8 - uintptr_t Available0 : 1; // 9 - uintptr_t Available1 : 1; // 10 - uintptr_t Available2 : 1; // 11 - uintptr_t Address : 20; // 12-31 + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Dirty : 1; // 6 + uintptr_t PageAttributeTable : 1; // 7 + uintptr_t Global : 1; // 8 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 + uintptr_t Address : 20; // 12-31 #elif defined(aa64) #endif - }; - uintptr_t raw; + }; + uintptr_t raw; - /** @brief Set Address */ - void SetAddress(uintptr_t _Address) - { + /** @brief Set Address */ + void SetAddress(uintptr_t _Address) + { #if defined(a64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #elif defined(a32) - _Address &= 0x000FFFFF; - this->raw &= 0xFFC00003; - this->raw |= (_Address << 12); + _Address &= 0x000FFFFF; + this->raw &= 0xFFC00003; + this->raw |= (_Address << 12); #elif defined(aa64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #endif - } + } - /** @brief Get Address */ - uintptr_t GetAddress() - { + /** @brief Get Address */ + uintptr_t GetAddress() + { #if defined(a64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #elif defined(a32) - return ((uintptr_t)(this->raw & 0x003FFFFF000) >> 12); + return ((uintptr_t)(this->raw & 0x003FFFFF000) >> 12); #elif defined(aa64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #endif - } - }; + } + }; - struct __packed PageTableEntryPtr - { + struct __packed PageTableEntryPtr + { #if defined(a64) - PageTableEntry Entries[512]; + PageTableEntry Entries[512]; #elif defined(a32) - PageTableEntry Entries[1024]; + PageTableEntry Entries[1024]; #elif defined(aa64) #endif - }; + }; - union __packed PageDirectoryEntry - { + union __packed PageDirectoryEntry + { #if defined(a64) - struct - { - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Available0 : 1; // 6 - uintptr_t PageSize : 1; // 7 - uintptr_t Available1 : 4; // 8-11 - uintptr_t Address : 40; // 12-51 - uintptr_t Available2 : 11; // 52-62 - uintptr_t ExecuteDisable : 1; // 63 - }; + struct + { + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Available0 : 1; // 6 + uintptr_t PageSize : 1; // 7 + uintptr_t Available1 : 4; // 8-11 + uintptr_t Address : 40; // 12-51 + uintptr_t Available2 : 11; // 52-62 + uintptr_t ExecuteDisable : 1; // 63 + }; - struct - { - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Dirty : 1; // 6 - uintptr_t PageSize : 1; // 7 - uintptr_t Global : 1; // 8 - uintptr_t Available0 : 1; // 9 - uintptr_t Available1 : 1; // 10 - uintptr_t Available2 : 1; // 11 - uintptr_t PageAttributeTable : 1; // 12 - uintptr_t Reserved0 : 8; // 13-20 - uintptr_t Address : 31; // 21-51 - uintptr_t Available3 : 1; // 52 - uintptr_t Available4 : 1; // 53 - uintptr_t Available5 : 1; // 54 - uintptr_t Available6 : 1; // 55 - uintptr_t Available7 : 1; // 56 - uintptr_t Available8 : 1; // 57 - uintptr_t Available9 : 1; // 58 - uintptr_t ProtectionKey : 4; // 59-62 - uintptr_t ExecuteDisable : 1; // 63 - } TwoMB; + struct + { + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Dirty : 1; // 6 + uintptr_t PageSize : 1; // 7 + uintptr_t Global : 1; // 8 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 + uintptr_t PageAttributeTable : 1; // 12 + uintptr_t Reserved0 : 8; // 13-20 + uintptr_t Address : 31; // 21-51 + uintptr_t Available3 : 1; // 52 + uintptr_t Available4 : 1; // 53 + uintptr_t Available5 : 1; // 54 + uintptr_t Available6 : 1; // 55 + uintptr_t Available7 : 1; // 56 + uintptr_t Available8 : 1; // 57 + uintptr_t Available9 : 1; // 58 + uintptr_t ProtectionKey : 4; // 59-62 + uintptr_t ExecuteDisable : 1; // 63 + } TwoMiB; #elif defined(a32) - struct - { - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Available0 : 1; // 6 - uintptr_t PageSize : 1; // 7 - uintptr_t Available1 : 4; // 8-11 - uintptr_t Address : 20; // 12-31 - }; + struct + { + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Available0 : 1; // 6 + uintptr_t PageSize : 1; // 7 + uintptr_t Available1 : 4; // 8-11 + uintptr_t Address : 20; // 12-31 + }; - struct - { - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Dirty : 1; // 6 - uintptr_t PageSize : 1; // 7 - uintptr_t Global : 1; // 8 - uintptr_t Available0 : 1; // 9 - uintptr_t Available1 : 1; // 10 - uintptr_t Available2 : 1; // 11 - uintptr_t PageAttributeTable : 1; // 12 - uintptr_t Address0 : 8; // 13-20 - uintptr_t Reserved0 : 1; // 21 - uintptr_t Address1 : 10; // 22-31 - } FourMB; + struct + { + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Dirty : 1; // 6 + uintptr_t PageSize : 1; // 7 + uintptr_t Global : 1; // 8 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 + uintptr_t PageAttributeTable : 1; // 12 + uintptr_t Address0 : 8; // 13-20 + uintptr_t Reserved0 : 1; // 21 + uintptr_t Address1 : 10; // 22-31 + } FourMiB; #elif defined(aa64) #endif - uintptr_t raw; + uintptr_t raw; - /** @brief Set PageTableEntryPtr address */ - void SetAddress(uintptr_t _Address) - { + /** @brief Set PageTableEntryPtr address */ + void SetAddress(uintptr_t _Address) + { #if defined(a64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #elif defined(a32) - _Address &= 0x000FFFFF; - this->raw &= 0xFFC00003; - this->raw |= (_Address << 12); + _Address &= 0x000FFFFF; + this->raw &= 0xFFC00003; + this->raw |= (_Address << 12); #elif defined(aa64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #endif - } + } - /** @brief Get PageTableEntryPtr address */ - uintptr_t GetAddress() - { + /** @brief Get PageTableEntryPtr address */ + uintptr_t GetAddress() + { #if defined(a64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #elif defined(a32) - return ((uintptr_t)(this->raw & 0x003FFFFF000) >> 12); + return ((uintptr_t)(this->raw & 0x003FFFFF000) >> 12); #elif defined(aa64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #endif - } - }; + } + }; - struct __packed PageDirectoryEntryPtr - { - PageDirectoryEntry Entries[512]; - }; + struct __packed PageDirectoryEntryPtr + { + PageDirectoryEntry Entries[512]; + }; - union __packed PageDirectoryPointerTableEntry - { + union __packed PageDirectoryPointerTableEntry + { #if defined(a64) - struct - { - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Available0 : 1; // 6 - uintptr_t PageSize : 1; // 7 - uintptr_t Available1 : 4; // 8-11 - uintptr_t Address : 40; // 12-51 - uintptr_t Available2 : 11; // 52-62 - uintptr_t ExecuteDisable : 1; // 63 - }; + struct + { + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Available0 : 1; // 6 + uintptr_t PageSize : 1; // 7 + uintptr_t Available1 : 4; // 8-11 + uintptr_t Address : 40; // 12-51 + uintptr_t Available2 : 11; // 52-62 + uintptr_t ExecuteDisable : 1; // 63 + }; - struct - { - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Dirty : 1; // 6 - uintptr_t PageSize : 1; // 7 - uintptr_t Global : 1; // 8 - uintptr_t Available0 : 1; // 9 - uintptr_t Available1 : 1; // 10 - uintptr_t Available2 : 1; // 11 - uintptr_t PageAttributeTable : 1; // 12 - uintptr_t Reserved0 : 17; // 13-29 - uintptr_t Address : 22; // 30-51 - uintptr_t Available3 : 1; // 52 - uintptr_t Available4 : 1; // 53 - uintptr_t Available5 : 1; // 54 - uintptr_t Available6 : 1; // 55 - uintptr_t Available7 : 1; // 56 - uintptr_t Available8 : 1; // 57 - uintptr_t Available9 : 1; // 58 - uintptr_t ProtectionKey : 4; // 59-62 - uintptr_t ExecuteDisable : 1; // 63 - } OneGB; + struct + { + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Dirty : 1; // 6 + uintptr_t PageSize : 1; // 7 + uintptr_t Global : 1; // 8 + uintptr_t Available0 : 1; // 9 + uintptr_t Available1 : 1; // 10 + uintptr_t Available2 : 1; // 11 + uintptr_t PageAttributeTable : 1; // 12 + uintptr_t Reserved0 : 17; // 13-29 + uintptr_t Address : 22; // 30-51 + uintptr_t Available3 : 1; // 52 + uintptr_t Available4 : 1; // 53 + uintptr_t Available5 : 1; // 54 + uintptr_t Available6 : 1; // 55 + uintptr_t Available7 : 1; // 56 + uintptr_t Available8 : 1; // 57 + uintptr_t Available9 : 1; // 58 + uintptr_t ProtectionKey : 4; // 59-62 + uintptr_t ExecuteDisable : 1; // 63 + } OneGiB; #elif defined(aa64) #endif - uintptr_t raw; + uintptr_t raw; - /** @brief Set PageDirectoryEntryPtr address */ - void SetAddress(uintptr_t _Address) - { + /** @brief Set PageDirectoryEntryPtr address */ + void SetAddress(uintptr_t _Address) + { #if defined(a64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #elif defined(aa64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #endif - } + } - /** @brief Get PageDirectoryEntryPtr address */ - uintptr_t GetAddress() - { + /** @brief Get PageDirectoryEntryPtr address */ + uintptr_t GetAddress() + { #if defined(a64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #elif defined(a32) - return 0; + return 0; #elif defined(aa64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #endif - } - }; + } + }; - struct __packed PageDirectoryPointerTableEntryPtr - { - PageDirectoryPointerTableEntry Entries[512]; - }; + struct __packed PageDirectoryPointerTableEntryPtr + { + PageDirectoryPointerTableEntry Entries[512]; + }; - union __packed PageMapLevel4 - { + union __packed PageMapLevel4 + { #if defined(a64) - struct - { - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Available0 : 1; // 6 - uintptr_t Reserved0 : 1; // 7 - uintptr_t Available1 : 4; // 8-11 - uintptr_t Address : 40; // 12-51 - uintptr_t Available2 : 11; // 52-62 - uintptr_t ExecuteDisable : 1; // 63 - }; + struct + { + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Available0 : 1; // 6 + uintptr_t Reserved0 : 1; // 7 + uintptr_t Available1 : 4; // 8-11 + uintptr_t Address : 40; // 12-51 + uintptr_t Available2 : 11; // 52-62 + uintptr_t ExecuteDisable : 1; // 63 + }; #elif defined(aa64) #endif - uintptr_t raw; + uintptr_t raw; - /** @brief Set PageDirectoryPointerTableEntryPtr address */ - void SetAddress(uintptr_t _Address) - { + /** @brief Set PageDirectoryPointerTableEntryPtr address */ + void SetAddress(uintptr_t _Address) + { #if defined(a64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #elif defined(aa64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #endif - } + } - /** @brief Get PageDirectoryPointerTableEntryPtr address */ - uintptr_t GetAddress() - { + /** @brief Get PageDirectoryPointerTableEntryPtr address */ + uintptr_t GetAddress() + { #if defined(a64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #elif defined(a32) - return 0; + return 0; #elif defined(aa64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #endif - } - }; + } + }; - struct __packed PageMapLevel4Ptr - { - PageMapLevel4 Entries[512]; - }; + struct __packed PageMapLevel4Ptr + { + PageMapLevel4 Entries[512]; + }; - union __packed PageMapLevel5 - { + union __packed PageMapLevel5 + { #if defined(a64) - struct - { - uintptr_t Present : 1; // 0 - uintptr_t ReadWrite : 1; // 1 - uintptr_t UserSupervisor : 1; // 2 - uintptr_t WriteThrough : 1; // 3 - uintptr_t CacheDisable : 1; // 4 - uintptr_t Accessed : 1; // 5 - uintptr_t Available0 : 1; // 6 - uintptr_t Reserved0 : 1; // 7 - uintptr_t Available1 : 4; // 8-11 - uintptr_t Address : 40; // 12-51 - uintptr_t Available2 : 11; // 52-62 - uintptr_t ExecuteDisable : 1; // 63 - }; + struct + { + uintptr_t Present : 1; // 0 + uintptr_t ReadWrite : 1; // 1 + uintptr_t UserSupervisor : 1; // 2 + uintptr_t WriteThrough : 1; // 3 + uintptr_t CacheDisable : 1; // 4 + uintptr_t Accessed : 1; // 5 + uintptr_t Available0 : 1; // 6 + uintptr_t Reserved0 : 1; // 7 + uintptr_t Available1 : 4; // 8-11 + uintptr_t Address : 40; // 12-51 + uintptr_t Available2 : 11; // 52-62 + uintptr_t ExecuteDisable : 1; // 63 + }; #elif defined(aa64) #endif - uintptr_t raw; + uintptr_t raw; - /** @brief Set PageMapLevel4Ptr address */ - void SetAddress(uintptr_t _Address) - { + /** @brief Set PageMapLevel4Ptr address */ + void SetAddress(uintptr_t _Address) + { #if defined(a64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #elif defined(aa64) - _Address &= 0x000000FFFFFFFFFF; - this->raw &= 0xFFF0000000000FFF; - this->raw |= (_Address << 12); + _Address &= 0x000000FFFFFFFFFF; + this->raw &= 0xFFF0000000000FFF; + this->raw |= (_Address << 12); #endif - } + } - /** @brief Get PageMapLevel4Ptr address */ - uintptr_t GetAddress() - { + /** @brief Get PageMapLevel4Ptr address */ + uintptr_t GetAddress() + { #if defined(a64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #elif defined(a32) - return 0; + return 0; #elif defined(aa64) - return (this->raw & 0x000FFFFFFFFFF000) >> 12; + return (this->raw & 0x000FFFFFFFFFF000) >> 12; #endif - } - }; + } + }; - class PageTable - { - public: + class PageTable + { + public: #if defined(a64) - PageMapLevel4 Entries[512]; + PageMapLevel4 Entries[512]; #elif defined(a32) - PageDirectoryEntry Entries[1024]; + PageDirectoryEntry Entries[1024]; #elif defined(aa64) #endif - /** - * @brief Update CR3 with this PageTable - */ - void Update(); + /** + * @brief Update CR3 with this PageTable + */ + void Update(); - /** - * @brief Fork this PageTable - * - * @return A new PageTable with the same content - */ - PageTable Fork(); - } __aligned(0x1000); + /** + * @brief Fork this PageTable + * + * @return A new PageTable with the same content + */ + PageTable Fork(); + } __aligned(0x1000); - class Physical - { - private: - NewLock(MemoryLock); + class Physical + { + private: + NewLock(MemoryLock); - uint64_t TotalMemory = 0; - uint64_t FreeMemory = 0; - uint64_t ReservedMemory = 0; - uint64_t UsedMemory = 0; - uint64_t PageBitmapIndex = 0; - Bitmap PageBitmap; + std::atomic_uint64_t TotalMemory = 0; + std::atomic_uint64_t FreeMemory = 0; + std::atomic_uint64_t ReservedMemory = 0; + std::atomic_uint64_t UsedMemory = 0; + uint64_t PageBitmapIndex = 0; + Bitmap PageBitmap; - void ReserveEssentials(); + void ReserveEssentials(); - public: - Bitmap GetPageBitmap() { return PageBitmap; } + public: + Bitmap GetPageBitmap() { return PageBitmap; } - /** - * @brief Get Total Memory - * - * @return uint64_t - */ - uint64_t GetTotalMemory(); + /** + * @brief Get Total Memory + * + * @return uint64_t + */ + uint64_t GetTotalMemory(); - /** - * @brief Get Free Memory - * - * @return uint64_t - */ - uint64_t GetFreeMemory(); + /** + * @brief Get Free Memory + * + * @return uint64_t + */ + uint64_t GetFreeMemory(); - /** - * @brief Get Reserved Memory - * - * @return uint64_t - */ - uint64_t GetReservedMemory(); + /** + * @brief Get Reserved Memory + * + * @return uint64_t + */ + uint64_t GetReservedMemory(); - /** - * @brief Get Used Memory - * - * @return uint64_t - */ - uint64_t GetUsedMemory(); + /** + * @brief Get Used Memory + * + * @return uint64_t + */ + uint64_t GetUsedMemory(); - /** - * @brief Swap page - * - * @param Address Address of the page - * @return true if swap was successful - * @return false if swap was unsuccessful - */ - bool SwapPage(void *Address); + /** + * @brief Swap page + * + * @param Address Address of the page + * @return true if swap was successful + * @return false if swap was unsuccessful + */ + bool SwapPage(void *Address); - /** - * @brief Swap pages - * - * @param Address Address of the pages - * @param PageCount Number of pages - * @return true if swap was successful - * @return false if swap was unsuccessful - */ - bool SwapPages(void *Address, size_t PageCount); + /** + * @brief Swap pages + * + * @param Address Address of the pages + * @param PageCount Number of pages + * @return true if swap was successful + * @return false if swap was unsuccessful + */ + bool SwapPages(void *Address, size_t PageCount); - /** - * @brief Unswap page - * - * @param Address Address of the page - * @return true if unswap was successful - * @return false if unswap was unsuccessful - */ - bool UnswapPage(void *Address); + /** + * @brief Unswap page + * + * @param Address Address of the page + * @return true if unswap was successful + * @return false if unswap was unsuccessful + */ + bool UnswapPage(void *Address); - /** - * @brief Unswap pages - * - * @param Address Address of the pages - * @param PageCount Number of pages - * @return true if unswap was successful - * @return false if unswap was unsuccessful - */ - bool UnswapPages(void *Address, size_t PageCount); + /** + * @brief Unswap pages + * + * @param Address Address of the pages + * @param PageCount Number of pages + * @return true if unswap was successful + * @return false if unswap was unsuccessful + */ + bool UnswapPages(void *Address, size_t PageCount); - /** - * @brief Lock page - * - * @param Address Address of the page - */ - void LockPage(void *Address); + /** + * @brief Lock page + * + * @param Address Address of the page + */ + void LockPage(void *Address); - /** - * @brief Lock pages - * - * @param Address Address of the pages - * @param PageCount Number of pages - */ - void LockPages(void *Address, size_t PageCount); + /** + * @brief Lock pages + * + * @param Address Address of the pages + * @param PageCount Number of pages + */ + void LockPages(void *Address, size_t PageCount); - void ReservePage(void *Address); - void ReservePages(void *Address, size_t PageCount); - void UnreservePage(void *Address); - void UnreservePages(void *Address, size_t PageCount); + void ReservePage(void *Address); + void ReservePages(void *Address, size_t PageCount); + void UnreservePage(void *Address); + void UnreservePages(void *Address, size_t PageCount); - /** - * @brief Request page - * - * @return void* Allocated page address - */ - void *RequestPage(); + /** + * @brief Request page + * + * @return void* Allocated page address + */ + void *RequestPage(); - /** - * @brief Request pages - * - * @param PageCount Number of pages - * @return void* Allocated pages address - */ - void *RequestPages(size_t Count); + /** + * @brief Request pages + * + * @param PageCount Number of pages + * @return void* Allocated pages address + */ + void *RequestPages(std::size_t Count); - /** - * @brief Free page - * - * @param Address Address of the page - */ - void FreePage(void *Address); + /** + * @brief Free page + * + * @param Address Address of the page + */ + void FreePage(void *Address); - /** - * @brief Free pages - * - * @param Address Address of the pages - * @param PageCount Number of pages - */ - void FreePages(void *Address, size_t Count); + /** + * @brief Free pages + * + * @param Address Address of the pages + * @param PageCount Number of pages + */ + void FreePages(void *Address, size_t Count); - /** @brief Do not use. */ - void Init(); + /** @brief Do not use. */ + void Init(); - /** @brief Do not use. */ - Physical(); + /** @brief Do not use. */ + Physical(); - /** @brief Do not use. */ - ~Physical(); - }; + /** @brief Do not use. */ + ~Physical(); + }; - class Virtual - { - private: - NewLock(MemoryLock); - PageTable *Table = nullptr; + class Virtual + { + private: + NewLock(MemoryLock); + PageTable *Table = nullptr; - public: - enum MapType - { - NoMapType, - FourKB, - TwoMB, - FourMB, - OneGB - }; + public: + enum MapType + { + NoMapType, + FourKiB, + TwoMiB, + FourMiB, + OneGiB + }; - class PageMapIndexer - { - public: + class PageMapIndexer + { + public: #if defined(a64) - uintptr_t PMLIndex = 0; - uintptr_t PDPTEIndex = 0; + uintptr_t PMLIndex = 0; + uintptr_t PDPTEIndex = 0; #endif - uintptr_t PDEIndex = 0; - uintptr_t PTEIndex = 0; - PageMapIndexer(uintptr_t VirtualAddress); - }; + uintptr_t PDEIndex = 0; + uintptr_t PTEIndex = 0; + PageMapIndexer(uintptr_t VirtualAddress); + }; - /** - * @brief Check if page has the specified flag. - * - * @param VirtualAddress Virtual address of the page - * @param Flag Flag to check - * @param Type Type of the page. Check MapType enum. - * @return true if page has the specified flag. - * @return false if page is has the specified flag. - */ - bool Check(void *VirtualAddress, PTFlag Flag = PTFlag::P, MapType Type = MapType::FourKB); + /** + * @brief Check if page has the specified flag. + * + * @param VirtualAddress Virtual address of the page + * @param Flag Flag to check + * @param Type Type of the page. Check MapType enum. + * @return true if page has the specified flag. + * @return false if page is has the specified flag. + */ + bool Check(void *VirtualAddress, PTFlag Flag = PTFlag::P, MapType Type = MapType::FourKiB); - /** - * @brief Get physical address of the page. - * @param VirtualAddress Virtual address of the page. - * @return Physical address of the page. - */ - void *GetPhysical(void *VirtualAddress); + /** + * @brief Get physical address of the page. + * @param VirtualAddress Virtual address of the page. + * @return Physical address of the page. + */ + void *GetPhysical(void *VirtualAddress); - /** - * @brief Get map type of the page. - * @param VirtualAddress Virtual address of the page. - * @return Map type of the page. - */ - MapType GetMapType(void *VirtualAddress); + /** + * @brief Get map type of the page. + * @param VirtualAddress Virtual address of the page. + * @return Map type of the page. + */ + MapType GetMapType(void *VirtualAddress); #ifdef a64 - PageMapLevel5 *GetPML5(void *VirtualAddress, MapType Type = MapType::FourKB); - PageMapLevel4 *GetPML4(void *VirtualAddress, MapType Type = MapType::FourKB); - PageDirectoryPointerTableEntry *GetPDPTE(void *VirtualAddress, MapType Type = MapType::FourKB); + PageMapLevel5 *GetPML5(void *VirtualAddress, MapType Type = MapType::FourKiB); + PageMapLevel4 *GetPML4(void *VirtualAddress, MapType Type = MapType::FourKiB); + PageDirectoryPointerTableEntry *GetPDPTE(void *VirtualAddress, MapType Type = MapType::FourKiB); #endif /* a64 */ - PageDirectoryEntry *GetPDE(void *VirtualAddress, MapType Type = MapType::FourKB); - PageTableEntry *GetPTE(void *VirtualAddress, MapType Type = MapType::FourKB); + PageDirectoryEntry *GetPDE(void *VirtualAddress, MapType Type = MapType::FourKiB); + PageTableEntry *GetPTE(void *VirtualAddress, MapType Type = MapType::FourKiB); - /** - * @brief Map page. - * - * @param VirtualAddress Virtual address of the page. - * @param PhysicalAddress Physical address of the page. - * @param Flags Flags of the page. Check PTFlag enum. - * @param Type Type of the page. Check MapType enum. - */ - void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flag = PTFlag::P, MapType Type = MapType::FourKB); + /** + * @brief Map page. + * + * @param VirtualAddress Virtual address of the page. + * @param PhysicalAddress Physical address of the page. + * @param Flags Flags of the page. Check PTFlag enum. + * @param Type Type of the page. Check MapType enum. + */ + void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flag = PTFlag::P, MapType Type = MapType::FourKiB); - /** - * @brief Map multiple pages. - * - * @param VirtualAddress First virtual address of the page. - * @param PhysicalAddress First physical address of the page. - * @param Length Length to map. - * @param Flags Flags of the page. Check PTFlag enum. - * @param Type Type of the page. Check MapType enum. - */ - __always_inline inline void Map(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, MapType Type = MapType::FourKB) - { - int PageSize = PAGE_SIZE_4K; + /** + * @brief Map multiple pages. + * + * @param VirtualAddress First virtual address of the page. + * @param PhysicalAddress First physical address of the page. + * @param Length Length to map. + * @param Flags Flags of the page. Check PTFlag enum. + * @param Type Type of the page. Check MapType enum. + */ + __always_inline inline void Map(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, MapType Type = MapType::FourKiB) + { + int PageSize = PAGE_SIZE_4K; - if (Type == MapType::TwoMB) - PageSize = PAGE_SIZE_2M; - else if (Type == MapType::FourMB) - PageSize = PAGE_SIZE_4M; - else if (Type == MapType::OneGB) - PageSize = PAGE_SIZE_1G; + if (Type == MapType::TwoMiB) + PageSize = PAGE_SIZE_2M; + else if (Type == MapType::FourMiB) + PageSize = PAGE_SIZE_4M; + else if (Type == MapType::OneGiB) + PageSize = PAGE_SIZE_1G; - for (uintptr_t i = 0; i < Length; i += PageSize) - this->Map((void *)((uintptr_t)VirtualAddress + i), (void *)((uintptr_t)PhysicalAddress + i), Flags, Type); - } + for (uintptr_t i = 0; i < Length; i += PageSize) + this->Map((void *)((uintptr_t)VirtualAddress + i), (void *)((uintptr_t)PhysicalAddress + i), Flags, Type); + } - /** - * @brief Map multiple pages efficiently. - * - * This function will detect the best page size to map the pages. - * - * @note This function will not check if PSE or 1GB pages are enabled or supported. - * - * @param VirtualAddress First virtual address of the page. - * @param PhysicalAddress First physical address of the page. - * @param Length Length of the pages. - * @param Flags Flags of the page. Check PTFlag enum. - * @param Fit If true, the function will try to fit the pages in the smallest page size. - * @param FailOnModulo If true, the function will return NoMapType if the length is not a multiple of the page size. - * @return The best page size to map the pages. - */ - __always_inline inline MapType OptimizedMap(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, bool Fit = false, bool FailOnModulo = false) - { - if (unlikely(Fit)) - { - while (Length >= PAGE_SIZE_1G) - { - this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::OneGB); - VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_1G); - PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_1G); - Length -= PAGE_SIZE_1G; - } + /** + * @brief Map multiple pages efficiently. + * + * This function will detect the best page size to map the pages. + * + * @note This function will not check if PSE or 1GB pages are enabled or supported. + * + * @param VirtualAddress First virtual address of the page. + * @param PhysicalAddress First physical address of the page. + * @param Length Length of the pages. + * @param Flags Flags of the page. Check PTFlag enum. + * @param Fit If true, the function will try to fit the pages in the smallest page size. + * @param FailOnModulo If true, the function will return NoMapType if the length is not a multiple of the page size. + * @return The best page size to map the pages. + */ + __always_inline inline MapType OptimizedMap(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, bool Fit = false, bool FailOnModulo = false) + { + if (unlikely(Fit)) + { + while (Length >= PAGE_SIZE_1G) + { + this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::OneGiB); + VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_1G); + PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_1G); + Length -= PAGE_SIZE_1G; + } - while (Length >= PAGE_SIZE_4M) - { - this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::FourMB); - VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_4M); - PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_4M); - Length -= PAGE_SIZE_4M; - } + while (Length >= PAGE_SIZE_4M) + { + this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::FourMiB); + VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_4M); + PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_4M); + Length -= PAGE_SIZE_4M; + } - while (Length >= PAGE_SIZE_2M) - { - this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::TwoMB); - VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_2M); - PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_2M); - Length -= PAGE_SIZE_2M; - } + while (Length >= PAGE_SIZE_2M) + { + this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::TwoMiB); + VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_2M); + PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_2M); + Length -= PAGE_SIZE_2M; + } - while (Length >= PAGE_SIZE_4K) - { - this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::FourKB); - VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_4K); - PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_4K); - Length -= PAGE_SIZE_4K; - } + while (Length >= PAGE_SIZE_4K) + { + this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::FourKiB); + VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_4K); + PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_4K); + Length -= PAGE_SIZE_4K; + } - return Virtual::MapType::FourKB; - } + return Virtual::MapType::FourKiB; + } - Virtual::MapType Type = Virtual::MapType::FourKB; + Virtual::MapType Type = Virtual::MapType::FourKiB; - if (Length >= PAGE_SIZE_1G) - { - Type = Virtual::MapType::OneGB; - if (Length % PAGE_SIZE_1G != 0) - { - warn("Length is not a multiple of 1GB."); - if (FailOnModulo) - return Virtual::MapType::NoMapType; - } - } - else if (Length >= PAGE_SIZE_4M) - { - Type = Virtual::MapType::FourMB; - if (Length % PAGE_SIZE_4M != 0) - { - warn("Length is not a multiple of 4MB."); - if (FailOnModulo) - return Virtual::MapType::NoMapType; - } - } - else if (Length >= PAGE_SIZE_2M) - { - Type = Virtual::MapType::TwoMB; - if (Length % PAGE_SIZE_2M != 0) - { - warn("Length is not a multiple of 2MB."); - if (FailOnModulo) - return Virtual::MapType::NoMapType; - } - } + if (Length >= PAGE_SIZE_1G) + { + Type = Virtual::MapType::OneGiB; + if (Length % PAGE_SIZE_1G != 0) + { + warn("Length is not a multiple of 1GB."); + if (FailOnModulo) + return Virtual::MapType::NoMapType; + } + } + else if (Length >= PAGE_SIZE_4M) + { + Type = Virtual::MapType::FourMiB; + if (Length % PAGE_SIZE_4M != 0) + { + warn("Length is not a multiple of 4MB."); + if (FailOnModulo) + return Virtual::MapType::NoMapType; + } + } + else if (Length >= PAGE_SIZE_2M) + { + Type = Virtual::MapType::TwoMiB; + if (Length % PAGE_SIZE_2M != 0) + { + warn("Length is not a multiple of 2MB."); + if (FailOnModulo) + return Virtual::MapType::NoMapType; + } + } - this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Type); - return Type; - } + this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Type); + return Type; + } - /** - * @brief Unmap page. - * - * @param VirtualAddress Virtual address of the page. - * @param Type Type of the page. Check MapType enum. - */ - void Unmap(void *VirtualAddress, MapType Type = MapType::FourKB); + /** + * @brief Unmap page. + * + * @param VirtualAddress Virtual address of the page. + * @param Type Type of the page. Check MapType enum. + */ + void Unmap(void *VirtualAddress, MapType Type = MapType::FourKiB); - /** - * @brief Unmap multiple pages. - * - * @param VirtualAddress First virtual address of the page. - * @param Length Length to map. - * @param Type Type of the page. Check MapType enum. - */ - __always_inline inline void Unmap(void *VirtualAddress, size_t Length, MapType Type = MapType::FourKB) - { - int PageSize = PAGE_SIZE_4K; + /** + * @brief Unmap multiple pages. + * + * @param VirtualAddress First virtual address of the page. + * @param Length Length to map. + * @param Type Type of the page. Check MapType enum. + */ + __always_inline inline void Unmap(void *VirtualAddress, size_t Length, MapType Type = MapType::FourKiB) + { + int PageSize = PAGE_SIZE_4K; - if (Type == MapType::TwoMB) - PageSize = PAGE_SIZE_2M; - else if (Type == MapType::FourMB) - PageSize = PAGE_SIZE_4M; - else if (Type == MapType::OneGB) - PageSize = PAGE_SIZE_1G; + if (Type == MapType::TwoMiB) + PageSize = PAGE_SIZE_2M; + else if (Type == MapType::FourMiB) + PageSize = PAGE_SIZE_4M; + else if (Type == MapType::OneGiB) + PageSize = PAGE_SIZE_1G; - for (uintptr_t i = 0; i < Length; i += PageSize) - this->Unmap((void *)((uintptr_t)VirtualAddress + i), Type); - } + for (uintptr_t i = 0; i < Length; i += PageSize) + this->Unmap((void *)((uintptr_t)VirtualAddress + i), Type); + } - /** - * @brief Remap page. - * - * @param VirtualAddress Virtual address of the page. - * @param PhysicalAddress Physical address of the page. - * @param Flags Flags of the page. Check PTFlag enum. - * @param Type Type of the page. Check MapType enum. - */ - __always_inline inline void Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type = MapType::FourKB) - { - this->Unmap(VirtualAddress, Type); - this->Map(VirtualAddress, PhysicalAddress, Flags, Type); - } + /** + * @brief Remap page. + * + * @param VirtualAddress Virtual address of the page. + * @param PhysicalAddress Physical address of the page. + * @param Flags Flags of the page. Check PTFlag enum. + * @param Type Type of the page. Check MapType enum. + */ + __always_inline inline void Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type = MapType::FourKiB) + { + this->Unmap(VirtualAddress, Type); + this->Map(VirtualAddress, PhysicalAddress, Flags, Type); + } - /** - * @brief Construct a new Virtual object - * - * @param Table Page table. If null, it will use the current page table. - */ - Virtual(PageTable *Table = nullptr); + /** + * @brief Construct a new Virtual object + * + * @param Table Page table. If null, it will use the current page table. + */ + Virtual(PageTable *Table = nullptr); - /** - * @brief Destroy the Virtual object - * - */ - ~Virtual(); - }; + /** + * @brief Destroy the Virtual object + * + */ + ~Virtual(); + }; - class StackGuard - { - private: - struct AllocatedPages - { - void *PhysicalAddress; - void *VirtualAddress; - }; + class StackGuard + { + private: + struct AllocatedPages + { + void *PhysicalAddress; + void *VirtualAddress; + }; - void *StackBottom = nullptr; - void *StackTop = nullptr; - void *StackPhysicalBottom = nullptr; - void *StackPhysicalTop = nullptr; - uint64_t Size = 0; - bool UserMode = false; - bool Expanded = false; - PageTable *Table = nullptr; - std::vector AllocatedPagesList; + void *StackBottom = nullptr; + void *StackTop = nullptr; + void *StackPhysicalBottom = nullptr; + void *StackPhysicalTop = nullptr; + uint64_t Size = 0; + bool UserMode = false; + bool Expanded = false; + PageTable *Table = nullptr; + std::vector AllocatedPagesList; - public: - std::vector GetAllocatedPages() { return AllocatedPagesList; } + public: + std::vector GetAllocatedPages() { return AllocatedPagesList; } - /** @brief Fork stack guard */ - void Fork(StackGuard *Parent); + /** @brief Fork stack guard */ + void Fork(StackGuard *Parent); - /** @brief For general info */ - uint64_t GetSize() { return Size; } + /** @brief For general info */ + uint64_t GetSize() { return Size; } - /** @brief For general info */ - bool GetUserMode() { return UserMode; } + /** @brief For general info */ + bool GetUserMode() { return UserMode; } - /** @brief For general info */ - bool IsExpanded() { return Expanded; } + /** @brief For general info */ + bool IsExpanded() { return Expanded; } - /** @brief For general info */ - void *GetStackBottom() { return StackBottom; } + /** @brief For general info */ + void *GetStackBottom() { return StackBottom; } - /** @brief For RSP */ - void *GetStackTop() { return StackTop; } + /** @brief For RSP */ + void *GetStackTop() { return StackTop; } - /** @brief For general info (avoid if possible) - * @note This can be used only if the stack was NOT expanded. - */ - void *GetStackPhysicalBottom() - { - if (Expanded) - return nullptr; - return StackPhysicalBottom; - } + /** @brief For general info (avoid if possible) + * @note This can be used only if the stack was NOT expanded. + */ + void *GetStackPhysicalBottom() + { + if (Expanded) + return nullptr; + return StackPhysicalBottom; + } - /** @brief For general info (avoid if possible) - * @note This can be used only if the stack was NOT expanded. - */ - void *GetStackPhysicalTop() - { - if (Expanded) - return nullptr; - return StackPhysicalTop; - } + /** @brief For general info (avoid if possible) + * @note This can be used only if the stack was NOT expanded. + */ + void *GetStackPhysicalTop() + { + if (Expanded) + return nullptr; + return StackPhysicalTop; + } - /** @brief Called by exception handler */ - bool Expand(uintptr_t FaultAddress); - /** - * @brief Construct a new Stack Guard object - * @param User Stack for user mode? - */ - StackGuard(bool User, PageTable *Table); - /** - * @brief Destroy the Stack Guard object - */ - ~StackGuard(); - }; + /** @brief Called by exception handler */ + bool Expand(uintptr_t FaultAddress); + /** + * @brief Construct a new Stack Guard object + * @param User Stack for user mode? + */ + StackGuard(bool User, PageTable *Table); + /** + * @brief Destroy the Stack Guard object + */ + ~StackGuard(); + }; - class MemMgr - { - public: - struct AllocatedPages - { - void *Address; - size_t PageCount; - }; + class MemMgr + { + public: + struct AllocatedPages + { + void *Address; + std::size_t PageCount; + }; - std::vector GetAllocatedPagesList() { return AllocatedPagesList; } - uint64_t GetAllocatedMemorySize(); + std::vector GetAllocatedPagesList() { return AllocatedPagesList; } + uint64_t GetAllocatedMemorySize(); - bool Add(void *Address, size_t Count); + bool Add(void *Address, size_t Count); - void *RequestPages(size_t Count, bool User = false); - void FreePages(void *Address, size_t Count); + void *RequestPages(std::size_t Count, bool User = false); + void FreePages(void *Address, size_t Count); - void DetachAddress(void *Address); + void DetachAddress(void *Address); - MemMgr(PageTable *Table = nullptr, VirtualFileSystem::Node *Directory = nullptr); - ~MemMgr(); + MemMgr(PageTable *Table = nullptr, VirtualFileSystem::Node *Directory = nullptr); + ~MemMgr(); - private: - NewLock(MgrLock); - Bitmap PageBitmap; - PageTable *Table; - VirtualFileSystem::Node *Directory; + private: + NewLock(MgrLock); + Bitmap PageBitmap; + PageTable *Table; + VirtualFileSystem::Node *Directory; - std::vector AllocatedPagesList; - }; + std::vector AllocatedPagesList; + }; + + class SmartHeap + { + private: + void *Object = nullptr; + std::size_t ObjectSize = 0; + + public: + auto GetObject() { return Object; } + SmartHeap(std::size_t Size); + ~SmartHeap(); + + void *operator->() { return Object; } + void *operator*() { return Object; } + operator void *() { return Object; } + operator const char *() + { + return r_cst(const char *, Object); + } + void operator=(void *Address) + { + memcpy(Object, Address, ObjectSize); + } + }; } void InitializeMemoryManagement(); diff --git a/include/power.hpp b/include/power.hpp index c8406cf..be24192 100644 --- a/include/power.hpp +++ b/include/power.hpp @@ -63,7 +63,6 @@ namespace Power void InitDSDT(); Power(); - ~Power(); }; } diff --git a/include/stb/image.h b/include/stb/image.h index 7cd378e..1f6fdd7 100644 --- a/include/stb/image.h +++ b/include/stb/image.h @@ -127,6 +127,10 @@ RECENT REVISION HISTORY: #ifndef STBI_INCLUDE_STB_IMAGE_H #define STBI_INCLUDE_STB_IMAGE_H +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-parameter" + // DOCUMENTATION // // Limitations: @@ -9142,6 +9146,8 @@ STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user return stbi__is_16_main(&s); } +#pragma GCC diagnostic pop + #endif // STB_IMAGE_IMPLEMENTATION /* diff --git a/include/symbols.hpp b/include/symbols.hpp index 3711037..d9e2159 100644 --- a/include/symbols.hpp +++ b/include/symbols.hpp @@ -17,29 +17,31 @@ #pragma once #include +#include namespace SymbolResolver { - class Symbols - { - private: - struct SymbolTable - { - uintptr_t Address; - char *FunctionName; - }; + class Symbols + { + private: + struct SymbolTable + { + uintptr_t Address = 0; + char *FunctionName = (char *)""; + }; - SymbolTable SymTable[0x10000]; - int64_t TotalEntries = 0; - void *Image; + std::vector SymTable; + void *Image; + bool SymbolTableExists = false; - public: - int64_t GetTotalEntries() { return this->TotalEntries; } - void *GetImage() { return this->Image; } - const char *GetSymbolFromAddress(uintptr_t Address); - void AddSymbol(uintptr_t Address, const char *Name); - void AddBySymbolInfo(uint64_t Num, uint64_t EntSize, uint64_t Shndx, uintptr_t Sections); - Symbols(uintptr_t ImageAddress); - ~Symbols(); - }; + public: + decltype(SymbolTableExists) &SymTableExists = this->SymbolTableExists; + void *GetImage() { return this->Image; } + const char *GetSymbolFromAddress(uintptr_t Address); + void AddSymbol(uintptr_t Address, const char *Name); + void AddSymbolInfoFromGRUB(uint64_t Num, uint64_t EntSize, uint64_t Shndx, uintptr_t Sections); + void AppendSymbols(uintptr_t ImageAddress, uintptr_t BaseAddress = 0); + Symbols(uintptr_t ImageAddress); + ~Symbols(); + }; } diff --git a/include/task.hpp b/include/task.hpp index 6678060..9499721 100644 --- a/include/task.hpp +++ b/include/task.hpp @@ -32,14 +32,15 @@ namespace Tasking { - /** @brief Instruction Pointer */ + using VirtualFileSystem::FileDescriptorTable; + using VirtualFileSystem::Node; + + /** Instruction Pointer */ typedef __UINTPTR_TYPE__ IP; - /** @brief Process ID */ + /** Process ID */ typedef int PID; - /** @brief Thread ID */ + /** Thread ID */ typedef int TID; - /* @brief Token */ - typedef __UINTPTR_TYPE__ Token; enum TaskArchitecture { @@ -47,7 +48,10 @@ namespace Tasking x32, x64, ARM32, - ARM64 + ARM64, + + _ArchitectureMin = UnknownArchitecture, + _ArchitectureMax = ARM64 }; enum TaskCompatibility @@ -55,26 +59,35 @@ namespace Tasking UnknownPlatform, Native, Linux, - Windows + Windows, + + _CompatibilityMin = UnknownPlatform, + _CompatibilityMax = Windows }; - enum TaskTrustLevel + enum TaskExecutionMode { - UnknownElevation, + UnknownExecutionMode, Kernel, System, - User + User, + + _ExecuteModeMin = UnknownExecutionMode, + _ExecuteModeMax = User }; - enum TaskStatus + enum TaskStatus : int { UnknownStatus, Ready, Running, Sleeping, - Waiting, - Stopped, - Terminated + Blocked, + Zombie, + Terminated, + + _StatusMin = UnknownStatus, + _StatusMax = Terminated }; enum TaskPriority @@ -84,60 +97,81 @@ namespace Tasking Low = 2, Normal = 5, High = 8, - Critical = 10 + Critical = 10, + + _PriorityMin = UnknownPriority, + _PriorityMax = Critical }; enum KillErrorCodes : int { KILL_SCHEDULER_DESTRUCTION = -0xFFFF, KILL_CXXABI_EXCEPTION = -0xECE97, + KILL_BY_OTHER_PROCESS = -0x7A55, KILL_SYSCALL = -0xCA11, + KILL_CRASH = -0xDEAD, KILL_OOM = -0x1008, KILL_ERROR = -0x1, KILL_SUCCESS = 0, }; - struct TaskSecurity - { - TaskTrustLevel TrustLevel; - Token UniqueToken; - bool IsCritical; - bool IsDebugEnabled; - bool IsKernelDebugEnabled; - }; - struct TaskInfo { - size_t OldUserTime = 0; - size_t OldKernelTime = 0; + uint64_t OldUserTime = 0; + uint64_t OldKernelTime = 0; - size_t SleepUntil = 0; - size_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0; - uint64_t Year, Month, Day, Hour, Minute, Second; - bool Affinity[256]; // MAX_CPU - TaskPriority Priority; - TaskArchitecture Architecture; - TaskCompatibility Compatibility; + uint64_t SleepUntil = 0; + uint64_t KernelTime = 0, UserTime = 0, SpawnTime = 0, LastUpdateTime = 0; + uint64_t Year = 0, Month = 0, Day = 0, Hour = 0, Minute = 0, Second = 0; + bool Affinity[256] = {true}; // MAX_CPU + TaskPriority Priority = TaskPriority::Normal; + TaskArchitecture Architecture = TaskArchitecture::UnknownArchitecture; + TaskCompatibility Compatibility = TaskCompatibility::UnknownPlatform; }; - struct TCB + /** + * TCB struct for gs register + */ + struct gsTCB { - /** @brief Used by syscall handler */ - uintptr_t SyscallStack; /* gs+0x0 */ + /** + * Used by syscall handler + * + * gs+0x0 + */ + uintptr_t SyscallStack = __UINTPTR_MAX__; - /** @brief Used by syscall handler */ - uintptr_t TempStack; /* gs+0x8 */ + /** + * Used by syscall handler + * + * gs+0x8 + */ + uintptr_t TempStack = __UINTPTR_MAX__; - TID ID; - char Name[256]; - struct PCB *Parent; - IP EntryPoint; - int ExitCode; + /** + * The current thread class + */ + class TCB *t; + }; + + class TCB + { + private: + class Task *ctx = nullptr; + + public: + TID ID = -1; + const char * Name = nullptr; + class PCB *Parent = nullptr; + IP EntryPoint = 0; + + std::atomic_int ExitCode; + std::atomic Status = TaskStatus::UnknownStatus; Memory::StackGuard *Stack; Memory::MemMgr *Memory; - TaskStatus Status; + int ErrorNumber; #if defined(a64) - CPU::x64::TrapFrame Registers; + CPU::x64::TrapFrame Registers{}; uintptr_t ShadowGSBase, GSBase, FSBase; #elif defined(a32) CPU::x32::TrapFrame Registers; // TODO @@ -146,52 +180,25 @@ namespace Tasking uintptr_t Registers; // TODO #endif uintptr_t IPHistory[128]; - TaskSecurity Security; - TaskInfo Info; + struct + { + TaskExecutionMode ExecutionMode = UnknownExecutionMode; + bool IsCritical = false; + bool IsDebugEnabled = false; + bool IsKernelDebugEnabled = false; + } Security{}; + TaskInfo Info{}; CPU::x64::FXState *FPU; - void Rename(const char *name) - { - CriticalSection cs; - if (strlen(name) > 256 || strlen(name) == 0) - { - debug("Invalid thread name"); - return; - } + void Rename(const char *name); + void SetPriority(TaskPriority priority); + int GetExitCode() { return ExitCode.load(); } + void SetCritical(bool Critical); + void SetDebugMode(bool Enable); + void SetKernelDebugMode(bool Enable); - trace("Renaming thread %s to %s", Name, name); - strncpy(Name, name, 256); - } - - void SetPriority(TaskPriority priority) - { - CriticalSection cs; - trace("Setting priority of thread %s to %d", Name, priority); - Info.Priority = priority; - } - - int GetExitCode() { return ExitCode; } - - void SetCritical(bool Critical) - { - CriticalSection cs; - trace("Setting criticality of thread %s to %s", Name, Critical ? "true" : "false"); - Security.IsCritical = Critical; - } - - void SetDebugMode(bool Enable) - { - CriticalSection cs; - trace("Setting debug mode of thread %s to %s", Name, Enable ? "true" : "false"); - Security.IsDebugEnabled = Enable; - } - - void SetKernelDebugMode(bool Enable) - { - CriticalSection cs; - trace("Setting kernel debug mode of thread %s to %s", Name, Enable ? "true" : "false"); - Security.IsKernelDebugEnabled = Enable; - } + void Block() { Status.store(TaskStatus::Blocked); } + void Unblock() { Status.store(TaskStatus::Ready); } void SYSV_ABI_Call(uintptr_t Arg1 = 0, uintptr_t Arg2 = 0, @@ -199,92 +206,79 @@ namespace Tasking uintptr_t Arg4 = 0, uintptr_t Arg5 = 0, uintptr_t Arg6 = 0, - void *Function = nullptr) - { - CriticalSection cs; -#if defined(a64) - this->Registers.rdi = Arg1; - this->Registers.rsi = Arg2; - this->Registers.rdx = Arg3; - this->Registers.rcx = Arg4; - this->Registers.r8 = Arg5; - this->Registers.r9 = Arg6; - if (Function != nullptr) - this->Registers.rip = (uint64_t)Function; -#else -#warning "SYSV ABI not implemented for this architecture" -#endif - } + void *Function = nullptr); + + TCB(class Task *ctx, + PCB *Parent, + IP EntryPoint, + const char **argv = nullptr, + const char **envp = nullptr, + const std::vector &auxv = std::vector(), + TaskArchitecture Architecture = TaskArchitecture::x64, + TaskCompatibility Compatibility = TaskCompatibility::Native, + bool ThreadNotReady = false); + + ~TCB(); }; - struct PCB + class PCB { - PID ID; - char Name[256]; - PCB *Parent; - int ExitCode; - TaskStatus Status; - TaskSecurity Security; - TaskInfo Info; + private: + class Task *ctx = nullptr; + bool OwnPageTable = false; + + public: + PID ID = -1; + const char * Name = nullptr; + PCB *Parent = nullptr; + std::atomic_int ExitCode; + std::atomic Status = Zombie; + struct + { + TaskExecutionMode ExecutionMode = UnknownExecutionMode; + bool IsCritical = false; + bool IsDebugEnabled = false; + bool IsKernelDebugEnabled = false; + struct + { + uint16_t UserID = UINT16_MAX; + uint16_t GroupID = UINT16_MAX; + } Real, Effective; + } Security{}; + TaskInfo Info{}; std::vector Threads; std::vector Children; InterProcessCommunication::IPC *IPC; Memory::PageTable *PageTable; SymbolResolver::Symbols *ELFSymbolTable; - VirtualFileSystem::Node *CurrentWorkingDirectory; - VirtualFileSystem::Node *ProcessDirectory; - VirtualFileSystem::Node *memDirectory; - - void SetWorkingDirectory(VirtualFileSystem::Node *node) - { - CriticalSection cs; - trace("Setting working directory of process %s to %#lx (%s)", Name, node, node->Name); - CurrentWorkingDirectory = node; - } - }; - - /** @brief Token Trust Level */ - enum TTL - { - UnknownTrustLevel = 0b0001, - Untrusted = 0b0010, - Trusted = 0b0100, - TrustedByKernel = 0b1000, - FullTrust = Trusted | TrustedByKernel, - AllFlags = 0b1111 - }; - - class Security - { - private: - struct TokenData - { - Token token; - int TrustLevel; - uint64_t OwnerID; - bool Process; - }; - - std::vector Tokens; + Node *CurrentWorkingDirectory; + Node *ProcessDirectory; + Node *memDirectory; + Memory::MemMgr *Memory; + FileDescriptorTable *FileDescriptors; public: - Token CreateToken(); - bool TrustToken(Token token, TTL TrustLevel); - bool AddTrustLevel(Token token, TTL TrustLevel); - bool RemoveTrustLevel(Token token, TTL TrustLevel); - bool UntrustToken(Token token); - bool DestroyToken(Token token); - bool IsTokenTrusted(Token token, TTL TrustLevel); - bool IsTokenTrusted(Token token, int TrustLevel); - int GetTokenTrustLevel(Token token); - Security(); - ~Security(); + void Rename(const char *name); + void SetWorkingDirectory(Node *node); + + PCB(class Task *ctx, + PCB *Parent, + const char *Name, + TaskExecutionMode ExecutionMode, + void *Image = nullptr, + bool DoNotCreatePageTable = false, + uint16_t UserID = -1, + uint16_t GroupID = -1); + + ~PCB(); }; class Task : public Interrupts::Handler { private: - Security SecurityManager; + NewLock(SchedulerLock); + NewLock(TaskingLock); + PID NextPID = 0; TID NextTID = 0; @@ -295,30 +289,76 @@ namespace Tasking std::atomic_size_t SchedulerTicks = 0; std::atomic_size_t LastTaskTicks = 0; std::atomic_int LastCore = 0; - bool StopScheduler = false; + std::atomic_bool StopScheduler = false; + std::atomic_bool SchedulerUpdateTrapFrame = false; + bool InvalidPCB(PCB *pcb); bool InvalidTCB(TCB *tcb); + /** + * @note This function is NOT thread safe + */ void RemoveThread(TCB *tcb); + + /** + * @note This function is NOT thread safe + */ void RemoveProcess(PCB *pcb); - void UpdateUsage(TaskInfo *Info, TaskSecurity *Security, int Core); + void UpdateUsage(TaskInfo *Info, + TaskExecutionMode Mode, + int Core); + /** + * @note This function is NOT thread safe + */ bool FindNewProcess(void *CPUDataPointer); + + /** + * @note This function is NOT thread safe + */ bool GetNextAvailableThread(void *CPUDataPointer); + + /** + * @note This function is NOT thread safe + */ bool GetNextAvailableProcess(void *CPUDataPointer); + + /** + * @note This function is NOT thread safe + */ bool SchedulerSearchProcessThread(void *CPUDataPointer); + + /** + * @note This function is NOT thread safe + */ void UpdateProcessStatus(); + + /** + * @note This function is NOT thread safe + */ void WakeUpThreads(); #if defined(a64) + /** + * @note This function is NOT thread safe + */ void Schedule(CPU::x64::TrapFrame *Frame); + void OnInterruptReceived(CPU::x64::TrapFrame *Frame); #elif defined(a32) + /** + * @note This function is NOT thread safe + */ void Schedule(void *Frame); + void OnInterruptReceived(CPU::x32::TrapFrame *Frame); #elif defined(aa64) + /** + * @note This function is NOT thread safe + */ void Schedule(CPU::aarch64::TrapFrame *Frame); + void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame); #endif @@ -328,42 +368,62 @@ namespace Tasking size_t GetLastTaskTicks() { return LastTaskTicks.load(); } int GetLastCore() { return LastCore.load(); } std::vector GetProcessList() { return ProcessList; } - Security *GetSecurityManager() { return &SecurityManager; } void CleanupProcessesThread(); void Panic() { StopScheduler = true; } bool IsPanic() { return StopScheduler; } - __always_inline inline void Schedule() + + /** + * Yield the current thread and switch + * to another thread if available + */ + __always_inline inline void Yield() { + /* This will trigger the IRQ16 + instantly so we won't execute + the next instruction */ #if defined(a86) - asmv("int $0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */ + asmv("int $0x30"); #elif defined(aa64) - asmv("svc #0x30"); /* This will trigger the IRQ16 instantly so we won't execute the next instruction */ + asmv("svc #0x30"); #endif } + + /** + * Update the current thread's trap frame + * without switching to another thread + */ + __always_inline inline void UpdateFrame() + { + SchedulerUpdateTrapFrame = true; + Yield(); + } + void SignalShutdown(); - void RevertProcessCreation(PCB *Process); - void RevertThreadCreation(TCB *Thread); void KillThread(TCB *tcb, enum KillErrorCodes Code) { tcb->Status = TaskStatus::Terminated; tcb->ExitCode = (int)Code; + debug("Killing thread %s(%d) with exit code %d", + tcb->Name, tcb->ID, Code); } void KillProcess(PCB *pcb, enum KillErrorCodes Code) { pcb->Status = TaskStatus::Terminated; pcb->ExitCode = (int)Code; + debug("Killing process %s(%d) with exit code %d", + pcb->Name, pcb->ID, Code); } /** - * @brief Get the Current Process object + * Get the Current Process object * @return PCB* */ PCB *GetCurrentProcess(); /** - * @brief Get the Current Thread object + * Get the Current Thread object * @return TCB* */ TCB *GetCurrentThread(); @@ -372,17 +432,17 @@ namespace Tasking TCB *GetThreadByID(TID ID); - /** @brief Wait for process to terminate */ + /** Wait for process to terminate */ void WaitForProcess(PCB *pcb); - /** @brief Wait for thread to terminate */ + /** Wait for thread to terminate */ void WaitForThread(TCB *tcb); void WaitForProcessStatus(PCB *pcb, TaskStatus Status); void WaitForThreadStatus(TCB *tcb, TaskStatus Status); /** - * @brief Sleep for a given amount of milliseconds + * Sleep for a given amount of milliseconds * * @param Milliseconds Amount of milliseconds to sleep */ @@ -390,9 +450,11 @@ namespace Tasking PCB *CreateProcess(PCB *Parent, const char *Name, - TaskTrustLevel TrustLevel, + TaskExecutionMode TrustLevel, void *Image = nullptr, - bool DoNotCreatePageTable = false); + bool DoNotCreatePageTable = false, + uint16_t UserID = UINT16_MAX, + uint16_t GroupID = UINT16_MAX); TCB *CreateThread(PCB *Parent, IP EntryPoint, @@ -405,11 +467,17 @@ namespace Tasking Task(const IP EntryPoint); ~Task(); + + friend PCB; + friend TCB; }; } -#define PEXIT(Code) TaskManager->GetCurrentProcess()->ExitCode = Code -#define TEXIT(Code) TaskManager->GetCurrentThread()->ExitCode = Code +#define thisProcess TaskManager->GetCurrentProcess() +#define thisThread TaskManager->GetCurrentThread() + +#define PEXIT(Code) thisProcess->ExitCode = Code +#define TEXIT(Code) thisThread->ExitCode = Code extern "C" void TaskingScheduler_OneShot(int TimeSlice); diff --git a/include/time.hpp b/include/time.hpp index 9a4d4ce..2f8ca7b 100644 --- a/include/time.hpp +++ b/include/time.hpp @@ -65,9 +65,9 @@ namespace Time uint32_t clk = 0; HPET *hpet = nullptr; - size_t ClassCreationTime = 0; + uint64_t ClassCreationTime = 0; - inline size_t ConvertUnit(Units Unit) + inline uint64_t ConvertUnit(Units Unit) { switch (Unit) { @@ -101,9 +101,9 @@ namespace Time public: bool Sleep(size_t Duration, Units Unit); - size_t GetCounter(); - size_t CalculateTarget(size_t Target, Units Unit); - size_t GetNanosecondsSinceClassCreation(); + uint64_t GetCounter(); + uint64_t CalculateTarget(uint64_t Target, Units Unit); + uint64_t GetNanosecondsSinceClassCreation(); HighPrecisionEventTimer(void *hpet); ~HighPrecisionEventTimer(); @@ -112,10 +112,10 @@ namespace Time class TimeStampCounter { private: - size_t clk = 0; - size_t ClassCreationTime = 0; + uint64_t clk = 0; + uint64_t ClassCreationTime = 0; - inline size_t ConvertUnit(Units Unit) + inline uint64_t ConvertUnit(Units Unit) { switch (Unit) { @@ -149,9 +149,9 @@ namespace Time public: bool Sleep(size_t Duration, Units Unit); - size_t GetCounter(); - size_t CalculateTarget(size_t Target, Units Unit); - size_t GetNanosecondsSinceClassCreation(); + uint64_t GetCounter(); + uint64_t CalculateTarget(uint64_t Target, Units Unit); + uint64_t GetNanosecondsSinceClassCreation(); TimeStampCounter(); ~TimeStampCounter(); @@ -190,9 +190,9 @@ namespace Time } bool Sleep(size_t Duration, Units Unit); - size_t GetCounter(); - size_t CalculateTarget(size_t Target, Units Unit); - size_t GetNanosecondsSinceClassCreation(); + uint64_t GetCounter(); + uint64_t CalculateTarget(uint64_t Target, Units Unit); + uint64_t GetNanosecondsSinceClassCreation(); void FindTimers(void *acpi); time(); ~time(); diff --git a/include/types.h b/include/types.h index 5a8f2b2..dfd761a 100644 --- a/include/types.h +++ b/include/types.h @@ -51,6 +51,10 @@ #define foreach for #define in : +#define forItr(itr, container) \ + for (auto itr = container.begin(); \ + itr != container.end(); ++itr) + #define r_cst(t, v) reinterpret_cast(v) #define c_cst(t, v) const_cast(v) #define s_cst(t, v) static_cast(v) @@ -194,8 +198,35 @@ typedef __SIG_ATOMIC_TYPE__ sig_atomic_t; // TODO: ssize_t typedef intptr_t ssize_t; -typedef long off_t; +#if defined(a64) || defined(aa64) +typedef int64_t off_t; typedef long long off64_t; +typedef __INT32_TYPE__ mode_t; +typedef int64_t dev_t; +typedef int64_t ino64_t; +typedef int64_t ino_t; +typedef unsigned int nlink_t; +typedef int blksize_t; +typedef int64_t blkcnt_t; +typedef int64_t blkcnt64_t; +typedef int64_t time_t; +typedef unsigned uid_t; +typedef unsigned gid_t; +#elif defined(a32) +typedef int32_t off_t; +typedef long long off64_t; +typedef __INT32_TYPE__ mode_t; +typedef int32_t dev_t; +typedef int32_t ino64_t; +typedef int32_t ino_t; +typedef unsigned int nlink_t; +typedef int blksize_t; +typedef int32_t blkcnt_t; +typedef int32_t blkcnt64_t; +typedef int32_t time_t; +typedef unsigned uid_t; +typedef unsigned gid_t; +#endif #define INT8_MAX __INT8_MAX__ #define INT8_MIN (-INT8_MAX - 1) diff --git a/include/vm.hpp b/include/vm.hpp new file mode 100644 index 0000000..327957f --- /dev/null +++ b/include/vm.hpp @@ -0,0 +1,36 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_VIRTUALIZATION_H__ +#define __FENNIX_KERNEL_VIRTUALIZATION_H__ + +#include + +/** + * Detects if the system is running in + * a virtualized environment. + * + * @return true if the system is running + * in a virtualized environment, false otherwise. + * + * @note This function will check every + * time it is called, so it is recommended + * to call it once and store the result. + */ +bool IsVirtualizedEnvironment(); + +#endif // !__FENNIX_KERNEL_VIRTUALIZATION_H__ diff --git a/include_std/algorithm b/include_std/algorithm new file mode 100644 index 0000000..55e4f7d --- /dev/null +++ b/include_std/algorithm @@ -0,0 +1,65 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once + +namespace std +{ + template + OutputIt copy(InputIt first, InputIt last, OutputIt result) + { + while (first != last) + { + *result = *first; + ++result; + ++first; + } + return result; + } + + template + void swap(T &a, T &b) + { + T temp = move(a); + a = move(b); + b = move(temp); + } + + template + constexpr const T &min(const T &a, const T &b) + { + return (a < b) ? a : b; + } + + template + constexpr const T &max(const T &a, const T &b) + { + return (a > b) ? a : b; + } + + template + InputIt find(InputIt first, InputIt last, const T &value) + { + while (first != last) + { + if (*first == value) + return first; + ++first; + } + return last; + } +} diff --git a/include_std/assert.h b/include_std/assert.h index e5c2ecc..3244430 100644 --- a/include_std/assert.h +++ b/include_std/assert.h @@ -20,31 +20,31 @@ #include -#define assert(x) \ - do \ - { \ - if (!(x)) \ - { \ - void *CallerAddress = __builtin_extract_return_addr(__builtin_return_address(0)); \ - error("Assertion failed! [%s] [%#lx => %s:%s:%d]", #x, CallerAddress, __FILE__, __FUNCTION__, __LINE__); \ - while (1) \ - ; \ - } \ - } while (0) +#define assert(x) \ + do \ + { \ + if (!(x)) \ + { \ + error("Assertion failed! [%s] [%s:%s:%d]", \ + #x, __FILE__, __FUNCTION__, __LINE__); \ + int3; \ + while (true) \ + ; \ + } \ + } while (0) -#define assert_allow_continue(x) \ - do \ - { \ - if (!(x)) \ - { \ - void *CallerAddress = __builtin_extract_return_addr(__builtin_return_address(0)); \ - error("Assertion failed! [%s] [%#lx => %s:%s:%d]", #x, CallerAddress, __FILE__, __FUNCTION__, __LINE__); \ - } \ - } while (0) +#define assert_allow_continue(x) \ + do \ + { \ + if (!(x)) \ + { \ + error("Assertion failed! [%s] [%s:%s:%d]", \ + #x, __FILE__, __FUNCTION__, __LINE__); \ + } \ + } while (0) -#define static_assert(x) \ - switch (x) \ - case 0: \ - case (x): +#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus) +#define static_assert _Static_assert +#endif #endif // !__FENNIX_KERNEL_ASSERT_H__ diff --git a/include_std/atomic b/include_std/atomic index 47ebc29..932851d 100644 --- a/include_std/atomic +++ b/include_std/atomic @@ -16,4 +16,651 @@ */ #pragma once -#include + +#include +#include +#include + +namespace std +{ +#define _atomic(T) T +#define builtin_atomic_n(name) __atomic_##name##_n +#define builtin_atomic(name) __atomic_##name + + /** + * Specifies the memory ordering constraints for atomic operations. + * + * This enum specifies the possible values for the memory order + * parameter of atomic operations. + * + * Possible values are: + * + * - memory_order_relaxed: There are no synchronization + * or ordering constraints imposed on other reads or writes, + * only this operation's atomicity is guaranteed. + * + * - memory_order_consume: A load operation with this + * memory order performs a consume operation on the + * affected memory location: no reads or writes in the + * current thread dependent on the value currently loaded + * can be reordered before this load. + * + * - memory_order_acquire: A load operation with this + * memory order performs the acquire operation on the + * affected memory location: no reads or writes in the + * current thread can be reordered before this load. + * + * - memory_order_release: A store operation with this + * memory order performs the release operation: no reads + * or writes in the current thread can be reordered after + * this store. + * + * - memory_order_acq_rel: A read-modify-write operation + * with this memory order is both an acquire operation + * and a release operation. + * + * - memory_order_seq_cst: A load operation with this + * memory order performs an acquire operation, a store + * performs a release operation, and read-modify-write + * performs both an acquire operation and a release + * operation, plus a single total order exists in which + * all threads observe all modifications in the same order. + */ + enum class memory_order : int + { + relaxed, + consume, + acquire, + release, + acq_rel, + seq_cst + }; + + /** + * Relaxed memory order + * + * No synchronization or ordering constraints + * imposed on other reads or writes. + * Only atomicity is guaranteed. */ + inline constexpr memory_order memory_order_relaxed = + memory_order::relaxed; + + /** + * Consume memory order + * + * A load operation with this memory order + * performs a consume operation on the affected + * memory location. No reads or writes in the + * current thread dependent on the value + * currently loaded can be reordered before this + * load. Writes to data-dependent variables in + * other threads that release the same atomic + * variable are visible in the current thread. + */ + inline constexpr memory_order memory_order_consume = + memory_order::consume; + + /** Acquire memory order + * + * A load operation with this memory order + * performs the acquire operation on the affected + * memory location. No reads or writes in the + * current thread can be reordered before this + * load. All writes in other threads that release + * the same atomic variable are visible in the + * current thread. */ + inline constexpr memory_order memory_order_acquire = + memory_order::acquire; + + /** Release memory order + * + * A store operation with this memory order + * performs the release operation. No reads or + * writes in the current thread can be reordered + * after this store. All writes in the current + * thread are visible in other threads that acquire + * the same atomic variable, and writes that carry + * a dependency into the atomic variable become + * visible in other threads that consume the same + * atomic. */ + inline constexpr memory_order memory_order_release = + memory_order::release; + + /** Acquire-release memory order + * + * A read-modify-write operation with this memory + * order is both an acquire operation and a release + * operation. No memory reads or writes in the + * current thread can be reordered before the load, + * nor after the store. All writes in other threads + * that release the same atomic variable are visible + * before the modification, and the modification is + * visible in other threads that acquire the same + * atomic variable. */ + inline constexpr memory_order memory_order_acq_rel = + memory_order::acq_rel; + + /** Sequentially-consistent memory order + * + * A load operation with this memory order performs + * an acquire operation, a store performs a release + * operation, and read-modify-write performs both an + * acquire operation and a release operation. + * Additionally, a single total order exists in which + * all threads observe all modifications in the same + * order. */ + inline constexpr memory_order memory_order_seq_cst = + memory_order::seq_cst; + + template + class atomic + { + _atomic(T) value; + + public: + atomic() : value(0) {} + atomic(T desired) : value(desired) {} + // atomic(const atomic &) = delete; + + /** + * Load the value of the atomic variable + * + * @note Order must be one of memory_order::relaxed, + * memory_order::consume, memory_order::acquire or + * memory_order::seq_cst + * + * @param order Memory order constraint to use + * @return The value of the atomic variable + */ + T load(memory_order order = memory_order::seq_cst) const + { + return builtin_atomic_n(load)(&this->value, + static_cast(order)); + } + + /** + * @copydoc load() + */ + T load(memory_order order = memory_order::seq_cst) const volatile + { + return builtin_atomic_n(load)(&this->value, + static_cast(order)); + } + + /** + * Store the value of the atomic variable + * + * @note Order must be one of memory_order::relaxed, + * memory_order::release or memory_order::seq_cst + * + * @param desired The value to store + * @param order Memory order constraint to use + */ + void store(T desired, memory_order order = memory_order::seq_cst) + { + builtin_atomic_n(store)(&this->value, desired, + static_cast(order)); + } + + /** + * @copydoc store() + */ + void store(T desired, + memory_order order = memory_order::seq_cst) volatile + { + builtin_atomic_n(store)(&this->value, desired, + static_cast(order)); + } + + /** + * Exchange the value of the atomic variable + * + * @param desired The value to exchange + * @param order Memory order constraint to use + * @return The value of the atomic variable before the exchange + */ + T exchange(T desired, memory_order order = memory_order::seq_cst) + { + return builtin_atomic_n(exchange)(&this->value, desired, + static_cast(order)); + } + + /** + * @copydoc exchange() + */ + T exchange(T desired, + memory_order order = memory_order::seq_cst) volatile + { + return builtin_atomic_n(exchange)(&this->value, desired, + static_cast(order)); + } + + /** + * Compare and exchange the value of the atomic variable + * + * @param expected The expected value + * @param desired The desired value + * @param success Memory order constraint to use if the exchange succeeds + * @param failure Memory order constraint to use if the exchange fails + * @return True if the exchange succeeded, false otherwise + */ + bool compare_exchange_weak(T &expected, T desired, + memory_order success, + memory_order failure) + { + return builtin_atomic(compare_exchange_weak)(&this->value, &expected, + desired, false, success, + failure); + } + + /** + * @copydoc compare_exchange_weak() + */ + bool compare_exchange_weak(T &expected, T desired, + memory_order success, + memory_order failure) volatile + { + return builtin_atomic(compare_exchange_weak)(&this->value, &expected, + desired, false, success, + failure); + } + + /** + * Compare and exchange the value of the atomic variable + * + * @param expected The expected value + * @param desired The desired value + * @param order Memory order constraint to use + * @return True if the exchange succeeded, false otherwise + */ + bool compare_exchange_weak(T &expected, T desired, + memory_order order = + memory_order_seq_cst) + { + return builtin_atomic(compare_exchange_weak)(&this->value, &expected, + desired, false, order, + static_cast(order)); + } + + /** + * @copydoc compare_exchange_weak() + */ + bool compare_exchange_weak(T &expected, T desired, + memory_order order = + memory_order_seq_cst) volatile + { + return builtin_atomic(compare_exchange_weak)(&this->value, &expected, + desired, false, order, + static_cast(order)); + } + + /** + * Compare and exchange the value of the atomic variable + * + * @param expected The expected value + * @param desired The desired value + * @param success Memory order constraint to use if the exchange succeeds + * @param failure Memory order constraint to use if the exchange fails + * @return True if the exchange succeeded, false otherwise + */ + bool compare_exchange_strong(T &expected, T desired, + memory_order success, + memory_order failure) + { + return builtin_atomic(compare_exchange_strong)(&this->value, &expected, + desired, true, success, + failure); + } + + /** + * @copydoc compare_exchange_strong() + */ + bool compare_exchange_strong(T &expected, T desired, + memory_order success, + memory_order failure) volatile + { + return builtin_atomic(compare_exchange_strong)(&this->value, &expected, + desired, true, success, + failure); + } + + /** + * Compare and exchange the value of the atomic variable + * + * @param expected The expected value + * @param desired The desired value + * @param order Memory order constraint to use + * @return True if the exchange succeeded, false otherwise + */ + bool compare_exchange_strong(T &expected, T desired, + memory_order order = + memory_order_seq_cst) + { + return builtin_atomic(compare_exchange_strong)(&this->value, &expected, + desired, true, order, + static_cast(order)); + } + + /** + * @copydoc compare_exchange_strong() + */ + bool compare_exchange_strong(T &expected, T desired, + memory_order order = + memory_order_seq_cst) volatile + { + return builtin_atomic(compare_exchange_strong)(&this->value, &expected, + desired, true, order, + static_cast(order)); + } + + /** + * Fetch and add the value of the atomic variable + * + * @param arg The value to add + * @param order Memory order constraint to use + * @return The value of the atomic variable before the addition + */ + T fetch_add(T arg, memory_order order = + memory_order_seq_cst) + { + return builtin_atomic(fetch_add)(&this->value, arg, + static_cast(order)); + } + + /** + * @copydoc fetch_add() + */ + T fetch_add(T arg, memory_order order = + memory_order_seq_cst) volatile + { + return builtin_atomic(fetch_add)(&this->value, arg, + static_cast(order)); + } + + /** + * Fetch and subtract the value of the atomic variable + * + * @param arg The value to subtract + * @param order Memory order constraint to use + * @return The value of the atomic variable before the subtraction + */ + T fetch_sub(T arg, memory_order order = + memory_order_seq_cst) + { + return builtin_atomic(fetch_sub)(&this->value, arg, + static_cast(order)); + } + + /** + * @copydoc fetch_sub() + */ + T fetch_sub(T arg, memory_order order = + memory_order_seq_cst) volatile + { + return builtin_atomic(fetch_sub)(&this->value, arg, + static_cast(order)); + } + + /** + * Fetch and bitwise AND the value of the atomic variable + * + * @param arg The value to AND + * @param order Memory order constraint to use + * @return The value of the atomic variable before the AND + */ + T fetch_and(T arg, memory_order order = + memory_order_seq_cst) + { + return builtin_atomic(fetch_and)(&this->value, arg, + static_cast(order)); + } + + /** + * @copydoc fetch_and() + */ + T fetch_and(T arg, memory_order order = + memory_order_seq_cst) volatile + { + return builtin_atomic(fetch_and)(&this->value, arg, + static_cast(order)); + } + + /** + * Fetch and bitwise OR the value of the atomic variable + * + * @param arg The value to OR + * @param order Memory order constraint to use + * @return The value of the atomic variable before the OR + */ + T fetch_or(T arg, memory_order order = + memory_order_seq_cst) + { + return builtin_atomic(fetch_or)(&this->value, arg, + static_cast(order)); + } + + /** + * @copydoc fetch_or() + */ + T fetch_or(T arg, memory_order order = + memory_order_seq_cst) volatile + { + return builtin_atomic(fetch_or)(&this->value, arg, + static_cast(order)); + } + + /** + * Fetch and bitwise XOR the value of the atomic variable + * + * @param arg The value to XOR + * @param order Memory order constraint to use + * @return The value of the atomic variable before the XOR + */ + T fetch_xor(T arg, memory_order order = + memory_order_seq_cst) + { + return builtin_atomic(fetch_xor)(&this->value, arg, + static_cast(order)); + } + + /** + * @copydoc fetch_xor() + */ + T fetch_xor(T arg, memory_order order = + memory_order_seq_cst) volatile + { + return builtin_atomic(fetch_xor)(&this->value, arg, + static_cast(order)); + } + + /** + * Fetch and bitwise NAND the value of the atomic variable + * + * @param arg The value to NAND + * @param order Memory order constraint to use + * @return The value of the atomic variable before the NAND + */ + T fetch_nand(T arg, memory_order order = + memory_order_seq_cst) + { + return builtin_atomic(fetch_nand)(&this->value, arg, + static_cast(order)); + } + + /** + * @copydoc fetch_nand() + */ + T fetch_nand(T arg, memory_order order = + memory_order_seq_cst) volatile + { + return builtin_atomic(fetch_nand)(&this->value, arg, + static_cast(order)); + } + + /** + * Notify all threads waiting on this atomic variable + */ + void notify_all() { stub; } + + /** + * @copydoc notify_all() + */ + void notify_all() volatile { stub; } + + /** + * Notify one thread waiting on this atomic variable + */ + void notify_one() { stub; } + + /** + * @copydoc notify_one() + */ + void notify_one() volatile { stub; } + + /** + * Wait for the atomic variable to change + * + * @param old The value to wait for + * @param order Memory order constraint to use + */ + void wait(T old, memory_order order = + memory_order::seq_cst) const + { + while (this->load(order) == old) + ; + } + + /** + * Check whether this atomic type is lock-free + * @return True if this atomic type is lock-free + */ + bool is_lock_free() const + { + stub; + return true; + } + + /** + * @copydoc is_lock_free() + */ + bool is_lock_free() const volatile + { + stub; + return true; + } + + /** + * Equals true if this atomic type is always lock-free + */ + static constexpr bool is_always_lock_free = true; + + /************************************************/ + T operator++() { return this->fetch_add(1) + 1; } + // T operator++() volatile { return this->fetch_add(1) + 1; } + + T operator++(int) { return this->fetch_add(1); } + // T operator++(int) volatile { return this->fetch_add(1); } + /************************************************/ + T operator--() { return this->fetch_sub(1) - 1; } + // T operator--() volatile { return this->fetch_sub(1) - 1; } + + T operator--(int) { return this->fetch_sub(1); } + // T operator--(int) volatile { return this->fetch_sub(1); } + /************************************************/ + T operator+=(T arg) { return this->fetch_add(arg) + arg; } + // T operator+=(T arg) volatile { return this->fetch_add(arg) + arg; } + + // T operator+=(ptrdiff_t arg) { return this->fetch_add(arg) + arg; } + // T operator+=(ptrdiff_t arg) volatile { return this->fetch_add(arg) + arg; } + /************************************************/ + T operator-=(T arg) { return this->fetch_sub(arg) - arg; } + // T operator-=(T arg) volatile { return this->fetch_sub(arg) - arg; } + + // T operator-=(ptrdiff_t arg) { return this->fetch_sub(arg) - arg; } + // T operator-=(ptrdiff_t arg) volatile { return this->fetch_sub(arg) - arg; } + /************************************************/ + T operator&=(T arg) { return this->fetch_and(arg) & arg; } + // T operator&=(T arg) volatile { return this->fetch_and(arg) & arg; } + + T operator|=(T arg) { return this->fetch_or(arg) | arg; } + // T operator|=(T arg) volatile { return this->fetch_or(arg) | arg; } + + T operator^=(T arg) { return this->fetch_xor(arg) ^ arg; } + // T operator^=(T arg) volatile { return this->fetch_xor(arg) ^ arg; } + /************************************************/ + T operator=(T desired) + { + this->store(desired); + return desired; + } + // T operator=(T desired) volatile + // { + // this->store(desired); + // return desired; + // } + + atomic &operator=(const atomic &other) = delete; + atomic &operator=(const atomic &other) volatile = delete; + /************************************************/ + + /* non standard functions */ + + T operator->() { return this->load(); } + T operator~() { return this->fetch_nand(-1); } + + operator bool() { return this->load() != 0; } + operator T() const { return this->load(); } + + bool operator==(const atomic &other) const { return this->load() == other.load(); } + bool operator==(T other) const { return this->load() == other; } + }; + + typedef atomic atomic_bool; + typedef atomic atomic_char; + typedef atomic atomic_schar; + typedef atomic atomic_uchar; + typedef atomic atomic_short; + typedef atomic atomic_ushort; + typedef atomic atomic_int; + typedef atomic atomic_uint; + typedef atomic atomic_long; + typedef atomic atomic_ulong; + typedef atomic atomic_llong; + typedef atomic atomic_ullong; + typedef atomic atomic_char16_t; + typedef atomic atomic_char32_t; + typedef atomic atomic_wchar_t; + typedef atomic atomic_int8_t; + typedef atomic atomic_uint8_t; + typedef atomic atomic_int16_t; + typedef atomic atomic_uint16_t; + typedef atomic atomic_int32_t; + typedef atomic atomic_uint32_t; + typedef atomic atomic_int64_t; + typedef atomic atomic_uint64_t; + typedef atomic atomic_int_least8_t; + typedef atomic atomic_uint_least8_t; + typedef atomic atomic_int_least16_t; + typedef atomic atomic_uint_least16_t; + typedef atomic atomic_int_least32_t; + typedef atomic atomic_uint_least32_t; + typedef atomic atomic_int_least64_t; + typedef atomic atomic_uint_least64_t; + typedef atomic atomic_int_fast8_t; + typedef atomic atomic_uint_fast8_t; + typedef atomic atomic_int_fast16_t; + typedef atomic atomic_uint_fast16_t; + typedef atomic atomic_int_fast32_t; + typedef atomic atomic_uint_fast32_t; + typedef atomic atomic_int_fast64_t; + typedef atomic atomic_uint_fast64_t; + typedef atomic atomic_intptr_t; + typedef atomic atomic_uintptr_t; + typedef atomic atomic_size_t; + typedef atomic atomic_ptrdiff_t; + typedef atomic atomic_intmax_t; + typedef atomic atomic_uintmax_t; +} + +#undef builtin_atomic_n +#undef builtin_atomic diff --git a/include_std/cstddef b/include_std/cstddef index bbfa92b..f6852ff 100644 --- a/include_std/cstddef +++ b/include_std/cstddef @@ -19,6 +19,6 @@ namespace std { - typedef unsigned long size_t; - typedef long ptrdiff_t; + typedef __SIZE_TYPE__ size_t; + typedef __PTRDIFF_TYPE__ ptrdiff_t; } diff --git a/include_std/errno.h b/include_std/errno.h index 1991559..23fe896 100644 --- a/include_std/errno.h +++ b/include_std/errno.h @@ -18,135 +18,392 @@ #ifndef _ERRNO_H #define _ERRNO_H -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Argument list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 35 /* Resource deadlock would occur */ -#define ENAMETOOLONG 36 /* File name too long */ -#define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define EILSEQ 84 /* Illegal byte sequence */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ -#define ECANCELED 125 /* Operation Canceled */ -#define ENOKEY 126 /* Required key not available */ -#define EKEYEXPIRED 127 /* Key has expired */ -#define EKEYREVOKED 128 /* Key has been revoked */ -#define EKEYREJECTED 129 /* Key was rejected by service */ -#define EOWNERDEAD 130 /* Owner died */ -#define ENOTRECOVERABLE 131 /* State not recoverable */ +/** @brief Operation not permitted */ +#define EPERM 1 + +/** @brief No such file or directory */ +#define ENOENT 2 + +/** @brief No such process */ +#define ESRCH 3 + +/** @brief Interrupted system call */ +#define EINTR 4 + +/** @brief I/O error */ +#define EIO 5 + +/** @brief No such device or address */ +#define ENXIO 6 + +/** @brief Argument list too long */ +#define E2BIG 7 + +/** @brief Exec format error */ +#define ENOEXEC 8 + +/** @brief Bad file number */ +#define EBADF 9 + +/** @brief No child processes */ +#define ECHILD 10 + +/** @brief Try again */ +#define EAGAIN 11 + +/** @brief Out of memory */ +#define ENOMEM 12 + +/** @brief Permission denied */ +#define EACCES 13 + +/** @brief Bad address */ +#define EFAULT 14 + +/** @brief Block device required */ +#define ENOTBLK 15 + +/** @brief Device or resource busy */ +#define EBUSY 16 + +/** @brief File exists */ +#define EEXIST 17 + +/** @brief Cross-device link */ +#define EXDEV 18 + +/** @brief No such device */ +#define ENODEV 19 + +/** @brief Not a directory */ +#define ENOTDIR 20 + +/** @brief Is a directory */ +#define EISDIR 21 + +/** @brief Invalid argument */ +#define EINVAL 22 + +/** @brief File table overflow */ +#define ENFILE 23 + +/** @brief Too many open files */ +#define EMFILE 24 + +/** @brief Not a typewriter */ +#define ENOTTY 25 + +/** @brief Text file busy */ +#define ETXTBSY 26 + +/** @brief File too large */ +#define EFBIG 27 + +/** @brief No space left on device */ +#define ENOSPC 28 + +/** @brief Illegal seek */ +#define ESPIPE 29 + +/** @brief Read-only file system */ +#define EROFS 30 + +/** @brief Too many links */ +#define EMLINK 31 + +/** @brief Broken pipe */ +#define EPIPE 32 + +/** @brief Math argument out of domain of func */ +#define EDOM 33 + +/** @brief Math result not representable */ +#define ERANGE 34 + +/** @brief Resource deadlock would occur */ +#define EDEADLK 35 + +/** @brief File name too long */ +#define ENAMETOOLONG 36 + +/** @brief No record locks available */ +#define ENOLCK 37 + +/** @brief Function not implemented */ +#define ENOSYS 38 + +/** @brief Directory not empty */ +#define ENOTEMPTY 39 + +/** @brief Too many symbolic links encountered */ +#define ELOOP 40 + +/** @brief No message of desired type */ +#define ENOMSG 42 + +/** @brief Identifier removed */ +#define EIDRM 43 + +/** @brief Channel number out of range */ +#define ECHRNG 44 + +/** @brief Level 2 not synchronized */ +#define EL2NSYNC 45 + +/** @brief Level 3 halted */ +#define EL3HLT 46 + +/** @brief Level 3 reset */ +#define EL3RST 47 + +/** @brief Link number out of range */ +#define ELNRNG 48 + +/** @brief Protocol driver not attached */ +#define EUNATCH 49 + +/** @brief No CSI structure available */ +#define ENOCSI 50 + +/** @brief Level 2 halted */ +#define EL2HLT 51 + +/** @brief Invalid exchange */ +#define EBADE 52 + +/** @brief Invalid request descriptor */ +#define EBADR 53 + +/** @brief Exchange full */ +#define EXFULL 54 + +/** @brief No anode */ +#define ENOANO 55 + +/** @brief Invalid request code */ +#define EBADRQC 56 + +/** @brief Invalid slot */ +#define EBADSLT 57 + +/** @brief Bad font file format */ +#define EBFONT 59 + +/** @brief Device not a stream */ +#define ENOSTR 60 + +/** @brief No data available */ +#define ENODATA 61 + +/** @brief Timer expired */ +#define ETIME 62 + +/** @brief Out of streams resources */ +#define ENOSR 63 + +/** @brief Machine is not on the network */ +#define ENONET 64 + +/** @brief Package not installed */ +#define ENOPKG 65 + +/** @brief Object is remote */ +#define EREMOTE 66 + +/** @brief Link has been severed */ +#define ENOLINK 67 + +/** @brief Advertise error */ +#define EADV 68 + +/** @brief Srmount error */ +#define ESRMNT 69 + +/** @brief Communication error on send */ +#define ECOMM 70 + +/** @brief Protocol error */ +#define EPROTO 71 + +/** @brief Multihop attempted */ +#define EMULTIHOP 72 + +/** @brief RFS specific error */ +#define EDOTDOT 73 + +/** @brief Not a data message */ +#define EBADMSG 74 + +/** @brief Value too large for defined data type */ +#define EOVERFLOW 75 + +/** @brief Name not unique on network */ +#define ENOTUNIQ 76 + +/** @brief File descriptor in bad state */ +#define EBADFD 77 + +/** @brief Remote address changed */ +#define EREMCHG 78 + +/** @brief Can not access a needed shared library */ +#define ELIBACC 79 + +/** @brief Accessing a corrupted shared library */ +#define ELIBBAD 80 + +/** @brief .lib section in a.out corrupted */ +#define ELIBSCN 81 + +/** @brief Attempting to link in too many shared libraries */ +#define ELIBMAX 82 + +/** @brief Cannot exec a shared library directly */ +#define ELIBEXEC 83 + +/** @brief Illegal byte sequence */ +#define EILSEQ 84 + +/** @brief Interrupted system call should be restarted */ +#define ERESTART 85 + +/** @brief Streams pipe error */ +#define ESTRPIPE 86 + +/** @brief Too many users */ +#define EUSERS 87 + +/** @brief Socket operation on non-socket */ +#define ENOTSOCK 88 + +/** @brief Destination address required */ +#define EDESTADDRREQ 89 + +/** @brief Message too long */ +#define EMSGSIZE 90 + +/** @brief Protocol wrong type for socket */ +#define EPROTOTYPE 91 + +/** @brief Protocol not available */ +#define ENOPROTOOPT 92 + +/** @brief Protocol not supported */ +#define EPROTONOSUPPORT 93 + +/** @brief Socket type not supported */ +#define ESOCKTNOSUPPORT 94 + +/** @brief Operation not supported on transport endpoint */ +#define EOPNOTSUPP 95 + +/** @brief Protocol family not supported */ +#define EPFNOSUPPORT 96 + +/** @brief Address family not supported by protocol */ +#define EAFNOSUPPORT 97 + +/** @brief Address already in use */ +#define EADDRINUSE 98 + +/** @brief Cannot assign requested address */ +#define EADDRNOTAVAIL 99 + +/** @brief Network is down */ +#define ENETDOWN 100 + +/** @brief Network is unreachable */ +#define ENETUNREACH 101 + +/** @brief Network dropped connection because of reset */ +#define ENETRESET 102 + +/** @brief Software caused connection abort */ +#define ECONNABORTED 103 + +/** @brief Connection reset by peer */ +#define ECONNRESET 104 + +/** @brief No buffer space available */ +#define ENOBUFS 105 + +/** @brief Transport endpoint is already connected */ +#define EISCONN 106 + +/** @brief Transport endpoint is not connected */ +#define ENOTCONN 107 + +/** @brief Cannot send after transport endpoint shutdown */ +#define ESHUTDOWN 108 + +/** @brief Too many references: cannot splice */ +#define ETOOMANYREFS 109 + +/** @brief Connection timed out */ +#define ETIMEDOUT 110 + +/** @brief Connection refused */ +#define ECONNREFUSED 111 + +/** @brief Host is down */ +#define EHOSTDOWN 112 + +/** @brief No route to host */ +#define EHOSTUNREACH 113 + +/** @brief Operation already in progress */ +#define EALREADY 114 + +/** @brief Operation now in progress */ +#define EINPROGRESS 115 + +/** @brief Stale NFS file handle */ +#define ESTALE 116 + +/** @brief Structure needs cleaning */ +#define EUCLEAN 117 + +/** @brief Not a XENIX named type file */ +#define ENOTNAM 118 + +/** @brief No XENIX semaphores available */ +#define ENAVAIL 119 + +/** @brief Is a named type file */ +#define EISNAM 120 + +/** @brief Remote I/O error */ +#define EREMOTEIO 121 + +/** @brief Quota exceeded */ +#define EDQUOT 122 + +/** @brief No medium found */ +#define ENOMEDIUM 123 + +/** @brief Wrong medium type */ +#define EMEDIUMTYPE 124 + +/** @brief Operation Canceled */ +#define ECANCELED 125 + +/** @brief Required key not available */ +#define ENOKEY 126 + +/** @brief Key has expired */ +#define EKEYEXPIRED 127 + +/** @brief Key has been revoked */ +#define EKEYREVOKED 128 + +/** @brief Key was rejected by service */ +#define EKEYREJECTED 129 + +/** @brief Owner died */ +#define EOWNERDEAD 130 + +/** @brief State not recoverable */ +#define ENOTRECOVERABLE 131 extern int *__errno_location(void) __attribute__((const)); #define errno (*__errno_location()) diff --git a/include_std/float.h b/include_std/float.h new file mode 100644 index 0000000..ec7b1a4 --- /dev/null +++ b/include_std/float.h @@ -0,0 +1,30 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once + +/* Stubs */ +#define FLT_RADIX 2 +#if a64 +#define DBL_MANT_DIG 53 +#define DBL_MAX_10_EXP 308 +#define DBL_MAX 1.7976931348623157e+308 +#elif a32 +#define DBL_MANT_DIG 24 +#define DBL_MAX_10_EXP 38 +#define DBL_MAX 3.4028234663852886e+38 +#endif diff --git a/include_std/functional b/include_std/functional new file mode 100644 index 0000000..e2bdcea --- /dev/null +++ b/include_std/functional @@ -0,0 +1,30 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once + +namespace std +{ + template + struct equal_to + { + bool operator()(const T &lhs, const T &rhs) const + { + return lhs == rhs; + } + }; +} diff --git a/include_std/mutex b/include_std/mutex new file mode 100644 index 0000000..2b255b0 --- /dev/null +++ b/include_std/mutex @@ -0,0 +1,66 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once + +#include + +#include +#include +#include + +namespace std +{ + /** + * A mutex implementation. + * + * @note The TaskManager must be + * initialized before using this class. + */ + class mutex + { + private: + atomic_bool Locked = false; + vector Waiting; + Tasking::TCB *Holder = nullptr; + + public: + void lock(); + bool try_lock(); + void unlock(); + + mutex() = default; + mutex(const mutex &) = delete; + ~mutex() = default; + }; + + template + class lock_guard + { + private: + Mutex &m; + + public: + explicit lock_guard(Mutex &mutex) + : m(mutex) { m.lock(); } + + ~lock_guard() { m.unlock(); } + + lock_guard(const lock_guard &) = delete; + lock_guard &operator=(const lock_guard &) = delete; + }; +} diff --git a/include_std/std.hpp b/include_std/std.hpp index 1b01608..1a32a8e 100644 --- a/include_std/std.hpp +++ b/include_std/std.hpp @@ -22,7 +22,8 @@ #define __FENNIX_KERNEL_STD_H__ #include -#include +#include +#include #include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include /** * @brief // stub namespace for std::align_val_t and new operator diff --git a/include_std/std/atomic.hpp b/include_std/std/atomic.hpp deleted file mode 100644 index bee5b49..0000000 --- a/include_std/std/atomic.hpp +++ /dev/null @@ -1,521 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#ifndef __FENNIX_KERNEL_STD_ATOMIC_H__ -#define __FENNIX_KERNEL_STD_ATOMIC_H__ - -#include -#include -#include - -namespace std -{ -#define _atomic(T) T -#define builtin_atomic_n(name) __atomic_##name##_n -#define builtin_atomic(name) __atomic_##name - - /** - * @brief Specifies the memory ordering constraints for atomic operations. - * - * This enum specifies the possible values for the memory order parameter of atomic operations. - * - * Possible values are: - * - * - memory_order_relaxed: There are no synchronization - * or ordering constraints imposed on other reads or writes, - * only this operation's atomicity is guaranteed. - * - * - memory_order_consume: A load operation with this - * memory order performs a consume operation on the - * affected memory location: no reads or writes in the - * current thread dependent on the value currently loaded - * can be reordered before this load. - * - * - memory_order_acquire: A load operation with this - * memory order performs the acquire operation on the - * affected memory location: no reads or writes in the - * current thread can be reordered before this load. - * - * - memory_order_release: A store operation with this - * memory order performs the release operation: no reads - * or writes in the current thread can be reordered after - * this store. - * - * - memory_order_acq_rel: A read-modify-write operation - * with this memory order is both an acquire operation - * and a release operation. - * - * - memory_order_seq_cst: A load operation with this - * memory order performs an acquire operation, a store - * performs a release operation, and read-modify-write - * performs both an acquire operation and a release - * operation, plus a single total order exists in which - * all threads observe all modifications in the same order. - */ - enum class memory_order : int - { - relaxed, - consume, - acquire, - release, - acq_rel, - seq_cst - }; - - inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; - inline constexpr memory_order memory_order_consume = memory_order::consume; - inline constexpr memory_order memory_order_acquire = memory_order::acquire; - inline constexpr memory_order memory_order_release = memory_order::release; - inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; - inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; - - template - class atomic - { - _atomic(T) value; - - public: - atomic() noexcept : value(0) {} - atomic(T desired) noexcept : value(desired) {} - // atomic(const atomic &) = delete; - - /** - * @brief Load the value of the atomic variable - * - * @note Order must be one of memory_order::relaxed, memory_order::consume, memory_order::acquire or memory_order::seq_cst - * - * @param order Memory order constraint to use - * @return The value of the atomic variable - */ - T load(memory_order order = memory_order::seq_cst) const noexcept - { - return builtin_atomic_n(load)(&this->value, static_cast(order)); - } - - /** - * @copydoc load() - */ - T load(memory_order order = memory_order::seq_cst) const volatile noexcept - { - return builtin_atomic_n(load)(&this->value, static_cast(order)); - } - - /** - * @brief Store the value of the atomic variable - * - * @note Order must be one of memory_order::relaxed, memory_order::release or memory_order::seq_cst - * - * @param desired The value to store - * @param order Memory order constraint to use - */ - void store(T desired, memory_order order = memory_order::seq_cst) noexcept - { - builtin_atomic_n(store)(&this->value, desired, static_cast(order)); - } - - /** - * @copydoc store() - */ - void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept - { - builtin_atomic_n(store)(&this->value, desired, static_cast(order)); - } - - /** - * @brief Exchange the value of the atomic variable - * - * @param desired The value to exchange - * @param order Memory order constraint to use - * @return The value of the atomic variable before the exchange - */ - T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept - { - return builtin_atomic_n(exchange)(&this->value, desired, static_cast(order)); - } - - /** - * @copydoc exchange() - */ - T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept - { - return builtin_atomic_n(exchange)(&this->value, desired, static_cast(order)); - } - - /** - * @brief Compare and exchange the value of the atomic variable - * - * @param expected The expected value - * @param desired The desired value - * @param success Memory order constraint to use if the exchange succeeds - * @param failure Memory order constraint to use if the exchange fails - * @return True if the exchange succeeded, false otherwise - */ - bool compare_exchange_weak(T &expected, T desired, std::memory_order success, std::memory_order failure) noexcept - { - return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, success, failure); - } - - /** - * @copydoc compare_exchange_weak() - */ - bool compare_exchange_weak(T &expected, T desired, std::memory_order success, std::memory_order failure) volatile noexcept - { - return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, success, failure); - } - - /** - * @brief Compare and exchange the value of the atomic variable - * - * @param expected The expected value - * @param desired The desired value - * @param order Memory order constraint to use - * @return True if the exchange succeeded, false otherwise - */ - bool compare_exchange_weak(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) noexcept - { - return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, order, static_cast(order)); - } - - /** - * @copydoc compare_exchange_weak() - */ - bool compare_exchange_weak(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) volatile noexcept - { - return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, order, static_cast(order)); - } - - /** - * @brief Compare and exchange the value of the atomic variable - * - * @param expected The expected value - * @param desired The desired value - * @param success Memory order constraint to use if the exchange succeeds - * @param failure Memory order constraint to use if the exchange fails - * @return True if the exchange succeeded, false otherwise - */ - bool compare_exchange_strong(T &expected, T desired, std::memory_order success, std::memory_order failure) noexcept - { - return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, success, failure); - } - - /** - * @copydoc compare_exchange_strong() - */ - bool compare_exchange_strong(T &expected, T desired, std::memory_order success, std::memory_order failure) volatile noexcept - { - return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, success, failure); - } - - /** - * @brief Compare and exchange the value of the atomic variable - * - * @param expected The expected value - * @param desired The desired value - * @param order Memory order constraint to use - * @return True if the exchange succeeded, false otherwise - */ - bool compare_exchange_strong(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) noexcept - { - return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, order, static_cast(order)); - } - - /** - * @copydoc compare_exchange_strong() - */ - bool compare_exchange_strong(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) volatile noexcept - { - return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, order, static_cast(order)); - } - - /** - * @brief Fetch and add the value of the atomic variable - * - * @param arg The value to add - * @param order Memory order constraint to use - * @return The value of the atomic variable before the addition - */ - T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept - { - return builtin_atomic(fetch_add)(&this->value, arg, static_cast(order)); - } - - /** - * @copydoc fetch_add() - */ - T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept - { - return builtin_atomic(fetch_add)(&this->value, arg, static_cast(order)); - } - - /** - * @brief Fetch and subtract the value of the atomic variable - * - * @param arg The value to subtract - * @param order Memory order constraint to use - * @return The value of the atomic variable before the subtraction - */ - T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept - { - return builtin_atomic(fetch_sub)(&this->value, arg, static_cast(order)); - } - - /** - * @copydoc fetch_sub() - */ - T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept - { - return builtin_atomic(fetch_sub)(&this->value, arg, static_cast(order)); - } - - /** - * @brief Fetch and bitwise AND the value of the atomic variable - * - * @param arg The value to AND - * @param order Memory order constraint to use - * @return The value of the atomic variable before the AND - */ - T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept - { - return builtin_atomic(fetch_and)(&this->value, arg, static_cast(order)); - } - - /** - * @copydoc fetch_and() - */ - T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept - { - return builtin_atomic(fetch_and)(&this->value, arg, static_cast(order)); - } - - /** - * @brief Fetch and bitwise OR the value of the atomic variable - * - * @param arg The value to OR - * @param order Memory order constraint to use - * @return The value of the atomic variable before the OR - */ - T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept - { - return builtin_atomic(fetch_or)(&this->value, arg, static_cast(order)); - } - - /** - * @copydoc fetch_or() - */ - T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept - { - return builtin_atomic(fetch_or)(&this->value, arg, static_cast(order)); - } - - /** - * @brief Fetch and bitwise XOR the value of the atomic variable - * - * @param arg The value to XOR - * @param order Memory order constraint to use - * @return The value of the atomic variable before the XOR - */ - T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept - { - return builtin_atomic(fetch_xor)(&this->value, arg, static_cast(order)); - } - - /** - * @copydoc fetch_xor() - */ - T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept - { - return builtin_atomic(fetch_xor)(&this->value, arg, static_cast(order)); - } - - /** - * @brief Fetch and bitwise NAND the value of the atomic variable - * - * @param arg The value to NAND - * @param order Memory order constraint to use - * @return The value of the atomic variable before the NAND - */ - T fetch_nand(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept - { - return builtin_atomic(fetch_nand)(&this->value, arg, static_cast(order)); - } - - /** - * @copydoc fetch_nand() - */ - T fetch_nand(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept - { - return builtin_atomic(fetch_nand)(&this->value, arg, static_cast(order)); - } - - /** - * @brief Notify all threads waiting on this atomic variable - */ - void notify_all() noexcept - { - fixme("not implemented"); - } - - /** - * @copydoc notify_all() - */ - void notify_all() volatile noexcept - { - fixme("not implemented"); - } - - /** - * @brief Notify one thread waiting on this atomic variable - */ - void notify_one() noexcept - { - fixme("not implemented"); - } - - /** - * @copydoc notify_one() - */ - void notify_one() volatile noexcept - { - fixme("not implemented"); - } - - /** - * @brief Wait for the atomic variable to change - * - * @param old The value to wait for - * @param order Memory order constraint to use - */ - void wait(T old, std::memory_order order = std::memory_order::seq_cst) const noexcept - { - fixme("not implemented"); - } - - /** - * @copydoc wait() - */ - void wait(T old, std::memory_order order = std::memory_order::seq_cst) const volatile noexcept - { - fixme("not implemented"); - } - - /** - * @brief Check whether this atomic type is lock-free - * @return True if this atomic type is lock-free - */ - bool is_lock_free() const noexcept - { - fixme("not implemented"); - return true; - } - - /** - * @copydoc is_lock_free() - */ - bool is_lock_free() const volatile noexcept - { - fixme("not implemented"); - return true; - } - - /** - * @brief Equals true if this atomic type is always lock-free - */ - static constexpr bool is_always_lock_free = true; - - T operator++() noexcept { return this->fetch_add(1) + 1; } - T operator--() noexcept { return this->fetch_sub(1) - 1; } - T operator++(int) noexcept { return this->fetch_add(1); } - T operator--(int) noexcept { return this->fetch_sub(1); } - - T operator+=(T desired) noexcept { return this->fetch_add(desired) + desired; } - T operator-=(T desired) noexcept { return this->fetch_sub(desired) - desired; } - // T operator+=(std::ptrdiff_t desired) noexcept { return this->fetch_add(desired) + desired; } - // T operator-=(std::ptrdiff_t desired) noexcept { return this->fetch_sub(desired) - desired; } - - T operator&=(T desired) noexcept { return this->fetch_and(desired) & desired; } - T operator|=(T desired) noexcept { return this->fetch_or(desired) | desired; } - T operator^=(T desired) noexcept { return this->fetch_xor(desired) ^ desired; } - - T operator->() noexcept { return this->load(); } - T operator~() noexcept { return this->fetch_nand(-1); } - - bool operator==(const atomic &other) const noexcept { return this->load() == other.load(); } - bool operator==(T other) const noexcept { return this->load() == other; } - - atomic &operator=(const atomic &) = delete; - T operator=(T desired) noexcept - { - this->store(desired); - return desired; - } - - operator bool() noexcept { return this->load() != 0; } - // operator T() noexcept { return this->load(); } - operator T() const noexcept { return this->load(); } - }; - - typedef atomic atomic_bool; - typedef atomic atomic_char; - typedef atomic atomic_schar; - typedef atomic atomic_uchar; - typedef atomic atomic_short; - typedef atomic atomic_ushort; - typedef atomic atomic_int; - typedef atomic atomic_uint; - typedef atomic atomic_long; - typedef atomic atomic_ulong; - typedef atomic atomic_llong; - typedef atomic atomic_ullong; - typedef atomic atomic_char16_t; - typedef atomic atomic_char32_t; - typedef atomic atomic_wchar_t; - typedef atomic atomic_int8_t; - typedef atomic atomic_uint8_t; - typedef atomic atomic_int16_t; - typedef atomic atomic_uint16_t; - typedef atomic atomic_int32_t; - typedef atomic atomic_uint32_t; - typedef atomic atomic_int64_t; - typedef atomic atomic_uint64_t; - typedef atomic atomic_int_least8_t; - typedef atomic atomic_uint_least8_t; - typedef atomic atomic_int_least16_t; - typedef atomic atomic_uint_least16_t; - typedef atomic atomic_int_least32_t; - typedef atomic atomic_uint_least32_t; - typedef atomic atomic_int_least64_t; - typedef atomic atomic_uint_least64_t; - typedef atomic atomic_int_fast8_t; - typedef atomic atomic_uint_fast8_t; - typedef atomic atomic_int_fast16_t; - typedef atomic atomic_uint_fast16_t; - typedef atomic atomic_int_fast32_t; - typedef atomic atomic_uint_fast32_t; - typedef atomic atomic_int_fast64_t; - typedef atomic atomic_uint_fast64_t; - typedef atomic atomic_intptr_t; - typedef atomic atomic_uintptr_t; - typedef atomic atomic_size_t; - typedef atomic atomic_ptrdiff_t; - typedef atomic atomic_intmax_t; - typedef atomic atomic_uintmax_t; -} - -#undef builtin_atomic_n -#undef builtin_atomic - -#endif // !__FENNIX_KERNEL_STD_ATOMIC_H__ diff --git a/include_std/std/smart_ptr.hpp b/include_std/std/smart_ptr.hpp index 31b27a8..94c4d58 100644 --- a/include_std/std/smart_ptr.hpp +++ b/include_std/std/smart_ptr.hpp @@ -20,6 +20,7 @@ #include +#include #include // show debug messages @@ -249,24 +250,6 @@ namespace std } }; - template - struct remove_reference - { - typedef T type; - }; - - template - struct remove_reference - { - typedef T type; - }; - - template - struct remove_reference - { - typedef T type; - }; - template using remove_reference_t = typename remove_reference::type; diff --git a/include_std/std/string.hpp b/include_std/std/string.hpp index 7b53663..2a9937b 100644 --- a/include_std/std/string.hpp +++ b/include_std/std/string.hpp @@ -24,6 +24,7 @@ // show debug messages // #define DEBUG_CPP_STRING 1 +// #define DEBUG_CPP_STRING_VERBOSE 1 #ifdef DEBUG_CPP_STRING #define strdbg(m, ...) debug(m, ##__VA_ARGS__) @@ -31,6 +32,12 @@ #define strdbg(m, ...) #endif +#ifdef DEBUG_CPP_STRING_VERBOSE +#define v_strdbg(m, ...) debug(m, ##__VA_ARGS__) +#else +#define v_strdbg(m, ...) +#endif + // TODO: Somewhere the delete is called twice, causing a double free error. namespace std @@ -55,51 +62,65 @@ namespace std this->Capacity = this->Length + 1; this->Data = new char[this->Capacity]; strcpy(this->Data, Str); - strdbg("New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); } ~string() { - strdbg("String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); delete[] this->Data, this->Data = nullptr; } size_t length() const { - strdbg("String length: %d", this->Length); + v_strdbg("String length: %d", + this->Length); return this->Length; } size_t capacity() const { - strdbg("String capacity: %d", this->Capacity); + v_strdbg("String capacity: %d", + this->Capacity); return this->Capacity; } const char *c_str() const { - strdbg("String data: \"%s\"", this->Data); + v_strdbg("String data: \"%s\"", + this->Data); return this->Data; } void resize(size_t NewLength) { strdbg("String resize: %d", NewLength); - if (NewLength > this->Capacity) + if (NewLength < this->Capacity) { - size_t newCapacity = NewLength + 1; - char *newData = new char[newCapacity]; + this->Length = NewLength; + this->Data[this->Length] = '\0'; - strcpy(newData, this->Data); - - strdbg("old: %#lx, new: %#lx", this->Data, newData); - delete[] this->Data; - this->Data = newData; - this->Capacity = newCapacity; + strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); + return; } + + size_t newCapacity = NewLength + 1; + char *newData = new char[newCapacity]; + strcpy(newData, this->Data); + + strdbg("old: %#lx, new: %#lx", + this->Data, newData); + + delete[] this->Data; + this->Data = newData; this->Length = NewLength; - this->Data[this->Length] = '\0'; - strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + this->Capacity = newCapacity; + + strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); } void concat(const string &Other) @@ -108,7 +129,8 @@ namespace std this->resize(NewLength); strcat(this->Data, Other.Data); - strdbg("String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); } bool empty() const @@ -392,14 +414,26 @@ namespace std for (size_t i = 0; i < Str.Length; i++) this->Data[Pos + i] = Str.Data[i]; - strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); + } + + void pop_back() + { + strdbg("String pop_back"); + if (this->Length > 0) + { + this->Data[this->Length - 1] = '\0'; + this->Length--; + } } string operator+(const string &Other) const { string result = *this; result.concat(Other); - strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", result.Data, result.Data, result.Length, result.Capacity); + strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", + result.Data, result.Data, result.Length, result.Capacity); return result; } @@ -407,21 +441,33 @@ namespace std { string result = *this; result.concat(Other); - strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", result.Data, result.Data, result.Length, result.Capacity); + strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", + result.Data, result.Data, result.Length, result.Capacity); return result; } string &operator+=(const string &Other) { this->concat(Other); - strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); return *this; } string &operator+=(const char *Other) { this->concat(Other); - strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); + return *this; + } + + string &operator+=(char Other) + { + const char str[2] = {Other, '\0'}; + this->concat(str); + strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); return *this; } @@ -430,15 +476,16 @@ namespace std // string &operator=(const string &Other) // { - // if (this != &Other) - // { - // delete[] this->Data; - // this->Data = Other.Data; - // this->Length = Other.Length; - // this->Capacity = Other.Capacity; - // strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); - // } - // return *this; + // if (this != &Other) + // { + // delete[] this->Data; + // this->Data = Other.Data; + // this->Length = Other.Length; + // this->Capacity = Other.Capacity; + // strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", + // this->Data, this->Data, this->Length, this->Capacity); + // } + // return *this; // } string &operator=(const char *Other) @@ -448,21 +495,24 @@ namespace std delete[] this->Data; this->Data = new char[this->Capacity]; strcpy(this->Data, Other); - strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); return *this; } string &operator<<(const string &Other) { this->concat(Other); - strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); return *this; } string &operator<<(const char *Other) { this->concat(Other); - strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity); + strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this->Data, this->Data, this->Length, this->Capacity); return *this; } @@ -478,6 +528,18 @@ namespace std return this->Data[Index]; } + char &operator[](size_t Index) + { + strdbg("String index: %d", Index); + return this->Data[Index]; + } + + const char &operator[](size_t Index) const + { + strdbg("String index: %d", Index); + return this->Data[Index]; + } + bool operator==(const string &Other) const { strdbg("String compared: \"%s\" == \"%s\"", this->Data, Other.Data); @@ -513,25 +575,29 @@ namespace std iterator &operator++() { ++this->Pointer; - strdbg("String iterator incremented: %#lx", this->Pointer); + strdbg("String iterator incremented: %#lx", + this->Pointer); return *this; } char &operator*() { - strdbg("String iterator dereferenced: %#lx", this->Pointer); + strdbg("String iterator dereferenced: %#lx", + this->Pointer); return *this->Pointer; } bool operator!=(const iterator &Other) const { - strdbg("String iterator compared: %#lx != %#lx", this->Pointer, Other.Pointer); + strdbg("String iterator compared: %#lx != %#lx", + this->Pointer, Other.Pointer); return this->Pointer != Other.Pointer; } bool operator==(const iterator &Other) const { - strdbg("String iterator compared: %#lx == %#lx", this->Pointer, Other.Pointer); + strdbg("String iterator compared: %#lx == %#lx", + this->Pointer, Other.Pointer); return this->Pointer == Other.Pointer; } }; diff --git a/include_std/std/unordered_map.hpp b/include_std/std/unordered_map.hpp index 9e956f3..345f682 100644 --- a/include_std/std/unordered_map.hpp +++ b/include_std/std/unordered_map.hpp @@ -21,111 +21,111 @@ #include #include #include -#include #include +#include namespace std { - template - class unordered_map - { - public: - typedef std::pair key_value_pair; - typedef std::list bucket; - typedef typename std::vector::iterator iterator; - typedef typename std::vector::const_iterator const_iterator; + template + class unordered_map + { + public: + typedef std::pair key_value_pair; + typedef std::list bucket; + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; - private: - static const size_t DEFAULT_NUM_BUCKETS = 10; - std::vector bkts; + private: + static const size_t DEFAULT_NUM_BUCKETS = 10; + std::vector bkts; - size_t hash(const key_type &key) const - { - std::hash hash_function; - return hash_function(key) % this->bkts.size(); - } + size_t hash(const key_type &key) const + { + std::hash hash_function; + return hash_function(key) % this->bkts.size(); + } - public: - unordered_map() : bkts(DEFAULT_NUM_BUCKETS) {} - unordered_map(size_t num_buckets) : bkts(num_buckets) {} + public: + unordered_map() : bkts(DEFAULT_NUM_BUCKETS) {} + unordered_map(size_t num_buckets) : bkts(num_buckets) {} - void insert(const key_value_pair &pair) - { - size_t bucket_index = hash(pair.first); - bucket &bkt = this->bkts[bucket_index]; - for (auto it = bkt.begin(); it != bkt.end(); ++it) - { - if (it->first == pair.first) - { - it->second = pair.second; - return; - } - } - bkt.push_back(pair); - } + void insert(const key_value_pair &pair) + { + size_t bucket_index = hash(pair.first); + bucket &bkt = this->bkts[bucket_index]; + for (auto it = bkt.begin(); it != bkt.end(); ++it) + { + if (it->first == pair.first) + { + it->second = pair.second; + return; + } + } + bkt.push_back(pair); + } - bool contains(const key_type &key) const - { - size_t bucket_index = hash(key); - const bucket &bkt = this->bkts[bucket_index]; - for (auto it = bkt.begin(); it != bkt.end(); ++it) - { - if (it->first == key) - { - return true; - } - } - return false; - } + bool contains(const key_type &key) const + { + size_t bucket_index = hash(key); + const bucket &bkt = this->bkts[bucket_index]; + for (auto it = bkt.begin(); it != bkt.end(); ++it) + { + if (it->first == key) + { + return true; + } + } + return false; + } - iterator find(const key_type &k) - { - size_t bucket_index = hash(k); - bucket &bkt = this->bkts[bucket_index]; - for (auto it = bkt.begin(); it != bkt.end(); ++it) - { - if (it->first == k) - return it; - } - return bkt.end(); - } + iterator find(const key_type &k) + { + size_t bucket_index = hash(k); + bucket &bkt = this->bkts[bucket_index]; + for (auto it = bkt.begin(); it != bkt.end(); ++it) + { + if (it->first == k) + return it; + } + return bkt.end(); + } - const_iterator find(const key_type &k) const - { - size_t bucket_index = hash(k); - const bucket &bkt = this->bkts[bucket_index]; - for (auto it = bkt.begin(); it != bkt.end(); ++it) - { - if (it->first == k) - return it; - } - return bkt.end(); - } + const_iterator find(const key_type &k) const + { + size_t bucket_index = hash(k); + const bucket &bkt = this->bkts[bucket_index]; + for (auto it = bkt.begin(); it != bkt.end(); ++it) + { + if (it->first == k) + return it; + } + return bkt.end(); + } - iterator end() noexcept { return this->bkts.end(); } + iterator end() { return this->bkts.end(); } - size_t size() const - { - size_t count = 0; - foreach (const auto &bkt in this->bkts) - count += bkt.size(); + size_t size() const + { + size_t count = 0; + foreach (const auto &bkt in this->bkts) + count += bkt.size(); - return count; - } + return count; + } - value_type &operator[](const key_type &key) - { - size_t bucket_index = hash(key); - bucket &bkt = this->bkts[bucket_index]; - for (auto it = bkt.begin(); it != bkt.end(); ++it) - { - if (it->first == key) - return it->second; - } - bkt.emplace_back(key, value_type()); - return bkt.back().second; - } - }; + value_type &operator[](const key_type &key) + { + size_t bucket_index = hash(key); + bucket &bkt = this->bkts[bucket_index]; + for (auto it = bkt.begin(); it != bkt.end(); ++it) + { + if (it->first == key) + return it->second; + } + bkt.emplace_back(key, value_type()); + return bkt.back().second; + } + }; } #endif // !__FENNIX_KERNEL_STD_UNORDERED_MAP_H__ diff --git a/include_std/std/vector.hpp b/include_std/std/vector.hpp deleted file mode 100644 index 43e76fc..0000000 --- a/include_std/std/vector.hpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#ifndef __FENNIX_KERNEL_STD_VECTOR_H__ -#define __FENNIX_KERNEL_STD_VECTOR_H__ - -#include -#include -#include - -namespace std -{ - template - class vector - { - private: - size_t VectorSize = 0; - size_t VectorCapacity = 0; - T *VectorBuffer = nullptr; - - public: - typedef T *iterator; - typedef const T *const_iterator; - - NIF vector() - { -#ifdef DEBUG_MEM_ALLOCATION - debug("VECTOR INIT: vector( )"); -#endif - VectorCapacity = 0; - VectorSize = 0; - VectorBuffer = 0; - } - - NIF vector(size_t Size) - { - VectorCapacity = Size; - VectorSize = Size; -#ifdef DEBUG_MEM_ALLOCATION - debug("VECTOR INIT: vector( %lld )", Size); -#endif - VectorBuffer = new T[Size]; - } - - NIF vector(size_t Size, const T &Initial) - { - VectorSize = Size; - VectorCapacity = Size; -#ifdef DEBUG_MEM_ALLOCATION - debug("VECTOR INIT: vector( %lld %llx )", Size, Initial); -#endif - assert(Size > 0); - VectorBuffer = new T[Size]; - for (size_t i = 0; i < Size; i++) - VectorBuffer[i] = Initial; - } - - NIF vector(const vector &v) - { - VectorSize = v.VectorSize; - VectorCapacity = v.VectorCapacity; -#ifdef DEBUG_MEM_ALLOCATION - debug("VECTOR INIT: vector( )->Size: %lld", VectorSize); -#endif - if (!v.VectorBuffer || VectorSize <= 0) - return; - - VectorBuffer = new T[VectorSize]; - for (size_t i = 0; i < VectorSize; i++) - VectorBuffer[i] = v.VectorBuffer[i]; - } - - NIF ~vector() - { -#ifdef DEBUG_MEM_ALLOCATION - debug("VECTOR INIT: ~vector( ~%lx )", VectorBuffer); -#endif - VectorSize = 0; - VectorCapacity = 0; - if (VectorBuffer != nullptr) - { - delete[] VectorBuffer, VectorBuffer = nullptr; - } - } - - NIF void remove(size_t Position) - { - if (Position >= VectorSize) - return; - memset(&*(VectorBuffer + Position), 0, sizeof(T)); - for (size_t i = 0; i < VectorSize - 1; i++) - { - *(VectorBuffer + Position + i) = *(VectorBuffer + Position + i + 1); - } - VectorSize--; - } - - NIF void remove(const T &Value) - { - for (size_t i = 0; i < VectorSize; i++) - { - if (VectorBuffer[i] == Value) - { - remove(i); - return; - } - } - } - - NIF T &null_elem() - { - static T null_elem{}; - return null_elem; - } - - NIF bool null_elem(size_t Index) - { - if (!reinterpret_cast(&VectorBuffer[Index])) - return false; - return true; - } - - NIF T &next(size_t Position) - { - if (Position + 1 < VectorSize && reinterpret_cast(&VectorBuffer[Position + 1])) - return VectorBuffer[Position + 1]; - warn("next( %lld ) is null (requested by %#lx)", Position, __builtin_return_address(0)); - return this->null_elem(); - } - - NIF T &prev(size_t Position) - { - if (Position > 0 && reinterpret_cast(&VectorBuffer[Position - 1])) - return VectorBuffer[Position - 1]; - warn("prev( %lld ) is null (requested by %#lx)", Position, __builtin_return_address(0)); - return this->null_elem(); - } - - NIF T &next(const T &Value) - { - for (size_t i = 0; i < VectorSize; i++) - { - if (VectorBuffer[i] == Value) - { - if (i + 1 < VectorSize && reinterpret_cast(&VectorBuffer[i + 1])) - return VectorBuffer[i + 1]; - else - break; - } - } - warn("next( %#lx ) is null (requested by %#lx)", Value, __builtin_return_address(0)); - return this->null_elem(); - } - - NIF T &prev(const T &Value) - { - for (size_t i = 0; i < VectorSize; i++) - { - if (VectorBuffer[i] == Value) - { - if (i > 0 && reinterpret_cast(&VectorBuffer[i - 1])) - return VectorBuffer[i - 1]; - else - break; - } - } - warn("prev( %#lx ) is null (requested by %#lx)", Value, __builtin_return_address(0)); - return this->null_elem(); - } - - NIF size_t capacity() const { return VectorCapacity; } - - NIF size_t size() const { return VectorSize; } - - NIF bool empty() const; - - NIF iterator begin() { return VectorBuffer; } - - NIF iterator end() { return VectorBuffer + size(); } - - NIF T &front() { return VectorBuffer[0]; } - - NIF T &back() { return VectorBuffer[VectorSize - 1]; } - - NIF void push_back(const T &Value) - { - if (VectorSize >= VectorCapacity) - reserve(VectorCapacity + 5); - VectorBuffer[VectorSize++] = Value; - } - - NIF void pop_back() { VectorSize--; } - - NIF void reverse() - { - if (VectorSize <= 1) - return; - for (size_t i = 0, j = VectorSize - 1; i < j; i++, j--) - { - T c = *(VectorBuffer + i); - *(VectorBuffer + i) = *(VectorBuffer + j); - *(VectorBuffer + j) = c; - } - } - - NIF void reserve(size_t Capacity) - { - if (VectorBuffer == 0) - { - VectorSize = 0; - VectorCapacity = 0; - } -#ifdef DEBUG_MEM_ALLOCATION - debug("VECTOR ALLOCATION: reverse( %lld )", Capacity); -#endif - T *NewBuffer = new T[Capacity]; - size_t _Size = Capacity < VectorSize ? Capacity : VectorSize; - for (size_t i = 0; i < _Size; i++) - NewBuffer[i] = VectorBuffer[i]; - VectorCapacity = Capacity; -#ifdef DEBUG_MEM_ALLOCATION - debug("VECTOR ALLOCATION: reverse( )->Buffer:~%lld", VectorBuffer); -#endif - delete[] VectorBuffer; - VectorBuffer = NewBuffer; - } - - NIF void resize(size_t Size) - { - reserve(Size); - VectorSize = Size; - } - - NIF void clear() - { - VectorCapacity = 0; - VectorSize = 0; - if (VectorBuffer != nullptr) - { - delete[] VectorBuffer, VectorBuffer = nullptr; - } - } - - NIF T *data() { return VectorBuffer; } - - NIF T &operator[](size_t Index) - { - if (!reinterpret_cast(&VectorBuffer[Index])) - { - warn("operator[]( %lld ) is null (requested by %#lx)", Index, __builtin_return_address(0)); - return this->null_elem(); - } - return VectorBuffer[Index]; - } - - NIF vector &operator=(const vector &v) - { - delete[] VectorBuffer; - VectorSize = v.VectorSize; - VectorCapacity = v.VectorCapacity; -#ifdef DEBUG_MEM_ALLOCATION - debug("VECTOR ALLOCATION: operator=( )->Size:%lld", VectorSize); -#endif - VectorBuffer = new T[VectorSize]; - for (size_t i = 0; i < VectorSize; i++) - VectorBuffer[i] = v.VectorBuffer[i]; - return *this; - } - }; -} - -#endif // !__FENNIX_KERNEL_STD_VECTOR_H__ diff --git a/include_std/stdarg.h b/include_std/stdarg.h index 714a590..f079bb0 100644 --- a/include_std/stdarg.h +++ b/include_std/stdarg.h @@ -20,6 +20,4 @@ #include - - #endif // !__FENNIX_KERNEL_STDARG_H__ diff --git a/include_std/string.hpp b/include_std/string similarity index 100% rename from include_std/string.hpp rename to include_std/string diff --git a/include_std/type_trails b/include_std/type_trails new file mode 100644 index 0000000..4a129ef --- /dev/null +++ b/include_std/type_trails @@ -0,0 +1,45 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once + +namespace std +{ + template + struct is_trivially_copyable + { + static constexpr bool value = __is_trivially_copyable(T); + }; + + template + struct remove_reference + { + typedef T type; + }; + + template + struct remove_reference + { + typedef T type; + }; + + template + struct remove_reference + { + typedef T type; + }; +} diff --git a/include_std/utility b/include_std/utility new file mode 100644 index 0000000..9f2fbbb --- /dev/null +++ b/include_std/utility @@ -0,0 +1,29 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once + +#include + +namespace std +{ + template + typename std::remove_reference::type &&move(T &&arg) + { + return static_cast::type &&>(arg); + } +} diff --git a/include_std/vector b/include_std/vector index fceebaa..93da616 100644 --- a/include_std/vector +++ b/include_std/vector @@ -16,4 +16,288 @@ */ #pragma once -#include + +#include + +#include +#include +#include +#include +#include +#include + +// #define DEBUG_VECTOR_MESSAGES 1 + +#ifdef DEBUG_VECTOR_MESSAGES +#define vDebug(m, ...) debug(m, ##__VA_ARGS__) +#else +#define vDebug(m, ...) +#endif + +namespace std +{ + template + class vector + { + private: + size_t VectorSize = 0; + size_t VectorCapacity = 0; + T *VectorBuffer = nullptr; + + public: + typedef T *iterator; + typedef const T *const_iterator; + + vector() { vDebug("%#lx: ( empty init )", this); } + + vector(size_t Size) + : VectorSize(Size), + VectorCapacity(Size), + VectorBuffer(new T[Size]) + { + vDebug("%#lx: ( init w/size: %lld )", this, Size); + } + + vector(size_t Size, const T &Initial) + : VectorSize(Size), + VectorCapacity(Size), + VectorBuffer(new T[Size]) + { + vDebug("%#lx: ( init w/size: %lld, initial vector: %llx )", this, + Size, Initial); + + assert(Size > 0); + for (size_t i = 0; i < Size; i++) + VectorBuffer[i] = Initial; + } + + vector(const vector &v) + : VectorSize(v.VectorSize), + VectorCapacity(v.VectorCapacity), + VectorBuffer(nullptr) + { + vDebug("%#lx: ( vector copy: %#lx )", this, &v); + + if (!v.VectorBuffer || VectorSize <= 0) + return; + + VectorBuffer = new T[VectorSize]; + std::copy(v.VectorBuffer, v.VectorBuffer + VectorSize, VectorBuffer); + } + + ~vector() + { + vDebug("%#lx: ( deinit )", this); + + VectorSize = 0; + VectorCapacity = 0; + if (VectorBuffer != nullptr) + { + delete[] VectorBuffer; + VectorBuffer = nullptr; + } + } + + void erase(iterator Position) + { + vDebug("%#lx: Erasing element at position %lld (v. size: %lld)", this, + Position - this->VectorBuffer, this->VectorSize); + + if (Position == this->end()) + { + warn("%#lx: Cannot erase element at end of vector", this); + return; + } + + assert(Position >= this->VectorBuffer); + assert(Position < this->VectorBuffer + this->VectorSize); + + size_t index = Position - this->VectorBuffer; + + if (std::is_trivially_copyable::value) + { + this->VectorBuffer[index] = T(); + vDebug("%#lx: %#lx is trivially copyable", this, + &this->VectorBuffer[index]); + } + else + { + this->VectorBuffer[index].~T(); + vDebug("%#lx: %#lx is not trivially copyable", this, + &this->VectorBuffer[index]); + } + + for (size_t i = index; i < this->VectorSize - 1; ++i) + { + this->VectorBuffer[i] = std::move(this->VectorBuffer[i + 1]); + } + this->VectorSize--; + } + + T &next(size_t Position) + { + if (Position + 1 < this->VectorSize) + return this->VectorBuffer[Position + 1]; + + warn("%#lx: next( %lld ) is null (requested by %#lx)", this, + Position, __builtin_return_address(0)); + + return {}; + } + + T &prev(size_t Position) + { + if (Position > 0) + return this->VectorBuffer[Position - 1]; + + warn("%#lx: prev( %lld ) is null (requested by %#lx)", this, + Position, __builtin_return_address(0)); + + return {}; + } + + T &next(const T &Value) + { + for (size_t i = 0; i < this->VectorSize; i++) + { + if (std::equal_to()(this->VectorBuffer[i], Value)) + { + if (i + 1 < this->VectorSize) + return this->VectorBuffer[i + 1]; + else + break; + } + } + + warn("%#lx: next( %#lx ) is null (requested by %#lx)", this, + Value, __builtin_return_address(0)); + + return {}; + } + + T &prev(const T &Value) + { + for (size_t i = 0; i < this->VectorSize; i++) + { + if (std::equal_to()(this->VectorBuffer[i], Value)) + { + if (i > 0) + return this->VectorBuffer[i - 1]; + else + break; + } + } + + warn("%#lx: prev( %#lx ) is null (requested by %#lx)", this, + Value, __builtin_return_address(0)); + + return {}; + } + + void push_back(const T &Value) + { + vDebug("%#lx: push_back( %#lx )", this, Value); + + if (this->VectorSize >= this->VectorCapacity) + { + size_t newCapacity = this->VectorCapacity == 0 + ? 1 + : this->VectorCapacity * 2; + reserve(newCapacity); + } + + this->VectorBuffer[this->VectorSize++] = Value; + } + + void reverse() + { + if (this->VectorSize <= 1) + return; + + for (size_t i = 0, j = this->VectorSize - 1; i < j; i++, j--) + { + T &elem1 = this->VectorBuffer[i]; + T &elem2 = this->VectorBuffer[j]; + std::swap(elem1, elem2); + } + } + + void reserve(size_t Capacity) + { + assert(!(Capacity <= VectorCapacity)); + + T *NewBuffer = new T[Capacity]; + size_t Size = std::min(Capacity, this->VectorSize); + for (size_t i = 0; i < Size; i++) + NewBuffer[i] = std::move(this->VectorBuffer[i]); + + vDebug("%#lx: reserve( %lld )->Buffer:~%#lx", this, + Capacity, this->VectorBuffer); + + delete[] this->VectorBuffer; + this->VectorBuffer = NewBuffer; + this->VectorCapacity = Capacity; + } + + void resize(size_t Size) + { + reserve(Size); + this->VectorSize = Size; + } + + void clear() + { + this->VectorCapacity = 0; + this->VectorSize = 0; + if (VectorBuffer != nullptr) + { + delete[] this->VectorBuffer; + this->VectorBuffer = nullptr; + } + } + + T &operator[](size_t Index) + { + if (Index >= this->VectorSize || !this->VectorBuffer) + { + warn("%#lx: operator[]( %lld ) is null (requested by %#lx)", this, + Index, __builtin_return_address(0)); + + static T null_elem{}; + return null_elem; + } + return this->VectorBuffer[Index]; + } + + vector &operator=(const vector &v) + { + if (this == &v) + return *this; + + delete[] this->VectorBuffer; + this->VectorSize = v.VectorSize; + this->VectorCapacity = v.VectorCapacity; + + vDebug("%#lx: operator=( )->Size:%lld", this, + this->VectorSize); + + this->VectorBuffer = new T[this->VectorSize]; + for (size_t i = 0; i < this->VectorSize; i++) + this->VectorBuffer[i] = v.VectorBuffer[i]; + + return *this; + } + + void pop_back() { this->VectorSize--; } + T &front() { return this->VectorBuffer[0]; } + T &back() { return this->VectorBuffer[this->VectorSize - 1]; } + T *data() { return this->VectorBuffer; } + bool empty() const { return this->VectorSize == 0; } + size_t capacity() const { return this->VectorCapacity; } + size_t size() const { return this->VectorSize; } + iterator begin() { return this->VectorBuffer; } + iterator end() { return this->VectorBuffer + size(); } + const_iterator begin() const { return this->VectorBuffer; } + const_iterator end() const { return this->VectorBuffer + size(); } + }; +} diff --git a/kernel.h b/kernel.h index 139564b..9d78006 100644 --- a/kernel.h +++ b/kernel.h @@ -23,7 +23,6 @@ #include #ifdef __cplusplus #include -#include #include #include #include @@ -58,7 +57,6 @@ extern VirtualFileSystem::Virtual *vfs; extern Driver::Driver *DriverManager; extern Disk::Manager *DiskManager; extern NetworkInterfaceManager::NetworkInterface *NIManager; -extern Recovery::KernelRecovery *RecoveryScreen; extern VirtualFileSystem::Node *DevFS; extern VirtualFileSystem::Node *MntFS; extern VirtualFileSystem::Node *ProcFS; diff --git a/syscalls.h b/syscalls.h index d011183..c68b775 100644 --- a/syscalls.h +++ b/syscalls.h @@ -35,68 +35,58 @@ #include -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif +#define LTS_SET_GS 0x1 +#define LTS_SET_FS 0x2 +#define LTS_GET_FS 0x3 +#define LTS_GET_GS 0x4 +#define LTS_SET_CPUID 0x5 +#define LTS_GET_CPUID 0x6 -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -enum MemoryMapFlags +typedef enum { MAP_PRESENT = 1 << 0, MAP_WRITABLE = 1 << 1, MAP_USER = 1 << 2, -}; +} MemoryMapFlags; -enum KCtl +typedef enum { - KCTL_NULL, + SYSCALL_SEEK_SET = 0, + SYSCALL_SEEK_CUR = 1, + SYSCALL_SEEK_END = 2 +} FileSeekMode; - KCTL_GET_PID, - KCTL_GET_TID, - KCTL_GET_UID, - KCTL_GET_GID, +typedef enum +{ + /** + * Print a string to the screen using KPrint + * + * The uptime is prepended to the + * string before printing. + * + * Arguments: + * Arg1 - String to print + * Arg2 - Length of string + */ + KCTL_PRINT = 0, /** - * @brief Get the page size + * Get the page size */ KCTL_GET_PAGE_SIZE, /** - * @brief Check whether the current thread is critical + * Check whether the current + * thread is critical */ KCTL_IS_CRITICAL, - - /** - * @brief Register an ELF library - * @fn int RegisterELFLib(char *Identifier, char *Path) - */ - KCTL_REGISTER_ELF_LIB, - - /** - * @brief Get an ELF library - * @fn uintptr_t GetELFLib(char *Identifier); - */ - KCTL_GET_ELF_LIB_MEMORY_IMAGE, - - /** - * @brief Get the absolute path of a library file - * @fn int GetAbsolutePath(char *Identifier, char *Buffer, size_t BufferSize) - */ - KCTL_GET_ABSOLUTE_PATH, -}; +} KCtl; /** - * @enum NativeSyscalls - * Enumeration of all the native syscalls available in the kernel + * Enumeration of all the native syscalls + * available in the kernel */ -enum NativeSyscalls +typedef enum { /** * @@ -104,17 +94,17 @@ enum NativeSyscalls * */ - /** @brief Exit the process. - * @fn int Exit(int Code) - * This syscall is used to exit the current process with the provided exit code. + /** + * This syscall is used to exit the current + * process with the provided exit code. + * + * @param Code The exit code + * @return This syscall does not return + * + * @note No permissions are required to call + * this syscall */ - _Exit = 0, - - /** @brief Print a message to the kernel console - * @fn int Print(char Char, int Index) - * This syscall is used to print a message to the kernel console. - */ - _Print, + sys_Exit = 0, /** * @@ -122,40 +112,81 @@ enum NativeSyscalls * */ - /** @brief Request pages of memory - * @fn uintptr_t RequestPages(size_t Count) - * This syscall is used to request a specific number of pages of memory from the kernel. + /** + * This syscall is used to request a specific + * number of pages of memory from the kernel. + * + * @param Count The number of pages to request + * @return The address of the first page of + * memory that was requested + * + * @note No permissions are required to call + * this syscall */ - _RequestPages, - - /** @brief Free pages of memory - * @fn int FreePages(uintptr_t Address, size_t Count) - * This syscall is used to free a specific number of pages of memory that were previously requested. - */ - _FreePages, - - /** @brief Detach memory address - * @fn int DetachAddress(uintptr_t Address) - * This syscall is used to detach a specific memory address from the current process. - */ - _DetachAddress, + sys_RequestPages, /** - * @brief Map memory address - * @fn int MapAddress(uintptr_t VirtualAddress, uintptr_t PhysicalAddress, size_t Size, enum MemoryMapFlags Flags) - * This syscall is used to map a specific memory address to the current process. + * This syscall is used to free a specific + * number of pages of memory that were + * previously requested. * - * @param Size The size of the memory region to map. Not pages. + * @param Address The address of the first + * page of memory to free + * @param Count The number of pages to free + * @return 0 on success, errno on failure + * + * @note No permissions are required to call + * this syscall */ - _MemoryMap, + sys_FreePages, - /** @brief Unmap memory address - * @fn int UnmapAddress(uintptr_t VirtualAddress, size_t Size) - * This syscall is used to unmap a specific memory address from the current process. + /** + * This syscall is used to detach a specific + * memory address from the current process. + * This means that the address will no longer + * be freed when the process exits. * - * @param Size The size of the memory region to unmap. Not pages. + * @param Address The address to detach + * @return 0 on success, errno on failure + * + * @note The process must be trusted by the + * kernel to call this syscall */ - _MemoryUnmap, + sys_DetachAddress, + + /** + * This syscall is used to map a specific + * memory address to the current process. + * + * @param VirtualAddress The virtual address + * to map + * @param PhysicalAddress The physical address + * to map + * @param Size The size of the memory region + * to map + * @param Flags The flags to use when mapping + * the memory region (see MemoryMapFlags) + * @return 0 on success, errno on failure + * + * @note The process must be trusted by the + * kernel to call this syscall + */ + sys_MemoryMap, + + /** + * This syscall is used to unmap a specific + * memory address from the current process. + * + * @param VirtualAddress The virtual address + * to unmap + * @param Size The size of the memory region + * to unmap + * @return 0 on success, errno on failure + * + * @note The process must be trusted by the + * kernel to call this syscall + */ + sys_MemoryUnmap, /** * @@ -163,11 +194,25 @@ enum NativeSyscalls * */ - /** @brief Kernel Control - * @fn uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4) - * This syscall is used to control certain aspects of the kernel or get information about it. + /** + * Kernel Control + * + * This syscall is used to control certain + * aspects of the kernel or get information + * about it. + * + * @param Command The command to execute + * @param Arg1 The first argument + * @param Arg2 The second argument + * @param Arg3 The third argument + * @param Arg4 The fourth argument + * @return The result of the command, or + * errno on failure + * + * @note No permissions are required to + * call this syscall */ - _KernelCTL, + sys_KernelCTL, /** * @@ -175,41 +220,100 @@ enum NativeSyscalls * */ - /** @brief Open a file - * @fn void *FileOpen(const char *Path, uint64_t Flags) - * This syscall is used to open a file with the provided path and flags. + /** + * This syscall is used to open a file with + * the provided path and flags. + * + * @param Path The path to the file to open + * @param Flags The flags to use when opening + * the file + * @param Mode The mode to use when opening + * the file + * @return The file descriptor of the opened + * file, or errno on failure + * + * @note No permissions are required to + * call this syscall */ - _FileOpen, + sys_FileOpen, - /** @brief Close a file - * @fn int FileClose(void *KernelPrivate) - * This syscall is used to close a file that was previously opened. + /** + * This syscall is used to close a file + * that was previously opened. + * + * @param FileDescriptor The file descriptor + * of the file to close + * + * @note No permissions are required to + * call this syscall */ - _FileClose, + sys_FileClose, - /** @brief Read from a file - * @fn uint64_t FileRead(void *KernelPrivate, uint8_t *Buffer, uint64_t Size) - * This syscall is used to read a specific number of bytes from a file at a specific offset. + /** + * This syscall is used to read a specific + * number of bytes from a file at a specific + * offset. + * + * @param FileDescriptor The file descriptor + * of the file to read from + * @param Buffer The buffer to read into + * @param Count The number of bytes to read + * @return The number of bytes read, or + * errno on failure + * + * @note No permissions are required to + * call this syscall */ - _FileRead, + sys_FileRead, - /** @brief Write to a file - * @fn uint64_t FileWrite(void *KernelPrivate, uint8_t *Buffer, uint64_t Size) - * This syscall is used to write a specific number of bytes to a file at a specific offset. + /** + * This syscall is used to write a specific + * number of bytes to a file at a specific + * offset. + * + * @param FileDescriptor The file descriptor + * of the file to write to + * @param Buffer The buffer to write from + * @param Count The number of bytes to write + * @return The number of bytes written, or + * errno on failure + * + * @note No permissions are required to + * call this syscall */ - _FileWrite, + sys_FileWrite, - /** @brief Seek in a file - * @fn off_t FileSeek(void *KernelPrivate, off_t Offset, int Whence) - * This syscall is used to change the current offset in a file. + /** + * This syscall is used to change the current + * offset in a file. + * + * @param FileDescriptor The file descriptor + * of the file to seek in + * @param Offset The offset to seek to + * @param Whence The seek mode + * (see FileSeekMode) + * @return The new offset, or errno on failure + * + * @note No permissions are required to + * call this syscall */ - _FileSeek, + sys_FileSeek, - /** @brief Get file status - * @fn - * This syscall is used to retrieve information about a file such as its size, permissions, etc. + /** + * This syscall is used to retrieve information + * about a file such as its size, permissions, + * etc. + * + * @param FileDescriptor The file descriptor + * of the file to get information about + * @param StatBuffer The buffer to store the + * information in + * @return 0 on success, errno on failure + * + * @note No permissions are required to + * call this syscall */ - _FileStatus, + sys_FileStatus, /** * @@ -218,160 +322,156 @@ enum NativeSyscalls */ /** - * @brief Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc. + * Creates/Reads/Writes/Deletes an IPC Pipe/Shared Memory/Message Queue/etc. + * * @fn int IPC(enum IPCCommand Command, enum IPCType Type, int ID, int Flags, void *Buffer, size_t Size) * This syscall is used to create, read, write or delete an IPC Pipe/Shared Memory/Message Queue/etc. */ - _IPC, + sys_IPC, - /** @brief Sleep for a specific amount of time + /** + * Get/Set the local thread state + * + * @fn int LocalThreadStorage(int Code, unsigned long Address) + * This syscall is used to get or set the local thread state. + */ + sys_LocalThreadState, + + /** + * Sleep for a specific amount of time + * * @fn int Sleep(uint64_t Milliseconds) * This syscall is used to sleep the current thread for a specific amount of time. */ - _Sleep, + sys_Sleep, - /** @brief Fork the current process + /** + * Fork the current process + * * @fn int Fork() * This syscall is used to create a new process that is a copy of the current process. */ - _Fork, + sys_Fork, - /** @brief Wait for a process or a thread + /** + * Wait for a process or a thread + * * @fn * This syscall is used to wait for a specific process or thread to terminate. It returns the exit code of the process or thread. */ - _Wait, + sys_Wait, - /** @brief Kill a process or a thread + /** + * Kill a process or a thread + * * @fn * This syscall is used to send a termination signal to a specific process or thread */ - _Kill, + sys_Kill, - /** @brief Spawn a new process + /** + * Spawn a new process + * * @fn * This syscall is used to create a new process with the provided path and arguments. */ - _Spawn, + sys_Spawn, - /** @brief Spawn a new thread + /** + * Spawn a new thread + * * @fn int SpawnThread(uint64_t InstructionPointer) * This syscall is used to create a new thread within the current process with the provided function and arguments. */ - _SpawnThread, + sys_SpawnThread, - /** @brief Get thread list of a process + /** + * Get thread list of a process + * * @fn * This syscall is used to retrieve a list of all the threads within a specific process. */ - _GetThreadListOfProcess, + sys_GetThreadListOfProcess, - /** @brief Get current process + /** + * Get current process + * * @fn * This syscall is used to retrieve information about the current process. */ - _GetCurrentProcess, + sys_GetCurrentProcess, - /** @brief Get current thread + /** + * Get current thread + * * @fn * This syscall is used to retrieve information about the current thread. */ - _GetCurrentThread, + sys_GetCurrentThread, - /** @brief Get current process ID + /** + * Get current process ID + * * @fn int GetCurrentProcessID() * This syscall is used to retrieve information about the current process. */ - _GetCurrentProcessID, + sys_GetCurrentProcessID, - /** @brief Get current thread ID + /** + * Get current thread ID + * * @fn int GetCurrentThreadID() * This syscall is used to retrieve information about the current thread. */ - _GetCurrentThreadID, + sys_GetCurrentThreadID, - /** @brief Get process by PID + /** + * Get process by PID + * * @fn * This syscall is used to retrieve information about a specific process by its PID. */ - _GetProcessByPID, + sys_GetProcessByPID, - /** @brief Get thread by TID + /** + * Get thread by TID + * * @fn * This syscall is used to retrieve information about a specific thread by its TID. */ - _GetThreadByTID, + sys_GetThreadByTID, - /** @brief Kill a process + /** + * Kill a process + * * @fn * This syscall is used to send a termination signal to a specific process. */ - _KillProcess, + sys_KillProcess, - /** @brief Kill a thread + /** + * Kill a thread + * * @fn * This syscall is used to send a termination signal to a specific thread. */ - _KillThread, + sys_KillThread, - /** @brief Reserved syscall */ - _SysReservedCreateProcess, + /** + * Reserved syscall */ - /** @brief Reserved syscall */ - _SysReservedCreateThread, + sys_SysReservedCreateProcess, - /** @brief Not a real syscall */ - _MaxSyscall -}; + /** + * Reserved syscall */ -/** - * @enum SyscallsErrorCodes - * Enumeration of all the error codes that can be returned by a syscall - */ -enum SyscallsErrorCodes -{ - /** - * @brief Access denied - * This error code is returned when the current thread does not have the required permissions to perform the requested operation. - */ - SYSCALL_ACCESS_DENIED = -0xDEADACC, - /** - * @brief Invalid argument - * This error code is returned when an invalid argument is passed to a syscall. - */ - SYSCALL_INVALID_ARGUMENT = -0xBADAEE, - /** - * @brief Invalid syscall - * This error code is returned when an invalid syscall number is passed to the syscall handler. - */ - SYSCALL_INVALID_SYSCALL = -0xBAD55CA, - /** - * @brief Internal error - * This error code is returned when an internal error occurs in the syscall handler. - */ - SYSCALL_INTERNAL_ERROR = -0xBADBAD5, - /** - * @brief Not implemented - * This error code is returned when a syscall is not implemented. - */ - SYSCALL_NOT_IMPLEMENTED = -0xBAD5EED, - /** - * @brief Generic error - * This error code is returned when a syscall fails for an unknown reason. - */ - SYSCALL_ERROR = -1, - /** - * @brief Success - * This error code is returned when a syscall succeeds. - */ - SYSCALL_OK = 0, -}; + sys_SysReservedCreateThread, -static inline bool IsSyscallError(long ret) -{ - return ret < 0; -} + /** Not a real syscall */ + sys_MaxSyscall +} NativeSyscalls; +#ifndef syscall0 static inline long syscall0(long syscall) { long ret; @@ -381,7 +481,9 @@ static inline long syscall0(long syscall) : "rcx", "r11", "memory"); return ret; } +#endif +#ifndef syscall1 static inline long syscall1(long syscall, long arg1) { long ret; @@ -391,7 +493,9 @@ static inline long syscall1(long syscall, long arg1) : "rcx", "r11", "memory"); return ret; } +#endif +#ifndef syscall2 static inline long syscall2(long syscall, long arg1, long arg2) { long ret; @@ -401,7 +505,9 @@ static inline long syscall2(long syscall, long arg1, long arg2) : "rcx", "r11", "memory"); return ret; } +#endif +#ifndef syscall3 static inline long syscall3(long syscall, long arg1, long arg2, long arg3) { long ret; @@ -411,7 +517,9 @@ static inline long syscall3(long syscall, long arg1, long arg2, long arg3) : "rcx", "r11", "memory"); return ret; } +#endif +#ifndef syscall4 static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4) { long ret; @@ -422,7 +530,9 @@ static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long : "rcx", "r11", "memory"); return ret; } +#endif +#ifndef syscall5 static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5) { long ret; @@ -434,7 +544,9 @@ static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long : "rcx", "r11", "memory"); return ret; } +#endif +#ifndef syscall6 static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6) { long ret; @@ -447,5 +559,6 @@ static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long : "rcx", "r11", "memory"); return ret; } +#endif #endif // !__FENNIX_KERNEL_SYSCALLS_LIST_H__