From af8a516fc22865abd80d6e26f1541fa3d6bebfdc Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 9 May 2024 00:42:44 +0200 Subject: MHR-23: :boom:, refactors. - Move NewBoot to /Boot, thus making Kernel directory only containing the kernel. Signed-off-by: Amlal El Mahrouss --- Kernel/ArchKit/ArchKit.hpp | 50 + Kernel/ArchKit/compile_flags.txt | 7 + Kernel/Builtins/.gitkeep | 0 Kernel/Builtins/ACPI/.gitkeep | 0 Kernel/Builtins/ACPI/ACPI.hxx | 73 + Kernel/Builtins/ACPI/ACPIFactoryInterface.hxx | 55 + Kernel/Builtins/ACPI/compile_flags.txt | 4 + Kernel/Builtins/AHCI/.gitkeep | 0 Kernel/Builtins/AHCI/AHCI.hxx | 368 +++++ Kernel/Builtins/AHCI/compile_flags.txt | 4 + Kernel/Builtins/APM/.gitkeep | 0 Kernel/Builtins/ATA/ATA.hxx | 156 +++ Kernel/Builtins/ATA/compile_flags.txt | 4 + Kernel/Builtins/HPET/.gitkeep | 0 Kernel/Builtins/HPET/Defines.hxx | 42 + Kernel/Builtins/IEEE802/.gitkeep | 0 Kernel/Builtins/IEEE802/compile_flags.txt | 4 + Kernel/Builtins/MBCI/Interface.hxx | 10 + Kernel/Builtins/MBCI/MBCI.hxx | 55 + Kernel/Builtins/NVME/.gitkeep | 0 Kernel/Builtins/NVME/compile_flags.txt | 4 + Kernel/Builtins/OHCI/.gitkeep | 0 Kernel/Builtins/PS2/PS2MouseInterface.hxx | 112 ++ Kernel/Builtins/ReadMe.txt | 19 + Kernel/Builtins/SCSI/.gitkeep | 0 Kernel/Builtins/SCSI/SCSI.hxx | 14 + Kernel/Builtins/Toolbox/Lerp.hxx | 20 + Kernel/Builtins/Toolbox/Rsrc/Cursor.rsrc | 63 + Kernel/Builtins/Toolbox/Toolbox.hxx | 84 ++ Kernel/Builtins/WiFi/.gitkeep | 0 Kernel/Builtins/WiFi/compile_flags.txt | 4 + Kernel/Builtins/XHCI/.gitkeep | 0 Kernel/Builtins/XHCI/Defines.hxx | 70 + Kernel/Builtins/XHCI/compile_flags.txt | 4 + Kernel/CFKit/GUIDWizard.hpp | 22 + Kernel/CFKit/GUIDWrapper.hpp | 58 + Kernel/CFKit/Property.hpp | 46 + Kernel/CFKit/URL.hpp | 33 + Kernel/CFKit/compile_flags.txt | 5 + Kernel/CRT/__mpcc_alloca.hxx | 15 + Kernel/CRT/__mpcc_defines.hxx | 98 ++ Kernel/CRT/__mpcc_exception.hxx | 39 + Kernel/CRT/__mpcc_malloc.hxx | 30 + Kernel/CompilerKit/CompilerKit.hxx | 13 + Kernel/CompilerKit/Detail.hxx | 27 + Kernel/CompilerKit/Version.hxx | 4 + Kernel/Docs/SPECIFICATION.md | 62 + Kernel/Docs/TODO-LIST.md | 23 + Kernel/DriverKit/KernelCall.c | 25 + Kernel/DriverKit/KernelDev.c | 37 + Kernel/DriverKit/KernelDev.h | 33 + Kernel/DriverKit/KernelDispatchCall.S | 21 + Kernel/DriverKit/KernelPrint.c | 33 + Kernel/DriverKit/KernelPrint.h | 18 + Kernel/DriverKit/KernelStd.h | 22 + Kernel/DriverKit/KernelStdCxx.cc | 24 + Kernel/DriverKit/KernelString.c | 34 + Kernel/DriverKit/KernelString.h | 16 + Kernel/Drivers/.gitkeep | 0 Kernel/Drivers/Bonjour/Bonjour.c | 20 + Kernel/Drivers/Bonjour/DriverRsrc.rsrc | 25 + Kernel/Drivers/Bonjour/x86_64.mk | 52 + Kernel/Drivers/MahroussUpdate/DriverRsrc.rsrc | 25 + Kernel/Drivers/MahroussUpdate/MahroussUpdate.cc | 24 + Kernel/Drivers/MahroussUpdate/MahroussUpdate.hxx | 37 + Kernel/Drivers/MahroussUpdate/x86_64.mk | 53 + Kernel/Drivers/SampleDriver/DriverRsrc.rsrc | 25 + Kernel/Drivers/SampleDriver/SampleDriver.c | 25 + Kernel/Drivers/SampleDriver/x86_64.mk | 52 + Kernel/FSKit/Defines.hxx | 11 + Kernel/FSKit/IndexableProperty.hxx | 58 + Kernel/FSKit/NewFS.hxx | 313 +++++ Kernel/FirmwareKit/.gitkeep | 0 Kernel/FirmwareKit/CoreBoot/.gitkeep | 0 Kernel/FirmwareKit/EFI.hxx | 7 + Kernel/FirmwareKit/EFI/API.hxx | 145 ++ Kernel/FirmwareKit/EFI/EFI.hxx | 774 +++++++++++ Kernel/FirmwareKit/EPM.hxx | 128 ++ Kernel/FirmwareKit/Handover.hxx | 110 ++ Kernel/HALKit/.gitkeep | 0 Kernel/HALKit/64x0/.hgkeep | 0 Kernel/HALKit/64x0/APM/.hgkeep | 0 Kernel/HALKit/64x0/HalVirtualMemory.cxx | 17 + Kernel/HALKit/64x0/MBCI/.gitkeep | 0 Kernel/HALKit/AMD64/CPUID.hxx | 81 ++ Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx | 123 ++ Kernel/HALKit/AMD64/HalControlRegister.s | 40 + .../HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp | 101 ++ .../HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp | 124 ++ Kernel/HALKit/AMD64/HalDebugOutput.cxx | 145 ++ Kernel/HALKit/AMD64/HalDebugPort.cxx | 40 + Kernel/HALKit/AMD64/HalDescriptorLoader.cpp | 90 ++ Kernel/HALKit/AMD64/HalHardwareMP.cpp | 34 + Kernel/HALKit/AMD64/HalInstallTIB.asm | 22 + Kernel/HALKit/AMD64/HalInterruptAPI.asm | 222 +++ Kernel/HALKit/AMD64/HalKernelMain.cxx | 85 ++ Kernel/HALKit/AMD64/HalKernelMouse.cxx | 190 +++ Kernel/HALKit/AMD64/HalNewBoot.asm | 41 + Kernel/HALKit/AMD64/HalPageAlloc.cpp | 103 ++ Kernel/HALKit/AMD64/HalPageAlloc.hpp | 88 ++ Kernel/HALKit/AMD64/HalProcessor.cpp | 97 ++ Kernel/HALKit/AMD64/HalRoutines.s | 12 + Kernel/HALKit/AMD64/HalSMPCore.cxx | 30 + Kernel/HALKit/AMD64/HalSMPCoreManager.asm | 26 + Kernel/HALKit/AMD64/Hypervisor.hpp | 26 + Kernel/HALKit/AMD64/MBCI/.gitkeep | 0 Kernel/HALKit/AMD64/PCI/Database.cxx | 11 + Kernel/HALKit/AMD64/PCI/Device.cxx | 130 ++ Kernel/HALKit/AMD64/PCI/Dma.cxx | 82 ++ Kernel/HALKit/AMD64/PCI/Express.cxx | 11 + Kernel/HALKit/AMD64/PCI/IO.cxx | 7 + Kernel/HALKit/AMD64/PCI/Iterator.cxx | 44 + Kernel/HALKit/AMD64/PCI/PCI.cxx | 7 + Kernel/HALKit/AMD64/Processor.hpp | 212 +++ Kernel/HALKit/AMD64/Storage/AHCI.cxx | 67 + Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx | 38 + Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx | 192 +++ Kernel/HALKit/ARM64/.gitkeep | 0 Kernel/HALKit/ARM64/ACPI/.gitkeep | 0 Kernel/HALKit/ARM64/Storage/.gitkeep | 0 Kernel/HALKit/AXP/CR.s | 11 + Kernel/HALKit/AXP/CoreInterruptHandlerDEC.cpp | 0 Kernel/HALKit/AXP/CoreSyscallHandlerDEC.cpp | 20 + Kernel/HALKit/AXP/HAL.s | 13 + Kernel/HALKit/AXP/Processor.hpp | 7 + Kernel/HALKit/AXP/README | 1 + Kernel/HALKit/AXP/README.TXT | 1 + Kernel/HALKit/AXP/SYSCALL.s | 10 + Kernel/HALKit/AXP/VM.s | 5 + Kernel/HALKit/POWER/.gitkeep | 0 Kernel/HALKit/POWER/APM/.gitkeep | 0 Kernel/HALKit/POWER/HalContextSwitchPowerPC.s | 28 + Kernel/HALKit/POWER/HalHardware.cxx | 19 + Kernel/HALKit/POWER/HalHart.cxx | 25 + Kernel/HALKit/POWER/HalSerialPort.cxx | 27 + Kernel/HALKit/POWER/HalStartSequence.s | 14 + Kernel/HALKit/POWER/HalThread.cxx | 13 + Kernel/HALKit/POWER/HalVirtualMemory.cxx | 54 + Kernel/HALKit/POWER/Hart.hxx | 28 + Kernel/HALKit/POWER/MBCI/.gitkeep | 0 Kernel/HALKit/POWER/MBCI/HalMBCIHost.cxx | 8 + Kernel/HALKit/POWER/Processor.hpp | 55 + Kernel/HALKit/POWER/ppc-cpu.h | 1424 ++++++++++++++++++++ Kernel/HALKit/POWER/ppc-mmu.h | 811 +++++++++++ Kernel/HALKit/RISCV/.keep | 0 Kernel/HALKit/RISCV/APM/.gitkeep | 0 Kernel/HALKit/RISCV/Hart.hxx | 18 + Kernel/HALKit/RISCV/Storage/.gitkeep | 0 Kernel/HALKit/X86S/.gitkeep | 0 Kernel/HALKit/X86S/ACPI/.gitkeep | 0 Kernel/HALKit/X86S/Storage/.gitkeep | 0 Kernel/HALKit/compile_flags.txt | 6 + Kernel/HintKit/CompilerHint.hxx | 23 + Kernel/KernelKit/CodeManager.hpp | 33 + Kernel/KernelKit/DebugOutput.hpp | 184 +++ Kernel/KernelKit/Defines.hpp | 12 + Kernel/KernelKit/DeviceManager.hpp | 131 ++ Kernel/KernelKit/DriveManager.hxx | 146 ++ Kernel/KernelKit/FileManager.hpp | 258 ++++ Kernel/KernelKit/Framebuffer.hpp | 90 ++ Kernel/KernelKit/HError.hpp | 49 + Kernel/KernelKit/KernelHeap.hpp | 39 + Kernel/KernelKit/LoaderInterface.hpp | 33 + Kernel/KernelKit/LockDelegate.hpp | 64 + Kernel/KernelKit/MSDOS.hpp | 68 + Kernel/KernelKit/PCI/Database.hpp | 38 + Kernel/KernelKit/PCI/Device.hpp | 79 ++ Kernel/KernelKit/PCI/Dma.hpp | 81 ++ Kernel/KernelKit/PCI/Dma.inl | 20 + Kernel/KernelKit/PCI/Express.hpp | 11 + Kernel/KernelKit/PCI/IO-Impl-AMD64.inl | 47 + Kernel/KernelKit/PCI/IO.hpp | 59 + Kernel/KernelKit/PCI/Iterator.hpp | 38 + Kernel/KernelKit/PCI/PCI.hpp | 58 + Kernel/KernelKit/PE.hxx | 123 ++ Kernel/KernelKit/PECodeManager.hxx | 24 + Kernel/KernelKit/PEF.hpp | 114 ++ Kernel/KernelKit/PEFCodeManager.hxx | 60 + Kernel/KernelKit/PEFSharedObject.hxx | 112 ++ Kernel/KernelKit/PermissionSelector.hxx | 57 + Kernel/KernelKit/ProcessScheduler.hpp | 301 +++++ Kernel/KernelKit/SMPManager.hpp | 129 ++ Kernel/KernelKit/Semaphore.hpp | 42 + Kernel/KernelKit/ThreadLocalStorage.hxx | 53 + Kernel/KernelKit/ThreadLocalStorage.inl | 55 + Kernel/KernelKit/Timer.hpp | 64 + Kernel/KernelKit/UserHeap.hpp | 46 + Kernel/KernelKit/XCOFF.hxx | 38 + Kernel/KernelKit/compile_flags.txt | 5 + Kernel/KernelRsrc.rsrc | 27 + Kernel/Linker/16x0.json | 6 + Kernel/Linker/32x0.json | 6 + Kernel/Linker/64x0.json | 6 + Kernel/MoveAll.sh | 7 + Kernel/NetworkKit/IP.hpp | 83 ++ Kernel/NetworkKit/IPCEP.hxx | 57 + Kernel/NetworkKit/MAC.hxx | 29 + Kernel/NetworkKit/NetworkDevice.hpp | 65 + Kernel/NetworkKit/NetworkDevice.inl | 27 + Kernel/NetworkKit/compile_flags.txt | 5 + Kernel/NewKit/Application.hxx | 31 + Kernel/NewKit/Array.hpp | 69 + Kernel/NewKit/ArrayList.hpp | 58 + Kernel/NewKit/Atom.hpp | 46 + Kernel/NewKit/Crc32.hpp | 22 + Kernel/NewKit/CxxAbi.hpp | 28 + Kernel/NewKit/Defines.hpp | 150 +++ Kernel/NewKit/ErrorOr.hpp | 72 + Kernel/NewKit/Function.hpp | 53 + Kernel/NewKit/Json.hpp | 118 ++ Kernel/NewKit/KernelCheck.hpp | 63 + Kernel/NewKit/Macros.hpp | 98 ++ Kernel/NewKit/MutableArray.hpp | 232 ++++ Kernel/NewKit/New.hpp | 18 + Kernel/NewKit/NewKit.hpp | 22 + Kernel/NewKit/OwnPtr.hpp | 94 ++ Kernel/NewKit/PageAllocator.hpp | 21 + Kernel/NewKit/PageManager.hpp | 81 ++ Kernel/NewKit/Pair.hpp | 14 + Kernel/NewKit/Pmm.hpp | 44 + Kernel/NewKit/Ref.hpp | 89 ++ Kernel/NewKit/Stream.hpp | 58 + Kernel/NewKit/String.hpp | 76 ++ Kernel/NewKit/Utils.hpp | 29 + Kernel/NewKit/Variant.hpp | 54 + Kernel/NewKit/compile_flags.txt | 6 + Kernel/Objects/.hgkeep | 0 Kernel/Root/.gitkeep | 0 Kernel/Root/Applications/.gitkeep | 0 Kernel/Root/Assistants/.gitkeep | 0 Kernel/Root/Boot/.gitkeep | 0 Kernel/Root/Boot/Icons/bonjour-logo.ico | Bin 0 -> 108478 bytes Kernel/Root/Boot/Icons/boot-logo.ico | Bin 0 -> 108478 bytes Kernel/Root/Boot/Icons/driver-logo.ico | Bin 0 -> 108478 bytes Kernel/Root/Boot/Icons/kernel-logo.ico | Bin 0 -> 108478 bytes Kernel/Root/Boot/Icons/settings-icon.ico | Bin 0 -> 108478 bytes Kernel/Root/Boot/Icons/update-logo.ico | Bin 0 -> 108478 bytes Kernel/Root/Library/.gitkeep | 0 Kernel/Root/Mount/.gitkeep | 0 Kernel/Root/Support/.gitkeep | 0 Kernel/Root/System/.gitkeep | 0 Kernel/Root/System/FileExplorerHome.html | 34 + Kernel/Root/System/SystemTheme.css | 46 + Kernel/Root/Users/.gitkeep | 0 Kernel/Root/Users/Shared/.gitkeep | 0 Kernel/Source/AppMain.cxx | 193 +++ Kernel/Source/Array.cxx | 7 + Kernel/Source/ArrayList.cxx | 7 + Kernel/Source/Atom.cxx | 10 + Kernel/Source/CodeManager.cxx | 29 + Kernel/Source/Crc32.cxx | 74 + Kernel/Source/CxxAbi.cxx | 87 ++ Kernel/Source/Defines.cxx | 7 + Kernel/Source/DeviceManager.cxx | 7 + Kernel/Source/DriveManager.cxx | 149 ++ Kernel/Source/ErrorOr.cxx | 12 + Kernel/Source/FS/NewFS.cxx | 938 +++++++++++++ Kernel/Source/FileManager.cxx | 183 +++ Kernel/Source/Framebuffer.cxx | 96 ++ Kernel/Source/GUIDWizard.cxx | 65 + Kernel/Source/GUIDWrapper.cxx | 11 + Kernel/Source/HError.cxx | 18 + Kernel/Source/IndexableProperty.cxx | 57 + Kernel/Source/Json.cxx | 12 + Kernel/Source/KernelCheck.cxx | 109 ++ Kernel/Source/KernelHeap.cxx | 169 +++ Kernel/Source/LockDelegate.cxx | 12 + Kernel/Source/MutableArray.cxx | 7 + Kernel/Source/Network/IP.cxx | 126 ++ Kernel/Source/Network/IPCEP.cxx | 7 + Kernel/Source/Network/NetworkDevice.cxx | 15 + Kernel/Source/New+Delete.cxx | 50 + Kernel/Source/NewFS+FileManager.cxx | 89 ++ Kernel/Source/NewFS+IO.cxx | 101 ++ Kernel/Source/NewFS+Journal.cxx | 22 + Kernel/Source/OwnPtr.cxx | 7 + Kernel/Source/PEFCodeManager.cxx | 226 ++++ Kernel/Source/PEFSharedObjectRT.cxx | 107 ++ Kernel/Source/PRDT.cxx | 22 + Kernel/Source/PageAllocator.cxx | 52 + Kernel/Source/PageManager.cxx | 118 ++ Kernel/Source/PermissionSelector.cxx | 47 + Kernel/Source/Pmm.cxx | 85 ++ Kernel/Source/ProcessScheduler.cxx | 392 ++++++ Kernel/Source/ProcessTeam.cxx | 31 + Kernel/Source/Property.cxx | 20 + Kernel/Source/Ref.cxx | 7 + Kernel/Source/SMPManager.cxx | 217 +++ Kernel/Source/Semaphore.cxx | 53 + Kernel/Source/Storage/AHCIDeviceInterface.cxx | 35 + Kernel/Source/Storage/ATADeviceInterface.cxx | 88 ++ Kernel/Source/Storage/NVMEDeviceInterface.cxx | 15 + Kernel/Source/Storage/SCSIDeviceInterface.cxx | 11 + Kernel/Source/Stream.cxx | 12 + Kernel/Source/String.cxx | 248 ++++ Kernel/Source/ThreadLocalStorage.cxx | 58 + Kernel/Source/Timer.cxx | 41 + Kernel/Source/URL.cxx | 96 ++ Kernel/Source/UserHeap.cxx | 252 ++++ Kernel/Source/Utils.cxx | 253 ++++ Kernel/Source/Variant.cxx | 29 + Kernel/Source/compile_flags.txt | 7 + Kernel/StorageKit/AHCI.hpp | 33 + Kernel/StorageKit/ATA.hpp | 39 + Kernel/StorageKit/NVME.hpp | 43 + Kernel/StorageKit/PRDT.hpp | 36 + Kernel/StorageKit/SCSI.hxx | 11 + Kernel/StorageKit/Storage.hpp | 16 + Kernel/compile_flags.txt | 6 + Kernel/makefile | 87 ++ 310 files changed, 19281 insertions(+) create mode 100644 Kernel/ArchKit/ArchKit.hpp create mode 100644 Kernel/ArchKit/compile_flags.txt create mode 100644 Kernel/Builtins/.gitkeep create mode 100644 Kernel/Builtins/ACPI/.gitkeep create mode 100644 Kernel/Builtins/ACPI/ACPI.hxx create mode 100644 Kernel/Builtins/ACPI/ACPIFactoryInterface.hxx create mode 100644 Kernel/Builtins/ACPI/compile_flags.txt create mode 100644 Kernel/Builtins/AHCI/.gitkeep create mode 100644 Kernel/Builtins/AHCI/AHCI.hxx create mode 100644 Kernel/Builtins/AHCI/compile_flags.txt create mode 100644 Kernel/Builtins/APM/.gitkeep create mode 100644 Kernel/Builtins/ATA/ATA.hxx create mode 100644 Kernel/Builtins/ATA/compile_flags.txt create mode 100644 Kernel/Builtins/HPET/.gitkeep create mode 100644 Kernel/Builtins/HPET/Defines.hxx create mode 100644 Kernel/Builtins/IEEE802/.gitkeep create mode 100644 Kernel/Builtins/IEEE802/compile_flags.txt create mode 100644 Kernel/Builtins/MBCI/Interface.hxx create mode 100644 Kernel/Builtins/MBCI/MBCI.hxx create mode 100644 Kernel/Builtins/NVME/.gitkeep create mode 100644 Kernel/Builtins/NVME/compile_flags.txt create mode 100644 Kernel/Builtins/OHCI/.gitkeep create mode 100644 Kernel/Builtins/PS2/PS2MouseInterface.hxx create mode 100644 Kernel/Builtins/ReadMe.txt create mode 100644 Kernel/Builtins/SCSI/.gitkeep create mode 100644 Kernel/Builtins/SCSI/SCSI.hxx create mode 100644 Kernel/Builtins/Toolbox/Lerp.hxx create mode 100644 Kernel/Builtins/Toolbox/Rsrc/Cursor.rsrc create mode 100644 Kernel/Builtins/Toolbox/Toolbox.hxx create mode 100644 Kernel/Builtins/WiFi/.gitkeep create mode 100644 Kernel/Builtins/WiFi/compile_flags.txt create mode 100644 Kernel/Builtins/XHCI/.gitkeep create mode 100644 Kernel/Builtins/XHCI/Defines.hxx create mode 100644 Kernel/Builtins/XHCI/compile_flags.txt create mode 100644 Kernel/CFKit/GUIDWizard.hpp create mode 100644 Kernel/CFKit/GUIDWrapper.hpp create mode 100644 Kernel/CFKit/Property.hpp create mode 100644 Kernel/CFKit/URL.hpp create mode 100644 Kernel/CFKit/compile_flags.txt create mode 100644 Kernel/CRT/__mpcc_alloca.hxx create mode 100644 Kernel/CRT/__mpcc_defines.hxx create mode 100644 Kernel/CRT/__mpcc_exception.hxx create mode 100644 Kernel/CRT/__mpcc_malloc.hxx create mode 100644 Kernel/CompilerKit/CompilerKit.hxx create mode 100644 Kernel/CompilerKit/Detail.hxx create mode 100644 Kernel/CompilerKit/Version.hxx create mode 100644 Kernel/Docs/SPECIFICATION.md create mode 100644 Kernel/Docs/TODO-LIST.md create mode 100644 Kernel/DriverKit/KernelCall.c create mode 100644 Kernel/DriverKit/KernelDev.c create mode 100644 Kernel/DriverKit/KernelDev.h create mode 100644 Kernel/DriverKit/KernelDispatchCall.S create mode 100644 Kernel/DriverKit/KernelPrint.c create mode 100644 Kernel/DriverKit/KernelPrint.h create mode 100644 Kernel/DriverKit/KernelStd.h create mode 100644 Kernel/DriverKit/KernelStdCxx.cc create mode 100644 Kernel/DriverKit/KernelString.c create mode 100644 Kernel/DriverKit/KernelString.h create mode 100644 Kernel/Drivers/.gitkeep create mode 100644 Kernel/Drivers/Bonjour/Bonjour.c create mode 100644 Kernel/Drivers/Bonjour/DriverRsrc.rsrc create mode 100644 Kernel/Drivers/Bonjour/x86_64.mk create mode 100644 Kernel/Drivers/MahroussUpdate/DriverRsrc.rsrc create mode 100644 Kernel/Drivers/MahroussUpdate/MahroussUpdate.cc create mode 100644 Kernel/Drivers/MahroussUpdate/MahroussUpdate.hxx create mode 100644 Kernel/Drivers/MahroussUpdate/x86_64.mk create mode 100644 Kernel/Drivers/SampleDriver/DriverRsrc.rsrc create mode 100644 Kernel/Drivers/SampleDriver/SampleDriver.c create mode 100644 Kernel/Drivers/SampleDriver/x86_64.mk create mode 100644 Kernel/FSKit/Defines.hxx create mode 100644 Kernel/FSKit/IndexableProperty.hxx create mode 100644 Kernel/FSKit/NewFS.hxx create mode 100644 Kernel/FirmwareKit/.gitkeep create mode 100644 Kernel/FirmwareKit/CoreBoot/.gitkeep create mode 100644 Kernel/FirmwareKit/EFI.hxx create mode 100644 Kernel/FirmwareKit/EFI/API.hxx create mode 100644 Kernel/FirmwareKit/EFI/EFI.hxx create mode 100644 Kernel/FirmwareKit/EPM.hxx create mode 100644 Kernel/FirmwareKit/Handover.hxx create mode 100644 Kernel/HALKit/.gitkeep create mode 100644 Kernel/HALKit/64x0/.hgkeep create mode 100644 Kernel/HALKit/64x0/APM/.hgkeep create mode 100644 Kernel/HALKit/64x0/HalVirtualMemory.cxx create mode 100644 Kernel/HALKit/64x0/MBCI/.gitkeep create mode 100644 Kernel/HALKit/AMD64/CPUID.hxx create mode 100644 Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx create mode 100644 Kernel/HALKit/AMD64/HalControlRegister.s create mode 100644 Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp create mode 100644 Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp create mode 100644 Kernel/HALKit/AMD64/HalDebugOutput.cxx create mode 100644 Kernel/HALKit/AMD64/HalDebugPort.cxx create mode 100644 Kernel/HALKit/AMD64/HalDescriptorLoader.cpp create mode 100644 Kernel/HALKit/AMD64/HalHardwareMP.cpp create mode 100644 Kernel/HALKit/AMD64/HalInstallTIB.asm create mode 100644 Kernel/HALKit/AMD64/HalInterruptAPI.asm create mode 100644 Kernel/HALKit/AMD64/HalKernelMain.cxx create mode 100644 Kernel/HALKit/AMD64/HalKernelMouse.cxx create mode 100644 Kernel/HALKit/AMD64/HalNewBoot.asm create mode 100644 Kernel/HALKit/AMD64/HalPageAlloc.cpp create mode 100644 Kernel/HALKit/AMD64/HalPageAlloc.hpp create mode 100644 Kernel/HALKit/AMD64/HalProcessor.cpp create mode 100644 Kernel/HALKit/AMD64/HalRoutines.s create mode 100644 Kernel/HALKit/AMD64/HalSMPCore.cxx create mode 100644 Kernel/HALKit/AMD64/HalSMPCoreManager.asm create mode 100644 Kernel/HALKit/AMD64/Hypervisor.hpp create mode 100644 Kernel/HALKit/AMD64/MBCI/.gitkeep create mode 100644 Kernel/HALKit/AMD64/PCI/Database.cxx create mode 100644 Kernel/HALKit/AMD64/PCI/Device.cxx create mode 100644 Kernel/HALKit/AMD64/PCI/Dma.cxx create mode 100644 Kernel/HALKit/AMD64/PCI/Express.cxx create mode 100644 Kernel/HALKit/AMD64/PCI/IO.cxx create mode 100644 Kernel/HALKit/AMD64/PCI/Iterator.cxx create mode 100644 Kernel/HALKit/AMD64/PCI/PCI.cxx create mode 100644 Kernel/HALKit/AMD64/Processor.hpp create mode 100644 Kernel/HALKit/AMD64/Storage/AHCI.cxx create mode 100644 Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx create mode 100644 Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx create mode 100644 Kernel/HALKit/ARM64/.gitkeep create mode 100644 Kernel/HALKit/ARM64/ACPI/.gitkeep create mode 100644 Kernel/HALKit/ARM64/Storage/.gitkeep create mode 100644 Kernel/HALKit/AXP/CR.s create mode 100644 Kernel/HALKit/AXP/CoreInterruptHandlerDEC.cpp create mode 100644 Kernel/HALKit/AXP/CoreSyscallHandlerDEC.cpp create mode 100644 Kernel/HALKit/AXP/HAL.s create mode 100644 Kernel/HALKit/AXP/Processor.hpp create mode 100644 Kernel/HALKit/AXP/README create mode 100644 Kernel/HALKit/AXP/README.TXT create mode 100644 Kernel/HALKit/AXP/SYSCALL.s create mode 100644 Kernel/HALKit/AXP/VM.s create mode 100644 Kernel/HALKit/POWER/.gitkeep create mode 100644 Kernel/HALKit/POWER/APM/.gitkeep create mode 100644 Kernel/HALKit/POWER/HalContextSwitchPowerPC.s create mode 100644 Kernel/HALKit/POWER/HalHardware.cxx create mode 100644 Kernel/HALKit/POWER/HalHart.cxx create mode 100644 Kernel/HALKit/POWER/HalSerialPort.cxx create mode 100644 Kernel/HALKit/POWER/HalStartSequence.s create mode 100644 Kernel/HALKit/POWER/HalThread.cxx create mode 100644 Kernel/HALKit/POWER/HalVirtualMemory.cxx create mode 100644 Kernel/HALKit/POWER/Hart.hxx create mode 100644 Kernel/HALKit/POWER/MBCI/.gitkeep create mode 100644 Kernel/HALKit/POWER/MBCI/HalMBCIHost.cxx create mode 100644 Kernel/HALKit/POWER/Processor.hpp create mode 100644 Kernel/HALKit/POWER/ppc-cpu.h create mode 100644 Kernel/HALKit/POWER/ppc-mmu.h create mode 100644 Kernel/HALKit/RISCV/.keep create mode 100644 Kernel/HALKit/RISCV/APM/.gitkeep create mode 100644 Kernel/HALKit/RISCV/Hart.hxx create mode 100644 Kernel/HALKit/RISCV/Storage/.gitkeep create mode 100644 Kernel/HALKit/X86S/.gitkeep create mode 100644 Kernel/HALKit/X86S/ACPI/.gitkeep create mode 100644 Kernel/HALKit/X86S/Storage/.gitkeep create mode 100644 Kernel/HALKit/compile_flags.txt create mode 100644 Kernel/HintKit/CompilerHint.hxx create mode 100644 Kernel/KernelKit/CodeManager.hpp create mode 100644 Kernel/KernelKit/DebugOutput.hpp create mode 100644 Kernel/KernelKit/Defines.hpp create mode 100644 Kernel/KernelKit/DeviceManager.hpp create mode 100644 Kernel/KernelKit/DriveManager.hxx create mode 100644 Kernel/KernelKit/FileManager.hpp create mode 100644 Kernel/KernelKit/Framebuffer.hpp create mode 100644 Kernel/KernelKit/HError.hpp create mode 100644 Kernel/KernelKit/KernelHeap.hpp create mode 100644 Kernel/KernelKit/LoaderInterface.hpp create mode 100644 Kernel/KernelKit/LockDelegate.hpp create mode 100644 Kernel/KernelKit/MSDOS.hpp create mode 100644 Kernel/KernelKit/PCI/Database.hpp create mode 100644 Kernel/KernelKit/PCI/Device.hpp create mode 100644 Kernel/KernelKit/PCI/Dma.hpp create mode 100644 Kernel/KernelKit/PCI/Dma.inl create mode 100644 Kernel/KernelKit/PCI/Express.hpp create mode 100644 Kernel/KernelKit/PCI/IO-Impl-AMD64.inl create mode 100644 Kernel/KernelKit/PCI/IO.hpp create mode 100644 Kernel/KernelKit/PCI/Iterator.hpp create mode 100644 Kernel/KernelKit/PCI/PCI.hpp create mode 100644 Kernel/KernelKit/PE.hxx create mode 100644 Kernel/KernelKit/PECodeManager.hxx create mode 100644 Kernel/KernelKit/PEF.hpp create mode 100644 Kernel/KernelKit/PEFCodeManager.hxx create mode 100644 Kernel/KernelKit/PEFSharedObject.hxx create mode 100644 Kernel/KernelKit/PermissionSelector.hxx create mode 100644 Kernel/KernelKit/ProcessScheduler.hpp create mode 100644 Kernel/KernelKit/SMPManager.hpp create mode 100644 Kernel/KernelKit/Semaphore.hpp create mode 100644 Kernel/KernelKit/ThreadLocalStorage.hxx create mode 100644 Kernel/KernelKit/ThreadLocalStorage.inl create mode 100644 Kernel/KernelKit/Timer.hpp create mode 100644 Kernel/KernelKit/UserHeap.hpp create mode 100644 Kernel/KernelKit/XCOFF.hxx create mode 100644 Kernel/KernelKit/compile_flags.txt create mode 100644 Kernel/KernelRsrc.rsrc create mode 100644 Kernel/Linker/16x0.json create mode 100644 Kernel/Linker/32x0.json create mode 100644 Kernel/Linker/64x0.json create mode 100755 Kernel/MoveAll.sh create mode 100644 Kernel/NetworkKit/IP.hpp create mode 100644 Kernel/NetworkKit/IPCEP.hxx create mode 100644 Kernel/NetworkKit/MAC.hxx create mode 100644 Kernel/NetworkKit/NetworkDevice.hpp create mode 100644 Kernel/NetworkKit/NetworkDevice.inl create mode 100644 Kernel/NetworkKit/compile_flags.txt create mode 100644 Kernel/NewKit/Application.hxx create mode 100644 Kernel/NewKit/Array.hpp create mode 100644 Kernel/NewKit/ArrayList.hpp create mode 100644 Kernel/NewKit/Atom.hpp create mode 100644 Kernel/NewKit/Crc32.hpp create mode 100644 Kernel/NewKit/CxxAbi.hpp create mode 100644 Kernel/NewKit/Defines.hpp create mode 100644 Kernel/NewKit/ErrorOr.hpp create mode 100644 Kernel/NewKit/Function.hpp create mode 100644 Kernel/NewKit/Json.hpp create mode 100644 Kernel/NewKit/KernelCheck.hpp create mode 100644 Kernel/NewKit/Macros.hpp create mode 100644 Kernel/NewKit/MutableArray.hpp create mode 100644 Kernel/NewKit/New.hpp create mode 100644 Kernel/NewKit/NewKit.hpp create mode 100644 Kernel/NewKit/OwnPtr.hpp create mode 100644 Kernel/NewKit/PageAllocator.hpp create mode 100644 Kernel/NewKit/PageManager.hpp create mode 100644 Kernel/NewKit/Pair.hpp create mode 100644 Kernel/NewKit/Pmm.hpp create mode 100644 Kernel/NewKit/Ref.hpp create mode 100644 Kernel/NewKit/Stream.hpp create mode 100644 Kernel/NewKit/String.hpp create mode 100644 Kernel/NewKit/Utils.hpp create mode 100644 Kernel/NewKit/Variant.hpp create mode 100644 Kernel/NewKit/compile_flags.txt create mode 100644 Kernel/Objects/.hgkeep create mode 100644 Kernel/Root/.gitkeep create mode 100644 Kernel/Root/Applications/.gitkeep create mode 100644 Kernel/Root/Assistants/.gitkeep create mode 100644 Kernel/Root/Boot/.gitkeep create mode 100644 Kernel/Root/Boot/Icons/bonjour-logo.ico create mode 100644 Kernel/Root/Boot/Icons/boot-logo.ico create mode 100644 Kernel/Root/Boot/Icons/driver-logo.ico create mode 100644 Kernel/Root/Boot/Icons/kernel-logo.ico create mode 100644 Kernel/Root/Boot/Icons/settings-icon.ico create mode 100644 Kernel/Root/Boot/Icons/update-logo.ico create mode 100644 Kernel/Root/Library/.gitkeep create mode 100644 Kernel/Root/Mount/.gitkeep create mode 100644 Kernel/Root/Support/.gitkeep create mode 100644 Kernel/Root/System/.gitkeep create mode 100644 Kernel/Root/System/FileExplorerHome.html create mode 100644 Kernel/Root/System/SystemTheme.css create mode 100644 Kernel/Root/Users/.gitkeep create mode 100644 Kernel/Root/Users/Shared/.gitkeep create mode 100644 Kernel/Source/AppMain.cxx create mode 100644 Kernel/Source/Array.cxx create mode 100644 Kernel/Source/ArrayList.cxx create mode 100644 Kernel/Source/Atom.cxx create mode 100644 Kernel/Source/CodeManager.cxx create mode 100644 Kernel/Source/Crc32.cxx create mode 100644 Kernel/Source/CxxAbi.cxx create mode 100644 Kernel/Source/Defines.cxx create mode 100644 Kernel/Source/DeviceManager.cxx create mode 100644 Kernel/Source/DriveManager.cxx create mode 100644 Kernel/Source/ErrorOr.cxx create mode 100644 Kernel/Source/FS/NewFS.cxx create mode 100644 Kernel/Source/FileManager.cxx create mode 100644 Kernel/Source/Framebuffer.cxx create mode 100644 Kernel/Source/GUIDWizard.cxx create mode 100644 Kernel/Source/GUIDWrapper.cxx create mode 100644 Kernel/Source/HError.cxx create mode 100644 Kernel/Source/IndexableProperty.cxx create mode 100644 Kernel/Source/Json.cxx create mode 100644 Kernel/Source/KernelCheck.cxx create mode 100644 Kernel/Source/KernelHeap.cxx create mode 100644 Kernel/Source/LockDelegate.cxx create mode 100644 Kernel/Source/MutableArray.cxx create mode 100644 Kernel/Source/Network/IP.cxx create mode 100644 Kernel/Source/Network/IPCEP.cxx create mode 100644 Kernel/Source/Network/NetworkDevice.cxx create mode 100644 Kernel/Source/New+Delete.cxx create mode 100644 Kernel/Source/NewFS+FileManager.cxx create mode 100644 Kernel/Source/NewFS+IO.cxx create mode 100644 Kernel/Source/NewFS+Journal.cxx create mode 100644 Kernel/Source/OwnPtr.cxx create mode 100644 Kernel/Source/PEFCodeManager.cxx create mode 100644 Kernel/Source/PEFSharedObjectRT.cxx create mode 100644 Kernel/Source/PRDT.cxx create mode 100644 Kernel/Source/PageAllocator.cxx create mode 100644 Kernel/Source/PageManager.cxx create mode 100644 Kernel/Source/PermissionSelector.cxx create mode 100644 Kernel/Source/Pmm.cxx create mode 100644 Kernel/Source/ProcessScheduler.cxx create mode 100644 Kernel/Source/ProcessTeam.cxx create mode 100644 Kernel/Source/Property.cxx create mode 100644 Kernel/Source/Ref.cxx create mode 100644 Kernel/Source/SMPManager.cxx create mode 100644 Kernel/Source/Semaphore.cxx create mode 100644 Kernel/Source/Storage/AHCIDeviceInterface.cxx create mode 100644 Kernel/Source/Storage/ATADeviceInterface.cxx create mode 100644 Kernel/Source/Storage/NVMEDeviceInterface.cxx create mode 100644 Kernel/Source/Storage/SCSIDeviceInterface.cxx create mode 100644 Kernel/Source/Stream.cxx create mode 100644 Kernel/Source/String.cxx create mode 100644 Kernel/Source/ThreadLocalStorage.cxx create mode 100644 Kernel/Source/Timer.cxx create mode 100644 Kernel/Source/URL.cxx create mode 100644 Kernel/Source/UserHeap.cxx create mode 100644 Kernel/Source/Utils.cxx create mode 100644 Kernel/Source/Variant.cxx create mode 100644 Kernel/Source/compile_flags.txt create mode 100644 Kernel/StorageKit/AHCI.hpp create mode 100644 Kernel/StorageKit/ATA.hpp create mode 100644 Kernel/StorageKit/NVME.hpp create mode 100644 Kernel/StorageKit/PRDT.hpp create mode 100644 Kernel/StorageKit/SCSI.hxx create mode 100644 Kernel/StorageKit/Storage.hpp create mode 100644 Kernel/compile_flags.txt create mode 100644 Kernel/makefile (limited to 'Kernel') diff --git a/Kernel/ArchKit/ArchKit.hpp b/Kernel/ArchKit/ArchKit.hpp new file mode 100644 index 00000000..a341035b --- /dev/null +++ b/Kernel/ArchKit/ArchKit.hpp @@ -0,0 +1,50 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +#ifdef __NEWOS_AMD64__ +#include +#include +#include +#elif defined(__NEWOS_PPC__) +#include +#else +#error Unknown architecture +#endif + +namespace NewOS +{ + constexpr static inline SSizeT rt_hash_seed(const char* seed, int mul) + { + SSizeT hash = 0; + + for (SSizeT idx = 0; seed[idx] != 0; ++idx) + { + hash += seed[idx]; + hash ^= mul; + } + + return hash; + } +} // namespace NewOS + +#define kKernelMaxSystemCalls (256) + +typedef NewOS::Void (*rt_syscall_proc)(NewOS::HAL::StackFramePtr); + +extern NewOS::Array + kSyscalls; + +EXTERN_C NewOS::HAL::StackFramePtr rt_get_current_context(); +EXTERN_C NewOS::Void rt_do_context_switch(NewOS::HAL::StackFramePtr stackFrame); + +#include diff --git a/Kernel/ArchKit/compile_flags.txt b/Kernel/ArchKit/compile_flags.txt new file mode 100644 index 00000000..a3cab89d --- /dev/null +++ b/Kernel/ArchKit/compile_flags.txt @@ -0,0 +1,7 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I./ +-I../ +-I$(HOME)/ +-D__NEWOS_AMD64__ diff --git a/Kernel/Builtins/.gitkeep b/Kernel/Builtins/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/ACPI/.gitkeep b/Kernel/Builtins/ACPI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/ACPI/ACPI.hxx b/Kernel/Builtins/ACPI/ACPI.hxx new file mode 100644 index 00000000..d171bf3b --- /dev/null +++ b/Kernel/Builtins/ACPI/ACPI.hxx @@ -0,0 +1,73 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __ACPI__ +#define __ACPI__ + +/** + https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html +*/ + +#include + +namespace NewOS +{ + class SDT + { + public: + Char Signature[4]; + UInt32 Length; + UInt8 Revision; + Char Checksum; + Char OemId[6]; + Char OemTableId[8]; + UInt32 OemRev; + UInt32 CreatorID; + UInt32 CreatorRevision; + }; + + class RSDP : public SDT + { + public: + UInt32 RsdtAddress; + UIntPtr XsdtAddress; + UInt8 ExtendedChecksum; + UInt8 Reserved0[3]; + }; + + class ConfigHeader + { + public: + UInt64 BaseAddress; + UInt16 PciSegGroup; + UInt8 StartBus; + UInt8 EndBus; + UInt32 Reserved; + }; + + enum class AddressSpace : UInt8 + { + SystemMemory = 0, + SystemIO = 1, + Pci = 2, + Controller = 3, + SmBus = 4, + Count = 5, + Invalid = 0xFF, + }; + + class Address + { + public: + AddressSpace AddressSpaceId; + UInt8 RegisterBitWidth; + UInt8 RegisterBitOffset; + UInt8 Reserved; + UIntPtr Address; + }; +} // namespace NewOS + +#endif // !__ACPI__ diff --git a/Kernel/Builtins/ACPI/ACPIFactoryInterface.hxx b/Kernel/Builtins/ACPI/ACPIFactoryInterface.hxx new file mode 100644 index 00000000..a2fa4fd8 --- /dev/null +++ b/Kernel/Builtins/ACPI/ACPIFactoryInterface.hxx @@ -0,0 +1,55 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __ACPI_MANAGER__ +#define __ACPI_MANAGER__ + +#include +#include +#include +#include + +namespace NewOS +{ + class ACPIFactoryInterface final + { + public: + explicit ACPIFactoryInterface(voidPtr rsdPtr); + ~ACPIFactoryInterface() = default; + + ACPIFactoryInterface& operator=(const ACPIFactoryInterface&) = default; + ACPIFactoryInterface(const ACPIFactoryInterface&) = default; + + public: + void Shutdown(); // shutdown + void Reboot(); // soft-reboot + + public: + /// @brief Descriptor find factory. + /// @param signature The signature of the descriptor table (MADT, ACPI...) + /// @return the blob inside an ErrorOr object. + ErrorOr Find(const char* signature); + + /// @brief Checksum factory. + /// @param checksum the data to checksum + /// @param len it's size + /// @return if it succeed + bool Checksum(const char* checksum, SSizeT len); // watch for collides! + + public: + ErrorOr operator[](const char* signature) + { + return this->Find(signature); + } + + private: + VoidPtr fRsdp; // pointer to root descriptor. + SSizeT fEntries; // number of entries, -1 tells that no invalid entries were + // found. + }; +} // namespace NewOS + +#endif // !__ACPI_MANAGER__ diff --git a/Kernel/Builtins/ACPI/compile_flags.txt b/Kernel/Builtins/ACPI/compile_flags.txt new file mode 100644 index 00000000..1bc51142 --- /dev/null +++ b/Kernel/Builtins/ACPI/compile_flags.txt @@ -0,0 +1,4 @@ +-I./ +-I../ +-I../../ +-std=c++20 diff --git a/Kernel/Builtins/AHCI/.gitkeep b/Kernel/Builtins/AHCI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/AHCI/AHCI.hxx b/Kernel/Builtins/AHCI/AHCI.hxx new file mode 100644 index 00000000..8f28f076 --- /dev/null +++ b/Kernel/Builtins/AHCI/AHCI.hxx @@ -0,0 +1,368 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Defines.hxx + Purpose: AHCI header. + + Revision History: + + 03/02/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +#include +#include + +// Forward declarations of structs. + +struct HbaPort; +struct FisData; +struct FisRegD2H; +struct FisRegH2D; + +/// @brief Frame information type. +enum +{ + kFISTypeRegH2D = 0x27, // Register FIS - host to device + kFISTypeRegD2H = 0x34, // Register FIS - device to host + kFISTypeDMAAct = 0x39, // DMA activate FIS - device to host + kFISTypeDMASetup = 0x41, // DMA setup FIS - bidirectional + kFISTypeData = 0x46, // Data FIS - bidirectional + kFISTypeBIST = 0x58, // BIST activate FIS - bidirectional + kFISTypePIOSetup = 0x5F, // PIO setup FIS - device to host + kFISTypeDevBits = 0xA1, // Set device bits FIS - device to host +}; + +enum +{ + kAHCICmdIdentify = 0xEC, + kAHCICmdReadDma = 0xC8, + kAHCICmdReadDmaEx = 0x25, + kAHCICmdWriteDma = 0xCA, + kAHCICmdWriteDmaEx = 0x35 +}; + +typedef struct FisRegH2D final +{ + // DWORD 0 + NewOS::UInt8 FisType; // FIS_TYPE_REG_H2D + + NewOS::UInt8 PortMul : 4; // Port multiplier + NewOS::UInt8 Reserved0 : 3; // Reserved + NewOS::UInt8 CmdOrCtrl : 1; // 1: Command, 0: Control + + NewOS::UInt8 Command; // Command register + NewOS::UInt8 Featurel; // Feature register, 7:0 + + // DWORD 1 + NewOS::UInt8 Lba0; // LBA low register, 7:0 + NewOS::UInt8 Lba1; // LBA mid register, 15:8 + NewOS::UInt8 Lba2; // LBA high register, 23:16 + NewOS::UInt8 Device; // Device register + + // DWORD 2 + NewOS::UInt8 Lba3; // LBA register, 31:24 + NewOS::UInt8 Lba4; // LBA register, 39:32 + NewOS::UInt8 Lba5; // LBA register, 47:40 + NewOS::UInt8 FeatureHigh; // Feature register, 15:8 + + // DWORD 3 + NewOS::UInt8 CountLow; // Count register, 7:0 + NewOS::UInt8 CountHigh; // Count register, 15:8 + NewOS::UInt8 Icc; // Isochronous command completion + NewOS::UInt8 Control; // Control register + + // DWORD 4 + NewOS::UInt8 Reserved1[4]; // Reserved +} FisRegH2D; + +typedef struct FisRegD2H final +{ + // DWORD 0 + NewOS::UInt8 FisType; // FIS_TYPE_REG_D2H + + NewOS::UInt8 PortMul : 4; // Port multiplier + NewOS::UInt8 Reserved0 : 2; // Reserved + NewOS::UInt8 InterruptBit : 1; // Interrupt bit + NewOS::UInt8 Reserved1 : 1; // Reserved + + NewOS::UInt8 Status; // Status register + NewOS::UInt8 Rrror; // Error register + + // DWORD 1 + NewOS::UInt8 Lba0; // LBA low register, 7:0 + NewOS::UInt8 Lba1; // LBA mid register, 15:8 + NewOS::UInt8 Lba2; // LBA high register, 23:16 + NewOS::UInt8 Device; // Device register + + // DWORD 2 + NewOS::UInt8 Lba3; // LBA register, 31:24 + NewOS::UInt8 Lba4; // LBA register, 39:32 + NewOS::UInt8 Lba5; // LBA register, 47:40 + NewOS::UInt8 Rsv2; // Reserved + + // DWORD 3 + NewOS::UInt8 CountLow; // Count register, 7:0 + NewOS::UInt8 CountHigh; // Count register, 15:8 + NewOS::UInt8 Rsv3[2]; // Reserved + + // DWORD 4 + NewOS::UInt8 Rsv4[4]; // Reserved +} FisRegD2H; + +typedef struct FisData final +{ + // DWORD 0 + NewOS::UInt8 FisType; // FIS_TYPE_DATA + + NewOS::UInt8 PortMul : 4; // Port multiplier + NewOS::UInt8 Reserved0 : 4; // Reserved + + NewOS::UInt8 Reserved1[2]; // Reserved + + // DWORD 1 ~ N + NewOS::UInt32 Data[1]; // Payload +} FisData; + +typedef struct FisPioSetup final +{ + // DWORD 0 + NewOS::UInt8 FisType; // FIS_TYPE_PIO_SETUP + + NewOS::UInt8 PortMul : 4; // Port multiplier + NewOS::UInt8 Reserved0 : 1; // Reserved + NewOS::UInt8 DTD : 1; // Data transfer direction, 1 - device to host + NewOS::UInt8 InterruptBit : 1; // Interrupt bit + NewOS::UInt8 Reserved1 : 1; + + NewOS::UInt8 Status; // Status register + NewOS::UInt8 Error; // Error register + + // DWORD 1 + NewOS::UInt8 Lba0; // LBA low register, 7:0 + NewOS::UInt8 Lba1; // LBA mid register, 15:8 + NewOS::UInt8 Lba2; // LBA high register, 23:16 + NewOS::UInt8 Device; // Device register + + // DWORD 2 + NewOS::UInt8 Lba3; // LBA register, 31:24 + NewOS::UInt8 Lba4; // LBA register, 39:32 + NewOS::UInt8 Lba5; // LBA register, 47:40 + NewOS::UInt8 Rsv2; // Reserved + + // DWORD 3 + NewOS::UInt8 CountLow; // Count register, 7:0 + NewOS::UInt8 CountHigh; // Count register, 15:8 + NewOS::UInt8 Rsv3; // Reserved + NewOS::UInt8 EStatus; // New value of status register + + // DWORD 4 + NewOS::UInt16 TranferCount; // Transfer count + NewOS::UInt8 Rsv4[2]; // Reserved +} FisPioSetup; + +typedef struct FisDmaSetup final +{ + // DWORD 0 + NewOS::UInt8 FisType; // FIS_TYPE_DMA_SETUP + + NewOS::UInt8 PortMul : 4; // Port multiplier + NewOS::UInt8 Reserved0 : 1; // Reserved + NewOS::UInt8 DTD : 1; // Data transfer direction, 1 - device to host + NewOS::UInt8 InterruptBit : 1; // Interrupt bit + NewOS::UInt8 AutoEnable : 1; // Auto-activate. Specifies if DMA Activate FIS is needed + + NewOS::UInt8 Reserved1[2]; // Reserved + + // DWORD 1&2 + NewOS::UInt64 DmaBufferId; // DMA Buffer Identifier. Used to Identify DMA buffer in + // host memory. SATA Spec says host specific and not in + // Spec. Trying AHCI spec might work. + + // DWORD 3 + NewOS::UInt32 Rsvd; // More reserved + + // DWORD 4 + NewOS::UInt32 DmabufOffset; // Byte offset into buffer. First 2 bits must be 0 + + // DWORD 5 + NewOS::UInt32 TransferCount; // Number of bytes to transfer. Bit 0 must be 0 + + // DWORD 6 + NewOS::UInt32 Reserved3; // Reserved +} FisDmaSetup; + +typedef struct FisDevBits final +{ + // DWORD 0 + NewOS::UInt8 FisType; // FIS_TYPE_DMA_SETUP (A1h) + + NewOS::UInt8 Reserved0 : 5; // Reserved + NewOS::UInt8 R0 : 1; + NewOS::UInt8 InterruptBit : 1; + NewOS::UInt8 N : 1; + + NewOS::UInt8 StatusLow : 3; + NewOS::UInt8 R1 : 1; + NewOS::UInt8 StatusHigh : 3; + + NewOS::UInt8 R2 : 1; + NewOS::UInt8 Error; + + // DWORD 1 + NewOS::UInt32 Act; +} FisDevBits; + +/// \brief Enable AHCI device bit in GHC register. +#ifndef kAhciGHC_AE +#define kAhciGHC_AE (31) +#endif //! ifndef kAhciGHC_AE + +typedef struct HbaPort final +{ + NewOS::UInt32 Clb; // 0x00, command list base address, 1K-byte aligned + NewOS::UInt32 Clbu; // 0x04, command list base address upper 32 bits + NewOS::UInt32 Fb; // 0x08, FIS base address, 256-byte aligned + NewOS::UInt32 Fbu; // 0x0C, FIS base address upper 32 bits + NewOS::UInt32 Is; // 0x10, interrupt status + NewOS::UInt32 Ie; // 0x14, interrupt enable + NewOS::UInt32 Cmd; // 0x18, command and status + NewOS::UInt32 Reserved0; // 0x1C, Reserved + NewOS::UInt32 Tfd; // 0x20, task file data + NewOS::UInt32 Sig; // 0x24, signature + NewOS::UInt32 Ssts; // 0x28, SATA status (SCR0:SStatus) + NewOS::UInt32 Sctl; // 0x2C, SATA control (SCR2:SControl) + NewOS::UInt32 Serr; // 0x30, SATA error (SCR1:SError) + NewOS::UInt32 Sact; // 0x34, SATA active (SCR3:SActive) + NewOS::UInt32 Ci; // 0x38, command issue + NewOS::UInt32 Sntf; // 0x20, SATA notification (SCR4:SNotification) + NewOS::UInt32 Fbs; // 0x40, FIS-based switch control + NewOS::UInt32 Reserved1[11]; // 0x44 ~ 0x6F, Reserved + NewOS::UInt32 Vendor[4]; // 0x70 ~ 0x7F, vendor specific +} HbaPort; + +typedef struct HbaMem final +{ + // 0x00 - 0x2B, Generic Host Control + NewOS::UInt32 Cap; // 0x00, Host capability + NewOS::UInt32 Ghc; // 0x04, Global host control + NewOS::UInt32 Is; // 0x08, Interrupt status + NewOS::UInt32 Pi; // 0x0C, Port implemented + NewOS::UInt32 Vs; // 0x10, Version + NewOS::UInt32 Ccc_ctl; // 0x14, Command completion coalescing control + NewOS::UInt32 Ccc_pts; // 0x18, Command completion coalescing ports + NewOS::UInt32 Em_loc; // 0x1C, Enclosure management location + NewOS::UInt32 Em_ctl; // 0x20, Enclosure management control + NewOS::UInt32 Cap2; // 0x24, Host capabilities extended + NewOS::UInt32 Bohc; // 0x28, BIOS/OS handoff control and status + + NewOS::UInt16 Resv0; + NewOS::UInt32 Resv2; + + HbaPort Ports[1]; // 1 ~ 32 +} HbaMem; + +typedef struct HbaCmdHeader final +{ + // DW0 + NewOS::UInt8 Cfl : 5; // Command FIS length in DWORDS, 2 ~ 16 + NewOS::UInt8 Atapi : 1; // ATAPI + NewOS::UInt8 Write : 1; // Write, 1: H2D, 0: D2H + NewOS::UInt8 Prefetchable : 1; // Prefetchable + + NewOS::UInt8 Reset : 1; // Reset + NewOS::UInt8 BIST : 1; // BIST + NewOS::UInt8 Clear : 1; // Clear busy upon R_OK + NewOS::UInt8 Reserved0 : 1; // Reserved + NewOS::UInt8 Pmp : 4; // Port multiplier port + + NewOS::UInt16 Prdtl; // Physical region descriptor table length in entries + volatile NewOS::UInt32 Prdbc; // Physical region descriptor byte count transferred + + NewOS::UInt32 Ctba; // Command table descriptor base address + NewOS::UInt32 Ctbau; // Command table descriptor base address upper 32 bits + + NewOS::UInt32 Reserved1[4]; // Reserved +} HbaCmdHeader; + +typedef struct HbaFis final +{ + // 0x00 + FisDmaSetup Dsfis; // DMA Setup FIS + NewOS::UInt8 Pad0[4]; + // 0x20 + FisPioSetup Psfis; // PIO Setup FIS + NewOS::UInt8 Pad1[12]; + // 0x40 + FisRegD2H Rfis; // Register – Device to Host FIS + NewOS::UInt8 Pad2[4]; + // 0x58 + FisDevBits Sdbfis; // Set Device Bit FIS + // 0x60 + NewOS::UInt8 Ufis[64]; + // 0xA0 + NewOS::UInt8 Rsv[0x100 - 0xA0]; +} HbaFis; + +typedef struct HbaPrdtEntry final +{ + NewOS::UInt32 Dba; // Data base address + NewOS::UInt32 Dbau; // Data base address upper 32 bits + NewOS::UInt32 Reserved0; // Reserved + // DW3 + NewOS::UInt32 Dbc : 22; // Byte count, 4M max + NewOS::UInt32 Reserved1 : 9; // Reserved + NewOS::UInt32 InterruptBit : 1; // Interrupt on completion +} HbaPrdtEntry; + +typedef struct HbaCmdTbl final +{ + NewOS::UInt8 Cfis[64]; // Command FIS + NewOS::UInt8 Acmd[16]; // ATAPI command, 12 or 16 bytes + NewOS::UInt8 Rsv[48]; // Reserved + struct HbaPrdtEntry prdtEntries[1]; // Physical region descriptor table entries, 0 ~ 65535 +} HbaCmdTbl; + +/* EOF */ + +#if defined(__AHCI__) + +/// @brief Initializes an AHCI disk. +/// @param PortsImplemented the amount of port that have been detected. +/// @return +NewOS::Boolean drv_std_init(NewOS::UInt16& PortsImplemented); + +NewOS::Boolean drv_std_detected(NewOS::Void); + +/// @brief Read from disk. +/// @param Lba +/// @param Buf +/// @param SectorSz +/// @param Size +/// @return +NewOS::Void drv_std_read(NewOS::UInt64 Lba, NewOS::Char* Buf, NewOS::SizeT SectorSz, NewOS::SizeT Size); + +/// @brief Write to disk. +/// @param Lba +/// @param Buf +/// @param SectorSz +/// @param Size +/// @return +NewOS::Void drv_std_write(NewOS::UInt64 Lba, NewOS::Char* Buf, NewOS::SizeT SectorSz, NewOS::SizeT Size); + +/// @brief get sector count. +NewOS::SizeT drv_std_get_sector_count(); + +/// @brief get device size. +NewOS::SizeT drv_std_get_drv_size(); + +/// @brief get sector count. +NewOS::SizeT drv_std_get_sector_count(); + +/// @brief get device size. +NewOS::SizeT drv_std_get_drv_size(); + +#endif // ifdef __KERNEL__ diff --git a/Kernel/Builtins/AHCI/compile_flags.txt b/Kernel/Builtins/AHCI/compile_flags.txt new file mode 100644 index 00000000..1bc51142 --- /dev/null +++ b/Kernel/Builtins/AHCI/compile_flags.txt @@ -0,0 +1,4 @@ +-I./ +-I../ +-I../../ +-std=c++20 diff --git a/Kernel/Builtins/APM/.gitkeep b/Kernel/Builtins/APM/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/ATA/ATA.hxx b/Kernel/Builtins/ATA/ATA.hxx new file mode 100644 index 00000000..8f0abff8 --- /dev/null +++ b/Kernel/Builtins/ATA/ATA.hxx @@ -0,0 +1,156 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Defines.hxx + Purpose: ATA header. + + Revision History: + + 03/02/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +#ifndef __AHCI__ + +#include +#include + +///! Status register +#define ATA_SR_BSY 0x80 +#define ATA_SR_DRDY 0x40 +#define ATA_SR_DF 0x20 +#define ATA_SR_DSC 0x10 +#define ATA_SR_DRQ 0x08 +#define ATA_SR_CORR 0x04 +#define ATA_SR_IDX 0x02 +#define ATA_SR_ERR 0x01 + +///! Error register +#define ATA_ER_BBK 0x80 +#define ATA_ER_UNC 0x40 +#define ATA_ER_MC 0x20 +#define ATA_ER_IDNF 0x10 +#define ATA_ER_MCR 0x08 +#define ATA_ER_ABRT 0x04 +#define ATA_ER_TK0NF 0x02 +#define ATA_ER_AMNF 0x01 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +///! ident offsets, use with data that we got from ATA_CMD_IDENTIFY. +#define ATA_IDENT_DEVICE_TYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 + +#define ATA_MASTER 0x00 +#define ATA_SLAVE 0x01 + +///! Register +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SEC_COUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEVSEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_SEC_COUNT1 0x08 +#define ATA_REG_LBA3 0x09 +#define ATA_REG_LBA4 0x0A +#define ATA_REG_LBA5 0x0B +#define ATA_REG_CONTROL 0x0C +#define ATA_REG_ALT_STATUS 0x0C +#define ATA_REG_DEV_ADDRESS 0x0D + +#define ATA_REG_NEIN 0x01 + +#define ATA_PRIMARY_IO 0x1F0 +#define ATA_SECONDARY_IO 0x170 +#define ATA_PRIMARY_DCR_AS 0x3F6 +#define ATA_SECONDARY_DCR_AS 0x376 + +///! Irq +#define ATA_PRIMARY_IRQ 14 +#define ATA_SECONDARY_IRQ 15 + +///! Channels +#define ATA_PRIMARY 0x00 +#define ATA_SECONDARY 0x01 + +#define ATA_CYL_LOW 3 +#define ATA_CYL_MID 4 +#define ATA_CYL_HIGH 5 + +///! IO Direction +#define ATA_READ 0x00 +#define ATA_WRITE 0x013 + +#define ATA_PRIMARY_SEL 0xA0 +#define ATA_SECONDARY_SEL 0xB0 + +///! ATA address register. +#define ATA_ADDRESS1(x) (x + 3) +#define ATA_ADDRESS2(x) (x + 4) +#define ATA_ADDRESS3(x) (x + 5) + +///! ATA command register. +#define ATA_COMMAND(x) (x + 7) + +#define kATASectorSize (512U) + +enum +{ + kATADevicePATA, + kATADeviceSATA, + kATADevicePATA_PI, + kATADeviceSATA_PI, + kATADeviceCount, +}; + +#if defined(__ATA_PIO__) || defined(__ATA_DMA__) + +NewOS::Boolean drv_std_init(NewOS::UInt16 Bus, NewOS::UInt8 Drive, NewOS::UInt16& OutBus, NewOS::UInt8& OutMaster); + +NewOS::Boolean drv_std_detected(NewOS::Void); + +NewOS::Void drv_std_select(NewOS::UInt16 Bus); + +NewOS::Boolean drv_std_wait_io(NewOS::UInt16 IO); + +NewOS::Void drv_std_read(NewOS::UInt64 Lba, NewOS::UInt16 IO, NewOS::UInt8 Master, NewOS::Char* Buf, NewOS::SizeT SectorSz, NewOS::SizeT Size); + +NewOS::Void drv_std_write(NewOS::UInt64 Lba, NewOS::UInt16 IO, NewOS::UInt8 Master, NewOS::Char* Buf, NewOS::SizeT SectorSz, NewOS::SizeT Size); + +/// @brief get sector count. +NewOS::SizeT drv_std_get_sector_count(); + +/// @brief get device size. +NewOS::SizeT drv_std_get_drv_size(); + +#endif // ifdef __KERNEL__ +#endif // ifndef __ATA_PIO__ || __AHCI__ diff --git a/Kernel/Builtins/ATA/compile_flags.txt b/Kernel/Builtins/ATA/compile_flags.txt new file mode 100644 index 00000000..1bc51142 --- /dev/null +++ b/Kernel/Builtins/ATA/compile_flags.txt @@ -0,0 +1,4 @@ +-I./ +-I../ +-I../../ +-std=c++20 diff --git a/Kernel/Builtins/HPET/.gitkeep b/Kernel/Builtins/HPET/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/HPET/Defines.hxx b/Kernel/Builtins/HPET/Defines.hxx new file mode 100644 index 00000000..ae59f455 --- /dev/null +++ b/Kernel/Builtins/HPET/Defines.hxx @@ -0,0 +1,42 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: HPET.hxx + Purpose: HPET builtin. + + Revision History: + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace NewOS +{ + struct PACKED HPETAddressStructure final + { + NewOS::UInt8 AddressSpaceId; // 0 - system memory, 1 - system I/O + NewOS::UInt8 RegisterBitWidth; + NewOS::UInt8 RegisterBitOffset; + NewOS::UInt8 Reserved; + NewOS::UInt64 Address; + }; + + struct PACKED HPETHeader final : public SDT + { + NewOS::UInt8 HardwareRevId; + NewOS::UInt8 ComparatorCount : 5; + NewOS::UInt8 CounterSize : 1; + NewOS::UInt8 Reserved : 1; + NewOS::UInt8 LegacyReplacement : 1; + NewOS::UInt16 PciVendorId; + HPETAddressStructure Address; + NewOS::UInt8 HpetNumber; + NewOS::UInt16 MinimumTick; + NewOS::UInt8 PageProtection; + }; + +} // namespace NewOS \ No newline at end of file diff --git a/Kernel/Builtins/IEEE802/.gitkeep b/Kernel/Builtins/IEEE802/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/IEEE802/compile_flags.txt b/Kernel/Builtins/IEEE802/compile_flags.txt new file mode 100644 index 00000000..1fbcad21 --- /dev/null +++ b/Kernel/Builtins/IEEE802/compile_flags.txt @@ -0,0 +1,4 @@ +-I./ +-I../ +-I../Kernel +-std=c++20 diff --git a/Kernel/Builtins/MBCI/Interface.hxx b/Kernel/Builtins/MBCI/Interface.hxx new file mode 100644 index 00000000..d0c51a6c --- /dev/null +++ b/Kernel/Builtins/MBCI/Interface.hxx @@ -0,0 +1,10 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include \ No newline at end of file diff --git a/Kernel/Builtins/MBCI/MBCI.hxx b/Kernel/Builtins/MBCI/MBCI.hxx new file mode 100644 index 00000000..f9a20d7c --- /dev/null +++ b/Kernel/Builtins/MBCI/MBCI.hxx @@ -0,0 +1,55 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace NewOS +{ + struct MBCIHostInterface; + + /// @brief MBCI Host Interface header. + struct PACKED MBCIHostInterface final + { + UInt32 HostId; + UInt16 VendorId; + UInt16 DeviceId; + UInt8 MemoryType; + UInt16 HostType; + UInt16 HostFlags; + UInt8 Error; + UInt8 Status; + UInt8 InterruptEnable; + UInt64 BaseAddressRegister; + UInt64 BaseAddressRegisterSize; + }; + + /// @brief MBCI host flags. + enum MBCIHostFlags + { + kMBCIHostFlagsSupportsPageProtection, /// Page protected. + kMBCIHostFlagsSupportsAPM, /// Advanced Power Management. + kMBCIHostFlagsSupportsDaisyChain, /// Is daisy chained. + kMBCIHostFlagsSupportsHWInterrupts, /// Has HW interrupts. + kMBCIHostFlagsSupportsDMA, /// Has DMA. + kMBCIHostFlagsExtended = __UINT16_MAX__, // Extended flags table. + }; + + enum MBCIHostKind + { + kMBCIHostKindHardDisk, + kMBCIHostKindOpticalDisk, + kMBCIHostKindKeyboardLow, + kMBCIHostKindMouseLow, + kMBCIHostKindMouseHigh, + kMBCIHostKindKeyboardHigh, + kMBCIHostKindNetworkInterface, + kMBCIHostKindDaisyChain, + kMBCIHostKindStartExtended = __UINT16_MAX__, /// Extended vendor table. + }; +} // namespace NewOS diff --git a/Kernel/Builtins/NVME/.gitkeep b/Kernel/Builtins/NVME/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/NVME/compile_flags.txt b/Kernel/Builtins/NVME/compile_flags.txt new file mode 100644 index 00000000..1bc51142 --- /dev/null +++ b/Kernel/Builtins/NVME/compile_flags.txt @@ -0,0 +1,4 @@ +-I./ +-I../ +-I../../ +-std=c++20 diff --git a/Kernel/Builtins/OHCI/.gitkeep b/Kernel/Builtins/OHCI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/PS2/PS2MouseInterface.hxx b/Kernel/Builtins/PS2/PS2MouseInterface.hxx new file mode 100644 index 00000000..ef2319d5 --- /dev/null +++ b/Kernel/Builtins/PS2/PS2MouseInterface.hxx @@ -0,0 +1,112 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: PS2MouseInterface.hxx + Purpose: PS/2 mouse. + + Revision History: + + 03/02/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace NewOS +{ + /// @brief PS/2 Mouse driver interface + class PS2MouseInterface final + { + public: + explicit PS2MouseInterface() = default; + ~PS2MouseInterface() = default; + + NEWOS_COPY_DEFAULT(PS2MouseInterface); + + public: + /// @brief Enables PS2 mouse for kernel. + /// @return + Void Init() noexcept + { + HAL::rt_cli(); + + HAL::Out8(0x64, 0xA8); // enabling the auxiliary device - mouse + + this->Wait(); + HAL::Out8(0x64, 0x20); // tells the keyboard controller that we want to send a command to the mouse + this->WaitInput(); + + UInt8 status = HAL::In8(0x60); + status |= 0b10; + + this->Wait(); + HAL::Out8(0x64, 0x60); + this->Wait(); + HAL::Out8(0x60, status); // setting the correct bit is the "compaq" status byte + + this->Write(0xF6); + this->Read(); + + this->Write(0xF4); + this->Read(); + + HAL::rt_sti(); + } + + public: + Bool WaitInput() noexcept + { + UInt64 timeout = 100000; + + while (timeout) + { + if ((HAL::In8(0x64) & 0x1)) + { + return true; + } + + --timeout; + } // wait until we can read + + // return the ack bit. + return false; + } + + Bool Wait() noexcept + { + UInt64 timeout = 100000; + + while (timeout) + { + if ((HAL::In8(0x64) & 0b10) == 0) + { + return true; + } + + --timeout; + } // wait until we can read + + // return the ack bit. + return false; + } + + Void Write(UInt8 val) + { + HAL::Out8(0x64, 0xD4); + this->Wait(); + HAL::Out8(0x60, val); + this->Wait(); + } + + UInt8 Read() + { + this->WaitInput(); + return HAL::In8(0x60); + } + }; +} // namespace NewOS diff --git a/Kernel/Builtins/ReadMe.txt b/Kernel/Builtins/ReadMe.txt new file mode 100644 index 00000000..b090b2e5 --- /dev/null +++ b/Kernel/Builtins/ReadMe.txt @@ -0,0 +1,19 @@ +============== +NewOS Builtins +============== + +=============== +What are these? +=============== + +These are NewOS builtins device drivers. + +=================== +Maintainers/Authors +=================== + +ACPIFactoryInterface: Amlal EL Mahrouss. +AHCI: Amlal EL Mahrouss. +Toolbox: Amlal EL Mahrouss. +PS2: Amlal EL Mahrouss +ATA: Amlal EL Mahrouss \ No newline at end of file diff --git a/Kernel/Builtins/SCSI/.gitkeep b/Kernel/Builtins/SCSI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/SCSI/SCSI.hxx b/Kernel/Builtins/SCSI/SCSI.hxx new file mode 100644 index 00000000..955cda2b --- /dev/null +++ b/Kernel/Builtins/SCSI/SCSI.hxx @@ -0,0 +1,14 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +/// @file SCSI.hxx +/// @brief Serial SCSI driver. + +typedef NewOS::UInt16 scsi_packet_type[12]; diff --git a/Kernel/Builtins/Toolbox/Lerp.hxx b/Kernel/Builtins/Toolbox/Lerp.hxx new file mode 100644 index 00000000..aa652a61 --- /dev/null +++ b/Kernel/Builtins/Toolbox/Lerp.hxx @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +/// @file Lerp.hxx +/// @brief Linear interpolation implementation. + +/// @brief Linear interpolation equation solver. +/// @param from where? +/// @param to to? +/// @param at which state we're at **to**. +inline int Lerp(int from, int to, float percent) noexcept +{ + int difference = to - from; + return from + (difference * percent); +} diff --git a/Kernel/Builtins/Toolbox/Rsrc/Cursor.rsrc b/Kernel/Builtins/Toolbox/Rsrc/Cursor.rsrc new file mode 100644 index 00000000..7943b805 --- /dev/null +++ b/Kernel/Builtins/Toolbox/Rsrc/Cursor.rsrc @@ -0,0 +1,63 @@ +#define CURSOR_HEIGHT 57 +#define CURSOR_WIDTH 53 + +// array size is 9063 +static const unsigned int Cursor[] = { + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0e0e0e, 0x474747, 0x474747, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0e0e0e, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xdedede, 0x363636, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x0e0e0e, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x878787, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x363636, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xa5a5a5, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x979797, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x686868, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xdedede, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x686868, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xa5a5a5, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x585858, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0e0e0e, 0x585858, 0x222222, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x363636, 0x000000, 0x000000, 0x000000, 0x686868, 0xebebeb, 0xf9f9f9, 0x969696, 0x000000, 0x000000, 0x000000, 0x222222, 0xdedede, 0xf9f9f9, 0xdedede, 0x0e0e0e, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x787878, 0x000000, 0x000000, 0x000000, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x787878, 0x000000, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x575757, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x000000, 0x222222, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x979797, 0x000000, 0x000000, 0x000000, 0x969696, 0xf9f9f9, 0xdedede, 0x0e0e0e, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x000000, 0x000000, 0x000000, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x0e0e0e, 0x000000, 0x000000, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xdedede, 0x000000, 0x000000, 0x000000, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0x575757, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x000000, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x000000, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x000000, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0x979797, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x878787, 0x000000, 0x000000, 0x585858, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x979797, 0x000000, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x686868, 0x000000, 0x000000, 0x777777, 0xf9f9f9, 0xf9f9f9, 0xdedede, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0e0e0e, 0x474747, 0x474747, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x777777, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xcfcfcf, 0x000000, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xa5a5a5, 0x000000, 0x000000, 0x363636, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0e0e0e, 0xb3b3b3, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xdedede, 0x686868, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x363636, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x222222, 0x222222, 0x363636, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x787878, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xdedede, 0x222222, 0x000000, 0x000000, 0x000000, 0x000000, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x979797, 0x686868, 0x686868, 0xcfcfcf, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xcfcfcf, 0xd0d0d0, 0xdedede, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xa5a5a5, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xa5a5a5, 0x222222, 0x000000, 0x000000, 0xa5a5a5, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x787878, 0x000000, 0x000000, 0x686868, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x787878, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x0e0e0e, 0x000000, 0x000000, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x222222, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x222222, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x000000, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x979797, 0x000000, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x878787, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x787878, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xcfcfcf, 0x000000, 0x000000, 0x585858, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x000000, 0x000000, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x363636, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x686868, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x222222, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xd0d0d0, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x686868, 0x000000, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x474747, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x878787, 0x000000, 0x585858, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xb3b3b3, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0xa5a5a5, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x000000, 0x0e0e0e, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0x878787, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x0e0e0e, 0x000000, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x686868, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x000000, 0x000000, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x969696, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xcfcfcf, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xb3b3b3, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0x979797, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xa5a5a5, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x0e0e0e, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x000000, 0x0e0e0e, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x686868, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x787878, 0x000000, 0x777777, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x0e0e0e, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0xb4b4b4, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x0e0e0e, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0e0e0e, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x0e0e0e, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0x878787, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0x979797, 0x000000, 0x686868, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xa5a5a5, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0xb4b4b4, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x000000, 0x000000, 0xebebeb, 0xf9f9f9, 0xdedede, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x686868, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcfcfcf, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x979797, 0x000000, 0x474747, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x474747, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0x363636, 0x000000, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x878787, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xececec, 0x0e0e0e, 0x000000, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0x878787, 0x000000, 0x777777, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xa5a5a5, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x343434, 0xebebeb, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x575757, 0x000000, 0x878787, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x222222, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xb3b3b3, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x343434, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x0e0e0e, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x222222, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x222222, 0x222222, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xc2c2c2, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x686868, 0xdedede, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x686868, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x777777, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xdedede, 0x222222, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcfcfcf, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0x585858, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x222222, 0xc2c2c2, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xf9f9f9, 0xebebeb, 0x585858, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x474747, 0x878787, 0xa5a5a5, 0xa5a5a5, 0xa5a5a5, 0xa5a5a5, 0xa5a5a5, 0xa5a5a5, 0xa5a5a5, 0xa5a5a5, 0xa5a5a5, 0xa5a5a5, 0xa5a5a5, 0x979797, 0x686868, 0x0e0e0e, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 +}; diff --git a/Kernel/Builtins/Toolbox/Toolbox.hxx b/Kernel/Builtins/Toolbox/Toolbox.hxx new file mode 100644 index 00000000..7c685c0c --- /dev/null +++ b/Kernel/Builtins/Toolbox/Toolbox.hxx @@ -0,0 +1,84 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +EXTERN_C NewOS::Void _hal_init_mouse(); +EXTERN_C NewOS::Boolean _hal_draw_mouse(); +EXTERN_C NewOS::Void _hal_handle_mouse(); +EXTERN_C NewOS::Boolean _hal_left_button_pressed(); +EXTERN_C NewOS::Boolean _hal_middle_button_pressed(); +EXTERN_C NewOS::Boolean _hal_right_button_pressed(); + +#define ToolboxInitRsrc() NewOS::SizeT __ToolboxCursor = 0 + +#define kClearClr RGB(00, 00, 00) + +#define ToolboxClearRsrc() __ToolboxCursor = 0 + +/// @brief Performs OR drawing on the framebuffer. +#define ToolboxDrawOrRsrc(ImgPtr, _Height, _Width, BaseX, BaseY) \ + __ToolboxCursor = 0; \ + \ + for (NewOS::SizeT i = BaseX; i < (_Height + BaseX); ++i) \ + { \ + for (NewOS::SizeT u = BaseY; u < (_Width + BaseY); ++u) \ + { \ + *(((volatile NewOS::UInt32*)(kHandoverHeader->f_GOP.f_The + \ + 4 * kHandoverHeader->f_GOP.f_PixelPerLine * \ + i + \ + 4 * u))) |= ImgPtr[__ToolboxCursor]; \ + \ + ++__ToolboxCursor; \ + } \ + } + +/// @brief Draws a resource. +#define ToolboxDrawRsrc(ImgPtr, _Height, _Width, BaseX, BaseY) \ + __ToolboxCursor = 0; \ + \ + for (NewOS::SizeT i = BaseX; i < (_Height + BaseX); ++i) \ + { \ + for (NewOS::SizeT u = BaseY; u < (_Width + BaseY); ++u) \ + { \ + *(((volatile NewOS::UInt32*)(kHandoverHeader->f_GOP.f_The + \ + 4 * kHandoverHeader->f_GOP.f_PixelPerLine * \ + i + \ + 4 * u))) = ImgPtr[__ToolboxCursor]; \ + \ + ++__ToolboxCursor; \ + } \ + } + +/// @brief Cleans a resource. +#define ToolboxClearZone(_Height, _Width, BaseX, BaseY) \ + \ + for (NewOS::SizeT i = BaseX; i < _Height + BaseX; ++i) \ + { \ + for (NewOS::SizeT u = BaseY; u < _Width + BaseY; ++u) \ + { \ + *(((volatile NewOS::UInt32*)(kHandoverHeader->f_GOP.f_The + \ + 4 * kHandoverHeader->f_GOP.f_PixelPerLine * \ + i + \ + 4 * u))) = kClearClr; \ + } \ + } + +/// @brief Draws inside a zone. +#define ToolboxDrawZone(_Clr, _Height, _Width, BaseX, BaseY) \ + \ + for (NewOS::SizeT i = BaseX; i < (_Width + BaseX); ++i) \ + { \ + for (NewOS::SizeT u = BaseY; u < (_Height + BaseY); ++u) \ + { \ + *(((volatile NewOS::UInt32*)(kHandoverHeader->f_GOP.f_The + \ + 4 * kHandoverHeader->f_GOP.f_PixelPerLine * \ + i + \ + 4 * u))) = _Clr; \ + } \ + } diff --git a/Kernel/Builtins/WiFi/.gitkeep b/Kernel/Builtins/WiFi/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/WiFi/compile_flags.txt b/Kernel/Builtins/WiFi/compile_flags.txt new file mode 100644 index 00000000..1bc51142 --- /dev/null +++ b/Kernel/Builtins/WiFi/compile_flags.txt @@ -0,0 +1,4 @@ +-I./ +-I../ +-I../../ +-std=c++20 diff --git a/Kernel/Builtins/XHCI/.gitkeep b/Kernel/Builtins/XHCI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Builtins/XHCI/Defines.hxx b/Kernel/Builtins/XHCI/Defines.hxx new file mode 100644 index 00000000..11140ce7 --- /dev/null +++ b/Kernel/Builtins/XHCI/Defines.hxx @@ -0,0 +1,70 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Defines.hxx + Purpose: XHCI (and backwards) header. + + Revision History: + + 01/02/24: Added file (amlel) + 03/02/24: Update filename to Defines.hxx (amlel) + +------------------------------------------- */ + +#pragma once + +#include + +using namespace NewOS; + +#define kUSBCommand (UInt16)0x0 +#define kUSBStatus (UInt16)0x2 +#define kUSBInterruptEnable (UInt16)0x4 +#define kUSBFrameNum (UInt16)0x6 +#define kUSBFrameListBaseAddress (UInt16)0x8 +#define kUSBFrameModifyStart (UInt16)0xC +#define kUSBPort1StatusCtrl (UInt16)0x10 +#define kUSBPort2StatusCtrl (UInt16)0x12 + +typedef struct USBCommandRegister final +{ + UInt8 mReserved[8]; // Reserved + UInt8 + mMaxPacket; // 0 = Max packet size 32 bits 1 = Max packet size 64 bits + UInt8 mConfigure; + UInt8 mSoftwareDebug; + UInt8 mGlobalResume; + UInt8 mGlobalSuspend; + UInt8 mHostCtrlReset; + UInt8 mRun; // 1 = Controller execute frame list entries +} USBCommandRegister; + +typedef struct USBStatusRegister final +{ + UInt8 mReserved[8]; // Reserved + UInt8 mHalted; // 1 = bit 0 in CMD is zero 0 = bit 0 in CMD is 1 + UInt8 mProcessError; + UInt8 mSystemError; + UInt8 mResumeDetected; + UInt8 mErrorInterrupt; + UInt8 mInterrupt; +} USBStatusRegister; + +typedef struct USBInterruptEnableRegister final +{ + UInt8 mReserved[4]; // Reserved + UInt8 mShortPacket; // 1=Enable interrupt 0=Disable interrupt + UInt8 mComplete; // 1=Enable interrupt 0=Disable interrupt + UInt8 mResume; // 1=Enable interrupt 0=Disable interrupt + UInt8 mTimeoutCRC; // 1=Enable interrupt 0=Disable interrupt +} USBInterruptEnableRegister; + +/* + Some terminology: + + Frame Number: Number of processed entry of the Frame List. + Frame List Base Address: + 32-bit physical adress of Frame List. Remember that first 12 bytes are + always 0. The Frame List must contain 1024 entries. +*/ diff --git a/Kernel/Builtins/XHCI/compile_flags.txt b/Kernel/Builtins/XHCI/compile_flags.txt new file mode 100644 index 00000000..1bc51142 --- /dev/null +++ b/Kernel/Builtins/XHCI/compile_flags.txt @@ -0,0 +1,4 @@ +-I./ +-I../ +-I../../ +-std=c++20 diff --git a/Kernel/CFKit/GUIDWizard.hpp b/Kernel/CFKit/GUIDWizard.hpp new file mode 100644 index 00000000..17c878f5 --- /dev/null +++ b/Kernel/CFKit/GUIDWizard.hpp @@ -0,0 +1,22 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace NewOS::XRN::Version1 +{ + Ref make_sequence(const ArrayList& seq); + ErrorOr> try_guid_to_string(Ref& guid); +} // namespace NewOS::XRN::Version1 diff --git a/Kernel/CFKit/GUIDWrapper.hpp b/Kernel/CFKit/GUIDWrapper.hpp new file mode 100644 index 00000000..0a1e4144 --- /dev/null +++ b/Kernel/CFKit/GUIDWrapper.hpp @@ -0,0 +1,58 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +/* GUID for C++ Components */ + +#define kXRNNil "@{........-....-M...-N...-............}" + +// eXtensible Resource Information +namespace NewOS::XRN +{ + union GUIDSequence { + alignas(8) UShort u8[16]; + alignas(8) UShort u16[8]; + alignas(8) UInt u32[4]; + alignas(8) ULong u64[2]; + + struct + { + alignas(8) UInt fMs1; + UShort fMs2; + UShort fMs3; + UChar fMs4[8]; + }; + }; + + class GUID final + { + public: + explicit GUID() = default; + ~GUID() = default; + + public: + GUID& operator=(const GUID&) = default; + GUID(const GUID&) = default; + + public: + GUIDSequence& operator->() noexcept + { + return fUUID; + } + GUIDSequence& Leak() noexcept + { + return fUUID; + } + + private: + GUIDSequence fUUID; + }; +} // namespace NewOS::XRN diff --git a/Kernel/CFKit/Property.hpp b/Kernel/CFKit/Property.hpp new file mode 100644 index 00000000..5900d0b3 --- /dev/null +++ b/Kernel/CFKit/Property.hpp @@ -0,0 +1,46 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef _INC_PLIST_HPP__ +#define _INC_PLIST_HPP__ + +#include +#include +#include +#include + +namespace NewOS +{ + using PropertyId = Int; + + /// @brief Kernel property class. + class Property + { + public: + explicit Property(const StringView& sw) + : fName(sw) + { + } + + virtual ~Property() = default; + + public: + Property& operator=(const Property&) = default; + Property(const Property&) = default; + + bool StringEquals(StringView& name); + const PropertyId& GetPropertyById(); + + private: + Ref fName; + PropertyId fAction; + }; + + template + using PropertyArray = Array; +} // namespace NewOS + +#endif // !_INC_PLIST_HPP__ diff --git a/Kernel/CFKit/URL.hpp b/Kernel/CFKit/URL.hpp new file mode 100644 index 00000000..93a078a0 --- /dev/null +++ b/Kernel/CFKit/URL.hpp @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef _INC_URL_HPP_ +#define _INC_URL_HPP_ + +#include +#include + +namespace NewOS +{ + class URL final + { + public: + explicit URL(StringView& strUrl); + ~URL(); + + public: + Ref> Location() noexcept; + Ref> Protocol() noexcept; + + private: + Ref fUrlView; + }; + + ErrorOr url_extract_location(const char* url); + ErrorOr url_extract_protocol(const char* url); +} // namespace NewOS + +#endif /* ifndef _INC_URL_HPP_ */ diff --git a/Kernel/CFKit/compile_flags.txt b/Kernel/CFKit/compile_flags.txt new file mode 100644 index 00000000..a37ae6bf --- /dev/null +++ b/Kernel/CFKit/compile_flags.txt @@ -0,0 +1,5 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I./ +-I../ diff --git a/Kernel/CRT/__mpcc_alloca.hxx b/Kernel/CRT/__mpcc_alloca.hxx new file mode 100644 index 00000000..f15e059b --- /dev/null +++ b/Kernel/CRT/__mpcc_alloca.hxx @@ -0,0 +1,15 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +typedef void* ptr_type; +typedef __SIZE_TYPE__ size_type; + +inline void* __mpcc_alloca_gcc(size_type sz) +{ + return __builtin_alloca(sz); +} diff --git a/Kernel/CRT/__mpcc_defines.hxx b/Kernel/CRT/__mpcc_defines.hxx new file mode 100644 index 00000000..169dac8c --- /dev/null +++ b/Kernel/CRT/__mpcc_defines.hxx @@ -0,0 +1,98 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __MPCC_DEF__ +#define __MPCC_DEF__ + +#ifndef __GNUC__ + +typedef __SIZE_TYPE__ size_t; + +#ifdef __LP64__ +typedef long int ssize_t; +#else +typedef int ssize_t; +#endif // __LP64__ + +typedef size_t ptrdiff_t; +typedef size_t uintptr_t; +typedef void* voidptr_t; +typedef void* any_t; +typedef char* caddr_t; + +#ifndef NULL +#define NULL ((voidptr_t)0) +#endif // !null + +#ifdef __GNUC__ +#include +#define __mpcc_alloca(sz) __mpcc_alloca_gcc(sz) +#elif defined(__MPCC__) + +#define __alloca(sz) __mpcc_alloca(sz) +#endif + +#define __deref(ptr) (*(ptr)) + +#ifdef __cplusplus +#define __init_decl() \ + extern "C" \ + { +#define __fini_decl() \ + } \ + ; +#else +#define __init_decl() +#define __fini_decl() +#endif + +#if __has_builtin(__builtin_alloca) +#define alloca(sz) __builtin_alloca(sz) +#ifdef __alloca +#undef __alloca +#endif +#define __alloca alloca +#else +#warning alloca not detected +#endif + +typedef long long off_t; +typedef unsigned long long uoff_t; + +typedef union float_cast { + struct + { + unsigned int mantissa : 23; + unsigned int exponent : 8; + unsigned int sign : 1; + }; + + float f; +} __attribute__((packed)) float_cast_t; + +typedef union double_cast { + struct + { + unsigned long long int mantissa : 52; + unsigned int exponent : 11; + unsigned int sign : 1; + }; + + double f; +} __attribute__((packed)) double_cast_t; + +#endif // ifndef __GNUC__ + +/// Include these helpers as well. + +#ifdef __STD_CXX__ + +#include +#include + +#endif // ifdef __STD_CXX__ + +#endif /* __MPCC_DEF__ */ diff --git a/Kernel/CRT/__mpcc_exception.hxx b/Kernel/CRT/__mpcc_exception.hxx new file mode 100644 index 00000000..08af0762 --- /dev/null +++ b/Kernel/CRT/__mpcc_exception.hxx @@ -0,0 +1,39 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +/// @brief Standard C++ namespace +namespace std +{ +#ifdef __x86_64__ +#ifdef __KERNEL__ + inline void __throw_general(void) + { + __asm__("int $0xD"); + } +#else + inline void __throw_general(void) + { + __exit(33); + } +#endif +#else + inline void __throw_general(void) + { + __exit(33); + } +#endif // if __x86_64__ + + inline void __throw_domain_error(const char* error) + { + NewOS::kcout << "MPCC C++: Domain error: " << error << "\r"; + __throw_general(); + CANT_REACH(); // prevent from continuing. + } +} // namespace std diff --git a/Kernel/CRT/__mpcc_malloc.hxx b/Kernel/CRT/__mpcc_malloc.hxx new file mode 100644 index 00000000..d4d18327 --- /dev/null +++ b/Kernel/CRT/__mpcc_malloc.hxx @@ -0,0 +1,30 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +namespace stdx +{ + /// @brief allocate a new class. + /// @tparam KindClass the class type to allocate. + template + inline NewOS::VoidPtr allocate(Args&&... args) + { + return new KindClass(NewOS::forward(args)...); + } + + /// @brief free a class. + /// @tparam KindClass the class type to allocate. + template + inline NewOS::Void release(KindClass ptr) + { + if (!ptr) + return; + delete ptr; + } +} // namespace stdx diff --git a/Kernel/CompilerKit/CompilerKit.hxx b/Kernel/CompilerKit/CompilerKit.hxx new file mode 100644 index 00000000..7dbeaf17 --- /dev/null +++ b/Kernel/CompilerKit/CompilerKit.hxx @@ -0,0 +1,13 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef _INC_CL_HPP +#define _INC_CL_HPP + +#include +#include + +#endif /* ifndef _INC_CL_HPP */ diff --git a/Kernel/CompilerKit/Detail.hxx b/Kernel/CompilerKit/Detail.hxx new file mode 100644 index 00000000..6b4e49e9 --- /dev/null +++ b/Kernel/CompilerKit/Detail.hxx @@ -0,0 +1,27 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#ifdef __KERNEL__ +#include +#endif // ifdef __KERNEL__ + +#define NEWOS_COPY_DELETE(KLASS) \ + KLASS& operator=(const KLASS&) = delete; \ + KLASS(const KLASS&) = delete; + +#define NEWOS_COPY_DEFAULT(KLASS) \ + KLASS& operator=(const KLASS&) = default; \ + KLASS(const KLASS&) = default; + +#define NEWOS_MOVE_DELETE(KLASS) \ + KLASS& operator=(KLASS&&) = delete; \ + KLASS(KLASS&&) = delete; + +#define NEWOS_MOVE_DEFAULT(KLASS) \ + KLASS& operator=(KLASS&&) = default; \ + KLASS(KLASS&&) = default; diff --git a/Kernel/CompilerKit/Version.hxx b/Kernel/CompilerKit/Version.hxx new file mode 100644 index 00000000..c0d42603 --- /dev/null +++ b/Kernel/CompilerKit/Version.hxx @@ -0,0 +1,4 @@ +#pragma once + +#define BOOTLOADER_VERSION L"v1.14.2" +#define KERNEL_VERSION "v1.14.2" diff --git a/Kernel/Docs/SPECIFICATION.md b/Kernel/Docs/SPECIFICATION.md new file mode 100644 index 00000000..e218947e --- /dev/null +++ b/Kernel/Docs/SPECIFICATION.md @@ -0,0 +1,62 @@ +=================================== + +# 0: General Information + +=================================== + +- ABI and Format: PEF/PE32+. +- Kernel architecture: Portable hybrid kernel. +- Language: C++/(Assembly (AMD64, X64000, X86S, ARM64, POWER, RISCV)) + +=================================== + +# 1: The NewKernel + +=================================== + +- Drive/Device Abstraction. +- SMP, Preemptive Multi Threading. +- Separation of Files/Devices. +- Networking. +- Hardware Abstraction Layer. +- Native Filesystem support (NewFS, FAT32 and ffs2). +- Program Loaders. +- Thread Local Storage. +- Semaphore, Locks, Timers. +- Canary mechanisms. +- Dynamic Libraries. +- Cross Platform. +- Permission Selectors. + +=================================== + +# 2: The Filesystem + +=================================== + +- Catalog object with associated forks. +- Large storage support. +- Long file names. +- UNIX path style. + +================================== + +# 3: Common naming conventions: + +================================== + +- Kernel -> ke_init_x +- RunTime -> rt_copy_mem +- Hal -> hal_foo_bar + +=================================== + +# 4: The NewBoot + +=================================== + +- Capable of booting from a network drive. +- Loads a PE file which is the kernel. +- Sanity checks, based on the number of sections. +- Handover compliant. +- Does check for a valid partition (useful in the case of recovering) diff --git a/Kernel/Docs/TODO-LIST.md b/Kernel/Docs/TODO-LIST.md new file mode 100644 index 00000000..b7780b9f --- /dev/null +++ b/Kernel/Docs/TODO-LIST.md @@ -0,0 +1,23 @@ +# TODO list + +- We need preemptive multi-threading. [ X ] +- We then need sync primitives. [ X ] +- We also need a system library for the OS. [ X ] +- We need a bootloader for AMD64 [ X ] + - Implement Boot Services [ X ] + - Design Handover [ X ] + - Load kernel into memory [ X ] + - Fix bug in kernel loader, which causes a 06 #UD. [ X ] + - Load Kernel [ X ] + - Add IDT [ X ] + - AHCI driver [ WiP ] +- Context switch x87/SSE/AVX registers [ X ] +- Framebuffer [ X ] +- AHCI support [ ] +- Make installer [ ] + +Status: + +NewBoot: Need to boot from EPM partition. +
+NewKernel: New Filesystem in progress. diff --git a/Kernel/DriverKit/KernelCall.c b/Kernel/DriverKit/KernelCall.c new file mode 100644 index 00000000..43f8f714 --- /dev/null +++ b/Kernel/DriverKit/KernelCall.c @@ -0,0 +1,25 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: Kernel Definitions. + +------------------------------------------- */ + +#include +#include + +DK_EXTERN __attribute__((naked)) void __kernelDispatchCall(int32_t cnt, ...); + +DK_EXTERN void* kernelCall(const char* kernelRpcName, int32_t cnt, ...) +{ + if (!kernelRpcName || cnt == 0) + return NIL; + + va_list arg; + va_start(arg, cnt); + + __kernelDispatchCall(cnt, arg); + + va_end(arg); +} diff --git a/Kernel/DriverKit/KernelDev.c b/Kernel/DriverKit/KernelDev.c new file mode 100644 index 00000000..3cf8e4ea --- /dev/null +++ b/Kernel/DriverKit/KernelDev.c @@ -0,0 +1,37 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: Kernel Text I/O. + +------------------------------------------- */ + +#include + +/// @brief Open a new binary device from path. +DK_EXTERN kernelDeviceRef kernelOpenBinaryDevice(const char* devicePath) +{ + if (!devicePath) + return NIL; + + return kernelCall("OpenBinaryDevice", 1, devicePath); +} + +/// @brief Open a new character device from path. +DK_EXTERN kernelDeviceRef kernelOpenCharDevice(const char* devicePath) +{ + if (!devicePath) + return NIL; + + return kernelCall("OpenCharDevice", 1, devicePath); +} + +/// @brief Close any device. +/// @param device valid device. +DK_EXTERN void kernelCloseDevice(kernelDeviceRef device) +{ + if (!device) + return; + + kernelCall("CloseDevice", 1, device); +} diff --git a/Kernel/DriverKit/KernelDev.h b/Kernel/DriverKit/KernelDev.h new file mode 100644 index 00000000..7ce833e5 --- /dev/null +++ b/Kernel/DriverKit/KernelDev.h @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: Kernel Devices. + +------------------------------------------- */ + +#pragma once + +#include + +struct _kernelDevice; + +/// @brief Kernel Device driver. +typedef struct _kernelDevice +{ + char name[255]; // the device name. Could be /./DEVICE_NAME/ + int32_t (*read)(); // read from device. + int32_t (*write)(); // write to device. + struct _kernelDevice* (*open)(const char* path); // open device. + void (*close)(struct _kernelDevice* dev); // close device. +} kernelDevice, *kernelDeviceRef; + +/// @brief Open a new binary device from path. +DK_EXTERN kernelDeviceRef kernelOpenBinaryDevice(const char* devicePath); + +/// @brief Open a new character device from path. +DK_EXTERN kernelDeviceRef kernelOpenCharDevice(const char* devicePath); + +/// @brief Close any device. +/// @param device valid device. +DK_EXTERN void kernelCloseDevice(kernelDeviceRef device); diff --git a/Kernel/DriverKit/KernelDispatchCall.S b/Kernel/DriverKit/KernelDispatchCall.S new file mode 100644 index 00000000..64b6663e --- /dev/null +++ b/Kernel/DriverKit/KernelDispatchCall.S @@ -0,0 +1,21 @@ +.globl __kernelDispatchCall + +.section .text + +/* Really simple function, takes our va-list, + and brings it to the trap handler in the kernel. */ + +#ifdef __x86_64__ + +__kernelDispatchCall: + int $0x33 + ret + +#elif defined(__powerpc64__) + +__kernelDispatchCall: + /* There is no specific interrupt request id for a system call in POWER. */ + sc + blr + +#endif diff --git a/Kernel/DriverKit/KernelPrint.c b/Kernel/DriverKit/KernelPrint.c new file mode 100644 index 00000000..04be86fa --- /dev/null +++ b/Kernel/DriverKit/KernelPrint.c @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: Kernel Text I/O. + +------------------------------------------- */ + +#include + +DK_EXTERN void kernelPrintChar(const char ch) +{ + kernelCall("WriteCharacter", 1, ch); +} + +/// @brief print string to UART. +/// @param message UART to transmit. +DK_EXTERN void kernelPrintStr(const char* message) +{ + if (!message) + return; + if (*message == 0) + return; + + size_t index = 0; + size_t len = kernelStringLength(message); + + while (index < len) + { + kernelPrintChar(message[index]); + ++index; + } +} diff --git a/Kernel/DriverKit/KernelPrint.h b/Kernel/DriverKit/KernelPrint.h new file mode 100644 index 00000000..f40c8cea --- /dev/null +++ b/Kernel/DriverKit/KernelPrint.h @@ -0,0 +1,18 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: Kernel Text I/O. + +------------------------------------------- */ + +#pragma once + +#include + +/// @brief print character into UART. +DK_EXTERN void kernelPrintChar(const char ch); + +/// @brief print string to UART. +/// @param message UART to transmit. +DK_EXTERN void kernelPrintStr(const char* message); diff --git a/Kernel/DriverKit/KernelStd.h b/Kernel/DriverKit/KernelStd.h new file mode 100644 index 00000000..8bc53d89 --- /dev/null +++ b/Kernel/DriverKit/KernelStd.h @@ -0,0 +1,22 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: Kernel Definitions. + +------------------------------------------- */ + +#pragma once + +#if defined(__cplusplus) +#define DK_EXTERN extern "C" +#define NIL nullptr +#else +#define DK_EXTERN extern +#define NIL NULL +#endif // defined(__cplusplus) + +#include +#include + +DK_EXTERN void* kernelCall(const char* kernelRpcName, int32_t cnt, ...); diff --git a/Kernel/DriverKit/KernelStdCxx.cc b/Kernel/DriverKit/KernelStdCxx.cc new file mode 100644 index 00000000..99bcc579 --- /dev/null +++ b/Kernel/DriverKit/KernelStdCxx.cc @@ -0,0 +1,24 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: Driver C++ Definitions. + +------------------------------------------- */ + +#include + +void* operator new(size_t sz) { + if (!sz) ++sz; + + auto ptr = kernelCall("NewKernelHeap", 1, sz); + kernelCall("KernelHeapProtect", 1, ptr); + + return ptr; +} + +void operator delete(void* ptr) noexcept { + if (!ptr) return; + + kernelCall("DeleteKernelHeap", 1,ptr); +} diff --git a/Kernel/DriverKit/KernelString.c b/Kernel/DriverKit/KernelString.c new file mode 100644 index 00000000..4a5af99a --- /dev/null +++ b/Kernel/DriverKit/KernelString.c @@ -0,0 +1,34 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: Kernel Strings. + +------------------------------------------- */ + +#include + +DK_EXTERN size_t kernelStringLength(const char* str) +{ + size_t index = 0; + + while (str[index] != 0) + { + ++index; + } + + return index; +} + +DK_EXTERN int kernelStringCopy(char* dst, const char* src, size_t len) +{ + size_t index = 0; + + while (index != len) + { + dst[index] = src[index]; + ++index; + } + + return index; +} diff --git a/Kernel/DriverKit/KernelString.h b/Kernel/DriverKit/KernelString.h new file mode 100644 index 00000000..a9d592e4 --- /dev/null +++ b/Kernel/DriverKit/KernelString.h @@ -0,0 +1,16 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: Kernel Strings. + +------------------------------------------- */ + +#pragma once + +#include + +/// @brief DriverKit equivalent of POSIX's string.h. + +DK_EXTERN size_t kernelStringLength(const char* str); +DK_EXTERN int kernelStringCopy(char* dst, const char* src, size_t len); diff --git a/Kernel/Drivers/.gitkeep b/Kernel/Drivers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Drivers/Bonjour/Bonjour.c b/Kernel/Drivers/Bonjour/Bonjour.c new file mode 100644 index 00000000..71b304ef --- /dev/null +++ b/Kernel/Drivers/Bonjour/Bonjour.c @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +int __ImageStart(void) +{ + kernelPrintStr("Bonjour: Starting up zeroconf...\r"); + return 0; +} + +int __ImageEnd(void) +{ + kernelPrintStr("Bonjour: Shutting down zeroconf...\r"); + return 0; +} diff --git a/Kernel/Drivers/Bonjour/DriverRsrc.rsrc b/Kernel/Drivers/Bonjour/DriverRsrc.rsrc new file mode 100644 index 00000000..494e85ee --- /dev/null +++ b/Kernel/Drivers/Bonjour/DriverRsrc.rsrc @@ -0,0 +1,25 @@ +1 ICON "../../Root/Boot/Icons/bonjour-logo.ico" + +1 VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904E4" + BEGIN + VALUE "CompanyName", "SoftwareLabs" + VALUE "FileDescription", "New OS Bonjour driver." + VALUE "FileVersion", "1.00" + VALUE "InternalName", "Bonjour." + VALUE "LegalCopyright", "Copyright SoftwareLabs, all rights reserved." + VALUE "OriginalFilename", "Bonjour.exe" + VALUE "ProductName", "Bonjour." + VALUE "ProductVersion", "1.00" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1252 + END +END diff --git a/Kernel/Drivers/Bonjour/x86_64.mk b/Kernel/Drivers/Bonjour/x86_64.mk new file mode 100644 index 00000000..b2493edf --- /dev/null +++ b/Kernel/Drivers/Bonjour/x86_64.mk @@ -0,0 +1,52 @@ +################################################## +# (C) SoftwareLabs, all rights reserved. +# This is the sample driver makefile. +################################################## + +CC_GNU=x86_64-w64-mingw32-gcc +LD_GNU=x86_64-w64-mingw32-ld + +WINDRES=x86_64-w64-mingw32-windres + +ADD_FILE=touch +COPY=cp +HTTP_GET=wget + +LD_FLAGS=-e __ImageStart --subsystem=17 + +OBJ=*.o + + +REM=rm +REM_FLAG=-f + +FLAG_ASM=-f win64 +FLAG_GNU=-fshort-wchar -D__EFI_x86_64__ -mgeneral-regs-only -mno-red-zone -D__KERNEL__ -DEFI_FUNCTION_WRAPPER -I../ -I../../ -I./ -c -ffreestanding -std=c17 -D__HAVE_MAHROUSS_APIS__ -D__MAHROUSS__ -D__BOOTLOADER__ -I./ + +.PHONY: invalid-recipe +invalid-recipe: + @echo "invalid-recipe: Use make all instead." + +.PHONY: all +all: compile-amd64 + $(LD_GNU) $(OBJ) $(LD_FLAGS) -o Bonjour.exe + cp Bonjour.exe ../../Root/Boot/Bonjour.exe + +ifneq ($(DEBUG_SUPPORT), ) +DEBUG = -D__DEBUG__ +endif + +.PHONY: compile-amd64 +compile-amd64: + $(WINDRES) DriverRsrc.rsrc -O coff -o DriverRsrc.o + $(CC_GNU) $(FLAG_GNU) $(DEBUG) $(wildcard *.c) $(wildcard ../../DriverKit/*.c) $(wildcard ../../DriverKit/*.S) + +.PHONY: clean +clean: + $(REM) $(REM_FLAG) $(OBJ) Bonjour.exe + +.PHONY: help +help: + @echo "=== HELP ===" + @echo "clean: Clean driver." + @echo "compile-amd64: Build driver." diff --git a/Kernel/Drivers/MahroussUpdate/DriverRsrc.rsrc b/Kernel/Drivers/MahroussUpdate/DriverRsrc.rsrc new file mode 100644 index 00000000..88261a47 --- /dev/null +++ b/Kernel/Drivers/MahroussUpdate/DriverRsrc.rsrc @@ -0,0 +1,25 @@ +1 ICON "../../Root/Boot/Icons/update-logo.ico" + +1 VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904E4" + BEGIN + VALUE "CompanyName", "SoftwareLabs" + VALUE "FileDescription", "New OS Mahrouss Update driver." + VALUE "FileVersion", "1.00" + VALUE "InternalName", "Mahrouss Update." + VALUE "LegalCopyright", "Copyright SoftwareLabs, all rights reserved." + VALUE "OriginalFilename", "MahroussUpdate.exe" + VALUE "ProductName", "MahroussUpdate." + VALUE "ProductVersion", "1.00" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1252 + END +END diff --git a/Kernel/Drivers/MahroussUpdate/MahroussUpdate.cc b/Kernel/Drivers/MahroussUpdate/MahroussUpdate.cc new file mode 100644 index 00000000..eb8d03c7 --- /dev/null +++ b/Kernel/Drivers/MahroussUpdate/MahroussUpdate.cc @@ -0,0 +1,24 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +#include + +DK_EXTERN int __ImageStart(void) { + kernelPrintStr("Mahrouss Update: Looking for updates...\r"); + UpdateRequest req("mup://release-mahrouss.logic/newos/"); + + return 0; +} + +DK_EXTERN int __ImageEnd(void) { + return 0; +} + +///! @brief Use this to check your stack, if using MinGW/MSVC. +DK_EXTERN void ___chkstk_ms(void) {} diff --git a/Kernel/Drivers/MahroussUpdate/MahroussUpdate.hxx b/Kernel/Drivers/MahroussUpdate/MahroussUpdate.hxx new file mode 100644 index 00000000..5f866544 --- /dev/null +++ b/Kernel/Drivers/MahroussUpdate/MahroussUpdate.hxx @@ -0,0 +1,37 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +#include "DriverKit/KernelPrint.h" + +/// @file Software update job driver. + +class UpdateRequest; +class UpdateRequestObserver; + +class UpdateRequest +{ +public: + explicit UpdateRequest(const char* patchUrl = "mup://invalid-url-scheme/") + { + kernelStringCopy(this->fPatchUrl, patchUrl, kernelStringLength(patchUrl)); + + kernelPrintStr("Mahrouss Update, Looking at: "); + kernelPrintStr(patchUrl); + kernelPrintChar('\r'); + kernelPrintChar('\n'); + } + + ~UpdateRequest() + { + } + +private: + char fPatchUrl[4096] = {0}; +}; diff --git a/Kernel/Drivers/MahroussUpdate/x86_64.mk b/Kernel/Drivers/MahroussUpdate/x86_64.mk new file mode 100644 index 00000000..13b30d59 --- /dev/null +++ b/Kernel/Drivers/MahroussUpdate/x86_64.mk @@ -0,0 +1,53 @@ +################################################## +# (C) SoftwareLabs, all rights reserved. +# This is the sample driver makefile. +################################################## + +CC_GNU=x86_64-w64-mingw32-gcc +LD_GNU=x86_64-w64-mingw32-ld + +WINDRES=x86_64-w64-mingw32-windres + +ADD_FILE=touch +COPY=cp +HTTP_GET=wget + +LD_FLAGS=-e __ImageStart --subsystem=17 + +OBJ=*.o + + +REM=rm +REM_FLAG=-f + +FLAG_ASM=-f win64 +FLAG_GNU=-fshort-wchar -D__EFI_x86_64__ -mgeneral-regs-only -mno-red-zone -D__KERNEL__ -DEFI_FUNCTION_WRAPPER -I../ -I../../ -I./ -c -ffreestanding -D__HAVE_MAHROUSS_APIS__ -D__MAHROUSS__ -D__BOOTLOADER__ -I./ + +.PHONY: invalid-recipe +invalid-recipe: + @echo "invalid-recipe: Use make all instead." + +.PHONY: all +all: compile-amd64 + $(LD_GNU) $(OBJ) $(LD_FLAGS) -o MahroussUpdate.exe + cp MahroussUpdate.exe ../../Root/Boot/MahroussUpdate.exe + +ifneq ($(DEBUG_SUPPORT), ) +DEBUG = -D__DEBUG__ +endif + +.PHONY: compile-amd64 +compile-amd64: + $(WINDRES) DriverRsrc.rsrc -O coff -o DriverRsrc.o + $(CC_GNU) $(FLAG_GNU) -std=c17 $(DEBUG) $(wildcard *.c) $(wildcard ../../DriverKit/*.c) $(wildcard ../../DriverKit/*.S) + $(CC_GNU) $(FLAG_GNU) -std=c++17 -fno-rtti -fno-exceptions $(DEBUG) $(wildcard *.cc) $(wildcard ../../DriverKit/*.cc) + +.PHONY: clean +clean: + $(REM) $(REM_FLAG) $(OBJ) MahroussUpdate.exe + +.PHONY: help +help: + @echo "=== HELP ===" + @echo "clean: Clean driver." + @echo "compile-amd64: Build driver." diff --git a/Kernel/Drivers/SampleDriver/DriverRsrc.rsrc b/Kernel/Drivers/SampleDriver/DriverRsrc.rsrc new file mode 100644 index 00000000..3a3b8774 --- /dev/null +++ b/Kernel/Drivers/SampleDriver/DriverRsrc.rsrc @@ -0,0 +1,25 @@ +1 ICON "../../Root/Boot/Icons/driver-logo.ico" + +1 VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904E4" + BEGIN + VALUE "CompanyName", "SoftwareLabs" + VALUE "FileDescription", "New OS driver." + VALUE "FileVersion", "1.00" + VALUE "InternalName", "SampleDriver" + VALUE "LegalCopyright", "Copyright SoftwareLabs, all rights reserved." + VALUE "OriginalFilename", "SampleDriver.exe" + VALUE "ProductName", "SampleDriver" + VALUE "ProductVersion", "1.00" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1252 + END +END diff --git a/Kernel/Drivers/SampleDriver/SampleDriver.c b/Kernel/Drivers/SampleDriver/SampleDriver.c new file mode 100644 index 00000000..54f3ebef --- /dev/null +++ b/Kernel/Drivers/SampleDriver/SampleDriver.c @@ -0,0 +1,25 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +int __ImageStart(void) +{ + kernelPrintStr("SampleDriver: Starting up...\r"); + return 0; +} + +int __ImageEnd(void) +{ + kernelPrintStr("SampleDriver: Shutting down...\r"); + return 0; +} + +///! @brief Use this to check your stack, if using MinGW/MSVC. +void ___chkstk_ms(void) +{ +} diff --git a/Kernel/Drivers/SampleDriver/x86_64.mk b/Kernel/Drivers/SampleDriver/x86_64.mk new file mode 100644 index 00000000..5bdf0331 --- /dev/null +++ b/Kernel/Drivers/SampleDriver/x86_64.mk @@ -0,0 +1,52 @@ +################################################## +# (C) SoftwareLabs, all rights reserved. +# This is the sample driver makefile. +################################################## + +CC_GNU=x86_64-w64-mingw32-gcc +LD_GNU=x86_64-w64-mingw32-ld + +WINDRES=x86_64-w64-mingw32-windres + +ADD_FILE=touch +COPY=cp +HTTP_GET=wget + +LD_FLAGS=-e __ImageStart --subsystem=17 + +OBJ=*.o + + +REM=rm +REM_FLAG=-f + +FLAG_ASM=-f win64 +FLAG_GNU=-fshort-wchar -D__EFI_x86_64__ -mgeneral-regs-only -mno-red-zone -D__KERNEL__ -DEFI_FUNCTION_WRAPPER -I../ -I../../ -I./ -c -ffreestanding -std=c17 -D__HAVE_MAHROUSS_APIS__ -D__MAHROUSS__ -D__BOOTLOADER__ -I./ + +.PHONY: invalid-recipe +invalid-recipe: + @echo "invalid-recipe: Use make all instead." + +.PHONY: all +all: compile-amd64 + $(LD_GNU) $(OBJ) $(LD_FLAGS) -o SampleDriver.exe + cp SampleDriver.exe ../../Root/Boot/SampleDriver.exe + +ifneq ($(DEBUG_SUPPORT), ) +DEBUG = -D__DEBUG__ +endif + +.PHONY: compile-amd64 +compile-amd64: + $(WINDRES) DriverRsrc.rsrc -O coff -o DriverRsrc.o + $(CC_GNU) $(FLAG_GNU) $(DEBUG) $(wildcard *.c) $(wildcard ../../DriverKit/*.c) $(wildcard ../../DriverKit/*.S) + +.PHONY: clean +clean: + $(REM) $(REM_FLAG) $(OBJ) SampleDriver.exe + +.PHONY: help +help: + @echo "=== HELP ===" + @echo "clean: Clean driver." + @echo "compile-amd64: Build driver." diff --git a/Kernel/FSKit/Defines.hxx b/Kernel/FSKit/Defines.hxx new file mode 100644 index 00000000..bdaa8d77 --- /dev/null +++ b/Kernel/FSKit/Defines.hxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +#define FSKIT_VERSION "1.00" diff --git a/Kernel/FSKit/IndexableProperty.hxx b/Kernel/FSKit/IndexableProperty.hxx new file mode 100644 index 00000000..eae15317 --- /dev/null +++ b/Kernel/FSKit/IndexableProperty.hxx @@ -0,0 +1,58 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +#define kIndexerNodeNameLength 256 +#define kIndexerClaimed 0xCF + +namespace NewOS +{ + namespace Indexer + { + struct IndexProperty final + { + public: + Char Drive[kDriveNameLen]; + Char Path[kIndexerNodeNameLength]; + }; + + class IndexableProperty final : public Property + { + public: + explicit IndexableProperty() + : Property(StringBuilder::Construct("IndexableProperty").Leak().Leak()) + { + } + ~IndexableProperty() override = default; + + NEWOS_COPY_DEFAULT(IndexableProperty); + + public: + IndexProperty& LeakProperty() noexcept; + + public: + void AddFlag(Int16 flag); + void RemoveFlag(Int16 flag); + Int16 HasFlag(Int16 flag); + + private: + IndexProperty fIndex; + UInt32 fFlags; + }; + + /// @brief Index a file into the indexer instance. + /// @param filename path + /// @param filenameLen used bytes in path. + /// @param indexer the filesystem indexer. + /// @return none. + Void fs_index_file(const Char* filename, SizeT filenameLen, IndexableProperty& indexer); + } // namespace Indexer +} // namespace NewOS diff --git a/Kernel/FSKit/NewFS.hxx b/Kernel/FSKit/NewFS.hxx new file mode 100644 index 00000000..dca7aa2c --- /dev/null +++ b/Kernel/FSKit/NewFS.hxx @@ -0,0 +1,313 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: NewFS.hxx + Purpose: + + Revision History: + + ?/?/?: Added file (amlel) + 12/02/24: Add UUID macro for EPM and GPT partition schemes. + 3/16/24: Add mandatory sector size, kNewFSSectorSz is set to 2048 by +default. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +/** + @brief New File System specification. + @author Amlal EL Mahrouss +*/ + +#define kNewFSInvalidFork (-1) +#define kNewFSInvalidCatalog (-1) +#define kNewFSNodeNameLen (256) + +#define kNewFSSectorSz (512) + +#define kNewFSIdentLen (8) +#define kNewFSIdent " NewFS" +#define kNewFSPadLen (400) + +/// @brief Partition GUID on EPM and GPT disks. +#define kNewFSUUID "@{DD997393-9CCE-4288-A8D5-C0FDE3908DBE}" + +#define kNewFSVersionInteger (0x125) +#define kNewFSVerionString "1.25" + +/// @brief Standard fork types. +#define kNewFSDataFork "data" +#define kNewFSResourceFork "rsrc" + +#define kNewFSCatalogKindFile (1) +#define kNewFSCatalogKindDir (2) +#define kNewFSCatalogKindAlias (3) + +#define kNewFSForkSize (8192) + +//! shared between network or +//! other filesystems. Export forks as .zip when copying. +#define kNewFSCatalogKindShared (4) + +#define kNewFSCatalogKindResource (5) +#define kNewFSCatalogKindExecutable (6) + +#define kNewFSCatalogKindPage (8) + +#define kNewFSPartitionTypeStandard (7) +#define kNewFSPartitionTypePage (8) +#define kNewFSPartitionTypeBoot (9) + +#define kNewFSCatalogKindDevice (9) +#define kNewFSCatalogKindLock (10) + +#define kNewFSSeparator '/' + +#define kNewFSUpDir ".." +#define kNewFSRoot "/" + +#define kNewFSLF '\r' +#define kNewFSEOF (-1) + +#define kNewFSBitWidth (sizeof(NewCharType)) +#define kNewFSLbaType (NewOS::Lba) + +/// Start After the PM headers, pad 1024 bytes. +#define kNewFSAddressAsLba (512) +#define kNewFSCatalogStartAddress (1024 + sizeof(NewPartitionBlock) + sizeof(NewCatalog)) + +#define kResourceTypeDialog (10) +#define kResourceTypeString (11) +#define kResourceTypeMenu (12) + +#define kConfigLen (64) +#define kPartLen (32) + +#define kNewFSFlagDeleted (70) +#define kNewFSFlagUnallocated (0) +#define kNewFSFlagCreated (71) + +#define kNewFSMimeNameLen (200) + +#define kNewFSForkNameLen (200U) + +typedef NewOS::Char NewCharType; + +enum +{ + kNewFSHardDrive = 0xC0, // Hard Drive (SSD, HDD) + kNewFSOpticalDrive = 0x0C, // Blu-Ray/DVD + kNewFSMassStorageDevice = 0xCC, // USB + kNewFSScsi = 0xC4, // SCSI Hard Drive + kNewFSUnknown = 0xFF, // Unknown device. (floppy) + kNewFSDriveCount = 5, +}; + +/// @brief Catalog type. +struct PACKED NewCatalog final +{ + NewCharType Name[kNewFSNodeNameLen]; + NewCharType Mime[kNewFSMimeNameLen]; + + /// Catalog status flag. + NewOS::UInt16 Flags; + /// Custom catalog flags. + NewOS::UInt16 FileFlags; + /// Catalog kind. + NewOS::Int32 Kind; + + /// Size of the data fork. + NewOS::Lba DataForkSize; + + /// Size of all resource forks. + NewOS::Lba ResourceForkSize; + + NewOS::Lba DataFork; + NewOS::Lba ResourceFork; + + NewOS::Lba NextSibling; + NewOS::Lba PrevSibling; +}; + +/// @brief Fork type, contains a data page. +/// @note The way we store is way different than how other filesystems do, specific chunk of code are +/// written into either the data fork or resource fork, the resource fork is reserved for file metadata. +/// whereas the data fork is reserved for file data. +struct PACKED NewFork final +{ + NewCharType ForkName[kNewFSForkNameLen]; + NewOS::Char CatalogName[kNewFSNodeNameLen]; + + NewOS::Int32 Flags; + NewOS::Int32 Kind; + + NewOS::Int64 ResourceId; + NewOS::Int32 ResourceKind; + NewOS::Int32 ResourceFlags; + + NewOS::Lba DataOffset; // 8 Where to look for this data? + NewOS::SizeT DataSize; /// Data size according using sector count. + + NewOS::Lba NextSibling; + NewOS::Lba PreviousSibling; +}; + +/// @brief Partition block type +struct PACKED NewPartitionBlock final +{ + NewCharType Ident[kNewFSIdentLen]; + NewCharType PartitionName[kPartLen]; + + NewOS::Int32 Flags; + NewOS::Int32 Kind; + + NewOS::Lba StartCatalog; + NewOS::SizeT CatalogCount; + + NewOS::SizeT DiskSize; + + NewOS::SizeT FreeCatalog; + NewOS::SizeT FreeSectors; + + NewOS::SizeT SectorCount; + NewOS::SizeT SectorSize; + + NewOS::UInt64 Version; + + NewOS::Char Pad[kNewFSPadLen]; +}; + +namespace NewOS +{ + + enum + { + kNewFSSubDriveA, + kNewFSSubDriveB, + kNewFSSubDriveC, + kNewFSSubDriveD, + kNewFSSubDriveInvalid, + kNewFSSubDriveCount, + }; + + /// \brief Resource fork kind. + enum + { + kNewFSRsrcForkKind = 0, + kNewFSDataForkKind = 1 + }; + + /// + /// \name NewFSParser + /// \brief NewFS parser class. (catalog creation, remove removal, root, + /// forks...) Designed like the DOM, detects the filesystem automatically. + /// + + class NewFSParser final + { + public: + explicit NewFSParser() = default; + ~NewFSParser() = default; + + public: + NEWOS_COPY_DEFAULT(NewFSParser); + + public: + /// @brief Creates a new fork inside the New filesystem partition. + /// @param catalog it's catalog + /// @param theFork the fork itself. + /// @return the fork + _Output NewFork* CreateFork(_Input NewCatalog* catalog, + _Input NewFork& theFork); + + /// @brief Find fork inside New filesystem. + /// @param catalog the catalog. + /// @param name the fork name. + /// @return the fork. + _Output NewFork* FindFork(_Input NewCatalog* catalog, + _Input const Char* name, + Boolean dataOrRsrc); + + _Output Void RemoveFork(_Input NewFork* fork); + + _Output Void CloseFork(_Input NewFork* fork); + + _Output NewCatalog* FindCatalog(_Input const char* catalogName, Lba& outLba); + + _Output NewCatalog* GetCatalog(_Input const char* name); + + _Output NewCatalog* CreateCatalog(_Input const char* name, + _Input const Int32& flags, + _Input const Int32& kind); + + _Output NewCatalog* CreateCatalog(_Input const char* name); + + bool WriteCatalog(_Input _Output NewCatalog* catalog, + voidPtr data, + SizeT sizeOfData, + _Input const char* forkName); + + VoidPtr ReadCatalog(_Input _Output NewCatalog* catalog, + SizeT dataSz, + _Input const char* forkName); + + bool Seek(_Input _Output NewCatalog* catalog, SizeT off); + + SizeT Tell(_Input _Output NewCatalog* catalog); + + bool RemoveCatalog(_Input const Char* catalog); + + bool CloseCatalog(_InOut NewCatalog* catalog); + + /// @brief Make a EPM+NewFS drive out of the disk. + /// @param drive The drive to write on. + /// @return If it was sucessful, see DbgLastError(). + bool Format(_Input _Output DriveTrait* drive); + + public: + Int32 fDriveIndex{kNewFSSubDriveA}; + }; + + /// + /// \name NewFilesystemHelper + /// \brief Filesystem helper and utils. + /// + + class NewFilesystemHelper final + { + public: + static const char* Root(); + static const char* UpDir(); + static const char Separator(); + }; + + namespace Detail + { + Boolean fs_init_newfs(Void) noexcept; + } // namespace Detail +} // namespace NewOS + +/// @brief Write to newfs disk. +/// @param Mnt mounted interface. +/// @param DrvTrait drive info +/// @param DrvIndex drive index. +/// @return +NewOS::Int32 fs_newfs_write(NewOS::MountpointInterface* Mnt, + NewOS::DriveTrait& DrvTrait, + NewOS::Int32 DrvIndex); + +/// @brief Read from newfs disk. +/// @param Mnt mounted interface. +/// @param DrvTrait drive info +/// @param DrvIndex drive index. +/// @return +NewOS::Int32 fs_newfs_read(NewOS::MountpointInterface* Mnt, + NewOS::DriveTrait& DrvTrait, + NewOS::Int32 DrvIndex); diff --git a/Kernel/FirmwareKit/.gitkeep b/Kernel/FirmwareKit/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/FirmwareKit/CoreBoot/.gitkeep b/Kernel/FirmwareKit/CoreBoot/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/FirmwareKit/EFI.hxx b/Kernel/FirmwareKit/EFI.hxx new file mode 100644 index 00000000..c2585456 --- /dev/null +++ b/Kernel/FirmwareKit/EFI.hxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/FirmwareKit/EFI/API.hxx b/Kernel/FirmwareKit/EFI/API.hxx new file mode 100644 index 00000000..37781f23 --- /dev/null +++ b/Kernel/FirmwareKit/EFI/API.hxx @@ -0,0 +1,145 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __EFI_API__ +#define __EFI_API__ + +#include +#include +#include +#include + +#ifdef __NEWBOOT__ +// forward decl. +class BTextWriter; + +#define __BOOTKIT_NO_INCLUDE__ 1 + +#include +#include +#include +#include +#endif // ifdef __NEWBOOT__ + +inline EfiSystemTable* ST = nullptr; +inline EfiBootServices* BS = nullptr; + +EXTERN_C void rt_cli(); +EXTERN_C void rt_hlt(); + +namespace EFI +{ + /// @brief Halt and clear interrupts. + /// @return + inline Void Stop() noexcept + { + while (1) + { + rt_hlt(); + rt_cli(); + } + } + + /** +@brief Exit EFI API to let the OS load correctly. +Bascially frees everything we have in the EFI side. +*/ + inline void ExitBootServices(UInt64 MapKey, EfiHandlePtr ImageHandle) noexcept + { + if (!ST) + return; + + ST->BootServices->ExitBootServices(ImageHandle, MapKey); + } + + enum + { + kPartEPM, + kPartGPT, + kPartMBR, + kPartCnt, + }; + + inline UInt32 Platform() noexcept + { + return kPEMachineAMD64; + } + + /*** + * @brief Throw an error, stop execution as well. + * @param ErrorCode error code to be print. + * @param Reason reason to be print. + */ + inline void ThrowError(const EfiCharType* ErrorCode, + const EfiCharType* Reason) noexcept + { +#ifdef __DEBUG__ + ST->ConOut->OutputString(ST->ConOut, L"\r*** STOP ***\r"); + + ST->ConOut->OutputString(ST->ConOut, L"*** Error: "); + ST->ConOut->OutputString(ST->ConOut, ErrorCode); + + ST->ConOut->OutputString(ST->ConOut, L", Reason: "); + ST->ConOut->OutputString(ST->ConOut, Reason); + + ST->ConOut->OutputString(ST->ConOut, L" ***\r"); +#endif // ifdef __DEBUG__ + +#ifdef __NEWBOOT__ + ToolboxInitRsrc(); + + ToolboxDrawRsrc(NewBootFatal, NEWBOOTFATAL_HEIGHT, NEWBOOTFATAL_WIDTH, + (kHandoverHeader->f_GOP.f_Width - NEWBOOTFATAL_WIDTH) / 2, + (kHandoverHeader->f_GOP.f_Height - NEWBOOTFATAL_HEIGHT) / 2); + + ToolboxClearRsrc(); + + /// Show the QR code now. + + constexpr auto ver = 4; + auto ecc = qr::Ecc::H; + auto str = "https://el-mahrouss-logic.com/"; + auto len = StrLen("https://el-mahrouss-logic.com/"); + + qr::Qr encoder; + qr::QrDelegate encoderDelegate; + + encoder.encode(str, len, ecc, 0); // Manual mask 0 + + /// tell delegate to draw encoded QR. + encoderDelegate.draw(encoder, (kHandoverHeader->f_GOP.f_Width - encoder.side_size()) - 20, + (kHandoverHeader->f_GOP.f_Height - encoder.side_size()) / 2); + +#endif // ifdef __NEWBOOT__ + + EFI::Stop(); + } +} // namespace EFI + +inline void InitEFI(EfiSystemTable* SystemTable) noexcept +{ + if (!SystemTable) + return; + + ST = SystemTable; + BS = ST->BootServices; + + ST->ConOut->ClearScreen(SystemTable->ConOut); + ST->ConOut->SetAttribute(SystemTable->ConOut, kEFIYellow); + + ST->BootServices->SetWatchdogTimer(0, 0, 0, nullptr); + ST->ConOut->EnableCursor(ST->ConOut, false); +} + +#ifdef __BOOTLOADER__ + +#include + +#endif // ifdef __BOOTLOADER__ + +#define kNewOSSubsystem 17 + +#endif /* ifndef __EFI_API__ */ diff --git a/Kernel/FirmwareKit/EFI/EFI.hxx b/Kernel/FirmwareKit/EFI/EFI.hxx new file mode 100644 index 00000000..5f88fcaf --- /dev/null +++ b/Kernel/FirmwareKit/EFI/EFI.hxx @@ -0,0 +1,774 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __EFI__ +#define __EFI__ + +/** +@brief NewOS Implementation of EFI. +@note This API is in WiP, so it's not 'pretty', just deal with it. We'll be +improving that later. +@author Amlal El Mahrouss +*/ + +#include + +using namespace NewOS; + +/* we always use stdcall in EFI, the pascal way of calling functions. */ + +#ifndef EPI_API +#define EFI_API __attribute__((ms_abi)) +#endif // ifndef EPI_API + +// Forward decls + +struct EfiTableHeader; +struct EfiLoadFileProtocol; +struct EfiSimpleTextOutputProtocol; +struct EfiDevicePathProtocol; +struct EfiBootServices; +struct EfiMemoryDescriptor; +struct EfiSystemTable; +struct EfiGUID; +struct EfiFileDevicePathProtocol; +struct EfiHandle; +struct EfiGraphicsOutputProtocol; +struct EfiBitmask; +struct EfiFileProtocol; + +typedef UInt64 EfiStatusType; + +/// @brief Core Handle Kind +/// This is like NT's Win32 HANDLE type. +typedef struct EfiHandle +{ +} * EfiHandlePtr; + +/* UEFI uses wide characters by default. */ +typedef WideChar EfiCharType; + +typedef UInt64 EfiPhysicalAddress; +typedef UIntPtr EfiVirtualAddress; + +/// What's BootBolicy? +/// If TRUE, indicates that the request originates from the boot manager, and +/// that the boot manager is attempting to load FilePath as a boot selection. If +/// FALSE, then FilePath must match an exact file to be loaded. + +typedef UInt64(EFI_API* EfiTextString)(struct EfiSimpleTextOutputProtocol* This, + const WideChar* OutputString); + +typedef UInt64(EFI_API* EfiTextAttrib)(struct EfiSimpleTextOutputProtocol* This, + const WideChar Attribute); + +typedef UInt64(EFI_API* EfiTextClear)(struct EfiSimpleTextOutputProtocol* This); + +typedef UInt64(EFI_API* EfiLoadFile)(EfiLoadFileProtocol* This, + EfiFileDevicePathProtocol* FilePath, + Boolean BootPolicy, + UInt32* BufferSize, + VoidPtr Buffer); + +typedef UInt64(EFI_API* EfiCopyMem)(VoidPtr DstBuf, VoidPtr SrcBuf, SizeT Length); +typedef UInt64(EFI_API* EfiSetMem)(VoidPtr DstBuf, Char Byte, SizeT Length); + +typedef UInt64(EFI_API* EfiHandleProtocol)(EfiHandlePtr Handle, EfiGUID* Guid, VoidPtr* Device); + +typedef UInt64(EFI_API* EfiLocateDevicePath)(EfiGUID* Protocol, + EfiDevicePathProtocol** DevicePath, + EfiHandlePtr Device); + +typedef UInt64(EFI_API* EfiStartImage)(EfiHandlePtr Handle, VoidPtr ArgsSize, VoidPtr ArgsPtr); + +typedef UInt64(EFI_API* EfiLoadImage)(Boolean BootPolicy, + EfiHandlePtr ParentHandle, + EfiFileDevicePathProtocol* DeviceFile, + VoidPtr buffer, + SizeT size, + EfiHandlePtr* ppHandle); + +/// EFI pool helpers, taken from iPXE. + +typedef enum EfiMemoryType +{ + /// + /// Not used. + /// + EfiReservedMemoryType, + /// + /// The code portions of a loaded application. + /// (Note that UEFI OS loaders are UEFI applications.) + /// + EfiLoaderCode, + /// + /// The data portions of a loaded application and the default data allocation + /// type used by an application to allocate pool memory. + /// + EfiLoaderData, + /// + /// The code portions of a loaded Boot Services Driver. + /// + EfiBootServicesCode, + /// + /// The data portions of a loaded Boot Serves Driver, and the default data + /// allocation type used by a Boot Services Driver to allocate pool memory. + /// + EfiBootServicesData, + /// + /// The code portions of a loaded Runtime Services Driver. + /// + EfiRuntimeServicesCode, + /// + /// The data portions of a loaded Runtime Services Driver and the default + /// data allocation type used by a Runtime Services Driver to allocate pool + /// memory. + /// + EfiRuntimeServicesData, + /// + /// Free (unallocated) memory. + /// + EfiConventionalMemory, + /// + /// Memory in which errors have been detected. + /// + EfiUnusableMemory, + /// + /// Memory that holds the ACPI tables. + /// + EfiACPIReclaimMemory, + /// + /// Address space reserved for use by the firmware. + /// + EfiACPIMemoryNVS, + /// + /// Used by system firmware to request that a memory-mapped IO region + /// be mapped by the OS to a virtual address so it can be accessed by EFI + /// runtime services. + /// + EfiMemoryMappedIO, + /// + /// System memory-mapped IO region that is used to translate memory + /// cycles to IO cycles by the processor. + /// + EfiMemoryMappedIOPortSpace, + /// + /// Address space reserved by the firmware for code that is part of the + /// processor. + /// + EfiPalCode, + /// + /// A memory region that operates as EfiConventionalMemory, + /// however it happens to also support byte-addressable non-volatility. + /// + EfiPersistentMemory, + /// + /// A memory region that describes system memory that has not been accepted + /// by a corresponding call to the underlying isolation architecture. + /// + EfiUnacceptedMemoryType, + /// + /// The last type of memory. + /// Not a real type. + /// + EfiMaxMemoryType, +} EfiMemoryType; + +typedef enum EfiAllocateType +{ + /// Anything that satisfy the request. + AllocateAnyPages, + AllocateMaxAddress, + /// + /// Allocate pages at a specified address. + /// + AllocateAddress, + /// + /// Maximum enumeration value that may be used for bounds checking. + /// + MaxAllocateType +} EfiAllocateType; + +typedef struct EfiMemoryDescriptor +{ + /// + /// Kind of the memory region. + /// Kind EFI_MEMORY_TYPE is defined in the + /// AllocatePages() function description. + /// + UInt32 Kind; + /// + /// Physical address of the first byte in the memory region. PhysicalStart + /// must be aligned on a 4 KiB boundary, and must not be above + /// 0xfffffffffffff000. Kind EFI_PHYSICAL_ADDRESS is defined in the + /// AllocatePages() function description + /// + EfiPhysicalAddress PhysicalStart; + /// + /// Virtual address of the first byte in the memory region. + /// VirtualStart must be aligned on a 4 KiB boundary, + /// and must not be above 0xfffffffffffff000. + /// + EfiVirtualAddress VirtualStart; + /// + /// NumberOfPagesNumber of 4 KiB pages in the memory region. + /// NumberOfPages must not be 0, and must not be any value + /// that would represent a memory page with a start address, + /// either physical or virtual, above 0xfffffffffffff000. + /// + UInt64 NumberOfPages; + /// + /// Attributes of the memory region that describe the bit mask of capabilities + /// for that memory region, and not necessarily the current settings for that + /// memory region. + /// + UInt64 Attribute; +} EfiMemoryDescriptor; + +typedef UInt64(EFI_API* EfiAllocatePool)(EfiMemoryType PoolType, UInt32 Size, VoidPtr* Buffer); + +typedef UInt64(EFI_API* EfiFreePool)(VoidPtr Buffer); + +typedef UInt64(EFI_API* EfiCalculateCrc32)(VoidPtr Data, UInt32 DataSize, UInt32* CrcOut); + +/** +@brief Present in every header, used to identify a UEFI structure. +*/ +typedef struct EfiTableHeader +{ + UInt64 Signature; + UInt32 Revision; + UInt32 HeaderSize; + UInt32 Crc32; + UInt32 Reserved; +} EfiTableHeader; + +#define EFI_ACPI_TABLE_PROTOCOL_GUID \ + { \ + 0xffe06bdd, 0x6107, 0x46a6, \ + { \ + 0x7b, 0xb2, 0x5a, 0x9c, 0x7e, 0xc5, 0x27, 0x5c \ + } \ + } + +#define EFI_LOAD_FILE_PROTOCOL_GUID \ + { \ + 0x56EC3091, 0x954C, 0x11d2, \ + { \ + 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b \ + } \ + } + +#define EFI_LOAD_FILE2_PROTOCOL_GUID \ + { \ + 0x4006c0c1, 0xfcb3, 0x403e, \ + { \ + 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d \ + } \ + } + +#define EFI_LOADED_IMAGE_PROTOCOL_GUID \ + { \ + 0x5B1B31A1, 0x9562, 0x11d2, \ + { \ + 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B \ + } \ + } + +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + { \ + 0x9042a9de, 0x23dc, 0x4a38, \ + { \ + 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a \ + } \ + } + +#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000 + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + { \ + 0x0964e5b22, 0x6459, 0x11d2, \ + { \ + 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b \ + } \ + } + +#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \ + { \ + 0xbc62157e, 0x3e33, 0x4fec, \ + { \ + 0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf \ + } \ + } + +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ + { \ + 0x9576e91, 0x6d3f, 0x11d2, \ + { \ + 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b \ + } \ + } + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + { \ + 0x0964e5b22, 0x6459, 0x11d2, \ + { \ + 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b \ + } \ + } + +typedef UInt64(EfiImageUnload)(EfiHandlePtr ImageHandle); + +enum +{ + kPixelRedGreenBlueReserved8BitPerColor, + kPixelBlueGreenRedReserved8BitPerColor, + kPixelBitMask, + kPixelBltOnly, + kPixelFormatMax +}; + +typedef struct EfiBitmask +{ + UInt32 RedMask; + UInt32 GreenMask; + UInt32 BlueMask; + UInt32 ReservedMask; +} EfiBitmask; + +typedef struct +{ + UInt8 Blue; + UInt8 Green; + UInt8 Red; + UInt8 Reserved; +} EfiGraphicsOutputBltPixel; + +typedef enum EfiGraphicsOutputProtocolBltOperation +{ + EfiBltVideoFill, + EfiBltVideoToBltBuffer, + EfiBltBufferToVideo, + EfiBltVideoToVideo, + EfiGraphicsOutputBltOperationMax +} EfiGraphicsOutputProtocolBltOperation; + +typedef struct EfiGraphicsOutputProtocolModeInformation +{ + UInt32 Version; + UInt32 HorizontalResolution; + UInt32 VerticalResolution; + UInt32 PixelFormat; + EfiBitmask PixelInformation; + UInt32 PixelsPerScanLine; +} EfiGraphicsOutputProtocolModeInformation; + +typedef UInt64(EFI_API* EfiGraphicsOutputProtocolQueryMode)( + EfiGraphicsOutputProtocol* This, UInt32 ModeNumber, UInt32* SizeOfInfo, EfiGraphicsOutputProtocolModeInformation** Info); + +typedef UInt64(EFI_API* EfiGraphicsOutputProtocolSetMode)( + EfiGraphicsOutputProtocol* This, UInt32 ModeNumber); + +typedef UInt64(EFI_API* EfiGraphicsOutputProtocolBlt)( + EfiGraphicsOutputProtocol* This, EfiGraphicsOutputBltPixel* BltBuffer, EfiGraphicsOutputProtocolBltOperation BltOperation, UInt32 SourceX, UInt32 SourceY, UInt32 DestinationX, UInt32 DestinationY, UInt32 Width, UInt32 Height, UInt32 Delta); + +typedef struct +{ + UInt32 MaxMode; + UInt32 Mode; + EfiGraphicsOutputProtocolModeInformation* Info; + UInt32 SizeOfInfo; + UIntPtr FrameBufferBase; + UInt32 FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +typedef struct EfiGraphicsOutputProtocol +{ + EfiGraphicsOutputProtocolQueryMode QueryMode; + EfiGraphicsOutputProtocolSetMode SetMode; + EfiGraphicsOutputProtocolBlt Blt; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE* Mode; +} EfiGraphicsOutputProtocol; + +typedef struct EfiLoadImageProtocol +{ + UInt32 Revision; + EfiHandlePtr ParentHandle; + EfiSystemTable* SystemTable; + + // Source location of the image + EfiHandlePtr DeviceHandle; + EfiDevicePathProtocol* FilePath; + Void* Reserved; + + // Image’s load options + UInt32 LoadOptionsSize; + Void* LoadOptions; + + // Location where image was loaded + Void* ImageBase; + UInt64 ImageSize; + EfiMemoryType ImageCodeType; + EfiMemoryType ImageDataType; + EfiImageUnload Unload; +} EfiLoadImageProtocol; + +typedef struct EfiLoadFileProtocol +{ + EfiLoadFile LoadFile; +} EfiLoadFileProtocol; + +typedef struct EfiDevicePathProtocol +{ + UInt8 Kind; + UInt8 SubType; + UInt8 Length[2]; +} EfiDevicePathProtocol; + +typedef struct EfiFileDevicePathProtocol +{ + EfiDevicePathProtocol Proto; + + /// + /// File Path of this struct + /// + WideChar Path[kPathLen]; +} EfiFileDevicePathProtocol; + +typedef UInt64(EFI_API* EfiExitBootServices)(VoidPtr ImageHandle, + UInt32 MapKey); + +typedef UInt64(EFI_API* EfiAllocatePages)(EfiAllocateType AllocType, + EfiMemoryType MemType, + UInt32 Count, + EfiPhysicalAddress* Memory); + +typedef UInt64(EFI_API* EfiFreePages)(EfiPhysicalAddress* Memory, UInt32 Pages); + +typedef UInt64(EFI_API* EfiGetMemoryMap)(UInt32* MapSize, + EfiMemoryDescriptor* DescPtr, + UInt32* MapKey, + UInt32* DescSize, + UInt32* DescVersion); + +/** + * @brief GUID type, something you can also find in CFKit. + */ +typedef struct EfiGUID final +{ + UInt32 Data1; + UInt16 Data2; + UInt16 Data3; + UInt8 Data4[8]; +} EfiGUID; + +/*** + * Protocol stuff... + */ + +/** some helpers */ +#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 +#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 +#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 +#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 +#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 +#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 + +typedef UInt64(EFI_API* EfiLocateProtocol)(EfiGUID* Protocol, + VoidPtr Registration, + VoidPtr* Interface); + +typedef UInt64(EFI_API* EfiOpenProtocol)(EfiHandlePtr Handle, EfiGUID* Guid, VoidPtr* Interface, EfiHandlePtr AgentHandle, EfiHandlePtr ControllerHandle, UInt32 Attributes); + +typedef UInt64(EFI_API* EfiEnableCursor)(EfiSimpleTextOutputProtocol* This, Boolean Visible); + +/** +@name EfiBootServices +@brief UEFI Boot Services record, it contains functions necessary to a +firmware level application. +*/ +typedef struct EfiBootServices +{ + EfiTableHeader SystemTable; + VoidPtr RaiseTPL; + VoidPtr RestoreTPL; + EfiAllocatePages AllocatePages; + EfiFreePages FreePages; + EfiGetMemoryMap GetMemoryMap; + EfiAllocatePool AllocatePool; + EfiFreePool FreePool; + VoidPtr CreateEvent; + VoidPtr SetTimer; + VoidPtr WaitForEvent; + VoidPtr SignalEvent; + VoidPtr CloseEvent; + VoidPtr CheckEvent; + VoidPtr InstallProtocolInterface; + VoidPtr ReinstallProtocolInterface; + VoidPtr UninstallProtocolInterface; + EfiHandleProtocol HandleProtocol; + VoidPtr Reserved; + VoidPtr RegisterProtocolNotify; + VoidPtr LocateHandle; + EfiLocateDevicePath LocateDevicePath; + VoidPtr InstallConfigurationTable; + EfiLoadImage LoadImage; + EfiStartImage StartImage; + VoidPtr Exit; + VoidPtr UnloadImage; + EfiExitBootServices ExitBootServices; + VoidPtr GetNextMonotonicCount; + VoidPtr Stall; + EfiStatusType(EFI_API* SetWatchdogTimer)(UInt32 Timeout, UInt64 WatchdogCode, UInt32 DataSize, EfiCharType* Data); + VoidPtr ConnectController; + VoidPtr DisconnectController; + EfiOpenProtocol OpenProtocol; + VoidPtr CloseProtocol; + VoidPtr OpenProtocolInformation; + VoidPtr ProtocolsPerHandle; + VoidPtr LocateHandleBuffer; + EfiLocateProtocol LocateProtocol; + VoidPtr InstallMultipleProtocolInterfaces; + VoidPtr UninstallMultipleProtocolInterfaces; + EfiCalculateCrc32 CalculateCrc32; + EfiCopyMem CopyMem; + EfiSetMem SetMem; + VoidPtr CreateEventEx; +} EfiBootServices; + +#define kEntireDevPath 0xFF +#define kThisInstancePath 0x01 + +/** +@brief PrintF like protocol. +*/ +typedef struct EfiSimpleTextOutputProtocol +{ + VoidPtr Reset; + EfiTextString OutputString; + VoidPtr TestString; + VoidPtr QueryMode; + VoidPtr SetMode; + EfiTextAttrib SetAttribute; + EfiTextClear ClearScreen; + VoidPtr SetCursorPosition; + EfiEnableCursor EnableCursor; + VoidPtr Mode; +} EfiSimpleTextOutputProtocol; + +typedef UInt64(EFI_API* EfiOpenVolume)(struct EfiSimpleFilesystemProtocol*, + struct EfiFileProtocol**); + +struct EfiSimpleFilesystemProtocol +{ + UInt64 Revision; + EfiOpenVolume OpenVolume; +}; + +/** +@brief The Structure that they give you when booting. +*/ +typedef struct EfiSystemTable +{ + EfiTableHeader SystemHeader; + WideChar* FirmwareVendor; + UInt32 FirmwareRevision; + EfiHandlePtr ConsoleInHandle; + VoidPtr ConIn; + EfiHandlePtr ConsoleOutHandle; + EfiSimpleTextOutputProtocol* ConOut; + EfiHandlePtr StandardErrorHandle; + VoidPtr StdErr; + VoidPtr RuntimeServices; + EfiBootServices* BootServices; + UInt64 NumberOfTableEntries; + struct + { + EfiGUID VendorGUID; + VoidPtr VendorTable; + } * ConfigurationTable; +} EfiSystemTable; + +#define kEfiOk 0 +#define kEfiFail -1 + +#define EFI_EXTERN_C extern "C" + +typedef struct EfiIPV4 +{ + UInt8 Addr[4]; +} EfiIPV4; + +/// +/// 16-byte buffer. An IPv6 internet protocol address. +/// +typedef struct EfiIPV6 +{ + UInt8 Addr[16]; +} EfiIPV6; + +#define kEFIYellow (0x01 | 0x02 | 0x04 | 0x08) + +#ifdef __x86_64 +#define __EFI_x86_64__ 1 +#endif // __x86_64 + +enum +{ + kEFIHwDevicePath = 0x01, + kEFIAcpiDevicePath = 0x02, + kEFIMessaingDevicePath = 0x03, + kEFIMediaDevicePath = 0x04, + kEFIBiosBootPath = 0x05, + kEFIEndOfPath = 0x06, + kEFICount = 6, +}; + +#define END_DEVICE_PATH_TYPE 0x7f +#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xFF +#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 + +#define kEfiOffsetOf(T, F) __builtin_offsetof(T, F) + +/// File I/O macros + +#define kEFIFileRead 0x0000000000000001 +#define kEFIFileWrite 0x0000000000000002 +#define kEFIFileCreate 0x0000000000000000 + +#define kEFIReadOnly 0x01 +#define kEFIHidden 0x02 +#define kEFISystem 0x04 +#define kEFIReserved 0x08 +#define kEFIDirectory 0x10 +#define kEFIArchive 0x20 + +typedef struct EfiIOToken +{ + // + // If Event is NULL, then blocking I/O is performed. + // If Event is not NULL and non-blocking I/O is supported, then non-blocking + // I/O is performed, and Event will be signaled when the read request is + // completed. The caller must be prepared to handle the case where the + // callback associated with Event occurs before the original asynchronous I/O + // request call returns. + // + UInt64 Event; + + // + // Defines whether or not the signaled event encountered an error. + // + UInt64 Status; + + // + // For OpenEx(): Not Used, ignored. + // For ReadEx(): On input, the size of the Buffer. On output, the amount of + // data returned in Buffer. + // In both cases, the size is measured in bytes. + // For WriteEx(): On input, the size of the Buffer. On output, the amount of + // data actually written. + // In both cases, the size is measured in bytes. + // For FlushEx(): Not used, ignored. + // + UInt32 BufferSize; + + // + // For OpenEx(): Not Used, ignored. + // For ReadEx(): The buffer into which the data is read. + // For WriteEx(): The buffer of data to write. + // For FlushEx(): Not Used, ignored. + // + Void* Buffer; +} EfiIOToken; + +typedef struct EfiFileProtocol +{ + UInt64 Revision; + + EfiStatusType(EFI_API* Open)(struct EfiFileProtocol* This, + struct EfiFileProtocol** Out, + EfiCharType* CharType, + UInt64 OpenMode, + UInt64 Attrib); + + EfiStatusType(EFI_API* Close)(struct EfiFileProtocol* This); + + EfiStatusType(EFI_API* Delete)(struct EfiFileProtocol* This); + + EfiStatusType(EFI_API* Read)(struct EfiFileProtocol* This, UInt64* BufSize, VoidPtr BufOut); + + EfiStatusType(EFI_API* Write)(struct EfiFileProtocol* This, UInt64* BufSize, VoidPtr BufOut); + + EfiStatusType(EFI_API* GetPosition)(EfiFileProtocol* This, UInt64* Position); + + EfiStatusType(EFI_API* SetPosition)(EfiFileProtocol* This, UInt64* Position); + + EfiStatusType(EFI_API* GetInfo)(struct EfiFileProtocol*, struct EfiGUID*, UInt32*, void*); + + EfiStatusType(EFI_API* SetInfo)(struct EfiFileProtocol*, struct EfiGUID*, UInt32*, void*); + + EfiStatusType(EFI_API* Flush)(EfiFileProtocol*); + + EfiStatusType(EFI_API* OpenEx)(EfiFileProtocol* This, + EfiFileProtocol** OutHandle, + EfiCharType* Path, + UInt64 Mode, + UInt64 Attrib, + struct EfiIOToken* Token); + + EfiStatusType(EFI_API* ReadEx)(EfiFileProtocol* This, + struct EfiIOToken* Token); + EfiStatusType(EFI_API* WriteEx)(EfiFileProtocol* This, + struct EfiIOToken* Token); + EfiStatusType(EFI_API* FlushEx)(EfiFileProtocol* This, + struct EfiIOToken* Token); +} EfiFileProtocol, *EfiFileProtocolPtr; + +typedef UInt64 EfiCursorType; + +typedef struct EfiTime +{ + UInt16 Year; + UInt8 Month; + UInt8 Day; + UInt8 Hour; + UInt8 Minute; + UInt8 Second; + UInt8 Pad1; + UInt32 Nanosecond; + Int16 TimeZone; + UInt8 Daylight; + UInt8 Pad2; +} EfiTime; + +#define EFI_FILE_INFO_GUID \ + { \ + 0x09576e92, 0x6d3f, 0x11d2, \ + { \ + 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b \ + } \ + } + +struct EfiFileInfo final +{ + UInt64 Size; + UInt64 FileSize; + UInt64 PhysicalSize; + EfiTime CreateTime; + EfiTime LastAccessTime; + EfiTime EditTime; + UInt64 Attribute; + // Do not touch that, it's EFI specific. + WideChar FileName[1]; +}; + +#define EFI_FILE_PROTOCOL_REVISION 0x00010000 +#define EFI_FILE_PROTOCOL_REVISION2 0x00020000 +#define EFI_FILE_PROTOCOL_LATEST_REVISION EFI_FILE_PROTOCOL_REVISION2 + +#define EFI_EXTRA_DESCRIPTOR_SIZE 8 + +#endif // ifndef __EFI__ diff --git a/Kernel/FirmwareKit/EPM.hxx b/Kernel/FirmwareKit/EPM.hxx new file mode 100644 index 00000000..0051beac --- /dev/null +++ b/Kernel/FirmwareKit/EPM.hxx @@ -0,0 +1,128 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/** + @brief The Explicit Partition Map scheme. +*/ + +#ifndef __PARTITION_MAP__ +#define __PARTITION_MAP__ + +#include + +#define kEPMNameLength 32 +#define kEPMFilesystemLength 16 +#define kEPMMagicLength 5 + +/* The first 0 > 128 addresses of a disk contains these headers. */ + +/// @brief EPM GUID block. +typedef struct BlockGUID +{ + NewOS::UInt32 Data1; + NewOS::UInt16 Data2; + NewOS::UInt16 Data3; + NewOS::UInt8 Data4[8]; +} BlockGUID; + +/** + * @brief The EPM bootloader block. + * @note NumBlock and LbaStart are ignored on UEFI. + */ +struct PACKED BootBlock +{ + NewOS::Char Magic[kEPMMagicLength]; + NewOS::Char Name[kEPMNameLength]; + BlockGUID Uuid; + NewOS::Int32 Version; + NewOS::Int64 NumBlocks; + NewOS::Int64 SectorSz; + NewOS::Int64 LbaStart; +}; + +/** + * @brief The EPM partition block. + * used to describe a partition inside a media, doesn't exist on uefi. + */ +struct PACKED PartitionBlock +{ + NewOS::Char Name[kEPMNameLength]; + NewOS::Int32 Version; + NewOS::Int64 LbaEnd; + NewOS::Int64 SectorSz; + NewOS::Int64 LbaStart; + NewOS::Int16 Kind; + NewOS::Int32 FsVersion; + NewOS::Char Fs[kEPMFilesystemLength]; /* NewFS, ffs2... */ +}; + +/* @brief AMD64 magic for EPM */ +#define kEPMMagic86 "EPMAM" + +/* @brief RISC-V magic for EPM */ +#define kEPMMagicRISCV "EPMRV" + +/* @brief ARM magic for EPM */ +#define kEPMMagicARM "EPMAR" + +/* @brief 64x0 magic for EPM */ +#define kEPMMagic64k "EPM64" + +/* @brief 32x0 magic for EPM */ + +#define kEPMMagic32k "EPM32" + +/* @brief POWER magic for EPM */ + +#define kEPMMagicPPC "EPMPC" + +/* @brief UEFI magic for EPM */ + +#define kEPMMagicUEFI "EPMUE" + +/* @brief Invalid magic for EPM */ + +#define kEPMMagicError "EPM??" + +#define kEPMMaxBlks 128 + +///! @brief Version kind enum. +///! @brief Use in boot block version field. + +enum kEPMKind +{ + kEPMMpUx = 0xcf, + kEPMLinux = 0x8f, + kEPMBSD = 0x9f, + kEPMNewOS = 0x1f, +}; + +typedef struct BootBlock BootBlockType; +typedef struct PartitionBlock PartitionBlockType; + +#ifdef __x86_64__ +#define kEPMMagic kEPMMagic86 +#else +#ifdef __powerpc +#define kEPMMagic kEPMMagicPPC +#else +#define kEPMMagic kEPMMagicError +#endif +#endif + +///! @brief partition must start at this address. +///! Anything below is reserved for Data backup by the Main OS. +#define kEPMStartPartitionBlk (sizeof(BootBlock)) + +///! @brief Current EPM revision (2) +#define kEPMRevision (2) + +///! @brief Current EPM revision (2) +#define kEPMRevisionUEFI (0xF) + +/// END OF SPECS + +#endif // ifndef __PARTITION_MAP__ diff --git a/Kernel/FirmwareKit/Handover.hxx b/Kernel/FirmwareKit/Handover.hxx new file mode 100644 index 00000000..1d671f4e --- /dev/null +++ b/Kernel/FirmwareKit/Handover.hxx @@ -0,0 +1,110 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/** + * @file Handover.hxx + * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com) + * @brief The handover boot protocol. + * @version 0.3 + * @date 2024-02-23 + * + * @copyright Copyright (c) 2024, SoftwareLabs + * + */ + +#pragma once + +#include + +/* useful macros */ + +#define kHandoverMagic 0xBADCC +#define kHandoverVersion 0x112 + +#define kHandoverStructSz sizeof(HEL::HandoverHeader) + +namespace NewOS::HEL +{ + /** + @brief the kind of executable we're loading. +*/ + enum + { + kTypeKernel = 100, + kTypeKernelDriver = 101, + kTypeRsrc = 102, + kTypeCount = 3, + }; + + /** + @brief The executable architecture. +*/ + + enum + { + kArchAmd64 = 122, + kArchCount = 2, + }; + + /** +@brief The first struct that we read when inspecting The executable +it tells us more about it and IS format independent. +*/ + typedef struct HandoverHeader final + { + UInt64 f_TargetMagic; + Int32 f_TargetType; + Int32 f_TargetArch; + UIntPtr f_TargetStartAddress; + } __attribute__((packed)) HandoverHeader, *HandoverHeaderPtr; + + struct HandoverInformationHeader + { + UInt64 f_Magic; + UInt64 f_Version; + + voidPtr f_VirtualStart; + SizeT f_VirtualSize; + voidPtr f_PhysicalStart; + + WideChar f_FirmwareVendorName[32]; + SizeT f_FirmwareVendorLen; + + struct + { + VoidPtr f_SmBios; + VoidPtr f_RsdPtr; + } f_HardwareTables; + + struct + { + UIntPtr f_The; + SizeT f_Size; + UInt32 f_Width; + UInt32 f_Height; + UInt32 f_PixelFormat; + UInt32 f_PixelPerLine; + } f_GOP; + + UInt64 f_FirmwareSpecific[8]; + }; + + enum + { + kHandoverSpecificKind, + kHandoverSpecificAttrib, + kHandoverSpecificMemoryEfi, + }; + + /// @brief Bootloader main type. + typedef void (*BootMainKind)(NewOS::HEL::HandoverInformationHeader* handoverInfo); + + /// @brief Alias of bootloader main type. + typedef void (*HandoverProc)(HandoverInformationHeader* handoverInfo); +} // namespace NewOS::HEL + +/// @brief Bootloader global header. +inline NewOS::HEL::HandoverInformationHeader* kHandoverHeader = nullptr; diff --git a/Kernel/HALKit/.gitkeep b/Kernel/HALKit/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/64x0/.hgkeep b/Kernel/HALKit/64x0/.hgkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/64x0/APM/.hgkeep b/Kernel/HALKit/64x0/APM/.hgkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/64x0/HalVirtualMemory.cxx b/Kernel/HALKit/64x0/HalVirtualMemory.cxx new file mode 100644 index 00000000..fb15b2cb --- /dev/null +++ b/Kernel/HALKit/64x0/HalVirtualMemory.cxx @@ -0,0 +1,17 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +using namespace NewOS; + +/// @brief Flush system TLB, looks like the POWER version, as it acts the same, no specific instruction for that. +/// @note The 88K MMU should be present as well. +EXTERN_C void hal_flush_tlb() +{ + asm volatile("invltlb"); +} diff --git a/Kernel/HALKit/64x0/MBCI/.gitkeep b/Kernel/HALKit/64x0/MBCI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/AMD64/CPUID.hxx b/Kernel/HALKit/AMD64/CPUID.hxx new file mode 100644 index 00000000..0e570148 --- /dev/null +++ b/Kernel/HALKit/AMD64/CPUID.hxx @@ -0,0 +1,81 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: CPUID.hxx + Purpose: CPUID flags. + + Revision History: + + 30/01/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +enum +{ + CPU_FEATURE_ECX_SSE3 = 1 << 0, + CPU_FEATURE_ECX_PCLMUL = 1 << 1, + CPU_FEATURE_ECX_DTES64 = 1 << 2, + CPU_FEATURE_ECX_MONITOR = 1 << 3, + CPU_FEATURE_ECX_DS_CPL = 1 << 4, + CPU_FEATURE_ECX_VMX = 1 << 5, + CPU_FEATURE_ECX_SMX = 1 << 6, + CPU_FEATURE_ECX_EST = 1 << 7, + CPU_FEATURE_ECX_TM2 = 1 << 8, + CPU_FEATURE_ECX_SSSE3 = 1 << 9, + CPU_FEATURE_ECX_CID = 1 << 10, + CPU_FEATURE_ECX_SDBG = 1 << 11, + CPU_FEATURE_ECX_FMA = 1 << 12, + CPU_FEATURE_ECX_CX16 = 1 << 13, + CPU_FEATURE_ECX_XTPR = 1 << 14, + CPU_FEATURE_ECX_PDCM = 1 << 15, + CPU_FEATURE_ECX_PCID = 1 << 17, + CPU_FEATURE_ECX_DCA = 1 << 18, + CPU_FEATURE_ECX_SSE4_1 = 1 << 19, + CPU_FEATURE_ECX_SSE4_2 = 1 << 20, + CPU_FEATURE_ECX_X2APIC = 1 << 21, + CPU_FEATURE_ECX_MOVBE = 1 << 22, + CPU_FEATURE_ECX_POP3C = 1 << 23, + CPU_FEATURE_ECX_TSC = 1 << 24, + CPU_FEATURE_ECX_AES = 1 << 25, + CPU_FEATURE_ECX_XSAVE = 1 << 26, + CPU_FEATURE_ECX_OSXSAVE = 1 << 27, + CPU_FEATURE_ECX_AVX = 1 << 28, + CPU_FEATURE_ECX_F16C = 1 << 29, + CPU_FEATURE_ECX_RDRAND = 1 << 30, + CPU_FEATURE_ECX_HYPERVISOR = 1 << 31, + CPU_FEATURE_EDX_FPU = 1 << 0, + CPU_FEATURE_EDX_VME = 1 << 1, + CPU_FEATURE_EDX_DE = 1 << 2, + CPU_FEATURE_EDX_PSE = 1 << 3, + CPU_FEATURE_EDX_TSC = 1 << 4, + CPU_FEATURE_EDX_MSR = 1 << 5, + CPU_FEATURE_EDX_PAE = 1 << 6, + CPU_FEATURE_EDX_MCE = 1 << 7, + CPU_FEATURE_EDX_CX8 = 1 << 8, + CPU_FEATURE_EDX_APIC = 1 << 9, + CPU_FEATURE_EDX_SEP = 1 << 11, + CPU_FEATURE_EDX_MTRR = 1 << 12, + CPU_FEATURE_EDX_PGE = 1 << 13, + CPU_FEATURE_EDX_MCA = 1 << 14, + CPU_FEATURE_EDX_CMOV = 1 << 15, + CPU_FEATURE_EDX_PAT = 1 << 16, + CPU_FEATURE_EDX_PSE36 = 1 << 17, + CPU_FEATURE_EDX_PSN = 1 << 18, + CPU_FEATURE_EDX_CLFLUSH = 1 << 19, + CPU_FEATURE_EDX_DS = 1 << 21, + CPU_FEATURE_EDX_ACPI = 1 << 22, + CPU_FEATURE_EDX_MMX = 1 << 23, + CPU_FEATURE_EDX_FXSR = 1 << 24, + CPU_FEATURE_EDX_SSE = 1 << 25, + CPU_FEATURE_EDX_SSE2 = 1 << 26, + CPU_FEATURE_EDX_SS = 1 << 27, + CPU_FEATURE_EDX_HTT = 1 << 28, + CPU_FEATURE_EDX_TM = 1 << 29, + CPU_FEATURE_EDX_IA64 = 1 << 30, + CPU_FEATURE_EDX_PBE = 1 << 31 +}; + +typedef int CPU_FEATURE; \ No newline at end of file diff --git a/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx b/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx new file mode 100644 index 00000000..3609165f --- /dev/null +++ b/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx @@ -0,0 +1,123 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +namespace NewOS +{ + + /// Custom to the virtual machine, you'll need to parse the MADT instead. + + void rt_shutdown_acpi_qemu_20(void) + { + HAL::Out16(0xb004, 0x2000); + } + + void rt_shutdown_acpi_qemu_30_plus(void) + { + HAL::Out16(0x604, 0x2000); + } + + void rt_shutdown_acpi_virtualbox(void) + { + HAL::Out16(0x4004, 0x3400); + } + + /// You have to parse the MADT! + + ACPIFactoryInterface::ACPIFactoryInterface(voidPtr rsdPtr) + : fRsdp(rsdPtr), fEntries(0) + { + } + + Void ACPIFactoryInterface::Shutdown() + { +#ifdef __DEBUG__ + rt_shutdown_acpi_qemu_30_plus(); +#else + +#endif + } + + /// @brief Reboot (shutdowns on qemu.) + /// @return + Void ACPIFactoryInterface::Reboot() + { +#ifdef __DEBUG__ + rt_shutdown_acpi_qemu_30_plus(); +#else + +#endif + } + + /// @brief Finds a descriptor table inside ACPI XSDT. + ErrorOr ACPIFactoryInterface::Find(const char* signature) + { + MUST_PASS(fRsdp); + + if (!signature) + return ErrorOr{-2}; + + if (*signature == 0) + return ErrorOr{-3}; + + RSDP* rsdPtr = reinterpret_cast(this->fRsdp); + + if (rsdPtr->Revision <= 1) + { + return ErrorOr{-4}; + } + + SDT* xsdt = (SDT*)(rsdPtr->XsdtAddress >> (rsdPtr->XsdtAddress & 0xFFF)); + + SizeT num = xsdt->Length + sizeof(SDT) / 8; + + this->fEntries = num; + + kcout << "ACPI: Number of entries: " << number(num) << endl; + kcout << "ACPI: Address of XSDT: " << hex_number((UIntPtr)xsdt) << endl; + + constexpr short ACPI_SIGNATURE_LENGTH = 4; + + for (Size index = 0; index < num; ++index) + { + SDT* sdt = (SDT*)*((UInt64*)(UInt64)xsdt + sizeof(SDT) + (index * 8)); + + for (int signature_index = 0; signature_index < 4; signature_index++) + { + if (sdt->Signature[signature_index] != signature[signature_index]) + break; + + if (signature_index == 3) + return ErrorOr(reinterpret_cast((SDT*)sdt)); + } + } + + return ErrorOr{-1}; + } + + /*** + @brief check SDT header + @param checksum the header to checksum + @param len the length of it. +*/ + bool ACPIFactoryInterface::Checksum(const char* checksum, SSizeT len) + { + if (len == 0) + return -1; + + char chr = 0; + + for (int index = 0; index < len; ++index) + { + chr += checksum[index]; + } + + return chr == 0; + } +} // namespace NewOS diff --git a/Kernel/HALKit/AMD64/HalControlRegister.s b/Kernel/HALKit/AMD64/HalControlRegister.s new file mode 100644 index 00000000..7798ea09 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalControlRegister.s @@ -0,0 +1,40 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +.globl hal_write_cr3 +.globl hal_write_cr0 +.globl hal_read_cr2 +.globl hal_read_cr3 +.globl hal_read_cr0 +.globl hal_flush_tlb + +.text + +hal_flush_tlb: + call hal_read_cr3 + mov %rcx, %rax + call hal_write_cr3 + ret + +hal_read_cr3: + movq %cr3, %rax + ret + +hal_read_cr0: + movq %rax, %cr0 + ret + +hal_read_cr2: + movq %rax, %cr2 + ret + +hal_write_cr3: + movq %cr3, %rdi + ret + +hal_write_cr0: + movq %cr0, %rdi + ret diff --git a/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp b/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp new file mode 100644 index 00000000..1f2e21e2 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp @@ -0,0 +1,101 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +/// @brief Handle GPF fault. +/// @param rsp +EXTERN_C void idt_handle_gpf(NewOS::UIntPtr rsp) +{ + MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent()); + + NewOS::kcout << "New OS: Stack Pointer: " + << NewOS::StringBuilder::FromInt("rsp{%}", rsp); + + NewOS::kcout + << "New OS: General Protection Fault, caused by " + << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName(); + + NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); +} + +/// @brief Handle the scheduler interrupt, raised from the HPET timer. +/// @param rsp +EXTERN_C void idt_handle_scheduler(NewOS::UIntPtr rsp) +{ + NewOS::kcout << NewOS::StringBuilder::FromInt("rsp{%}", rsp); + + NewOS::kcout + << "New OS: Will be scheduled back later " + << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName() + << NewOS::end_line(); + + /// schedule another process. + if (!NewOS::ProcessHelper::StartScheduling()) + { + NewOS::kcout << "New OS: Continue schedule this process...\r"; + } +} + +/// @brief Handle page fault. +/// @param rsp +EXTERN_C void idt_handle_pf(NewOS::UIntPtr rsp) +{ + MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent()); + NewOS::kcout << NewOS::StringBuilder::FromInt("rsp{%}", rsp); + + NewOS::kcout + << "New OS: Segmentation Fault, caused by " + << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName(); + + NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); +} + +/// @brief Handle math fault. +/// @param rsp +EXTERN_C void idt_handle_math(NewOS::UIntPtr rsp) +{ + MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent()); + NewOS::kcout << NewOS::StringBuilder::FromInt("rsp{%}", rsp); + + NewOS::kcout + << "New OS: Math error, caused by " + << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName(); + + NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); +} + +/// @brief Handle any generic fault. +/// @param rsp +EXTERN_C void idt_handle_generic(NewOS::UIntPtr rsp) +{ + MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent()); + NewOS::kcout << NewOS::StringBuilder::FromInt("sp{%}", rsp); + + NewOS::kcout + << "New OS: Execution error, caused by " + << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName(); + + NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); +} + +/// @brief Handle #UD fault. +/// @param rsp +EXTERN_C void idt_handle_ud(NewOS::UIntPtr rsp) +{ + MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent()); + + NewOS::kcout << "New OS: Stack Pointer: " + << NewOS::StringBuilder::FromInt("rsp{%}", rsp); + + NewOS::kcout + << "New OS: Invalid interrupt, caused by " + << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName(); + + NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); +} diff --git a/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp new file mode 100644 index 00000000..2129d790 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp @@ -0,0 +1,124 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////////////// + +//! NOTE: fGSI stands 'Field Global System Interrupt' + +/////////////////////////////////////////////////////////////////////////////////////// + +namespace NewOS::HAL +{ + constexpr Int32 kThreadAPIC = 0; + constexpr Int32 kThreadLAPIC = 1; + constexpr Int32 kThreadIOAPIC = 2; + constexpr Int32 kThreadAPIC64 = 3; + constexpr Int32 kThreadBoot = 4; + + /* + * + * this is used to store info about the current running thread + * we use this struct to determine if we can use it, or mark it as used or on + * sleep. + * + */ + + struct ProcessorInfoAMD64 final + { + Int32 ThreadType; + UIntPtr JumpAddress; + + struct + { + UInt32 Code; + UInt32 Data; + UInt32 BSS; + } Selector; + }; + + STATIC voidPtr kApicMadt = nullptr; + STATIC const char* kApicSignature = "APIC"; + + /// @brief Multiple APIC descriptor table. + struct MadtType final : public SDT + { + struct MadtAddress final + { + UInt32 fFlags; // 1 = Dual Legacy PICs installed + UInt32 fPhysicalAddress; + + Char fType; + Char fRecLen; // record length + } Madt[]; + }; + + struct MadtProcessorLocalApic final + { + Char fProcessorId; + Char fApicId; + UInt32 fFlags; + }; + + struct MadtIOApic final + { + Char fApicId; + Char fReserved; + UInt32 fAddress; + UInt32 fSystemInterruptBase; + }; + + struct MadtInterruptSource final + { + Char fBusSource; + Char fIrqSource; + UInt32 fGSI; + UInt16 fFlags; + }; + + struct MadtInterruptNmi final + { + Char fNmiSource; + Char fReserved; + UInt16 fFlags; + UInt32 fGSI; + }; + + struct MadtLocalApicAddressOverride final + { + UInt16 fResvered; + UIntPtr fAddress; + }; + + /////////////////////////////////////////////////////////////////////////////////////// + + STATIC MadtType* kApicInfoBlock = nullptr; + + /////////////////////////////////////////////////////////////////////////////////////// + + void hal_system_get_cores(voidPtr rsdPtr) + { + kcout << "New OS: Constructing ACPIFactoryInterface...\r"; + + auto acpi = ACPIFactoryInterface(rsdPtr); + kApicMadt = acpi.Find(kApicSignature).Leak().Leak(); + + if (kApicMadt) + { + kcout << "New OS: Successfuly fetched the MADT!\r"; + kApicInfoBlock = (MadtType*)kApicMadt; + } + else + { + MUST_PASS(false); + } + } +} // namespace NewOS::HAL + +/////////////////////////////////////////////////////////////////////////////////////// diff --git a/Kernel/HALKit/AMD64/HalDebugOutput.cxx b/Kernel/HALKit/AMD64/HalDebugOutput.cxx new file mode 100644 index 00000000..3227be1f --- /dev/null +++ b/Kernel/HALKit/AMD64/HalDebugOutput.cxx @@ -0,0 +1,145 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include + +namespace NewOS +{ + enum CommStatus + { + kStateInvalid, + kStateReady = 0xCF, + kStateTransmit = 0xFC, + kStateCnt = 3 + }; + + namespace Detail + { + constexpr short PORT = 0x3F8; + + static int kState = kStateInvalid; + + /// @brief Init COM1. + /// @return + bool serial_init() noexcept + { +#ifdef __DEBUG__ + if (kState == kStateReady || kState == kStateTransmit) + return true; + + HAL::Out8(PORT + 1, 0x00); // Disable all interrupts + HAL::Out8(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + HAL::Out8(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud + HAL::Out8(PORT + 1, 0x00); // (hi byte) + HAL::Out8(PORT + 3, 0x03); // 8 bits, no parity, one stop bit + HAL::Out8(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + HAL::Out8(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + HAL::Out8(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip + HAL::Out8(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if + // serial returns same byte) + + // Check if serial is faulty (i.e: not same byte as sent) + if (HAL::In8(PORT) != 0xAE) + { + ke_stop(RUNTIME_CHECK_HANDSHAKE); + } + + kState = kStateReady; + + // If serial is not faulty set it in normal operation mode + // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) + HAL::Out8(Detail::PORT + 4, 0x0F); +#endif // __DEBUG__ + + return true; + } + } // namespace Detail + + EXTERN_C void ke_io_write(const char* bytes) + { +#ifdef __DEBUG__ + Detail::serial_init(); + + if (!bytes || Detail::kState != kStateReady) + return; + if (*bytes == 0) + return; + + Detail::kState = kStateTransmit; + + SizeT index = 0; + SizeT len = rt_string_len(bytes, 256); + + while (index < len) + { + if (bytes[index] == '\r') + HAL::Out8(Detail::PORT, '\r'); + + HAL::Out8(Detail::PORT, bytes[index] == '\r' ? '\n' : bytes[index]); + ++index; + } + + Detail::kState = kStateReady; +#endif // __DEBUG__ + } + + EXTERN_C void ke_io_read(const char* bytes) + { +#ifdef __DEBUG__ + Detail::serial_init(); + + if (!bytes || Detail::kState != kStateReady) + return; + + Detail::kState = kStateTransmit; + + SizeT index = 0; + + ///! TODO: Look on how to wait for the UART to complete. + while (true) + { + auto in = HAL::In8(Detail::PORT); + + ///! If enter pressed then break. + if (in == 0xD) + { + break; + } + + if (in < '0' || in < 'A' || in < 'a') + { + if (in != '@' || in != '!' || in != '?' || in != '.' || in != '/' || + in != ':') + { + continue; + } + } + + ((char*)bytes)[index] = in; + + ++index; + } + + ((char*)bytes)[index] = 0; + + Detail::kState = kStateReady; +#endif // __DEBUG__ + } + + TerminalDevice& TerminalDevice::Shared() noexcept + { + static TerminalDevice* out = nullptr; + + if (!out) + out = new TerminalDevice(NewOS::ke_io_write, NewOS::ke_io_read); + + return *out; + } + +} // namespace NewOS diff --git a/Kernel/HALKit/AMD64/HalDebugPort.cxx b/Kernel/HALKit/AMD64/HalDebugPort.cxx new file mode 100644 index 00000000..6d7a03f5 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalDebugPort.cxx @@ -0,0 +1,40 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +//! @file DebuggerPort.cxx +//! @brief UART debug via packets. + +#include +#include + +// after that we have start of additional data. + +namespace NewOS +{ + void rt_debug_listen(DebuggerPortHeader* theHook) noexcept + { + if (theHook == nullptr) + return; + + for (UInt32 i = 0U; i < kDebugMaxPorts; ++i) + { + HAL::Out16(theHook->fPort[i], kDebugMag0); + HAL::rt_wait_400ns(); + + HAL::Out16(theHook->fPort[i], kDebugMag1); + HAL::rt_wait_400ns(); + + HAL::Out16(theHook->fPort[i], kDebugMag2); + HAL::rt_wait_400ns(); + + HAL::Out16(theHook->fPort[i], kDebugMag3); + HAL::rt_wait_400ns(); + + if (HAL::In16(theHook->fPort[i] != kDebugUnboundPort)) + theHook->fBoundCnt++; + } + } +} // namespace NewOS diff --git a/Kernel/HALKit/AMD64/HalDescriptorLoader.cpp b/Kernel/HALKit/AMD64/HalDescriptorLoader.cpp new file mode 100644 index 00000000..689c1742 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalDescriptorLoader.cpp @@ -0,0 +1,90 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS::HAL +{ + namespace Detail + { + STATIC RegisterGDT kRegGdt; + STATIC HAL::Register64 kRegIdt; + + STATIC ::NewOS::Detail::AMD64::InterruptDescriptorAMD64 + kInterruptVectorTable[kKernelIdtSize]; + + STATIC Void RemapPIC(Void) noexcept + { + // Remap PIC. + HAL::Out8(0x20, 0x10 | 0x01); + HAL::Out8(0xA0, 0x10 | 0x01); + + HAL::Out8(0x21, 32); + HAL::Out8(0xA1, 40); + + HAL::Out8(0x21, 4); + HAL::Out8(0xA1, 2); + + HAL::Out8(0x21, 0x01); + HAL::Out8(0xA1, 0x01); + + HAL::Out8(0x21, 0x00); + HAL::Out8(0xA1, 0x00); + } + } // namespace Detail + + /// @brief Loads the provided Global Descriptor Table. + /// @param gdt + /// @return + Void GDTLoader::Load(RegisterGDT& gdt) + { + MUST_PASS(gdt.Base != 0); + + Detail::kRegGdt.Base = gdt.Base; + Detail::kRegGdt.Limit = gdt.Limit; + + hal_load_gdt(Detail::kRegGdt); + } + + Void IDTLoader::Load(Register64& idt) + { + volatile ::NewOS::UIntPtr** baseIdt = (volatile ::NewOS::UIntPtr**)idt.Base; + + MUST_PASS(baseIdt); + + Detail::RemapPIC(); + + for (UInt16 i = 0; i < kKernelIdtSize; ++i) + { + MUST_PASS(baseIdt[i]); + + Detail::kInterruptVectorTable[i].Selector = kGdtCodeSelector; + Detail::kInterruptVectorTable[i].Ist = 0x0; + Detail::kInterruptVectorTable[i].TypeAttributes = kInterruptGate; + Detail::kInterruptVectorTable[i].OffsetLow = ((UIntPtr)baseIdt[i] & 0xFFFF); + Detail::kInterruptVectorTable[i].OffsetMid = (((UIntPtr)baseIdt[i] >> 16) & 0xFFFF); + Detail::kInterruptVectorTable[i].OffsetHigh = + (((UIntPtr)baseIdt[i] >> 32) & 0xFFFFFFFF); + Detail::kInterruptVectorTable[i].Zero = 0x0; + } + + Detail::kRegIdt.Base = reinterpret_cast(Detail::kInterruptVectorTable); + Detail::kRegIdt.Limit = sizeof(::NewOS::Detail::AMD64::InterruptDescriptorAMD64) * + (kKernelIdtSize - 1); + + hal_load_idt(Detail::kRegIdt); + } + + void GDTLoader::Load(Ref& gdt) + { + GDTLoader::Load(gdt.Leak()); + } + + void IDTLoader::Load(Ref& idt) + { + IDTLoader::Load(idt.Leak()); + } +} // namespace NewOS::HAL diff --git a/Kernel/HALKit/AMD64/HalHardwareMP.cpp b/Kernel/HALKit/AMD64/HalHardwareMP.cpp new file mode 100644 index 00000000..2ebf45fd --- /dev/null +++ b/Kernel/HALKit/AMD64/HalHardwareMP.cpp @@ -0,0 +1,34 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +// bugs = 0 + +namespace NewOS +{ + /// @brief wakes up thread. + /// wakes up thread from hang. + void rt_wakeup_thread(HAL::StackFrame* stack) + { + HAL::rt_cli(); + + stack->Rcx = 0; + + HAL::rt_sti(); + } + + /// @brief makes thread sleep. + /// hooks and hangs thread to prevent code from executing. + void rt_hang_thread(HAL::StackFrame* stack) + { + HAL::rt_cli(); + + stack->Rcx = 1; + + HAL::rt_sti(); + } +} // namespace NewOS diff --git a/Kernel/HALKit/AMD64/HalInstallTIB.asm b/Kernel/HALKit/AMD64/HalInstallTIB.asm new file mode 100644 index 00000000..a5f3ef73 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalInstallTIB.asm @@ -0,0 +1,22 @@ +;; /* +;; * ======================================================== +;; * +;; * NewOS +;; * Copyright SoftwareLabs, all rights reserved. +;; * +;; * ======================================================== +;; */ + +[bits 64] + +[global rt_install_tib] + +;; changed: rs, fs +;; expected: rcx, rdx + +rt_install_tib: + mov rcx, gs ;; TIB -> Thread Information Block + mov rdx, fs ;; PIB -> Process Information Block + ret + +;; //////////////////////////////////////////////////// ;; diff --git a/Kernel/HALKit/AMD64/HalInterruptAPI.asm b/Kernel/HALKit/AMD64/HalInterruptAPI.asm new file mode 100644 index 00000000..e4063388 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalInterruptAPI.asm @@ -0,0 +1,222 @@ +;; /* +;; * --------------------------------------------------- +;; * +;; * Copyright SoftwareLabs, all rights reserved. +;; * +;; * File: HalInterruptAPI.asm +;; * Purpose: Interrupt routing, redirect raw interrupts into their handlers. +;; * +;; * --------------------------------------------------- +;; */ + +[bits 64] + +%define kInterruptId 0x21 + +%macro IntExp 1 +global __HCR_INT_%1 +__HCR_INT_%1: + cld + + iretq +%endmacro + +%macro IntNormal 1 +global __HCR_INT_%1 +__HCR_INT_%1: + cld + + iretq +%endmacro + +; This file handles the core interrupt table +; Last edited 31/01/24 + +global _ke_power_on_self_test +global ke_handle_irq +global kInterruptVectorTable + +extern _hal_handle_mouse +extern idt_handle_gpf +extern idt_handle_pf +extern ke_io_write +extern idt_handle_ud + +section .text + +IntNormal 0 +IntNormal 1 + +IntNormal 2 + +IntNormal 3 +IntNormal 4 +IntNormal 5 + +;; Invalid opcode interrupt +__HCR_INT_6: + cli + + push rax + + mov rcx, rsp + call idt_handle_ud + + pop rax + + sti + iretq + +IntNormal 7 +IntExp 8 +IntNormal 9 +IntExp 10 +IntExp 11 + +IntExp 12 + +__HCR_INT_13: + cli + + push rax + + mov rcx, rsp + call idt_handle_gpf + + pop rax + + sti + iretq + +__HCR_INT_14: + cli + + push rax + + mov rcx, rsp + call idt_handle_pf + + pop rax + + sti + iretq + +IntNormal 15 +IntNormal 16 +IntExp 17 +IntNormal 18 +IntNormal 19 +IntNormal 20 +IntNormal 21 +IntNormal 22 +IntNormal 23 +IntNormal 24 +IntNormal 25 +IntNormal 26 +IntNormal 27 +IntNormal 28 +IntNormal 29 +IntExp 30 + +IntNormal 31 + +IntNormal 32 + +IntNormal 33 + +IntNormal 34 +IntNormal 35 +IntNormal 36 +IntNormal 37 +IntNormal 38 +IntNormal 39 +IntNormal 40 +IntNormal 41 +IntNormal 42 +IntNormal 43 + +__HCR_INT_44: + cli + + ;; TODO: CoreEvents dispatch routine. + + push rax + call _hal_handle_mouse + pop rax + + sti + iretq + +IntNormal 45 +IntNormal 46 +IntNormal 47 +IntNormal 48 +IntNormal 49 + +__HCR_INT_50: + cli + + ;; todo handle system calls. + + sti + iretq + +IntNormal 51 +IntNormal 52 +IntNormal 53 +IntNormal 54 +IntNormal 55 +IntNormal 56 +IntNormal 57 +IntNormal 58 +IntNormal 59 +IntNormal 60 + +%assign i 61 +%rep 195 + IntNormal i +%assign i i+1 +%endrep + +;; this one is doing a POST for us. +;; testing interrupts. +_ke_power_on_self_test: + int 0x32 + int 0x32 + int 0x32 + int 0x32 + + ret + +[global hal_load_gdt] + +hal_load_gdt: + lgdt [rcx] + push 0x08 + lea rax, [rel rt_reload_segments] + push rax + retfq +rt_reload_segments: + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + ret + +global hal_load_idt + +hal_load_idt: + lidt [rcx] + sti + ret + +section .data + +kInterruptVectorTable: + %assign i 0 + %rep 256 + dq __HCR_INT_%+i + %assign i i+1 + %endrep diff --git a/Kernel/HALKit/AMD64/HalKernelMain.cxx b/Kernel/HALKit/AMD64/HalKernelMain.cxx new file mode 100644 index 00000000..e2533241 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalKernelMain.cxx @@ -0,0 +1,85 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +EXTERN_C NewOS::VoidPtr kInterruptVectorTable[]; +EXTERN_C void AppMain(); + +namespace NewOS::HAL +{ + /// @brief Gets the system cores using the MADT. + /// @param rsdPtr the RSD PTR. + extern void hal_system_get_cores(NewOS::voidPtr rsdPtr); +} // namespace NewOS::HAL + +EXTERN_C void hal_init_platform( + NewOS::HEL::HandoverInformationHeader* HandoverHeader) +{ + kHandoverHeader = HandoverHeader; + + if (kHandoverHeader->f_Magic != kHandoverMagic && + kHandoverHeader->f_Version != kHandoverVersion) + { + return; + } + + /// Setup kernel globals. + kKernelVirtualSize = HandoverHeader->f_VirtualSize; + kKernelVirtualStart = reinterpret_cast( + reinterpret_cast(HandoverHeader->f_VirtualStart) + kVirtualAddressStartOffset); + + kKernelPhysicalStart = HandoverHeader->f_PhysicalStart; + + STATIC NewOS::HAL::Detail::NewOSGDT GDT = { + {0, 0, 0, 0x00, 0x00, 0}, // null entry + {0, 0, 0, 0x9a, 0xaf, 0}, // kernel code + {0, 0, 0, 0x92, 0xaf, 0}, // kernel data + {0, 0, 0, 0x00, 0x00, 0}, // null entry + {0, 0, 0, 0x9a, 0xaf, 0}, // user code + {0, 0, 0, 0x92, 0xaf, 0}, // user data + }; + + NewOS::HAL::RegisterGDT gdtBase; + + gdtBase.Base = reinterpret_cast(&GDT); + gdtBase.Limit = sizeof(NewOS::HAL::Detail::NewOSGDT) - 1; + + /// Load GDT. + + NewOS::HAL::GDTLoader gdt; + gdt.Load(gdtBase); + + /// Load IDT. + + NewOS::HAL::Register64 idtBase; + idtBase.Base = (NewOS::UIntPtr)kInterruptVectorTable; + idtBase.Limit = 0; + + NewOS::HAL::IDTLoader idt; + idt.Load(idtBase); + + /// START POST + + NewOS::HAL::Detail::_ke_power_on_self_test(); + + NewOS::HAL::hal_system_get_cores(kHandoverHeader->f_HardwareTables.f_RsdPtr); + + /// END POST + + AppMain(); + + NewOS::ke_stop(RUNTIME_CHECK_BOOTSTRAP); +} diff --git a/Kernel/HALKit/AMD64/HalKernelMouse.cxx b/Kernel/HALKit/AMD64/HalKernelMouse.cxx new file mode 100644 index 00000000..926a9d5a --- /dev/null +++ b/Kernel/HALKit/AMD64/HalKernelMouse.cxx @@ -0,0 +1,190 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include +#include + +// forward decl. +EXTERN_C NewOS::Boolean _hal_draw_mouse(); +EXTERN_C NewOS::Void _hal_init_mouse(); + +STATIC NewOS::Int32 kPrevX = 10; +STATIC NewOS::Int32 kPrevY = 10; +STATIC NewOS::Int32 kX = 10; +STATIC NewOS::Int32 kY = 10; +STATIC NewOS::Int32 kMouseCycle = 0; +STATIC NewOS::PS2MouseInterface kMousePS2; +STATIC NewOS::Char kMousePacket[4] = {}; +STATIC NewOS::Boolean kMousePacketReady = false; + +STATIC ToolboxInitRsrc(); + +#define kPS2Leftbutton 0b00000001 +#define kPS2Middlebutton 0b00000010 +#define kPS2Rightbutton 0b00000100 +#define kPS2XSign 0b00010000 +#define kPS2YSign 0b00100000 +#define kPS2XOverflow 0b01000000 +#define kPS2YOverflow 0b10000000 + +using namespace NewOS; + +Void hal_handle_mouse() +{ + NewOS::UInt8 data = HAL::In8(0x60); + + switch (kMouseCycle) + { + case 0: + if (kMousePacketReady) + break; + if ((data & 0b00001000) == 0) + break; + kMousePacket[0] = data; + kMouseCycle++; + break; + case 1: + if (kMousePacketReady) + break; + kMousePacket[1] = data; + kMouseCycle++; + break; + case 2: + if (kMousePacketReady) + break; + kMousePacket[2] = data; + kMousePacketReady = true; + kMouseCycle = 0; + break; + } + + // Notify PIC controller that we're done with it's interrupt. + + NewOS::HAL::Out8(0x20, 0x20); + NewOS::HAL::Out8(0xA0, 0x20); +} + +/// @brief Interrupt handler for the mouse. +EXTERN_C Void _hal_handle_mouse() +{ + hal_handle_mouse(); +} + +EXTERN_C Boolean _hal_left_button_pressed() +{ + return kMousePacket[0] & kPS2Leftbutton; +} +EXTERN_C Boolean _hal_right_button_pressed() +{ + return kMousePacket[0] & kPS2Rightbutton; +} +EXTERN_C Boolean _hal_middle_button_pressed() +{ + return kMousePacket[0] & kPS2Middlebutton; +} + +/// @brief Draws the kernel's mouse. +EXTERN_C Boolean _hal_draw_mouse() +{ + if (!kMousePacketReady) + return false; + + bool xNegative, yNegative, xOverflow, yOverflow; + + if (kMousePacket[0] & kPS2XSign) + { + xNegative = true; + } + else + xNegative = false; + + if (kMousePacket[0] & kPS2YSign) + { + yNegative = true; + } + else + yNegative = false; + + if (kMousePacket[0] & kPS2XOverflow) + { + xOverflow = true; + } + else + xOverflow = false; + + if (kMousePacket[0] & kPS2YOverflow) + { + yOverflow = true; + } + else + yOverflow = false; + + if (!xNegative) + { + kX += kMousePacket[1]; + if (xOverflow) + { + kX += 255; + } + } + else + { + kMousePacket[1] = 256 - kMousePacket[1]; + kX -= kMousePacket[1]; + if (xOverflow) + { + kX -= 255; + } + } + + if (!yNegative) + { + kY -= kMousePacket[2]; + if (yOverflow) + { + kY -= 255; + } + } + else + { + kMousePacket[2] = 256 - kMousePacket[2]; + kY += kMousePacket[2]; + if (yOverflow) + { + kY += 255; + } + } + + if (kX < 0) + kX = 0; + if (kX > kHandoverHeader->f_GOP.f_Width - 8) + kX = kHandoverHeader->f_GOP.f_Width - 8; + + if (kY < 0) + kY = 0; + if (kY > kHandoverHeader->f_GOP.f_Height - 16) + kY = kHandoverHeader->f_GOP.f_Height - 16; + + /// Draw mouse here. + + kPrevX = kX; + kPrevY = kY; + + kMousePacketReady = false; + return true; +} + +/// @brief Init kernel mouse. +EXTERN_C Void _hal_init_mouse() +{ + kMousePS2.Init(); + + HAL::Out8(0x21, 0b11111001); + HAL::Out8(0xA1, 0b11101111); +} diff --git a/Kernel/HALKit/AMD64/HalNewBoot.asm b/Kernel/HALKit/AMD64/HalNewBoot.asm new file mode 100644 index 00000000..7c60d363 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalNewBoot.asm @@ -0,0 +1,41 @@ +;; /* +;; * ======================================================== +;; * +;; * NewOS +;; * Copyright SoftwareLabs, all rights reserved. +;; * +;; * ======================================================== +;; */ + +[bits 64] + +;; Global symbol of this unit +[global MainLong] +[global MainUnsupported] + +%define kTypeKernel 100 +%define kArchAmd64 122 +%define kHandoverMagic 0xBADCC + +section .NewBoot + +HandoverMagic: dq kHandoverMagic +HandoverType: dw kTypeKernel +HandoverArch: dw kArchAmd64 +;; This NewBootStart points to Main. +HandoverStart: dq __ImageStart + +section .text + +global __ImageStart +global __NewBootJumpProc + +extern hal_init_platform + +;; Just a simple setup, we'd also need to tell some before +__NewBootJumpProc: +__ImageStart: + push rcx + call hal_init_platform + pop rcx + ret diff --git a/Kernel/HALKit/AMD64/HalPageAlloc.cpp b/Kernel/HALKit/AMD64/HalPageAlloc.cpp new file mode 100644 index 00000000..db2aad73 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalPageAlloc.cpp @@ -0,0 +1,103 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include + +STATIC NewOS::Boolean kAllocationInProgress = false; + +namespace NewOS +{ + namespace HAL + { + namespace Detail + { + struct VirtualMemoryHeader + { + UInt32 Magic; + Boolean Present; + Boolean ReadWrite; + Boolean User; + SizeT PageSize; + }; + + struct VirtualMemoryHeaderTraits + { + /// @brief Get next header. + /// @param current + /// @return + VirtualMemoryHeader* Next(VirtualMemoryHeader* current) + { + return current + sizeof(PTE) + current->PageSize; + } + + /// @brief Get previous header. + /// @param current + /// @return + VirtualMemoryHeader* Prev(VirtualMemoryHeader* current) + { + return current - sizeof(PTE) - current->PageSize; + } + }; + } // namespace Detail + + /// @brief Allocates a new page of memory. + /// @param sz the size of it. + /// @param rw read/write flag. + /// @param user user flag. + /// @return the page table of it. + STATIC auto hal_try_alloc_new_page(Boolean rw, Boolean user, SizeT size) -> VoidPtr + { + if (kAllocationInProgress) + return nullptr; + + kAllocationInProgress = true; + + constexpr auto cVMTMagic = 0xDEEFD00D; + + ///! fetch from the start. + Detail::VirtualMemoryHeader* vmHeader = reinterpret_cast(kKernelVirtualStart); + Detail::VirtualMemoryHeaderTraits traits; + + while (vmHeader->Present && + vmHeader->Magic != cVMTMagic) + { + vmHeader = traits.Next(vmHeader); + } + + vmHeader->Magic = cVMTMagic; + vmHeader->Present = true; + vmHeader->ReadWrite = rw; + vmHeader->User = user; + vmHeader->PageSize = size; + + kAllocationInProgress = false; + + return reinterpret_cast(vmHeader); + } + + /// @brief Allocate a new page to be used by the OS. + /// @param rw read/write bit. + /// @param user user bit. + /// @return + auto hal_alloc_page(Boolean rw, Boolean user, SizeT size) -> VoidPtr + { + /// Wait for a ongoing allocation to complete. + while (kAllocationInProgress) + { + ; + } + + if (size == 0) + ++size; + + /// allocate new page. + return hal_try_alloc_new_page(rw, user, size); + } + } // namespace HAL +} // namespace NewOS diff --git a/Kernel/HALKit/AMD64/HalPageAlloc.hpp b/Kernel/HALKit/AMD64/HalPageAlloc.hpp new file mode 100644 index 00000000..2831c87a --- /dev/null +++ b/Kernel/HALKit/AMD64/HalPageAlloc.hpp @@ -0,0 +1,88 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +/** --------------------------------------------------- + + * THIS FILE CONTAINS CODE FOR X86_64 PAGING. + +------------------------------------------------------- */ + +#include + +#ifndef kPTEMax +#define kPTEMax (0x200) +#endif //! kPTEMax + +#ifndef kPTEAlign +#define kPTEAlign (0x1000) +#endif //! kPTEAlign + +#ifndef kPTESize +#define kPTESize (0x1000) +#endif // !kPTESize + +EXTERN_C void hal_flush_tlb(); +EXTERN_C void hal_write_cr3(NewOS::UIntPtr pde); +EXTERN_C void hal_write_cr0(NewOS::UIntPtr bit); + +EXTERN_C NewOS::UIntPtr hal_read_cr0(); // @brief CPU control register. +EXTERN_C NewOS::UIntPtr hal_read_cr2(); // @brief Fault address. +EXTERN_C NewOS::UIntPtr hal_read_cr3(); // @brief Page table. + +namespace NewOS::HAL +{ + struct PACKED PageTable64 final + { + bool Present : 1; + bool Rw : 1; + bool User : 1; + bool Wt : 1; + bool Cache : 1; + bool Accessed : 1; + NewOS::Int32 Reserved : 6; + NewOS::UIntPtr PhysicalAddress : 36; + NewOS::Int32 Reserved1 : 15; + bool ExecDisable : 1; + }; + + namespace Detail + { + enum class ControlRegisterBits + { + ProtectedModeEnable = 0, + MonitorCoProcessor = 1, + Emulation = 2, + TaskSwitched = 3, + ExtensionType = 4, + NumericError = 5, + WriteProtect = 16, + AlignementMask = 18, + NotWriteThrough = 29, + CacheDisable = 30, + PageEnable = 31, + }; + + inline UInt8 control_register_cast(ControlRegisterBits reg) + { + return static_cast(reg); + } + } // namespace Detail + + struct PageDirectory64 final + { + PageTable64 ALIGN(kPTEAlign) Pte[kPTEMax]; + }; + + VoidPtr hal_alloc_page(Boolean rw, Boolean user, SizeT size); +} // namespace NewOS::HAL + +namespace NewOS +{ + typedef HAL::PageTable64 PTE; + typedef HAL::PageDirectory64 PDE; +} // namespace NewOS diff --git a/Kernel/HALKit/AMD64/HalProcessor.cpp b/Kernel/HALKit/AMD64/HalProcessor.cpp new file mode 100644 index 00000000..31cee72c --- /dev/null +++ b/Kernel/HALKit/AMD64/HalProcessor.cpp @@ -0,0 +1,97 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +/** + * @file Processor.cpp + * @brief This file is about processor specific functions (in/out/cli/std...) + */ + +namespace NewOS::HAL +{ + void Out8(UInt16 port, UInt8 value) + { + asm volatile("outb %%al, %1" + : + : "a"(value), "Nd"(port) + : "memory"); + } + + void Out16(UInt16 port, UInt16 value) + { + asm volatile("outw %%ax, %1" + : + : "a"(value), "Nd"(port) + : "memory"); + } + + void Out32(UInt16 port, UInt32 value) + { + asm volatile("outl %%eax, %1" + : + : "a"(value), "Nd"(port) + : "memory"); + } + + UInt8 In8(UInt16 port) + { + UInt8 value = 0UL; + asm volatile("inb %1, %%al" + : "=a"(value) + : "Nd"(port) + : "memory"); + + return value; + } + + UInt16 In16(UInt16 port) + { + UInt16 value = 0UL; + asm volatile("inw %1, %%ax" + : "=a"(value) + : "Nd"(port) + : "memory"); + + return value; + } + + UInt32 In32(UInt16 port) + { + UInt32 value = 0UL; + asm volatile("inl %1, %%eax" + : "=a"(value) + : "Nd"(port) + : "memory"); + + return value; + } + + void rt_halt() + { + asm volatile("hlt"); + } + + void rt_cli() + { + asm volatile("cli"); + } + + void rt_sti() + { + asm volatile("sti"); + } + + void rt_cld() + { + asm volatile("cld"); + } + + void rt_std() + { + asm volatile("std"); + } +} // namespace NewOS::HAL diff --git a/Kernel/HALKit/AMD64/HalRoutines.s b/Kernel/HALKit/AMD64/HalRoutines.s new file mode 100644 index 00000000..e4944111 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalRoutines.s @@ -0,0 +1,12 @@ +.globl hal_load_idt +.globl hal_load_gdt +.globl rt_wait_400ns +.globl rt_get_current_context + +.section .text +rt_wait_400ns: + jmp .loop + .loop: + jmp .loop2 + .loop2: + ret diff --git a/Kernel/HALKit/AMD64/HalSMPCore.cxx b/Kernel/HALKit/AMD64/HalSMPCore.cxx new file mode 100644 index 00000000..a1310c4e --- /dev/null +++ b/Kernel/HALKit/AMD64/HalSMPCore.cxx @@ -0,0 +1,30 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +using namespace NewOS; +Void ProcessHeader::SetEntrypoint(UIntPtr& imageStart) noexcept +{ + if (imageStart == 0) + this->Crash(); + + this->StackFrame->Rbp = imageStart; + this->StackFrame->Rsp = this->StackFrame->Rbp; +} + +namespace NewOS +{ + bool rt_check_stack(HAL::StackFramePtr stackPtr) + { + if (!stackPtr) + return false; + if (stackPtr->Rbp == 0 || stackPtr->Rsp == 0) + return false; + + return true; + } +} // namespace NewOS diff --git a/Kernel/HALKit/AMD64/HalSMPCoreManager.asm b/Kernel/HALKit/AMD64/HalSMPCoreManager.asm new file mode 100644 index 00000000..18f80398 --- /dev/null +++ b/Kernel/HALKit/AMD64/HalSMPCoreManager.asm @@ -0,0 +1,26 @@ +;; /* +;; * ======================================================== +;; * +;; * NewOS +;; * Copyright SoftwareLabs, all rights reserved. +;; * +;; * ======================================================== +;; */ + +[bits 64] + +[global rt_get_current_context] +[global rt_do_context_switch] + +section .text + +;; writes to rdx the stackframe inside rcx. +;; rcx: Stack Pointer +;; rdx: SMP core address. +rt_do_context_switch: + + retfq + +;; gets the current stack frame. +rt_get_current_context: + retfq diff --git a/Kernel/HALKit/AMD64/Hypervisor.hpp b/Kernel/HALKit/AMD64/Hypervisor.hpp new file mode 100644 index 00000000..9beaae42 --- /dev/null +++ b/Kernel/HALKit/AMD64/Hypervisor.hpp @@ -0,0 +1,26 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +namespace NewOS +{ + MAKE_STRING_ENUM(HYPERVISOR) + ENUM_STRING(Qemu, "TCGTCGTCGTCG"); + ENUM_STRING(KVM, " KVMKVMKVM "); + ENUM_STRING(VMWare, "VMwareVMware"); + ENUM_STRING(VirtualBox, "VBoxVBoxVBox"); + ENUM_STRING(Xen, "XenVMMXenVMM"); + ENUM_STRING(Microsoft, "Microsoft Hv"); + ENUM_STRING(Parallels, " prl hyperv "); + ENUM_STRING(ParallelsAlt, " lrpepyh vr "); + ENUM_STRING(Bhyve, "bhyve bhyve "); + ENUM_STRING(Qnx, " QNXQVMBSQG "); + + END_STRING_ENUM() +} // namespace NewOS diff --git a/Kernel/HALKit/AMD64/MBCI/.gitkeep b/Kernel/HALKit/AMD64/MBCI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/AMD64/PCI/Database.cxx b/Kernel/HALKit/AMD64/PCI/Database.cxx new file mode 100644 index 00000000..1c2628d0 --- /dev/null +++ b/Kernel/HALKit/AMD64/PCI/Database.cxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ +} diff --git a/Kernel/HALKit/AMD64/PCI/Device.cxx b/Kernel/HALKit/AMD64/PCI/Device.cxx new file mode 100644 index 00000000..6f2265ae --- /dev/null +++ b/Kernel/HALKit/AMD64/PCI/Device.cxx @@ -0,0 +1,130 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +NewOS::UInt NewOSPCIReadRaw(NewOS::UInt bar, NewOS::UShort bus, NewOS::UShort dev, NewOS::UShort fun) +{ + NewOS::UInt target = 0x80000000 | ((NewOS::UInt)bus << 16) | + ((NewOS::UInt)dev << 11) | ((NewOS::UInt)fun << 8) | + (bar & 0xFC); + + NewOS::HAL::Out32((NewOS::UShort)NewOS::PCI::PciConfigKind::ConfigAddress, + target); + + return NewOS::HAL::In32((NewOS::UShort)NewOS::PCI::PciConfigKind::ConfigData); +} + +void NewOSPCISetCfgTarget(NewOS::UInt bar, NewOS::UShort bus, NewOS::UShort dev, NewOS::UShort fun) +{ + NewOS::UInt target = 0x80000000 | ((NewOS::UInt)bus << 16) | + ((NewOS::UInt)dev << 11) | ((NewOS::UInt)fun << 8) | + (bar & ~3); + + NewOS::HAL::Out32((NewOS::UShort)NewOS::PCI::PciConfigKind::ConfigAddress, + target); +} + +namespace NewOS::PCI +{ + Device::Device(UShort bus, UShort device, UShort func, UShort bar) + : fBus(bus), fDevice(device), fFunction(func), fBar(bar) + { + } + + Device::~Device() + { + } + + UInt Device::Read(UInt bar, Size sz) + { + NewOSPCISetCfgTarget(bar, fBus, fDevice, fFunction); + + if (sz == 4) + return HAL::In32((UShort)PciConfigKind::ConfigData + (fBar & 3)); + if (sz == 2) + return HAL::In16((UShort)PciConfigKind::ConfigData + (fBar & 3)); + if (sz == 1) + return HAL::In8((UShort)PciConfigKind::ConfigData + (fBar & 3)); + + return 0xFFFF; + } + + void Device::Write(UInt bar, UIntPtr data, Size sz) + { + NewOSPCISetCfgTarget(bar, fBus, fDevice, fFunction); + + if (sz == 4) + HAL::Out32((UShort)PciConfigKind::ConfigData + (fBar & 3), (UInt)data); + if (sz == 2) + HAL::Out16((UShort)PciConfigKind::ConfigData + (fBar & 3), (UShort)data); + if (sz == 1) + HAL::Out8((UShort)PciConfigKind::ConfigData + (fBar & 3), (UChar)data); + } + + UShort Device::DeviceId() + { + return (UShort)(NewOSPCIReadRaw(0x0 >> 16, fBus, fDevice, fFunction)); + } + + UShort Device::VendorId() + { + return (UShort)(NewOSPCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16); + } + + UShort Device::InterfaceId() + { + return (UShort)(NewOSPCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16); + } + + UChar Device::Class() + { + return (UChar)(NewOSPCIReadRaw(0x08, fBus, fDevice, fFunction) >> 24); + } + + UChar Device::Subclass() + { + return (UChar)(NewOSPCIReadRaw(0x08, fBus, fDevice, fFunction) >> 16); + } + + UChar Device::ProgIf() + { + return (UChar)(NewOSPCIReadRaw(0x08, fBus, fDevice, fFunction) >> 8); + } + + UChar Device::HeaderType() + { + return (UChar)(NewOSPCIReadRaw(0xC, fBus, fDevice, fFunction) >> 16); + } + + void Device::EnableMmio() + { + bool enable = Read(0x04, sizeof(UChar)) | (1 << 1); + Write(0x04, enable, sizeof(UShort)); + } + + void Device::BecomeBusMaster() + { + bool enable = Read(0x04, sizeof(UShort)) | (1 << 2); + Write(0x04, enable, sizeof(UShort)); + } + + UShort Device::Vendor() + { + UShort vendor = VendorId(); + + if (vendor != (UShort)PciConfigKind::Invalid) + fDevice = (UShort)Read(0x0, sizeof(UShort)); + + return fDevice; + } + + Device::operator bool() + { + return VendorId() != (UShort)PciConfigKind::Invalid; + } +} // namespace NewOS::PCI diff --git a/Kernel/HALKit/AMD64/PCI/Dma.cxx b/Kernel/HALKit/AMD64/PCI/Dma.cxx new file mode 100644 index 00000000..aacbafd8 --- /dev/null +++ b/Kernel/HALKit/AMD64/PCI/Dma.cxx @@ -0,0 +1,82 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + DMAWrapper::operator bool() + { + return fAddress; + } + + bool DMAWrapper::operator!() + { + return !fAddress; + } + + Boolean DMAWrapper::Check(UIntPtr offset) const + { + if (!fAddress) + return false; + if (offset == 0) + return true; + + kcout << "[DMAWrapper::IsIn] Checking offset..\n"; + return reinterpret_cast(fAddress) >= offset; + } + + bool DMAWrapper::Write(const UIntPtr& bit, const UIntPtr& offset) + { + if (!fAddress) + return false; + + kcout << "[DMAWrapper::Write] Writing at address..\n"; + + auto addr = + (volatile UIntPtr*)(reinterpret_cast(fAddress) + offset); + *addr = bit; + + return true; + } + + UIntPtr DMAWrapper::Read(const UIntPtr& offset) + { + kcout << "[DMAWrapper::Read] checking fAddress..\n"; + if (!fAddress) + return 0; + + kcout << "[DMAWrapper::Read] Reading fAddress..\n"; + return *(volatile UIntPtr*)(reinterpret_cast(fAddress) + offset); + ; + } + + UIntPtr DMAWrapper::operator[](const UIntPtr& offset) + { + return this->Read(offset); + } + + OwnPtr> DMAFactory::Construct(OwnPtr& dma) + { + if (!dma) + return {}; + + OwnPtr> dmaOwnPtr = + make_ptr, char*>(reinterpret_cast(dma->fAddress)); + + if (!dmaOwnPtr) + return {}; + + kcout << "Returning the new OwnPtr>!\r"; + return dmaOwnPtr; + } + + DMAWrapper& DMAWrapper::operator=(voidPtr Ptr) + { + fAddress = Ptr; + return *this; + } +} // namespace NewOS diff --git a/Kernel/HALKit/AMD64/PCI/Express.cxx b/Kernel/HALKit/AMD64/PCI/Express.cxx new file mode 100644 index 00000000..4fde7ca2 --- /dev/null +++ b/Kernel/HALKit/AMD64/PCI/Express.cxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ +} diff --git a/Kernel/HALKit/AMD64/PCI/IO.cxx b/Kernel/HALKit/AMD64/PCI/IO.cxx new file mode 100644 index 00000000..4bd4db4f --- /dev/null +++ b/Kernel/HALKit/AMD64/PCI/IO.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/HALKit/AMD64/PCI/Iterator.cxx b/Kernel/HALKit/AMD64/PCI/Iterator.cxx new file mode 100644 index 00000000..e1af15ad --- /dev/null +++ b/Kernel/HALKit/AMD64/PCI/Iterator.cxx @@ -0,0 +1,44 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +#define PCI_ITERATOR_FIND_AND_UNWRAP(DEV, SZ) \ + if (DEV.Leak()) \ + return DEV.Leak(); + +namespace NewOS::PCI +{ + Iterator::Iterator(const Types::PciDeviceKind& type) + { + // probe devices. + for (int bus = 0; bus < NEWOS_BUS_COUNT; ++bus) + { + for (int device = 0; device < NEWOS_DEVICE_COUNT; ++device) + { + for (int function = 0; function < NEWOS_FUNCTION_COUNT; ++function) + { + Device dev(bus, device, function, 0); + + if (dev.Class() == (UChar)type) + { + fDevices[bus].Leak().Leak() = dev; + } + } + } + } + } + + Iterator::~Iterator() + { + } + + Ref Iterator::operator[](const Size& sz) + { + PCI_ITERATOR_FIND_AND_UNWRAP(fDevices[sz], sz); + return {}; + } +} // namespace NewOS::PCI diff --git a/Kernel/HALKit/AMD64/PCI/PCI.cxx b/Kernel/HALKit/AMD64/PCI/PCI.cxx new file mode 100644 index 00000000..71644f17 --- /dev/null +++ b/Kernel/HALKit/AMD64/PCI/PCI.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/HALKit/AMD64/Processor.hpp b/Kernel/HALKit/AMD64/Processor.hpp new file mode 100644 index 00000000..69dc1acb --- /dev/null +++ b/Kernel/HALKit/AMD64/Processor.hpp @@ -0,0 +1,212 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Prcoessor.hxx + Purpose: AMD64 processor abstraction. + + Revision History: + + 30/01/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +#ifdef kCPUBackendName +#undef kCPUBackendName +#endif // ifdef kCPUBackendName + +#define kCPUBackendName "AMD64" + +#define IsActiveLow(FLG) (FLG & 2) +#define IsLevelTriggered(FLG) (FLG & 8) + +#define kInterruptGate (0x8E) +#define kTrapGate (0xEF) +#define kTaskGate (0b10001100) +#define kGdtCodeSelector (0x08) +#define kVirtualAddressStartOffset (0x10000000) + +namespace NewOS +{ + namespace Detail::AMD64 + { + struct PACKED InterruptDescriptorAMD64 final + { + UInt16 OffsetLow; // offset bits 0..15 + UInt16 Selector; // a code segment selector in GDT or LDT + UInt8 + Ist; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero. + UInt8 TypeAttributes; // gate type, dpl, and p fields + UInt16 OffsetMid; // offset bits 16..31 + UInt32 OffsetHigh; // offset bits 32..63 + UInt32 Zero; // reserved + }; + } // namespace Detail::AMD64 +} // namespace NewOS + +namespace NewOS::HAL +{ + EXTERN_C UChar In8(UInt16 port); + EXTERN_C UShort In16(UInt16 port); + EXTERN_C UInt In32(UInt16 port); + + EXTERN_C void Out16(UShort port, UShort byte); + EXTERN_C void Out8(UShort port, UChar byte); + EXTERN_C void Out32(UShort port, UInt byte); + + EXTERN_C void rt_wait_400ns(); + EXTERN_C void rt_halt(); + EXTERN_C void rt_cli(); + EXTERN_C void rt_sti(); + EXTERN_C void rt_cld(); + EXTERN_C void rt_std(); + + struct PACKED Register64 final + { + UShort Limit; + UIntPtr Base; + }; + + struct PACKED RegisterGDT final + { + UShort Limit; + UIntPtr Base; + }; + + using RawRegister = UInt64; + + using InterruptId = UShort; /* For each element in the IVT */ + using interruptTrap = UIntPtr(UIntPtr sp); + + typedef UIntPtr Reg; + + struct PACKED StackFrame final + { + Reg IntNum, Exception; + Reg Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; + Reg R8, R9, R10, R11, R12, R13, R14, R15; + Reg Gs, Fs; + }; + + typedef StackFrame* StackFramePtr; + + class InterruptDescriptor final + { + public: + UShort Offset; + UShort Selector; + UChar Ist; + UChar Atrributes; + + UShort SecondOffset; + UInt ThirdOffset; + UInt Zero; + + operator bool() + { + return Offset != 0xFFFF; + } + }; + + using InterruptDescriptorArray = Array; + + class SegmentDescriptor final + { + public: + UInt16 Base; + UInt8 BaseMiddle; + UInt8 BaseHigh; + + UShort Limit; + UChar Gran; + UChar AccessByte; + }; + + /*** + * @brief Segment Boolean operations + */ + class SegmentDescriptorComparator final + { + public: + bool IsValid(SegmentDescriptor& seg) + { + return seg.Base > seg.Limit; + } + bool Equals(SegmentDescriptor& seg, SegmentDescriptor& segRight) + { + return seg.Base == segRight.Base && seg.Limit == segRight.Limit; + } + }; + + using SegmentArray = Array; + + class GDTLoader final + { + public: + static void Load(RegisterGDT& gdt); + static void Load(Ref& gdt); + }; + + class IDTLoader final + { + public: + static void Load(Register64& idt); + static void Load(Ref& idt); + }; + + Void hal_system_get_cores(VoidPtr rsdPtr); + + /// @brief Processor specific structures. + namespace Detail + { + EXTERN_C void _ke_power_on_self_test(void); + + /** + @brief Global descriptor table entry, either null, code or data. +*/ + + struct PACKED NewOSGDTRecord final + { + UInt16 Limit0; + UInt16 Base0; + UInt8 Base1; + UInt8 AccessByte; + UInt8 Limit1_Flags; + UInt8 Base2; + }; + + struct PACKED ALIGN(0x1000) NewOSGDT final + { + NewOSGDTRecord Null; + NewOSGDTRecord KernCode; + NewOSGDTRecord KernData; + NewOSGDTRecord UserNull; + NewOSGDTRecord UserCode; + NewOSGDTRecord UserData; + }; + } // namespace Detail +} // namespace NewOS::HAL + +EXTERN_C void idt_handle_generic(NewOS::UIntPtr rsp); +EXTERN_C void idt_handle_gpf(NewOS::UIntPtr rsp); +EXTERN_C void idt_handle_math(NewOS::UIntPtr rsp); +EXTERN_C void idt_handle_pf(NewOS::UIntPtr rsp); + +EXTERN_C void hal_load_idt(NewOS::HAL::Register64 ptr); +EXTERN_C void hal_load_gdt(NewOS::HAL::RegisterGDT ptr); + +/// @brief Maximum size of the IDT. +#define kKernelIdtSize 0x100 +#define kKernelInterruptId 0x32 + +inline NewOS::VoidPtr kKernelVirtualStart = (NewOS::VoidPtr)kVirtualAddressStartOffset; +inline NewOS::UIntPtr kKernelVirtualSize = 0UL; + +inline NewOS::VoidPtr kKernelPhysicalStart = nullptr; diff --git a/Kernel/HALKit/AMD64/Storage/AHCI.cxx b/Kernel/HALKit/AMD64/Storage/AHCI.cxx new file mode 100644 index 00000000..109d9cb9 --- /dev/null +++ b/Kernel/HALKit/AMD64/Storage/AHCI.cxx @@ -0,0 +1,67 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/** + * @file AHCI.cxx + * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com) + * @brief AHCI driver. + * @version 0.1 + * @date 2024-02-02 + * + * @copyright Copyright (c) SoftwareLabs + * + */ + +#include +#include + +#ifdef __AHCI__ +enum +{ + kSATAProgIfAHCI = 0x01, + kSATASubClass = 0x06 +}; + +static NewOS::PCI::Device kAhciDevice; + +/// @brief Initializes an AHCI disk. +/// @param PortsImplemented the amount of port that have been detected. +/// @return +NewOS::Boolean drv_std_init(NewOS::UInt16& PortsImplemented) +{ + using namespace NewOS; + + PCI::Iterator iterator(Types::PciDeviceKind::MassStorageController); + for (SizeT devIndex = 0; devIndex < NEWOS_BUS_COUNT; ++devIndex) + { + if (iterator[devIndex].Leak().Subclass() == kSATASubClass && + iterator[devIndex].Leak().ProgIf() == kSATAProgIfAHCI) + { + iterator[devIndex].Leak().EnableMmio(); /// enable the memory i/o for this ahci device. + kAhciDevice = iterator[devIndex].Leak(); /// and then leak the reference. + + kcout << "New Kernel: [PCI] Found AHCI controller.\r"; + + return true; + } + } + + return false; +} + +NewOS::Boolean drv_std_detected(NewOS::Void) +{ + return kAhciDevice.DeviceId() != 0xFFFF; +} + +NewOS::Void drv_std_read(NewOS::UInt64 Lba, NewOS::Char* Buf, NewOS::SizeT SectorSz, NewOS::SizeT Size) +{ +} + +NewOS::Void drv_std_write(NewOS::UInt64 Lba, NewOS::Char* Buf, NewOS::SizeT SectorSz, NewOS::SizeT Size) +{ +} +#endif // __AHCI__ diff --git a/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx b/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx new file mode 100644 index 00000000..97812bd8 --- /dev/null +++ b/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx @@ -0,0 +1,38 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/** + * @file ATA-DMA.cxx + * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com) + * @brief ATA driver (DMA mode). + * @version 0.1 + * @date 2024-02-02 + * + * @copyright Copyright (c) SoftwareLabs + * + */ + +#include + +#include +#include + +using namespace NewOS; + +EXTERN_C Int32 kPRDTTransferStatus; +STATIC PRDT kPRDT; + +#ifdef __ATA_DMA__ + +#ifdef __ATA_PIO__ +#error You cant have both PIO and DMA enabled! +#endif /* ifdef __ATA_PIO__ */ + +#ifdef __AHCI__ +#error You cant have both ATA and AHCI enabled! +#endif /* ifdef __AHCI__ */ + +#endif /* ifdef __ATA_DMA__ */ diff --git a/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx b/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx new file mode 100644 index 00000000..d09d9a67 --- /dev/null +++ b/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx @@ -0,0 +1,192 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/** + * @file ATA-PIO.cxx + * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com) + * @brief ATA driver (PIO mode). + * @version 0.1 + * @date 2024-02-02 + * + * @copyright Copyright (c) SoftwareLabs + * + */ + +#include +#include + +#ifdef __ATA_PIO__ + +using namespace NewOS; +using namespace NewOS::HAL; + +/// bugs: 0 + +#define kATADataLen 256 + +static Boolean kATADetected = false; +static Int32 kATADeviceType = kATADeviceCount; +static Char kATAData[kATADataLen] = {0}; + +Boolean drv_std_wait_io(UInt16 IO) +{ + for (int i = 0; i < 4; i++) + In8(IO + ATA_REG_STATUS); + +ATAWaitForIO_Retry: + auto statRdy = In8(IO + ATA_REG_STATUS); + + if ((statRdy & ATA_SR_BSY)) + goto ATAWaitForIO_Retry; + +ATAWaitForIO_Retry2: + statRdy = In8(IO + ATA_REG_STATUS); + + if (statRdy & ATA_SR_ERR) + return false; + + if (!(statRdy & ATA_SR_DRDY)) + goto ATAWaitForIO_Retry2; + + return true; +} + +Void drv_std_select(UInt16 Bus) +{ + if (Bus == ATA_PRIMARY_IO) + Out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL); + else + Out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL); +} + +Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) +{ + if (drv_std_detected()) + return true; + + UInt16 IO = Bus; + + drv_std_select(IO); + + // Bus init, NEIN bit. + Out8(IO + ATA_REG_NEIN, 1); + + // identify until it's good. +ATAInit_Retry: + auto statRdy = In8(IO + ATA_REG_STATUS); + + if (statRdy & ATA_SR_ERR) + { + return false; + } + + if ((statRdy & ATA_SR_BSY)) + goto ATAInit_Retry; + + Out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + + /// fetch serial info + /// model, speed, number of sectors... + + drv_std_wait_io(IO); + + for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData) + { + kATAData[indexData] = In16(IO + ATA_REG_DATA); + } + + OutBus = (Bus == ATA_PRIMARY_IO) ? ATA_PRIMARY_IO : ATA_SECONDARY_IO; + + OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE; + + return true; +} + +Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size) +{ + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + + Lba /= SectorSz; + + drv_std_wait_io(IO); + drv_std_select(IO); + + Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + + /// Compute sector count. + Out8(IO + ATA_REG_SEC_COUNT0, SectorSz / (SectorSz / 2)); + + Out8(IO + ATA_REG_LBA0, (Lba)); + Out8(IO + ATA_REG_LBA1, (Lba) >> 8); + Out8(IO + ATA_REG_LBA2, (Lba) >> 16); + + Out8(IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO); + + drv_std_wait_io(IO); + + for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) + { + drv_std_wait_io(IO); + Buf[IndexOff] = In16(IO + ATA_REG_DATA); + drv_std_wait_io(IO); + } + + drv_std_wait_io(IO); +} + +Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size) +{ + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + + Lba /= SectorSz; + + drv_std_wait_io(IO); + drv_std_select(IO); + + /// Compute sector count. + Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + + Out8(IO + ATA_REG_SEC_COUNT0, SectorSz / (SectorSz / 2)); + + Out8(IO + ATA_REG_LBA0, (Lba)); + Out8(IO + ATA_REG_LBA1, (Lba) >> 8); + Out8(IO + ATA_REG_LBA2, (Lba) >> 16); + + Out8(IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); + + drv_std_wait_io(IO); + + for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) + { + drv_std_wait_io(IO); + Out16(IO + ATA_REG_DATA, Buf[IndexOff]); + drv_std_wait_io(IO); + } + + drv_std_wait_io(IO); +} + +/// @brief is ATA detected? +Boolean drv_std_detected(Void) +{ + return kATADetected; +} + +/*** + @brief Getter, gets the number of sectors inside the drive. +*/ +NewOS::SizeT drv_std_get_sector_count() +{ + return (kATAData[61] << 16) | kATAData[60]; +} + +/// @brief Get the drive size. +NewOS::SizeT drv_std_get_drv_size() +{ + return drv_std_get_sector_count() * kATASectorSize; +} + +#endif /* ifdef __ATA_PIO__ */ diff --git a/Kernel/HALKit/ARM64/.gitkeep b/Kernel/HALKit/ARM64/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/ARM64/ACPI/.gitkeep b/Kernel/HALKit/ARM64/ACPI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/ARM64/Storage/.gitkeep b/Kernel/HALKit/ARM64/Storage/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/AXP/CR.s b/Kernel/HALKit/AXP/CR.s new file mode 100644 index 00000000..4d68257d --- /dev/null +++ b/Kernel/HALKit/AXP/CR.s @@ -0,0 +1,11 @@ +.globl read_lr1 +.globl read_lr0 + +.section .text + read_lr0: + movq %r30, %cr3 + ret + + hal_read_cr0: + movq %r30, %cr0 + ret \ No newline at end of file diff --git a/Kernel/HALKit/AXP/CoreInterruptHandlerDEC.cpp b/Kernel/HALKit/AXP/CoreInterruptHandlerDEC.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/AXP/CoreSyscallHandlerDEC.cpp b/Kernel/HALKit/AXP/CoreSyscallHandlerDEC.cpp new file mode 100644 index 00000000..c6ef29fc --- /dev/null +++ b/Kernel/HALKit/AXP/CoreSyscallHandlerDEC.cpp @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +NewOS::Array + kSyscalls; + +extern "C" void rt_syscall_handle(NewOS::HAL::StackFrame* stack) +{ + for (NewOS::SizeT index = 0UL; index < kKernelMaxSystemCalls; ++index) + { + (kSyscalls[index].Leak().Leak())(stack->ID, stack); + } +} diff --git a/Kernel/HALKit/AXP/HAL.s b/Kernel/HALKit/AXP/HAL.s new file mode 100644 index 00000000..0178527f --- /dev/null +++ b/Kernel/HALKit/AXP/HAL.s @@ -0,0 +1,13 @@ +.globl rt_wait_400ns + +.section .text +rt_wait_400ns: + jmp .L +.L: + jmp .L2 + wtint ;; wait for interrupt +.L2: + + ret + + diff --git a/Kernel/HALKit/AXP/Processor.hpp b/Kernel/HALKit/AXP/Processor.hpp new file mode 100644 index 00000000..38277317 --- /dev/null +++ b/Kernel/HALKit/AXP/Processor.hpp @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once \ No newline at end of file diff --git a/Kernel/HALKit/AXP/README b/Kernel/HALKit/AXP/README new file mode 100644 index 00000000..91e7b134 --- /dev/null +++ b/Kernel/HALKit/AXP/README @@ -0,0 +1 @@ +This is for DEC Alpha. diff --git a/Kernel/HALKit/AXP/README.TXT b/Kernel/HALKit/AXP/README.TXT new file mode 100644 index 00000000..03c2b816 --- /dev/null +++ b/Kernel/HALKit/AXP/README.TXT @@ -0,0 +1 @@ +A Toy HAL to test the Kernel portability. diff --git a/Kernel/HALKit/AXP/SYSCALL.s b/Kernel/HALKit/AXP/SYSCALL.s new file mode 100644 index 00000000..19cab808 --- /dev/null +++ b/Kernel/HALKit/AXP/SYSCALL.s @@ -0,0 +1,10 @@ +.section .text +system_handle_user_call: + .cfi_startproc + + push %r0 + jmp %r1 + mov %r30, %r2 + + .cfi_endproc + retsys \ No newline at end of file diff --git a/Kernel/HALKit/AXP/VM.s b/Kernel/HALKit/AXP/VM.s new file mode 100644 index 00000000..7024086b --- /dev/null +++ b/Kernel/HALKit/AXP/VM.s @@ -0,0 +1,5 @@ +.global hal_flush_tlb + +.section .text +hal_flush_tlb: + swppal \ No newline at end of file diff --git a/Kernel/HALKit/POWER/.gitkeep b/Kernel/HALKit/POWER/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/POWER/APM/.gitkeep b/Kernel/HALKit/POWER/APM/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/POWER/HalContextSwitchPowerPC.s b/Kernel/HALKit/POWER/HalContextSwitchPowerPC.s new file mode 100644 index 00000000..64558ae1 --- /dev/null +++ b/Kernel/HALKit/POWER/HalContextSwitchPowerPC.s @@ -0,0 +1,28 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +.align 4 +.type name, @function +.text +.globl rt_do_context_switch + +/* r3 (3) = assigner stack, r4 (4) = assignee stack */ +rt_do_context_switch: + lwz 0(%4), 0(%3) + lwz 4(%4), 4(%3) + lwz 8(%4), 8(%3) + lwz 12(%4), 12(%3) + lwz 14(%4), 14(%3) + lwz 18(%4), 18(%3) + lwz 22(%4), 22(%3) + lwz 24(%4), 24(%3) + lwz 28(%4), 28(%3) + lwz 32(%4), 32(%3) + lwz 34(%4), 34(%3) + lwz 38(%4), 38(%3) + + /* we are done here, the assignee should start executing code now. */ + blr diff --git a/Kernel/HALKit/POWER/HalHardware.cxx b/Kernel/HALKit/POWER/HalHardware.cxx new file mode 100644 index 00000000..f2292965 --- /dev/null +++ b/Kernel/HALKit/POWER/HalHardware.cxx @@ -0,0 +1,19 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +namespace NewOS +{ + namespace HAL + { + UIntPtr hal_alloc_page(bool rw, bool user) + { + return 0; + } + } // namespace HAL +} // namespace NewOS diff --git a/Kernel/HALKit/POWER/HalHart.cxx b/Kernel/HALKit/POWER/HalHart.cxx new file mode 100644 index 00000000..960f0a62 --- /dev/null +++ b/Kernel/HALKit/POWER/HalHart.cxx @@ -0,0 +1,25 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +using namespace NewOS; + +/// @brief wakes up thread. +/// wakes up thread from hang. +void rt_wakeup_thread(HAL::StackFramePtr stack) +{ + NEWOS_UNUSED(stack); +} + +/// @brief makes thread sleep. +/// hooks and hangs thread to prevent code from executing. +void rt_hang_thread(HAL::StackFramePtr stack) +{ + NEWOS_UNUSED(stack); +} diff --git a/Kernel/HALKit/POWER/HalSerialPort.cxx b/Kernel/HALKit/POWER/HalSerialPort.cxx new file mode 100644 index 00000000..c2c75eef --- /dev/null +++ b/Kernel/HALKit/POWER/HalSerialPort.cxx @@ -0,0 +1,27 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +using namespace NewOS; + +/// @brief Writes to COM1. +/// @param bytes +void ke_io_write(const Char* bytes) +{ + if (!bytes) + return; + + SizeT index = 0; + SizeT len = rt_string_len(bytes, 256); + + while (index < len) + { + // TODO + ++index; + } +} diff --git a/Kernel/HALKit/POWER/HalStartSequence.s b/Kernel/HALKit/POWER/HalStartSequence.s new file mode 100644 index 00000000..fc969e9f --- /dev/null +++ b/Kernel/HALKit/POWER/HalStartSequence.s @@ -0,0 +1,14 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +.globl __ImageStart +.extern hal_init_platform +.align 4 +.text + +__ImageStart: + bl hal_init_platform + blr diff --git a/Kernel/HALKit/POWER/HalThread.cxx b/Kernel/HALKit/POWER/HalThread.cxx new file mode 100644 index 00000000..4f4eaec6 --- /dev/null +++ b/Kernel/HALKit/POWER/HalThread.cxx @@ -0,0 +1,13 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +EXTERN_C NewOS::HAL::StackFramePtr rt_get_current_context() +{ + return nullptr; +} diff --git a/Kernel/HALKit/POWER/HalVirtualMemory.cxx b/Kernel/HALKit/POWER/HalVirtualMemory.cxx new file mode 100644 index 00000000..c77c5b4d --- /dev/null +++ b/Kernel/HALKit/POWER/HalVirtualMemory.cxx @@ -0,0 +1,54 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +#include +#include + +/// @note refer to our SoC documentation. + +using namespace NewOS; + +/// @brief Write directly to the specific TLB. +/// @param mas0 +/// @param mas1 +/// @param mas2 +/// @param mas3 +/// @param mas7 +static void hal_write_tlb(uint32_t mas0, uint32_t mas1, uint32_t mas2, uint32_t mas3, uint32_t mas7) +{ + mtspr(MAS0, mas0); + mtspr(MAS1, mas1); + mtspr(MAS2, mas2); + mtspr(MAS3, mas3); + mtspr(MAS7, mas7); + + hal_flush_tlb(); +} + +void hal_set_tlb(uint8_t tlb, uint32_t epn, uint64_t rpn, uint8_t perms, uint8_t wimge, uint8_t ts, uint8_t esel, uint8_t tsize, uint8_t iprot) +{ + if ((mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1 && (tsize & 1)) + { + // this mmu-version does not allow odd tsize values + return; + } + uint32_t mas0 = FSL_BOOKE_MAS0(tlb, esel, 0); + uint32_t mas1 = FSL_BOOKE_MAS1(1, iprot, 0, ts, tsize); + uint32_t mas2 = FSL_BOOKE_MAS2(epn, wimge); + uint32_t mas3 = FSL_BOOKE_MAS3(rpn, 0, perms); + uint32_t mas7 = FSL_BOOKE_MAS7(rpn); + + hal_write_tlb(mas0, mas1, mas2, mas3, mas7); +} + +/// @brief Flush system TLB. +EXTERN_C void hal_flush_tlb() +{ + asm volatile("isync;tlbwe;msync;isync"); +} diff --git a/Kernel/HALKit/POWER/Hart.hxx b/Kernel/HALKit/POWER/Hart.hxx new file mode 100644 index 00000000..e26e0e39 --- /dev/null +++ b/Kernel/HALKit/POWER/Hart.hxx @@ -0,0 +1,28 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Hart.hxx + Purpose: POWER hardware threads. + + Revision History: + + 14/04/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +#include + +/// @brief hardware thread indentification type. +typedef NewOS::Int32 PPCHartType; + +/// @brief Hardware thread information structure. +typedef struct HalHardwareThread +{ + NewOS::UIntPtr fStartAddress; + NewOS::UInt8 fPrivleged : 1; + NewOS::UInt32 fPageFlags; + PPCHartType fIdentNumber; +} HalHardwareThread; diff --git a/Kernel/HALKit/POWER/MBCI/.gitkeep b/Kernel/HALKit/POWER/MBCI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/POWER/MBCI/HalMBCIHost.cxx b/Kernel/HALKit/POWER/MBCI/HalMBCIHost.cxx new file mode 100644 index 00000000..af0ac523 --- /dev/null +++ b/Kernel/HALKit/POWER/MBCI/HalMBCIHost.cxx @@ -0,0 +1,8 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include diff --git a/Kernel/HALKit/POWER/Processor.hpp b/Kernel/HALKit/POWER/Processor.hpp new file mode 100644 index 00000000..dd2d98f4 --- /dev/null +++ b/Kernel/HALKit/POWER/Processor.hpp @@ -0,0 +1,55 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + Purpose: POWER processor header. + +------------------------------------------- */ + +#pragma once + +#include +#include + +#define kHalPPCAlignment __attribute__((aligned(4))) + +namespace NewOS::HAL +{ + typedef UIntPtr Reg; + + struct kHalPPCAlignment StackFrame + { + Reg R0; + Reg R1; + Reg R2; + Reg R3; + Reg R4; + Reg R5; + Reg R6; + Reg R7; + Reg R8; + Reg PC; + Reg SP; + }; + + typedef StackFrame* StackFramePtr; + + inline void rt_halt() + { + while (1) + { + asm volatile("mr 0, 0"); // no oop. + } + } + + inline void rt_cli() + { + asm volatile("mr 0, 0"); // no oop + } +} // namespace NewOS::HAL + +EXTERN_C void int_handle_math(NewOS::UIntPtr sp); +EXTERN_C void int_handle_pf(NewOS::UIntPtr sp); + +/// @brief Flush system TLB. +EXTERN_C void hal_flush_tlb(); diff --git a/Kernel/HALKit/POWER/ppc-cpu.h b/Kernel/HALKit/POWER/ppc-cpu.h new file mode 100644 index 00000000..b7a96767 --- /dev/null +++ b/Kernel/HALKit/POWER/ppc-cpu.h @@ -0,0 +1,1424 @@ +#ifndef __ASM_PPC_PROCESSOR_H +#define __ASM_PPC_PROCESSOR_H + +/// ! @note The NeWS cpu is based on the e500 with 64-bit extensions, much like the 970. + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ __label__ _l; _l: &&_l; }) + +#define AAA_HACK_DISABLE +#ifdef AAA_HACK_DISABLE +/* warning this is just to make the compiler shut up.. It does not + match the definition in ptrace.h. So dont use this code. */ +struct pt_regs +{ + unsigned long nip; +}; + +#else +#include +#include +#endif + +/* Machine State Register (MSR) Fields */ + +#ifdef CONFIG_PPC64BRIDGE +#define MSR_SF (1 << 63) +#define MSR_ISF (1 << 61) +#endif /* CONFIG_PPC64BRIDGE */ +#define MSR_UCLE (1 << 26) /* User-mode cache lock enable (e500) */ +#define MSR_VEC (1 << 25) /* Enable AltiVec(74xx) */ +#define MSR_SPE (1 << 25) /* Enable SPE(e500) */ +#define MSR_POW (1 << 18) /* Enable Power Management */ +#define MSR_WE (1 << 18) /* Wait State Enable */ +#define MSR_TGPR (1 << 17) /* TLB Update registers in use */ +#define MSR_CE (1 << 17) /* Critical Interrupt Enable */ +#define MSR_ILE (1 << 16) /* Interrupt Little Endian */ +#define MSR_EE (1 << 15) /* External Interrupt Enable */ +#define MSR_PR (1 << 14) /* Problem State / Privilege Level */ +#define MSR_FP (1 << 13) /* Floating Point enable */ +#define MSR_ME (1 << 12) /* Machine Check Enable */ +#define MSR_FE0 (1 << 11) /* Floating Exception mode 0 */ +#define MSR_SE (1 << 10) /* Single Step */ +#define MSR_DWE (1 << 10) /* Debug Wait Enable (4xx) */ +#define MSR_UBLE (1 << 10) /* BTB lock enable (e500) */ +#define MSR_BE (1 << 9) /* Branch Trace */ +#define MSR_DE (1 << 9) /* Debug Exception Enable */ +#define MSR_FE1 (1 << 8) /* Floating Exception mode 1 */ +#define MSR_IP (1 << 6) /* Exception prefix 0x000/0xFFF */ +#define MSR_IR (1 << 5) /* Instruction Relocate */ +#define MSR_IS (1 << 5) /* Book E Instruction space */ +#define MSR_DR (1 << 4) /* Data Relocate */ +#define MSR_DS (1 << 4) /* Book E Data space */ +#define MSR_PE (1 << 3) /* Protection Enable */ +#define MSR_PX (1 << 2) /* Protection Exclusive Mode */ +#define MSR_PMM (1 << 2) /* Performance monitor mark bit (e500) */ +#define MSR_RI (1 << 1) /* Recoverable Exception */ +#define MSR_LE (1 << 0) /* Little Endian */ + +#ifdef CONFIG_APUS_FAST_EXCEPT +#define MSR_ MSR_ME | MSR_IP | MSR_RI +#else +#define MSR_ MSR_ME | MSR_RI +#endif +#ifndef CONFIG_E500 +#define MSR_KERNEL MSR_ | MSR_IR | MSR_DR +#else +#define MSR_KERNEL MSR_ME +#endif + +/* Floating Point Status and Control Register (FPSCR) Fields */ + +#define FPSCR_FX 0x80000000 /* FPU exception summary */ +#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */ +#define FPSCR_VX 0x20000000 /* Invalid operation summary */ +#define FPSCR_OX 0x10000000 /* Overflow exception summary */ +#define FPSCR_UX 0x08000000 /* Underflow exception summary */ +#define FPSCR_ZX 0x04000000 /* Zero-devide exception summary */ +#define FPSCR_XX 0x02000000 /* Inexact exception summary */ +#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */ +#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */ +#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */ +#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */ +#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */ +#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */ +#define FPSCR_FR 0x00040000 /* Fraction rounded */ +#define FPSCR_FI 0x00020000 /* Fraction inexact */ +#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */ +#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */ +#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */ +#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */ +#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */ +#define FPSCR_VE 0x00000080 /* Invalid op exception enable */ +#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */ +#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */ +#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */ +#define FPSCR_XE 0x00000008 /* FP inexact exception enable */ +#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */ +#define FPSCR_RN 0x00000003 /* FPU rounding control */ + +/* Special Purpose Registers (SPRNs)*/ + +/* PPC440 Architecture is BOOK-E */ +#ifdef CONFIG_440 +#define CONFIG_BOOKE +#endif + +#define SPRN_CCR0 0x3B3 /* Core Configuration Register 0 */ +#ifdef CONFIG_BOOKE +#define SPRN_CCR1 0x378 /* Core Configuration Register for 440 only */ +#endif +#define SPRN_CDBCR 0x3D7 /* Cache Debug Control Register */ +#define SPRN_CTR 0x009 /* Count Register */ +#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */ +#ifndef CONFIG_BOOKE +#define SPRN_DAC1 0x3F6 /* Data Address Compare 1 */ +#define SPRN_DAC2 0x3F7 /* Data Address Compare 2 */ +#else +#define SPRN_DAC1 0x13C /* Book E Data Address Compare 1 */ +#define SPRN_DAC2 0x13D /* Book E Data Address Compare 2 */ +#endif /* CONFIG_BOOKE */ +#define SPRN_DAR 0x013 /* Data Address Register */ +#define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */ +#define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */ +#define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */ +#define SPRN_DBAT1U 0x21A /* Data BAT 1 Upper Register */ +#define SPRN_DBAT2L 0x21D /* Data BAT 2 Lower Register */ +#define SPRN_DBAT2U 0x21C /* Data BAT 2 Upper Register */ +#define SPRN_DBAT3L 0x21F /* Data BAT 3 Lower Register */ +#define SPRN_DBAT3U 0x21E /* Data BAT 3 Upper Register */ +#define SPRN_DBAT4L 0x239 /* Data BAT 4 Lower Register */ +#define SPRN_DBAT4U 0x238 /* Data BAT 4 Upper Register */ +#define SPRN_DBAT5L 0x23B /* Data BAT 5 Lower Register */ +#define SPRN_DBAT5U 0x23A /* Data BAT 5 Upper Register */ +#define SPRN_DBAT6L 0x23D /* Data BAT 6 Lower Register */ +#define SPRN_DBAT6U 0x23C /* Data BAT 6 Upper Register */ +#define SPRN_DBAT7L 0x23F /* Data BAT 7 Lower Register */ +#define SPRN_DBAT7U 0x23E /* Data BAT 7 Lower Register */ +#define SPRN_DBCR 0x3F2 /* Debug Control Regsiter */ +#define DBCR_EDM 0x80000000 +#define DBCR_IDM 0x40000000 +#define DBCR_RST(x) (((x)&0x3) << 28) +#define DBCR_RST_NONE 0 +#define DBCR_RST_CORE 1 +#define DBCR_RST_CHIP 2 +#define DBCR_RST_SYSTEM 3 +#define DBCR_IC 0x08000000 /* Instruction Completion Debug Evnt */ +#define DBCR_BT 0x04000000 /* Branch Taken Debug Event */ +#define DBCR_EDE 0x02000000 /* Exception Debug Event */ +#define DBCR_TDE 0x01000000 /* TRAP Debug Event */ +#define DBCR_FER 0x00F80000 /* First Events Remaining Mask */ +#define DBCR_FT 0x00040000 /* Freeze Timers on Debug Event */ +#define DBCR_IA1 0x00020000 /* Instr. Addr. Compare 1 Enable */ +#define DBCR_IA2 0x00010000 /* Instr. Addr. Compare 2 Enable */ +#define DBCR_D1R 0x00008000 /* Data Addr. Compare 1 Read Enable */ +#define DBCR_D1W 0x00004000 /* Data Addr. Compare 1 Write Enable */ +#define DBCR_D1S(x) (((x)&0x3) << 12) /* Data Adrr. Compare 1 Size */ +#define DAC_BYTE 0 +#define DAC_HALF 1 +#define DAC_WORD 2 +#define DAC_QUAD 3 +#define DBCR_D2R 0x00000800 /* Data Addr. Compare 2 Read Enable */ +#define DBCR_D2W 0x00000400 /* Data Addr. Compare 2 Write Enable */ +#define DBCR_D2S(x) (((x)&0x3) << 8) /* Data Addr. Compare 2 Size */ +#define DBCR_SBT 0x00000040 /* Second Branch Taken Debug Event */ +#define DBCR_SED 0x00000020 /* Second Exception Debug Event */ +#define DBCR_STD 0x00000010 /* Second Trap Debug Event */ +#define DBCR_SIA 0x00000008 /* Second IAC Enable */ +#define DBCR_SDA 0x00000004 /* Second DAC Enable */ +#define DBCR_JOI 0x00000002 /* JTAG Serial Outbound Int. Enable */ +#define DBCR_JII 0x00000001 /* JTAG Serial Inbound Int. Enable */ +#ifndef CONFIG_BOOKE +#define SPRN_DBCR0 0x3F2 /* Debug Control Register 0 */ +#else +#define SPRN_DBCR0 0x134 /* Book E Debug Control Register 0 */ +#endif /* CONFIG_BOOKE */ +#ifndef CONFIG_BOOKE +#define SPRN_DBCR1 0x3BD /* Debug Control Register 1 */ +#define SPRN_DBSR 0x3F0 /* Debug Status Register */ +#else +#define SPRN_DBCR1 0x135 /* Book E Debug Control Register 1 */ +#ifdef CONFIG_BOOKE +#define SPRN_DBDR 0x3f3 /* Debug Data Register */ +#endif +#define SPRN_DBSR 0x130 /* Book E Debug Status Register */ +#define DBSR_IC 0x08000000 /* Book E Instruction Completion */ +#define DBSR_TIE 0x01000000 /* Book E Trap Instruction Event */ +#endif /* CONFIG_BOOKE */ +#define SPRN_DCCR 0x3FA /* Data Cache Cacheability Register */ +#define DCCR_NOCACHE 0 /* Noncacheable */ +#define DCCR_CACHE 1 /* Cacheable */ +#ifndef CONFIG_BOOKE +#define SPRN_DCDBTRL 0x39c /* Data Cache Debug Tag Register Low */ +#define SPRN_DCDBTRH 0x39d /* Data Cache Debug Tag Register High */ +#endif +#define SPRN_DCMP 0x3D1 /* Data TLB Compare Register */ +#define SPRN_DCWR 0x3BA /* Data Cache Write-thru Register */ +#define DCWR_COPY 0 /* Copy-back */ +#define DCWR_WRITE 1 /* Write-through */ +#ifndef CONFIG_BOOKE +#define SPRN_DEAR 0x3D5 /* Data Error Address Register */ +#else +#define SPRN_DEAR 0x03D /* Book E Data Error Address Register */ +#endif /* CONFIG_BOOKE */ +#define SPRN_DEC 0x016 /* Decrement Register */ +#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */ +#ifdef CONFIG_BOOKE +#define SPRN_DNV0 0x390 /* Data Cache Normal Victim 0 */ +#define SPRN_DNV1 0x391 /* Data Cache Normal Victim 1 */ +#define SPRN_DNV2 0x392 /* Data Cache Normal Victim 2 */ +#define SPRN_DNV3 0x393 /* Data Cache Normal Victim 3 */ +#endif +#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */ +#ifdef CONFIG_BOOKE +#define SPRN_DTV0 0x394 /* Data Cache Transient Victim 0 */ +#define SPRN_DTV1 0x395 /* Data Cache Transient Victim 1 */ +#define SPRN_DTV2 0x396 /* Data Cache Transient Victim 2 */ +#define SPRN_DTV3 0x397 /* Data Cache Transient Victim 3 */ +#define SPRN_DVLIM 0x398 /* Data Cache Victim Limit */ +#endif +#define SPRN_EAR 0x11A /* External Address Register */ +#ifndef CONFIG_BOOKE +#define SPRN_ESR 0x3D4 /* Exception Syndrome Register */ +#else +#define SPRN_ESR 0x03E /* Book E Exception Syndrome Register */ +#endif /* CONFIG_BOOKE */ +#define ESR_IMCP 0x80000000 /* Instr. Machine Check - Protection */ +#define ESR_IMCN 0x40000000 /* Instr. Machine Check - Non-config */ +#define ESR_IMCB 0x20000000 /* Instr. Machine Check - Bus error */ +#define ESR_IMCT 0x10000000 /* Instr. Machine Check - Timeout */ +#define ESR_PIL 0x08000000 /* Program Exception - Illegal */ +#define ESR_PPR 0x04000000 /* Program Exception - Priveleged */ +#define ESR_PTR 0x02000000 /* Program Exception - Trap */ +#define ESR_DST 0x00800000 /* Storage Exception - Data miss */ +#define ESR_DIZ 0x00400000 /* Storage Exception - Zone fault */ +#define SPRN_EVPR 0x3D6 /* Exception Vector Prefix Register */ +#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */ +#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */ +#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */ + +#define HID0_ICE_SHIFT 15 +#define HID0_DCE_SHIFT 14 +#define HID0_DLOCK_SHIFT 12 + +#define HID0_EMCP (1 << 31) /* Enable Machine Check pin */ +#define HID0_EBA (1 << 29) /* Enable Bus Address Parity */ +#define HID0_EBD (1 << 28) /* Enable Bus Data Parity */ +#define HID0_SBCLK (1 << 27) +#define HID0_EICE (1 << 26) +#define HID0_ECLK (1 << 25) +#define HID0_PAR (1 << 24) +#define HID0_DOZE (1 << 23) +#define HID0_NAP (1 << 22) +#define HID0_SLEEP (1 << 21) +#define HID0_DPM (1 << 20) +#define HID0_ICE (1 << HID0_ICE_SHIFT) /* Instruction Cache Enable */ +#define HID0_DCE (1 << HID0_DCE_SHIFT) /* Data Cache Enable */ +#define HID0_TBEN (1 << 14) /* Time Base Enable */ +#define HID0_ILOCK (1 << 13) /* Instruction Cache Lock */ +#define HID0_DLOCK (1 << HID0_DLOCK_SHIFT) /* Data Cache Lock */ +#define HID0_ICFI (1 << 11) /* Instr. Cache Flash Invalidate */ +#define HID0_DCFI (1 << 10) /* Data Cache Flash Invalidate */ +#define HID0_DCI HID0_DCFI +#define HID0_SPD (1 << 9) /* Speculative disable */ +#define HID0_ENMAS7 (1 << 7) /* Enable MAS7 Update for 36-bit phys */ +#define HID0_SGE (1 << 7) /* Store Gathering Enable */ +#define HID0_SIED HID_SGE /* Serial Instr. Execution [Disable] */ +#define HID0_DCFA (1 << 6) /* Data Cache Flush Assist */ +#define HID0_BTIC (1 << 5) /* Branch Target Instruction Cache Enable */ +#define HID0_ABE (1 << 3) /* Address Broadcast Enable */ +#define HID0_BHTE (1 << 2) /* Branch History Table Enable */ +#define HID0_BTCD (1 << 1) /* Branch target cache disable */ +#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */ +#define HID1_RFXE (1 << 17) /* Read Fault Exception Enable */ +#define HID1_ASTME (1 << 13) /* Address bus streaming mode */ +#define HID1_ABE (1 << 12) /* Address broadcast enable */ +#define HID1_MBDD (1 << 6) /* optimized sync instruction */ +#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */ +#ifndef CONFIG_BOOKE +#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */ +#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */ +#else +#define SPRN_IAC1 0x138 /* Book E Instruction Address Compare 1 */ +#define SPRN_IAC2 0x139 /* Book E Instruction Address Compare 2 */ +#endif /* CONFIG_BOOKE */ +#define SPRN_IBAT0L 0x211 /* Instruction BAT 0 Lower Register */ +#define SPRN_IBAT0U 0x210 /* Instruction BAT 0 Upper Register */ +#define SPRN_IBAT1L 0x213 /* Instruction BAT 1 Lower Register */ +#define SPRN_IBAT1U 0x212 /* Instruction BAT 1 Upper Register */ +#define SPRN_IBAT2L 0x215 /* Instruction BAT 2 Lower Register */ +#define SPRN_IBAT2U 0x214 /* Instruction BAT 2 Upper Register */ +#define SPRN_IBAT3L 0x217 /* Instruction BAT 3 Lower Register */ +#define SPRN_IBAT3U 0x216 /* Instruction BAT 3 Upper Register */ +#define SPRN_IBAT4L 0x231 /* Instruction BAT 4 Lower Register */ +#define SPRN_IBAT4U 0x230 /* Instruction BAT 4 Upper Register */ +#define SPRN_IBAT5L 0x233 /* Instruction BAT 5 Lower Register */ +#define SPRN_IBAT5U 0x232 /* Instruction BAT 5 Upper Register */ +#define SPRN_IBAT6L 0x235 /* Instruction BAT 6 Lower Register */ +#define SPRN_IBAT6U 0x234 /* Instruction BAT 6 Upper Register */ +#define SPRN_IBAT7L 0x237 /* Instruction BAT 7 Lower Register */ +#define SPRN_IBAT7U 0x236 /* Instruction BAT 7 Upper Register */ +#define SPRN_ICCR 0x3FB /* Instruction Cache Cacheability Register */ +#define ICCR_NOCACHE 0 /* Noncacheable */ +#define ICCR_CACHE 1 /* Cacheable */ +#define SPRN_ICDBDR 0x3D3 /* Instruction Cache Debug Data Register */ +#ifdef CONFIG_BOOKE +#define SPRN_ICDBTRL 0x39e /* instruction cache debug tag register low */ +#define SPRN_ICDBTRH 0x39f /* instruction cache debug tag register high */ +#endif +#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */ +#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */ +#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */ +#define SPRN_IMMR 0x27E /* Internal Memory Map Register */ +#ifdef CONFIG_BOOKE +#define SPRN_INV0 0x370 /* Instruction Cache Normal Victim 0 */ +#define SPRN_INV1 0x371 /* Instruction Cache Normal Victim 1 */ +#define SPRN_INV2 0x372 /* Instruction Cache Normal Victim 2 */ +#define SPRN_INV3 0x373 /* Instruction Cache Normal Victim 3 */ +#define SPRN_ITV0 0x374 /* Instruction Cache Transient Victim 0 */ +#define SPRN_ITV1 0x375 /* Instruction Cache Transient Victim 1 */ +#define SPRN_ITV2 0x376 /* Instruction Cache Transient Victim 2 */ +#define SPRN_ITV3 0x377 /* Instruction Cache Transient Victim 3 */ +#define SPRN_IVLIM 0x399 /* Instruction Cache Victim Limit */ +#endif +#define SPRN_LDSTCR 0x3F8 /* Load/Store Control Register */ +#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */ +#define SPRN_LR 0x008 /* Link Register */ +#define SPRN_MBAR 0x137 /* System memory base address */ +#define SPRN_MMCR0 0x3B8 /* Monitor Mode Control Register 0 */ +#define SPRN_MMCR1 0x3BC /* Monitor Mode Control Register 1 */ +#ifdef CONFIG_BOOKE +#define SPRN_MMUCR 0x3b2 /* MMU Control Register */ +#endif +#define SPRN_PBL1 0x3FC /* Protection Bound Lower 1 */ +#define SPRN_PBL2 0x3FE /* Protection Bound Lower 2 */ +#define SPRN_PBU1 0x3FD /* Protection Bound Upper 1 */ +#define SPRN_PBU2 0x3FF /* Protection Bound Upper 2 */ +#ifndef CONFIG_BOOKE +#define SPRN_PID 0x3B1 /* Process ID */ +#define SPRN_PIR 0x3FF /* Processor Identification Register */ +#else +#define SPRN_PID 0x030 /* Book E Process ID */ +#define SPRN_PIR 0x11E /* Book E Processor Identification Register */ +#endif /* CONFIG_BOOKE */ +#define SPRN_PIT 0x3DB /* Programmable Interval Timer */ +#define SPRN_PMC1 0x3B9 /* Performance Counter Register 1 */ +#define SPRN_PMC2 0x3BA /* Performance Counter Register 2 */ +#define SPRN_PMC3 0x3BD /* Performance Counter Register 3 */ +#define SPRN_PMC4 0x3BE /* Performance Counter Register 4 */ +#define SPRN_PVR 0x11F /* Processor Version Register */ +#define SPRN_RPA 0x3D6 /* Required Physical Address Register */ +#ifdef CONFIG_BOOKE +#define SPRN_RSTCFG 0x39b /* Reset Configuration */ +#endif +#define SPRN_SDA 0x3BF /* Sampled Data Address Register */ +#define SPRN_SDR1 0x019 /* MMU Hash Base Register */ +#define SPRN_SGR 0x3B9 /* Storage Guarded Register */ +#define SGR_NORMAL 0 +#define SGR_GUARDED 1 +#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */ +#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */ +#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */ +#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */ +#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */ +#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */ +#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */ +#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */ +#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */ +#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */ +#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */ +#define SPRN_SRR2 0x3DE /* Save/Restore Register 2 */ +#define SPRN_SRR3 0x3DF /* Save/Restore Register 3 */ + +#ifdef CONFIG_BOOKE +#define SPRN_SVR 0x3FF /* System Version Register */ +#else +#define SPRN_SVR 0x11E /* System Version Register */ +#endif +#define SPRN_TBHI 0x3DC /* Time Base High */ +#define SPRN_TBHU 0x3CC /* Time Base High User-mode */ +#define SPRN_TBLO 0x3DD /* Time Base Low */ +#define SPRN_TBLU 0x3CD /* Time Base Low User-mode */ +#define SPRN_TBRL 0x10C /* Time Base Read Lower Register */ +#define SPRN_TBRU 0x10D /* Time Base Read Upper Register */ +#define SPRN_TBWL 0x11C /* Time Base Write Lower Register */ +#define SPRN_TBWU 0x11D /* Time Base Write Upper Register */ +#ifndef CONFIG_BOOKE +#define SPRN_TCR 0x3DA /* Timer Control Register */ +#else +#define SPRN_TCR 0x154 /* Book E Timer Control Register */ +#endif /* CONFIG_BOOKE */ +#ifdef CONFIG_E500MC +#define TCR_WP(x) (((64 - x) & 0x3) << 30) | \ + (((64 - x) & 0x3c) << 15) /* WDT Period 2^x clocks*/ +#else +#define TCR_WP(x) (((x)&0x3) << 30) /* WDT Period */ +#define WP_2_17 0 /* 2^17 clocks */ +#define WP_2_21 1 /* 2^21 clocks */ +#define WP_2_25 2 /* 2^25 clocks */ +#define WP_2_29 3 /* 2^29 clocks */ +#endif /* CONFIG_E500 */ +#define TCR_WRC(x) (((x)&0x3) << 28) /* WDT Reset Control */ +#define WRC_NONE 0 /* No reset will occur */ +#define WRC_CORE 1 /* Core reset will occur */ +#define WRC_CHIP 2 /* Chip reset will occur */ +#define WRC_SYSTEM 3 /* System reset will occur */ +#define TCR_WIE 0x08000000 /* WDT Interrupt Enable */ +#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */ +#define TCR_FP(x) (((x)&0x3) << 24) /* FIT Period */ +#define FP_2_9 0 /* 2^9 clocks */ +#define FP_2_13 1 /* 2^13 clocks */ +#define FP_2_17 2 /* 2^17 clocks */ +#define FP_2_21 3 /* 2^21 clocks */ +#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */ +#define TCR_ARE 0x00400000 /* Auto Reload Enable */ +#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */ +#define THRM1_TIN (1 << 0) +#define THRM1_TIV (1 << 1) +#define THRM1_THRES (0x7f << 2) +#define THRM1_TID (1 << 29) +#define THRM1_TIE (1 << 30) +#define THRM1_V (1 << 31) +#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */ +#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */ +#define THRM3_E (1 << 31) +#define SPRN_TLBMISS 0x3D4 /* 980 7450 TLB Miss Register */ +#ifndef CONFIG_BOOKE +#define SPRN_TSR 0x3D8 /* Timer Status Register */ +#else +#define SPRN_TSR 0x150 /* Book E Timer Status Register */ +#endif /* CONFIG_BOOKE */ +#define TSR_ENW 0x80000000 /* Enable Next Watchdog */ +#define TSR_WIS 0x40000000 /* WDT Interrupt Status */ +#define TSR_WRS(x) (((x)&0x3) << 28) /* WDT Reset Status */ +#define WRS_NONE 0 /* No WDT reset occurred */ +#define WRS_CORE 1 /* WDT forced core reset */ +#define WRS_CHIP 2 /* WDT forced chip reset */ +#define WRS_SYSTEM 3 /* WDT forced system reset */ +#define TSR_PIS 0x08000000 /* PIT Interrupt Status */ +#define TSR_FIS 0x04000000 /* FIT Interrupt Status */ +#define SPRN_UMMCR0 0x3A8 /* User Monitor Mode Control Register 0 */ +#define SPRN_UMMCR1 0x3AC /* User Monitor Mode Control Register 0 */ +#define SPRN_UPMC1 0x3A9 /* User Performance Counter Register 1 */ +#define SPRN_UPMC2 0x3AA /* User Performance Counter Register 2 */ +#define SPRN_UPMC3 0x3AD /* User Performance Counter Register 3 */ +#define SPRN_UPMC4 0x3AE /* User Performance Counter Register 4 */ +#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */ +#define SPRN_XER 0x001 /* Fixed Point Exception Register */ +#define SPRN_ZPR 0x3B0 /* Zone Protection Register */ + +/* Book E definitions */ +#define SPRN_DECAR 0x036 /* Decrementer Auto Reload Register */ +#define SPRN_CSRR0 0x03A /* Critical SRR0 */ +#define SPRN_CSRR1 0x03B /* Critical SRR0 */ +#define SPRN_IVPR 0x03F /* Interrupt Vector Prefix Register */ +#define SPRN_USPRG0 0x100 /* User Special Purpose Register General 0 */ +#define SPRN_SPRG4R 0x104 /* Special Purpose Register General 4 Read */ +#define SPRN_SPRG5R 0x105 /* Special Purpose Register General 5 Read */ +#define SPRN_SPRG6R 0x106 /* Special Purpose Register General 6 Read */ +#define SPRN_SPRG7R 0x107 /* Special Purpose Register General 7 Read */ +#define SPRN_SPRG4W 0x114 /* Special Purpose Register General 4 Write */ +#define SPRN_SPRG5W 0x115 /* Special Purpose Register General 5 Write */ +#define SPRN_SPRG6W 0x116 /* Special Purpose Register General 6 Write */ +#define SPRN_SPRG7W 0x117 /* Special Purpose Register General 7 Write */ +#define SPRN_DBCR2 0x136 /* Debug Control Register 2 */ +#define SPRN_IAC3 0x13A /* Instruction Address Compare 3 */ +#define SPRN_IAC4 0x13B /* Instruction Address Compare 4 */ +#define SPRN_DVC1 0x13E /* Data Value Compare Register 1 */ +#define SPRN_DVC2 0x13F /* Data Value Compare Register 2 */ +#define SPRN_IVOR0 0x190 /* Interrupt Vector Offset Register 0 */ +#define SPRN_IVOR1 0x191 /* Interrupt Vector Offset Register 1 */ +#define SPRN_IVOR2 0x192 /* Interrupt Vector Offset Register 2 */ +#define SPRN_IVOR3 0x193 /* Interrupt Vector Offset Register 3 */ +#define SPRN_IVOR4 0x194 /* Interrupt Vector Offset Register 4 */ +#define SPRN_IVOR5 0x195 /* Interrupt Vector Offset Register 5 */ +#define SPRN_IVOR6 0x196 /* Interrupt Vector Offset Register 6 */ +#define SPRN_IVOR7 0x197 /* Interrupt Vector Offset Register 7 */ +#define SPRN_IVOR8 0x198 /* Interrupt Vector Offset Register 8 */ +#define SPRN_IVOR9 0x199 /* Interrupt Vector Offset Register 9 */ +#define SPRN_IVOR10 0x19a /* Interrupt Vector Offset Register 10 */ +#define SPRN_IVOR11 0x19b /* Interrupt Vector Offset Register 11 */ +#define SPRN_IVOR12 0x19c /* Interrupt Vector Offset Register 12 */ +#define SPRN_IVOR13 0x19d /* Interrupt Vector Offset Register 13 */ +#define SPRN_IVOR14 0x19e /* Interrupt Vector Offset Register 14 */ +#define SPRN_IVOR15 0x19f /* Interrupt Vector Offset Register 15 */ +#define SPRN_IVOR38 0x1b0 /* Interrupt Vector Offset Register 38 */ +#define SPRN_IVOR39 0x1b1 /* Interrupt Vector Offset Register 39 */ +#define SPRN_IVOR40 0x1b2 /* Interrupt Vector Offset Register 40 */ +#define SPRN_IVOR41 0x1b3 /* Interrupt Vector Offset Register 41 */ +#define SPRN_GIVOR2 0x1b8 /* Guest Interrupt Vector Offset Register 2 */ +#define SPRN_GIVOR3 0x1b9 /* Guest Interrupt Vector Offset Register 3 */ +#define SPRN_GIVOR4 0x1ba /* Guest Interrupt Vector Offset Register 4 */ +#define SPRN_GIVOR8 0x1bb /* Guest Interrupt Vector Offset Register 8 */ +#define SPRN_GIVOR13 0x1bc /* Guest Interrupt Vector Offset Register 13 */ +#define SPRN_GIVOR14 0x1bd /* Guest Interrupt Vector Offset Register 14 */ + +/* e500 definitions */ +#define SPRN_L1CFG0 0x203 /* L1 Cache Configuration Register 0 */ +#define SPRN_L1CFG1 0x204 /* L1 Cache Configuration Register 1 */ +#define SPRN_L2CFG0 0x207 /* L2 Cache Configuration Register 0 */ +#define SPRN_L1CSR0 0x3f2 /* L1 Data Cache Control and Status Register 0 */ +#define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */ +#define L1CSR0_CUL 0x00000400 /* (D-)Cache Unable to Lock */ +#define L1CSR0_DCLFR 0x00000100 /* D-Cache Lock Flash Reset */ +#define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */ +#define L1CSR0_DCE 0x00000001 /* Data Cache Enable */ +#define SPRN_L1CSR1 0x3f3 /* L1 Instruction Cache Control and Status Register 1 */ +#define L1CSR1_CPE 0x00010000 /* Instruction Cache Parity Enable */ +#define L1CSR1_ICUL 0x00000400 /* I-Cache Unable to Lock */ +#define L1CSR1_ICLFR 0x00000100 /* I-Cache Lock Flash Reset */ +#define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */ +#define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */ +#define SPRN_L1CSR2 0x25e /* L1 Data Cache Control and Status Register 2 */ +#define L1CSR2_DCWS 0x40000000 /* Data Cache Write Shadow */ +#define SPRN_L2CSR0 0x3f9 /* L2 Data Cache Control and Status Register 0 */ +#define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */ +#define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */ +#define L2CSR0_L2WP 0x1c000000 /* L2 I/D Way Partioning */ +#define L2CSR0_L2CM 0x03000000 /* L2 Cache Coherency Mode */ +#define L2CSR0_L2FI 0x00200000 /* L2 Cache Flash Invalidate */ +#define L2CSR0_L2IO 0x00100000 /* L2 Cache Instruction Only */ +#define L2CSR0_L2DO 0x00010000 /* L2 Cache Data Only */ +#define L2CSR0_L2REP 0x00003000 /* L2 Line Replacement Algo */ + +/* e6500 */ +#define L2CSR0_L2REP_SPLRUAGE 0x00000000 /* L2REP Streaming PLRU with Aging */ +#define L2CSR0_L2REP_FIFO 0x00001000 /* L2REP FIFO */ +#define L2CSR0_L2REP_SPLRU 0x00002000 /* L2REP Streaming PLRU */ +#define L2CSR0_L2REP_PLRU 0x00003000 /* L2REP PLRU */ + +#define L2CSR0_L2REP_MODE L2CSR0_L2REP_SPLRUAGE + +#define L2CSR0_L2FL 0x00000800 /* L2 Cache Flush */ +#define L2CSR0_L2LFC 0x00000400 /* L2 Cache Lock Flash Clear */ +#define L2CSR0_L2LOA 0x00000080 /* L2 Cache Lock Overflow Allocate */ +#define L2CSR0_L2LO 0x00000020 /* L2 Cache Lock Overflow */ +#define SPRN_L2CSR1 0x3fa /* L2 Data Cache Control and Status Register 1 */ + +#define SPRN_TLB0CFG 0x2B0 /* TLB 0 Config Register */ +#define SPRN_TLB1CFG 0x2B1 /* TLB 1 Config Register */ +#define TLBnCFG_NENTRY_MASK 0x00000fff +#define SPRN_TLB0PS 0x158 /* TLB 0 Page Size Register */ +#define SPRN_TLB1PS 0x159 /* TLB 1 Page Size Register */ +#define SPRN_MMUCSR0 0x3f4 /* MMU control and status register 0 */ +#define SPRN_MMUCFG 0x3F7 /* MMU Configuration Register */ +#define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */ +#define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */ +#define MMUCFG_MAVN_V2 0x00000001 /* v2.0 */ +#define SPRN_MAS0 0x270 /* MMU Assist Register 0 */ +#define SPRN_MAS1 0x271 /* MMU Assist Register 1 */ +#define SPRN_MAS2 0x272 /* MMU Assist Register 2 */ +#define SPRN_MAS3 0x273 /* MMU Assist Register 3 */ +#define SPRN_MAS4 0x274 /* MMU Assist Register 4 */ +#define SPRN_MAS5 0x275 /* MMU Assist Register 5 */ +#define SPRN_MAS6 0x276 /* MMU Assist Register 6 */ +#define SPRN_MAS7 0x3B0 /* MMU Assist Register 7 */ +#define SPRN_MAS8 0x155 /* MMU Assist Register 8 */ + +#define SPRN_IVOR32 0x210 /* Interrupt Vector Offset Register 32 */ +#define SPRN_IVOR33 0x211 /* Interrupt Vector Offset Register 33 */ +#define SPRN_IVOR34 0x212 /* Interrupt Vector Offset Register 34 */ +#define SPRN_IVOR35 0x213 /* Interrupt Vector Offset Register 35 */ +#define SPRN_IVOR36 0x214 /* Interrupt Vector Offset Register 36 */ +#define SPRN_IVOR37 0x215 /* Interrupt Vector Offset Register 37 */ +#define SPRN_SPEFSCR 0x200 /* SPE & Embedded FP Status & Control */ + +#define SPRN_MCSRR0 0x23a /* Machine Check Save and Restore Register 0 */ +#define SPRN_MCSRR1 0x23b /* Machine Check Save and Restore Register 1 */ +#define SPRN_BUCSR 0x3f5 /* Branch Control and Status Register */ +#define BUCSR_STAC_EN 0x01000000 /* Segment target addr cache enable */ +#define BUCSR_LS_EN 0x00400000 /* Link stack enable */ +#define BUCSR_BBFI 0x00000200 /* Branch buffer flash invalidate */ +#define BUCSR_BPEN 0x00000001 /* Branch prediction enable */ +#define BUCSR_ENABLE (BUCSR_STAC_EN | BUCSR_LS_EN | BUCSR_BBFI | BUCSR_BPEN) +#define SPRN_BBEAR 0x201 /* Branch Buffer Entry Address Register */ +#define SPRN_BBTAR 0x202 /* Branch Buffer Target Address Register */ +#define SPRN_PID1 0x279 /* Process ID Register 1 */ +#define SPRN_PID2 0x27a /* Process ID Register 2 */ +#define SPRN_MCSR 0x23c /* Machine Check Syndrome register */ +#define SPRN_MCAR 0x23d /* Machine Check Address register */ +#define MCSR_MCS 0x80000000 /* Machine Check Summary */ +#define MCSR_IB 0x40000000 /* Instruction PLB Error */ +#if defined(CONFIG_440) +#define MCSR_DRB 0x20000000 /* Data Read PLB Error */ +#define MCSR_DWB 0x10000000 /* Data Write PLB Error */ +#else +#define MCSR_DB 0x20000000 /* Data PLB Error */ +#endif /* defined(CONFIG_440) */ +#define MCSR_TLBP 0x08000000 /* TLB Parity Error */ +#define MCSR_ICP 0x04000000 /* I-Cache Parity Error */ +#define MCSR_DCSP 0x02000000 /* D-Cache Search Parity Error */ +#define MCSR_DCFP 0x01000000 /* D-Cache Flush Parity Error */ +#define MCSR_IMPE 0x00800000 /* Imprecise Machine Check Exception */ +#define ESR_ST 0x00800000 /* Store Operation */ + +#if defined(CONFIG_MPC86xx) +#define SPRN_MSSCR0 0x3f6 +#define SPRN_MSSSR0 0x3f7 +#endif + +#define SPRN_HDBCR0 0x3d0 +#define SPRN_HDBCR1 0x3d1 +#define SPRN_HDBCR2 0x3d2 +#define SPRN_HDBCR3 0x3d3 +#define SPRN_HDBCR4 0x3d4 +#define SPRN_HDBCR5 0x3d5 +#define SPRN_HDBCR6 0x3d6 +#define SPRN_HDBCR7 0x277 +#define SPRN_HDBCR8 0x278 + +/* Short-hand versions for a number of the above SPRNs */ + +#define CTR SPRN_CTR /* Counter Register */ +#define DAR SPRN_DAR /* Data Address Register */ +#define DABR SPRN_DABR /* Data Address Breakpoint Register */ +#define DAC1 SPRN_DAC1 /* Data Address Register 1 */ +#define DAC2 SPRN_DAC2 /* Data Address Register 2 */ +#define DBAT0L SPRN_DBAT0L /* Data BAT 0 Lower Register */ +#define DBAT0U SPRN_DBAT0U /* Data BAT 0 Upper Register */ +#define DBAT1L SPRN_DBAT1L /* Data BAT 1 Lower Register */ +#define DBAT1U SPRN_DBAT1U /* Data BAT 1 Upper Register */ +#define DBAT2L SPRN_DBAT2L /* Data BAT 2 Lower Register */ +#define DBAT2U SPRN_DBAT2U /* Data BAT 2 Upper Register */ +#define DBAT3L SPRN_DBAT3L /* Data BAT 3 Lower Register */ +#define DBAT3U SPRN_DBAT3U /* Data BAT 3 Upper Register */ +#define DBAT4L SPRN_DBAT4L /* Data BAT 4 Lower Register */ +#define DBAT4U SPRN_DBAT4U /* Data BAT 4 Upper Register */ +#define DBAT5L SPRN_DBAT5L /* Data BAT 5 Lower Register */ +#define DBAT5U SPRN_DBAT5U /* Data BAT 5 Upper Register */ +#define DBAT6L SPRN_DBAT6L /* Data BAT 6 Lower Register */ +#define DBAT6U SPRN_DBAT6U /* Data BAT 6 Upper Register */ +#define DBAT7L SPRN_DBAT7L /* Data BAT 7 Lower Register */ +#define DBAT7U SPRN_DBAT7U /* Data BAT 7 Upper Register */ +#define DBCR0 SPRN_DBCR0 /* Debug Control Register 0 */ +#define DBCR1 SPRN_DBCR1 /* Debug Control Register 1 */ +#define DBSR SPRN_DBSR /* Debug Status Register */ +#define DCMP SPRN_DCMP /* Data TLB Compare Register */ +#define DEC SPRN_DEC /* Decrement Register */ +#define DMISS SPRN_DMISS /* Data TLB Miss Register */ +#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */ +#define EAR SPRN_EAR /* External Address Register */ +#define ESR SPRN_ESR /* Exception Syndrome Register */ +#define HASH1 SPRN_HASH1 /* Primary Hash Address Register */ +#define HASH2 SPRN_HASH2 /* Secondary Hash Address Register */ +#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */ +#define HID1 SPRN_HID1 /* Hardware Implementation Register 1 */ +#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */ +#define IAC1 SPRN_IAC1 /* Instruction Address Register 1 */ +#define IAC2 SPRN_IAC2 /* Instruction Address Register 2 */ +#define IBAT0L SPRN_IBAT0L /* Instruction BAT 0 Lower Register */ +#define IBAT0U SPRN_IBAT0U /* Instruction BAT 0 Upper Register */ +#define IBAT1L SPRN_IBAT1L /* Instruction BAT 1 Lower Register */ +#define IBAT1U SPRN_IBAT1U /* Instruction BAT 1 Upper Register */ +#define IBAT2L SPRN_IBAT2L /* Instruction BAT 2 Lower Register */ +#define IBAT2U SPRN_IBAT2U /* Instruction BAT 2 Upper Register */ +#define IBAT3L SPRN_IBAT3L /* Instruction BAT 3 Lower Register */ +#define IBAT3U SPRN_IBAT3U /* Instruction BAT 3 Upper Register */ +#define IBAT4L SPRN_IBAT4L /* Instruction BAT 4 Lower Register */ +#define IBAT4U SPRN_IBAT4U /* Instruction BAT 4 Upper Register */ +#define IBAT5L SPRN_IBAT5L /* Instruction BAT 5 Lower Register */ +#define IBAT5U SPRN_IBAT5U /* Instruction BAT 5 Upper Register */ +#define IBAT6L SPRN_IBAT6L /* Instruction BAT 6 Lower Register */ +#define IBAT6U SPRN_IBAT6U /* Instruction BAT 6 Upper Register */ +#define IBAT7L SPRN_IBAT7L /* Instruction BAT 7 Lower Register */ +#define IBAT7U SPRN_IBAT7U /* Instruction BAT 7 Lower Register */ +#define ICMP SPRN_ICMP /* Instruction TLB Compare Register */ +#define IMISS SPRN_IMISS /* Instruction TLB Miss Register */ +#define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */ +#define LDSTCR SPRN_LDSTCR /* Load/Store Control Register */ +#define L2CR SPRN_L2CR /* PPC 750 L2 control register */ +#define LR SPRN_LR +#define MBAR SPRN_MBAR /* System memory base address */ +#if defined(CONFIG_MPC86xx) +#define MSSCR0 SPRN_MSSCR0 +#endif +#if defined(CONFIG_E500) || defined(CONFIG_MPC86xx) +#define PIR SPRN_PIR +#endif +#define SVR SPRN_SVR /* System-On-Chip Version Register */ +#define PVR SPRN_PVR /* Processor Version */ +#define RPA SPRN_RPA /* Required Physical Address Register */ +#define SDR1 SPRN_SDR1 /* MMU hash base register */ +#define SPR0 SPRN_SPRG0 /* Supervisor Kernel Registers */ +#define SPR1 SPRN_SPRG1 +#define SPR2 SPRN_SPRG2 +#define SPR3 SPRN_SPRG3 +#define SPRG0 SPRN_SPRG0 +#define SPRG1 SPRN_SPRG1 +#define SPRG2 SPRN_SPRG2 +#define SPRG3 SPRN_SPRG3 +#define SPRG4 SPRN_SPRG4 +#define SPRG5 SPRN_SPRG5 +#define SPRG6 SPRN_SPRG6 +#define SPRG7 SPRN_SPRG7 +#define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */ +#define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */ +#define SRR2 SPRN_SRR2 /* Save and Restore Register 2 */ +#define SRR3 SPRN_SRR3 /* Save and Restore Register 3 */ +#define SVR SPRN_SVR /* System Version Register */ +#define TBRL SPRN_TBRL /* Time Base Read Lower Register */ +#define TBRU SPRN_TBRU /* Time Base Read Upper Register */ +#define TBWL SPRN_TBWL /* Time Base Write Lower Register */ +#define TBWU SPRN_TBWU /* Time Base Write Upper Register */ +#define TCR SPRN_TCR /* Timer Control Register */ +#define TSR SPRN_TSR /* Timer Status Register */ +#define ICTC 1019 +#define THRM1 SPRN_THRM1 /* Thermal Management Register 1 */ +#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */ +#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */ +#define XER SPRN_XER + +#define DECAR SPRN_DECAR +#define CSRR0 SPRN_CSRR0 +#define CSRR1 SPRN_CSRR1 +#define IVPR SPRN_IVPR +#define USPRG0 SPRN_USPRG +#define SPRG4R SPRN_SPRG4R +#define SPRG5R SPRN_SPRG5R +#define SPRG6R SPRN_SPRG6R +#define SPRG7R SPRN_SPRG7R +#define SPRG4W SPRN_SPRG4W +#define SPRG5W SPRN_SPRG5W +#define SPRG6W SPRN_SPRG6W +#define SPRG7W SPRN_SPRG7W +#define DEAR SPRN_DEAR +#define DBCR2 SPRN_DBCR2 +#define IAC3 SPRN_IAC3 +#define IAC4 SPRN_IAC4 +#define DVC1 SPRN_DVC1 +#define DVC2 SPRN_DVC2 +#define IVOR0 SPRN_IVOR0 +#define IVOR1 SPRN_IVOR1 +#define IVOR2 SPRN_IVOR2 +#define IVOR3 SPRN_IVOR3 +#define IVOR4 SPRN_IVOR4 +#define IVOR5 SPRN_IVOR5 +#define IVOR6 SPRN_IVOR6 +#define IVOR7 SPRN_IVOR7 +#define IVOR8 SPRN_IVOR8 +#define IVOR9 SPRN_IVOR9 +#define IVOR10 SPRN_IVOR10 +#define IVOR11 SPRN_IVOR11 +#define IVOR12 SPRN_IVOR12 +#define IVOR13 SPRN_IVOR13 +#define IVOR14 SPRN_IVOR14 +#define IVOR15 SPRN_IVOR15 +#define IVOR32 SPRN_IVOR32 +#define IVOR33 SPRN_IVOR33 +#define IVOR34 SPRN_IVOR34 +#define IVOR35 SPRN_IVOR35 +#define MCSRR0 SPRN_MCSRR0 +#define MCSRR1 SPRN_MCSRR1 +#define L1CSR0 SPRN_L1CSR0 +#define L1CSR1 SPRN_L1CSR1 +#define L1CSR2 SPRN_L1CSR2 +#define L1CFG0 SPRN_L1CFG0 +#define L1CFG1 SPRN_L1CFG1 +#define L2CFG0 SPRN_L2CFG0 +#define L2CSR0 SPRN_L2CSR0 +#define L2CSR1 SPRN_L2CSR1 +#define MCSR SPRN_MCSR +#define MMUCSR0 SPRN_MMUCSR0 +#define BUCSR SPRN_BUCSR +#define PID0 SPRN_PID +#define PID1 SPRN_PID1 +#define PID2 SPRN_PID2 +#define MAS0 SPRN_MAS0 +#define MAS1 SPRN_MAS1 +#define MAS2 SPRN_MAS2 +#define MAS3 SPRN_MAS3 +#define MAS4 SPRN_MAS4 +#define MAS5 SPRN_MAS5 +#define MAS6 SPRN_MAS6 +#define MAS7 SPRN_MAS7 +#define MAS8 SPRN_MAS8 + +#if defined(CONFIG_4xx) || defined(CONFIG_44x) || defined(CONFIG_MPC85xx) +#define DAR_DEAR DEAR +#else +#define DAR_DEAR DAR +#endif + +/* Device Control Registers */ + +#define DCRN_BEAR 0x090 /* Bus Error Address Register */ +#define DCRN_BESR 0x091 /* Bus Error Syndrome Register */ +#define BESR_DSES 0x80000000 /* Data-Side Error Status */ +#define BESR_DMES 0x40000000 /* DMA Error Status */ +#define BESR_RWS 0x20000000 /* Read/Write Status */ +#define BESR_ETMASK 0x1C000000 /* Error Type */ +#define ET_PROT 0 +#define ET_PARITY 1 +#define ET_NCFG 2 +#define ET_BUSERR 4 +#define ET_BUSTO 6 +#define DCRN_DMACC0 0x0C4 /* DMA Chained Count Register 0 */ +#define DCRN_DMACC1 0x0CC /* DMA Chained Count Register 1 */ +#define DCRN_DMACC2 0x0D4 /* DMA Chained Count Register 2 */ +#define DCRN_DMACC3 0x0DC /* DMA Chained Count Register 3 */ +#define DCRN_DMACR0 0x0C0 /* DMA Channel Control Register 0 */ +#define DCRN_DMACR1 0x0C8 /* DMA Channel Control Register 1 */ +#define DCRN_DMACR2 0x0D0 /* DMA Channel Control Register 2 */ +#define DCRN_DMACR3 0x0D8 /* DMA Channel Control Register 3 */ +#define DCRN_DMACT0 0x0C1 /* DMA Count Register 0 */ +#define DCRN_DMACT1 0x0C9 /* DMA Count Register 1 */ +#define DCRN_DMACT2 0x0D1 /* DMA Count Register 2 */ +#define DCRN_DMACT3 0x0D9 /* DMA Count Register 3 */ +#define DCRN_DMADA0 0x0C2 /* DMA Destination Address Register 0 */ +#define DCRN_DMADA1 0x0CA /* DMA Destination Address Register 1 */ +#define DCRN_DMADA2 0x0D2 /* DMA Destination Address Register 2 */ +#define DCRN_DMADA3 0x0DA /* DMA Destination Address Register 3 */ +#define DCRN_DMASA0 0x0C3 /* DMA Source Address Register 0 */ +#define DCRN_DMASA1 0x0CB /* DMA Source Address Register 1 */ +#define DCRN_DMASA2 0x0D3 /* DMA Source Address Register 2 */ +#define DCRN_DMASA3 0x0DB /* DMA Source Address Register 3 */ +#define DCRN_DMASR 0x0E0 /* DMA Status Register */ +#define DCRN_EXIER 0x042 /* External Interrupt Enable Register */ +#define EXIER_CIE 0x80000000 /* Critical Interrupt Enable */ +#define EXIER_SRIE 0x08000000 /* Serial Port Rx Int. Enable */ +#define EXIER_STIE 0x04000000 /* Serial Port Tx Int. Enable */ +#define EXIER_JRIE 0x02000000 /* JTAG Serial Port Rx Int. Enable */ +#define EXIER_JTIE 0x01000000 /* JTAG Serial Port Tx Int. Enable */ +#define EXIER_D0IE 0x00800000 /* DMA Channel 0 Interrupt Enable */ +#define EXIER_D1IE 0x00400000 /* DMA Channel 1 Interrupt Enable */ +#define EXIER_D2IE 0x00200000 /* DMA Channel 2 Interrupt Enable */ +#define EXIER_D3IE 0x00100000 /* DMA Channel 3 Interrupt Enable */ +#define EXIER_E0IE 0x00000010 /* External Interrupt 0 Enable */ +#define EXIER_E1IE 0x00000008 /* External Interrupt 1 Enable */ +#define EXIER_E2IE 0x00000004 /* External Interrupt 2 Enable */ +#define EXIER_E3IE 0x00000002 /* External Interrupt 3 Enable */ +#define EXIER_E4IE 0x00000001 /* External Interrupt 4 Enable */ +#define DCRN_EXISR 0x040 /* External Interrupt Status Register */ +#define DCRN_IOCR 0x0A0 /* Input/Output Configuration Register */ +#define IOCR_E0TE 0x80000000 +#define IOCR_E0LP 0x40000000 +#define IOCR_E1TE 0x20000000 +#define IOCR_E1LP 0x10000000 +#define IOCR_E2TE 0x08000000 +#define IOCR_E2LP 0x04000000 +#define IOCR_E3TE 0x02000000 +#define IOCR_E3LP 0x01000000 +#define IOCR_E4TE 0x00800000 +#define IOCR_E4LP 0x00400000 +#define IOCR_EDT 0x00080000 +#define IOCR_SOR 0x00040000 +#define IOCR_EDO 0x00008000 +#define IOCR_2XC 0x00004000 +#define IOCR_ATC 0x00002000 +#define IOCR_SPD 0x00001000 +#define IOCR_BEM 0x00000800 +#define IOCR_PTD 0x00000400 +#define IOCR_ARE 0x00000080 +#define IOCR_DRC 0x00000020 +#define IOCR_RDM(x) (((x)&0x3) << 3) +#define IOCR_TCS 0x00000004 +#define IOCR_SCS 0x00000002 +#define IOCR_SPC 0x00000001 + +/* System-On-Chip Version Register */ + +/* System-On-Chip Version Register (SVR) field extraction */ + +#define SVR_VER(svr) (((svr) >> 16) & 0xFFFF) /* Version field */ +#define SVR_REV(svr) (((svr) >> 0) & 0xFF) /* Revision field */ + +#define SVR_CID(svr) (((svr) >> 28) & 0x0F) /* Company or manufacturer ID */ +#define SVR_SOCOP(svr) (((svr) >> 22) & 0x3F) /* SOC integration options */ +#define SVR_SID(svr) (((svr) >> 16) & 0x3F) /* SOC ID */ +#define SVR_PROC(svr) (((svr) >> 12) & 0x0F) /* Process revision field */ +#define SVR_MFG(svr) (((svr) >> 8) & 0x0F) /* Manufacturing revision */ +#define SVR_MJREV(svr) (((svr) >> 4) & 0x0F) /* Major SOC design revision indicator */ +#define SVR_MNREV(svr) (((svr) >> 0) & 0x0F) /* Minor SOC design revision indicator */ + +/* Processor Version Register */ + +/* Processor Version Register (PVR) field extraction */ + +#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */ +#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */ + +/* + * AMCC has further subdivided the standard ppc 16-bit version and + * revision subfields of the PVR for the ppc 403s into the following: + */ + +#define PVR_FAM(pvr) (((pvr) >> 20) & 0xFFF) /* Family field */ +#define PVR_MEM(pvr) (((pvr) >> 16) & 0xF) /* Member field */ +#define PVR_CORE(pvr) (((pvr) >> 12) & 0xF) /* Core field */ +#define PVR_CFG(pvr) (((pvr) >> 8) & 0xF) /* Configuration field */ +#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */ +#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */ + +/* e600 core PVR fields */ + +#define PVR_E600_VER(pvr) (((pvr) >> 15) & 0xFFFF) /* Version/type */ +#define PVR_E600_TECH(pvr) (((pvr) >> 12) & 0xF) /* Technology */ +#define PVR_E600_MAJ(pvr) (((pvr) >> 8) & 0xF) /* Major revision */ +#define PVR_E600_MIN(pvr) (((pvr) >> 0) & 0xFF) /* Minor revision */ + +/* Processor Version Numbers */ + +#define PVR_403GA 0x00200000 +#define PVR_403GB 0x00200100 +#define PVR_403GC 0x00200200 +#define PVR_403GCX 0x00201400 +#define PVR_405GP 0x40110000 +#define PVR_405GP_RB 0x40110040 +#define PVR_405GP_RC 0x40110082 +#define PVR_405GP_RD 0x401100C4 +#define PVR_405GP_RE 0x40110145 /* same as pc405cr rev c */ +#define PVR_405EP_RA 0x51210950 +#define PVR_405GPR_RB 0x50910951 +#define PVR_405EZ_RA 0x41511460 +#define PVR_405EXR2_RA 0x12911471 /* 405EXr rev A/B without Security */ +#define PVR_405EX1_RA 0x12911477 /* 405EX rev A/B with Security */ +#define PVR_405EXR1_RC 0x1291147B /* 405EXr rev C with Security */ +#define PVR_405EXR2_RC 0x12911479 /* 405EXr rev C without Security */ +#define PVR_405EX1_RC 0x1291147F /* 405EX rev C with Security */ +#define PVR_405EX2_RC 0x1291147D /* 405EX rev C without Security */ +#define PVR_405EXR1_RD 0x12911472 /* 405EXr rev D with Security */ +#define PVR_405EXR2_RD 0x12911470 /* 405EXr rev D without Security */ +#define PVR_405EX1_RD 0x12911475 /* 405EX rev D with Security */ +#define PVR_405EX2_RD 0x12911473 /* 405EX rev D without Security */ +#define PVR_440GP_RB 0x40120440 +#define PVR_440GP_RC 0x40120481 +#define PVR_440EP_RA 0x42221850 +#define PVR_440EP_RB 0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */ +#define PVR_440EP_RC 0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */ +#define PVR_440GR_RA 0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */ +#define PVR_440GR_RB 0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */ +#define PVR_440EPX1_RA 0x216218D0 /* 440EPX rev A with Security / Kasumi */ +#define PVR_440EPX2_RA 0x216218D4 /* 440EPX rev A without Security / Kasumi */ +#define PVR_440GRX1_RA 0x216218D0 /* 440GRX rev A with Security / Kasumi */ +#define PVR_440GRX2_RA 0x216218D4 /* 440GRX rev A without Security / Kasumi */ +#define PVR_440GX_RA 0x51B21850 +#define PVR_440GX_RB 0x51B21851 +#define PVR_440GX_RC 0x51B21892 +#define PVR_440GX_RF 0x51B21894 +#define PVR_405EP_RB 0x51210950 +#define PVR_440SP_6_RAB 0x53221850 /* 440SP rev A&B with RAID 6 support enabled */ +#define PVR_440SP_RAB 0x53321850 /* 440SP rev A&B without RAID 6 support */ +#define PVR_440SP_6_RC 0x53221891 /* 440SP rev C with RAID 6 support enabled */ +#define PVR_440SP_RC 0x53321891 /* 440SP rev C without RAID 6 support */ +#define PVR_440SPe_6_RA 0x53421890 /* 440SPe rev A with RAID 6 support enabled */ +#define PVR_440SPe_RA 0x53521890 /* 440SPe rev A without RAID 6 support */ +#define PVR_440SPe_6_RB 0x53421891 /* 440SPe rev B with RAID 6 support enabled */ +#define PVR_440SPe_RB 0x53521891 /* 440SPe rev B without RAID 6 support */ +#define PVR_460EX_SE_RA 0x130218A2 /* 460EX rev A with Security Engine */ +#define PVR_460EX_RA 0x130218A3 /* 460EX rev A without Security Engine */ +#define PVR_460EX_RB 0x130218A4 /* 460EX rev B with and without Sec Eng*/ +#define PVR_460GT_SE_RA 0x130218A0 /* 460GT rev A with Security Engine */ +#define PVR_460GT_RA 0x130218A1 /* 460GT rev A without Security Engine */ +#define PVR_460GT_RB 0x130218A5 /* 460GT rev B with and without Sec Eng*/ +#define PVR_460SX_RA 0x13541800 /* 460SX rev A */ +#define PVR_460SX_RA_V1 0x13541801 /* 460SX rev A Variant 1 Security disabled */ +#define PVR_460GX_RA 0x13541802 /* 460GX rev A */ +#define PVR_460GX_RA_V1 0x13541803 /* 460GX rev A Variant 1 Security disabled */ +#define PVR_APM821XX_RA 0x12C41C80 /* APM821XX rev A */ +#define PVR_601 0x00010000 +#define PVR_602 0x00050000 +#define PVR_603 0x00030000 +#define PVR_603e 0x00060000 +#define PVR_603ev 0x00070000 +#define PVR_603r 0x00071000 +#define PVR_604 0x00040000 +#define PVR_604e 0x00090000 +#define PVR_604r 0x000A0000 +#define PVR_620 0x00140000 +#define PVR_740 0x00080000 +#define PVR_750 PVR_740 +#define PVR_740P 0x10080000 +#define PVR_750P PVR_740P +#define PVR_7400 0x000C0000 +#define PVR_7410 0x800C0000 +#define PVR_7450 0x80000000 + +#define PVR_85xx 0x80200000 +#define PVR_85xx_REV1 (PVR_85xx | 0x0010) +#define PVR_85xx_REV2 (PVR_85xx | 0x0020) +#define PVR_VER_E500_V1 0x8020 +#define PVR_VER_E500_V2 0x8021 +#define PVR_VER_E500MC 0x8023 +#define PVR_VER_E5500 0x8024 +#define PVR_VER_E6500 0x8040 + +#define PVR_86xx 0x80040000 + +#define PVR_VIRTEX5 0x7ff21912 + +/* + * For the 8xx processors, all of them report the same PVR family for + * the ppc core. The various versions of these processors must be + * differentiated by the version number in the Communication Processor + * Module (CPM). + */ +#define PVR_821 0x00500000 +#define PVR_823 PVR_821 +#define PVR_850 PVR_821 +#define PVR_860 PVR_821 +#define PVR_7400 0x000C0000 +#define PVR_8240 0x00810100 + +/* + * PowerQUICC II family processors report different PVR values depending + * on silicon process (HiP3, HiP4, HiP7, etc.) + */ +#define PVR_8260 PVR_8240 +#define PVR_8260_HIP3 0x00810101 +#define PVR_8260_HIP4 0x80811014 +#define PVR_8260_HIP7 0x80822011 +#define PVR_8260_HIP7R1 0x80822013 +#define PVR_8260_HIP7RA 0x80822014 + +/* + * MPC 52xx + */ +#define PVR_5200 0x80822011 +#define PVR_5200B 0x80822014 + +/* + * 405EX/EXr CHIP_21 Errata + */ +#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY +#define CONFIG_SYS_4xx_CHIP_21_ERRATA +#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EX1_RC +#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EX1_RD +#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x0 +#endif + +#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY +#define CONFIG_SYS_4xx_CHIP_21_ERRATA +#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EX2_RC +#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EX2_RD +#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x1 +#endif + +#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_SECURITY +#define CONFIG_SYS_4xx_CHIP_21_ERRATA +#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EXR1_RC +#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EXR1_RD +#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x2 +#endif + +#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_NO_SECURITY +#define CONFIG_SYS_4xx_CHIP_21_ERRATA +#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EXR2_RC +#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EXR2_RD +#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x3 +#endif + +/* + * System Version Register + */ + +/* System Version Register (SVR) field extraction */ + +#define SVR_SUBVER(svr) (((svr) >> 8) & 0xFF) /* Process/MFG sub-version */ + +#define SVR_FAM(svr) (((svr) >> 20) & 0xFFF) /* Family field */ +#define SVR_MEM(svr) (((svr) >> 16) & 0xF) /* Member field */ + +#ifdef CONFIG_MPC8536 +#define SVR_MAJ(svr) (((svr) >> 4) & 0x7) /* Major revision field*/ +#else +#define SVR_MAJ(svr) (((svr) >> 4) & 0xF) /* Major revision field*/ +#endif +#define SVR_MIN(svr) (((svr) >> 0) & 0xF) /* Minor revision field*/ + +/* Some parts define SVR[0:23] as the SOC version */ +#define SVR_SOC_VER(svr) (((svr) >> 8) & 0xFFF7FF) /* SOC w/o E bit*/ + +/* whether MPC8xxxE (i.e. has SEC) */ +#if defined(CONFIG_MPC85xx) +#define IS_E_PROCESSOR(svr) (svr & 0x80000) +#else +#if defined(CONFIG_MPC83xx) +#define IS_E_PROCESSOR(spridr) (!(spridr & 0x00010000)) +#endif +#endif + +#define IS_SVR_REV(svr, maj, min) \ + ((SVR_MAJ(svr) == maj) && (SVR_MIN(svr) == min)) + +/* + * SVR_SOC_VER() Version Values + */ + +#define SVR_8533 0x803400 +#define SVR_8535 0x803701 +#define SVR_8536 0x803700 +#define SVR_8540 0x803000 +#define SVR_8541 0x807200 +#define SVR_8543 0x803200 +#define SVR_8544 0x803401 +#define SVR_8545 0x803102 +#define SVR_8547 0x803101 +#define SVR_8548 0x803100 +#define SVR_8555 0x807100 +#define SVR_8560 0x807000 +#define SVR_8567 0x807501 +#define SVR_8568 0x807500 +#define SVR_8569 0x808000 +#define SVR_8572 0x80E000 +#define SVR_P1010 0x80F100 +#define SVR_P1011 0x80E500 +#define SVR_P1012 0x80E501 +#define SVR_P1013 0x80E700 +#define SVR_P1014 0x80F101 +#define SVR_P1017 0x80F700 +#define SVR_P1020 0x80E400 +#define SVR_P1021 0x80E401 +#define SVR_P1022 0x80E600 +#define SVR_P1023 0x80F600 +#define SVR_P1024 0x80E402 +#define SVR_P1025 0x80E403 +#define SVR_P2010 0x80E300 +#define SVR_P2020 0x80E200 +#define SVR_P2040 0x821000 +#define SVR_P2041 0x821001 +#define SVR_P3041 0x821103 +#define SVR_P4040 0x820100 +#define SVR_P4080 0x820000 +#define SVR_P5010 0x822100 +#define SVR_P5020 0x822000 +#define SVR_P5021 0X820500 +#define SVR_P5040 0x820400 +#define SVR_T4240 0x824000 +#define SVR_T4120 0x824001 +#define SVR_T4160 0x824100 +#define SVR_T4080 0x824102 +#define SVR_C291 0x850000 +#define SVR_C292 0x850020 +#define SVR_C293 0x850030 +#define SVR_B4860 0X868000 +#define SVR_G4860 0x868001 +#define SVR_B4460 0x868003 +#define SVR_B4440 0x868100 +#define SVR_G4440 0x868101 +#define SVR_B4420 0x868102 +#define SVR_B4220 0x868103 +#define SVR_T1040 0x852000 +#define SVR_T1041 0x852001 +#define SVR_T1042 0x852002 +#define SVR_T1020 0x852100 +#define SVR_T1021 0x852101 +#define SVR_T1022 0x852102 +#define SVR_T1024 0x854000 +#define SVR_T1023 0x854100 +#define SVR_T1014 0x854400 +#define SVR_T1013 0x854500 +#define SVR_T2080 0x853000 +#define SVR_T2081 0x853100 + +#define SVR_8610 0x80A000 +#define SVR_8641 0x809000 +#define SVR_8641D 0x809001 + +#define SVR_9130 0x860001 +#define SVR_9131 0x860000 +#define SVR_9132 0x861000 +#define SVR_9232 0x861400 + +#define SVR_Unknown 0xFFFFFF + +#define _GLOBAL(n) \ + .globl n; \ + n: + +/* Macros for setting and retrieving special purpose registers */ + +#define stringify(s) tostring(s) +#define tostring(s) #s + +#define mfdcr(rn) ({unsigned int rval; \ + asm volatile("mfdcr %0," stringify(rn) \ + : "=r" (rval)); rval; }) +#define mtdcr(rn, v) asm volatile("mtdcr " stringify(rn) ",%0" \ + : \ + : "r"(v)) + +#define mfmsr() ({unsigned int rval; \ + asm volatile("mfmsr %0" : "=r" (rval)); rval; }) +#define mtmsr(v) asm volatile("mtmsr %0" \ + : \ + : "r"(v)) + +#define mfspr(rn) ({unsigned int rval; \ + asm volatile("mfspr %0," stringify(rn) \ + : "=r" (rval)); rval; }) +#define mtspr(rn, v) asm volatile("mtspr " stringify(rn) ",%0" \ + : \ + : "r"(v)) + +#define tlbie(v) asm volatile("tlbie %0 \n sync" \ + : \ + : "r"(v)) + +/* Segment Registers */ + +#define SR0 0 +#define SR1 1 +#define SR2 2 +#define SR3 3 +#define SR4 4 +#define SR5 5 +#define SR6 6 +#define SR7 7 +#define SR8 8 +#define SR9 9 +#define SR10 10 +#define SR11 11 +#define SR12 12 +#define SR13 13 +#define SR14 14 +#define SR15 15 + +#ifndef __ASSEMBLY__ + +#include + +struct cpu_type +{ + char name[15]; + uint32_t soc_ver; + uint32_t num_cores; + uint32_t mask; /* which cpu(s) actually exist */ +#ifdef CONFIG_HETROGENOUS_CLUSTERS + uint32_t dsp_num_cores; + uint32_t dsp_mask; /* which DSP cpu(s) actually exist */ +#endif +}; + +struct cpu_type* identify_cpu(uint32_t ver); +int fixup_cpu(void); + +int fsl_qoriq_core_to_cluster(unsigned int core); +int fsl_qoriq_dsp_core_to_cluster(unsigned int core); + +#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) +#define CPU_TYPE_ENTRY(n, v, nc) \ + { \ + .name = #n, .soc_ver = SVR_##v, .num_cores = (nc), \ + .mask = (1 << (nc)) - 1 \ + } +#define CPU_TYPE_ENTRY_MASK(n, v, nc, m) \ + { \ + .name = #n, .soc_ver = SVR_##v, .num_cores = (nc), .mask = (m) \ + } +#else +#if defined(CONFIG_MPC83xx) +#define CPU_TYPE_ENTRY(x) \ + { \ +#x, SPR_##x \ + } +#endif +#endif + +#ifndef CONFIG_MACH_SPECIFIC +extern int _machine; +extern int have_of; +#endif /* CONFIG_MACH_SPECIFIC */ + +/* what kind of prep workstation we are */ +extern int _prep_type; +/* + * This is used to identify the board type from a given PReP board + * vendor. Board revision is also made available. + */ +extern unsigned char ucSystemType; +extern unsigned char ucBoardRev; +extern unsigned char ucBoardRevMaj, ucBoardRevMin; + +struct task_struct; +void start_thread(struct pt_regs* regs, unsigned long nip, unsigned long sp); +void release_thread(struct task_struct*); + +/* + * Create a new Kernel thread. + */ +extern long kernel_thread(int (*fn)(void*), void* arg, unsigned long flags); + +/* + * Bus types + */ +#define EISA_bus 0 +#define EISA_bus__is_a_macro /* for versions in ksyms.c */ +#define MCA_bus 0 +#define MCA_bus__is_a_macro /* for versions in ksyms.c */ + +/* Lazy FPU handling on uni-processor */ +extern struct task_struct* last_task_used_math; +extern struct task_struct* last_task_used_altivec; + +/* + * this is the minimum allowable io space due to the location + * of the io areas on prep (first one at 0x80000000) but + * as soon as I get around to remapping the io areas with the BATs + * to match the mac we can raise this. -- Cort + */ +#define TASK_SIZE (0x80000000UL) + +/* This decides where the Kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3) + +typedef struct +{ + unsigned long seg; +} mm_segment_t; + +struct thread_struct +{ + unsigned long ksp; /* Kernel stack pointer */ + unsigned long wchan; /* Event task is sleeping on */ + struct pt_regs* regs; /* Pointer to saved register state */ + mm_segment_t fs; /* for get_fs() validation */ + void* pgdir; /* root of page-table tree */ + signed long last_syscall; + double fpr[32]; /* Complete floating point set */ + unsigned long fpscr_pad; /* fpr ... fpscr must be contiguous */ + unsigned long fpscr; /* Floating point status */ +#ifdef CONFIG_ALTIVEC + vector128 vr[32]; /* Complete AltiVec set */ + vector128 vscr; /* AltiVec status */ + unsigned long vrsave; +#endif /* CONFIG_ALTIVEC */ +}; + +#define INIT_SP (sizeof(init_stack) + (unsigned long)&init_stack) + +#define INIT_THREAD \ + { \ + INIT_SP, /* ksp */ \ + 0, /* wchan */ \ + (struct pt_regs*)INIT_SP - 1, /* regs */ \ + KERNEL_DS, /*fs*/ \ + swapper_pg_dir, /* pgdir */ \ + 0, /* last_syscall */ \ + {0}, 0, 0 \ + } + +/* + * Note: the vm_start and vm_end fields here should *not* + * be in Kernel space. (Could vm_end == vm_start perhaps?) + */ +#define INIT_MMAP \ + { \ + &init_mm, 0, 0x1000, NULL, \ + PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, \ + 1, NULL, NULL \ + } + +/* + * Return saved PC of a blocked thread. For now, this is the "user" PC + */ +static inline unsigned long thread_saved_pc(struct thread_struct* t) +{ + return (t->regs) ? t->regs->nip : 0; +} + +#define copy_segments(tsk, mm) \ + do \ + { \ + } while (0) +#define release_segments(mm) \ + do \ + { \ + } while (0) +#define forget_segments() \ + do \ + { \ + } while (0) + +unsigned long get_wchan(struct task_struct* p); + +#define KSTK_EIP(tsk) ((tsk)->thread.regs->nip) +#define KSTK_ESP(tsk) ((tsk)->thread.regs->gpr[1]) + +/* + * NOTE! The task struct and the stack go together + */ +#define THREAD_SIZE (2 * PAGE_SIZE) +#define alloc_task_struct() \ + ((struct task_struct*)__get_free_pages(GFP_KERNEL, 1)) +#define free_task_struct(p) free_pages((unsigned long)(p), 1) +#define get_task_struct(tsk) atomic_inc(&mem_map[MAP_NR(tsk)].count) + +/* in process.c - for early bootup debug -- Cort */ +int ll_printk(const char*, ...); +void ll_puts(const char*); + +#define init_task (init_task_union.task) +#define init_stack (init_task_union.stack) + +/* In misc.c */ +void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); + +#endif /* ndef ASSEMBLY*/ + +#ifdef CONFIG_MACH_SPECIFIC +#if defined(CONFIG_8xx) +#define _machine _MACH_8xx +#define have_of 0 +#elif defined(CONFIG_WALNUT) +#define _machine _MACH_walnut +#define have_of 0 +#elif defined(CONFIG_MPC8260) +#define _machine _MACH_8260 +#define have_of 0 +#else +#error "Machine not defined correctly" +#endif +#endif /* CONFIG_MACH_SPECIFIC */ + +#if defined(CONFIG_MPC85xx) || defined(CONFIG_440) +#define EPAPR_MAGIC (0x45504150) +#else +#define EPAPR_MAGIC (0x65504150) +#endif + +#endif /* __ASM_PPC_PROCESSOR_H */ diff --git a/Kernel/HALKit/POWER/ppc-mmu.h b/Kernel/HALKit/POWER/ppc-mmu.h new file mode 100644 index 00000000..8546b0fb --- /dev/null +++ b/Kernel/HALKit/POWER/ppc-mmu.h @@ -0,0 +1,811 @@ + +#ifndef _PPC_MMU_H_ +#define _PPC_MMU_H_ + +#ifndef __ASSEMBLY__ + +#include + +/* Hardware Page Table Entry */ +typedef struct _PTE +{ +#ifdef CONFIG_PPC64BRIDGE + unsigned long long vsid : 52; + unsigned long api : 5; + unsigned long : 5; + unsigned long h : 1; + unsigned long v : 1; + unsigned long long rpn : 52; +#else /* CONFIG_PPC64BRIDGE */ + unsigned long v : 1; /* Entry is valid */ + unsigned long vsid : 24; /* Virtual segment identifier */ + unsigned long h : 1; /* Hash algorithm indicator */ + unsigned long api : 6; /* Abbreviated page index */ + unsigned long rpn : 20; /* Real (physical) page number */ +#endif /* CONFIG_PPC64BRIDGE */ + unsigned long : 3; /* Unused */ + unsigned long r : 1; /* Referenced */ + unsigned long c : 1; /* Changed */ + unsigned long w : 1; /* Write-thru cache mode */ + unsigned long i : 1; /* Cache inhibited */ + unsigned long m : 1; /* Memory coherence */ + unsigned long g : 1; /* Guarded */ + unsigned long : 1; /* Unused */ + unsigned long pp : 2; /* Page protection */ +} PTE; + +/* Values for PP (assumes Ks=0, Kp=1) */ +#define PP_RWXX 0 /* Supervisor read/write, User none */ +#define PP_RWRX 1 /* Supervisor read/write, User read */ +#define PP_RWRW 2 /* Supervisor read/write, User read/write */ +#define PP_RXRX 3 /* Supervisor read, User read */ + +/* Segment Register */ +typedef struct _SEGREG +{ + unsigned long t : 1; /* Normal or I/O type */ + unsigned long ks : 1; /* Supervisor 'key' (normally 0) */ + unsigned long kp : 1; /* User 'key' (normally 1) */ + unsigned long n : 1; /* No-execute */ + unsigned long : 4; /* Unused */ + unsigned long vsid : 24; /* Virtual Segment Identifier */ +} SEGREG; + +/* Block Address Translation (BAT) Registers */ +typedef struct _P601_BATU +{ /* Upper part of BAT for 601 processor */ + unsigned long bepi : 15; /* Effective page index (virtual address) */ + unsigned long : 8; /* unused */ + unsigned long w : 1; + unsigned long i : 1; /* Cache inhibit */ + unsigned long m : 1; /* Memory coherence */ + unsigned long ks : 1; /* Supervisor key (normally 0) */ + unsigned long kp : 1; /* User key (normally 1) */ + unsigned long pp : 2; /* Page access protections */ +} P601_BATU; + +typedef struct _BATU +{ /* Upper part of BAT (all except 601) */ +#ifdef CONFIG_PPC64BRIDGE + unsigned long long bepi : 47; +#else /* CONFIG_PPC64BRIDGE */ + unsigned long bepi : 15; /* Effective page index (virtual address) */ +#endif /* CONFIG_PPC64BRIDGE */ + unsigned long : 4; /* Unused */ + unsigned long bl : 11; /* Block size mask */ + unsigned long vs : 1; /* Supervisor valid */ + unsigned long vp : 1; /* User valid */ +} BATU; + +typedef struct _P601_BATL +{ /* Lower part of BAT for 601 processor */ + unsigned long brpn : 15; /* Real page index (physical address) */ + unsigned long : 10; /* Unused */ + unsigned long v : 1; /* Valid bit */ + unsigned long bl : 6; /* Block size mask */ +} P601_BATL; + +typedef struct _BATL +{ /* Lower part of BAT (all except 601) */ +#ifdef CONFIG_PPC64BRIDGE + unsigned long long brpn : 47; +#else /* CONFIG_PPC64BRIDGE */ + unsigned long brpn : 15; /* Real page index (physical address) */ +#endif /* CONFIG_PPC64BRIDGE */ + unsigned long : 10; /* Unused */ + unsigned long w : 1; /* Write-thru cache */ + unsigned long i : 1; /* Cache inhibit */ + unsigned long m : 1; /* Memory coherence */ + unsigned long g : 1; /* Guarded (MBZ in IBAT) */ + unsigned long : 1; /* Unused */ + unsigned long pp : 2; /* Page access protections */ +} BATL; + +typedef struct _BAT +{ + BATU batu; /* Upper register */ + BATL batl; /* Lower register */ +} BAT; + +typedef struct _P601_BAT +{ + P601_BATU batu; /* Upper register */ + P601_BATL batl; /* Lower register */ +} P601_BAT; + +/* + * Simulated two-level MMU. This structure is used by the Kernel + * to keep track of MMU mappings and is used to update/maintain + * the hardware HASH table which is really a cache of mappings. + * + * The simulated structures mimic the hardware available on other + * platforms, notably the 80x86 and 680x0. + */ + +typedef struct _pte +{ + unsigned long page_num : 20; + unsigned long flags : 12; /* Page flags (some unused bits) */ +} pte; + +#define PD_SHIFT (10 + 12) /* Page directory */ +#define PD_MASK 0x02FF +#define PT_SHIFT (12) /* Page Table */ +#define PT_MASK 0x02FF +#define PG_SHIFT (12) /* Page Entry */ + +/* MMU context */ + +typedef struct _MMU_context +{ + SEGREG segs[16]; /* Segment registers */ + pte** pmap; /* Two-level page-map structure */ +} MMU_context; + +extern void _tlbie(unsigned long va); /* invalidate a TLB entry */ +extern void _tlbia(void); /* invalidate all TLB entries */ + +#ifdef CONFIG_ADDR_MAP +extern void init_addr_map(void); +#endif + +typedef enum +{ + IBAT0 = 0, + IBAT1, + IBAT2, + IBAT3, + DBAT0, + DBAT1, + DBAT2, + DBAT3, +#ifdef CONFIG_HIGH_BATS + IBAT4, + IBAT5, + IBAT6, + IBAT7, + DBAT4, + DBAT5, + DBAT6, + DBAT7 +#endif +} ppc_bat_t; + +extern int read_bat(ppc_bat_t bat, unsigned long* upper, unsigned long* lower); +extern int write_bat(ppc_bat_t bat, unsigned long upper, unsigned long lower); +extern void print_bats(void); + +#endif /* __ASSEMBLY__ */ + +#define BATU_VS 0x00000002 +#define BATU_VP 0x00000001 +#define BATU_INVALID 0x00000000 + +#define BATL_WRITETHROUGH 0x00000040 +#define BATL_CACHEINHIBIT 0x00000020 +#define BATL_MEMCOHERENCE 0x00000010 +#define BATL_GUARDEDSTORAGE 0x00000008 +#define BATL_NO_ACCESS 0x00000000 + +#define BATL_PP_MSK 0x00000003 +#define BATL_PP_00 0x00000000 /* No access */ +#define BATL_PP_01 0x00000001 /* Read-only */ +#define BATL_PP_10 0x00000002 /* Read-write */ +#define BATL_PP_11 0x00000003 + +#define BATL_PP_NO_ACCESS BATL_PP_00 +#define BATL_PP_RO BATL_PP_01 +#define BATL_PP_RW BATL_PP_10 + +/* BAT Block size values */ +#define BATU_BL_128K 0x00000000 +#define BATU_BL_256K 0x00000004 +#define BATU_BL_512K 0x0000000c +#define BATU_BL_1M 0x0000001c +#define BATU_BL_2M 0x0000003c +#define BATU_BL_4M 0x0000007c +#define BATU_BL_8M 0x000000fc +#define BATU_BL_16M 0x000001fc +#define BATU_BL_32M 0x000003fc +#define BATU_BL_64M 0x000007fc +#define BATU_BL_128M 0x00000ffc +#define BATU_BL_256M 0x00001ffc + +/* Block lengths for processors that support extended block length */ +#ifdef HID0_XBSEN +#define BATU_BL_512M 0x00003ffc +#define BATU_BL_1G 0x00007ffc +#define BATU_BL_2G 0x0000fffc +#define BATU_BL_4G 0x0001fffc +#define BATU_BL_MAX BATU_BL_4G +#else +#define BATU_BL_MAX BATU_BL_256M +#endif + +/* BAT Access Protection */ +#define BPP_XX 0x00 /* No access */ +#define BPP_RX 0x01 /* Read only */ +#define BPP_RW 0x02 /* Read/write */ + +/* Macros to get values from BATs, once data is in the BAT register format */ +#define BATU_VALID(x) (x & 0x3) +#define BATU_VADDR(x) (x & 0xfffe0000) +#define BATL_PADDR(x) ((phys_addr_t)((x & 0xfffe0000) | ((x & 0x0e00ULL) << 24) | ((x & 0x04ULL) << 30))) +#define BATU_SIZE(x) (1ULL << (fls((x & BATU_BL_MAX) >> 2) + 17)) + +/* bytes into BATU_BL */ +#define TO_BATU_BL(x) \ + (uint32_t)((((1ull << __ilog2_u64((uint64_t)x)) / (128 * 1024)) - 1) * 4) + +/* Used to set up SDR1 register */ +#define HASH_TABLE_SIZE_64K 0x00010000 +#define HASH_TABLE_SIZE_128K 0x00020000 +#define HASH_TABLE_SIZE_256K 0x00040000 +#define HASH_TABLE_SIZE_512K 0x00080000 +#define HASH_TABLE_SIZE_1M 0x00100000 +#define HASH_TABLE_SIZE_2M 0x00200000 +#define HASH_TABLE_SIZE_4M 0x00400000 +#define HASH_TABLE_MASK_64K 0x000 +#define HASH_TABLE_MASK_128K 0x001 +#define HASH_TABLE_MASK_256K 0x003 +#define HASH_TABLE_MASK_512K 0x007 +#define HASH_TABLE_MASK_1M 0x00F +#define HASH_TABLE_MASK_2M 0x01F +#define HASH_TABLE_MASK_4M 0x03F + +/* Control/status registers for the MPC8xx. + * A write operation to these registers causes serialized access. + * During software tablewalk, the registers used perform mask/shift-add + * operations when written/read. A TLB entry is created when the Mx_RPN + * is written, and the contents of several registers are used to + * create the entry. + */ +#define MI_CTR 784 /* Instruction TLB control register */ +#define MI_GPM 0x80000000 /* Set domain manager mode */ +#define MI_PPM 0x40000000 /* Set subpage protection */ +#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */ +#define MI_RSV4I 0x08000000 /* Reserve 4 TLB entries */ +#define MI_PPCS 0x02000000 /* Use MI_RPN prob/priv state */ +#define MI_IDXMASK 0x00001f00 /* TLB index to be loaded */ +#define MI_RESETVAL 0x00000000 /* Value of register at reset */ + +/* These are the Ks and Kp from the ppc books. For proper operation, + * Ks = 0, Kp = 1. + */ +#define MI_AP 786 +#define MI_Ks 0x80000000 /* Should not be set */ +#define MI_Kp 0x40000000 /* Should always be set */ + +/* The effective page number register. When read, contains the information + * about the last instruction TLB miss. When MI_RPN is written, bits in + * this register are used to create the TLB entry. + */ +#define MI_EPN 787 +#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */ +#define MI_EVALID 0x00000200 /* Entry is valid */ +#define MI_ASIDMASK 0x0000000f /* ASID match value */ + /* Reset value is undefined */ + +/* A "level 1" or "segment" or whatever you want to call it register. + * For the instruction TLB, it contains bits that get loaded into the + * TLB entry when the MI_RPN is written. + */ +#define MI_TWC 789 +#define MI_APG 0x000001e0 /* Access protection group (0) */ +#define MI_GUARDED 0x00000010 /* Guarded storage */ +#define MI_PSMASK 0x0000000c /* Mask of page size bits */ +#define MI_PS8MEG 0x0000000c /* 8M page size */ +#define MI_PS512K 0x00000004 /* 512K page size */ +#define MI_PS4K_16K 0x00000000 /* 4K or 16K page size */ +#define MI_SVALID 0x00000001 /* Segment entry is valid */ + /* Reset value is undefined */ + +/* Real page number. Defined by the pte. Writing this register + * causes a TLB entry to be created for the instruction TLB, using + * additional information from the MI_EPN, and MI_TWC registers. + */ +#define MI_RPN 790 + +/* Define an RPN value for mapping Kernel memory to large virtual + * pages for boot initialization. This has real page number of 0, + * large page size, shared page, cache enabled, and valid. + * Also mark all subpages valid and write access. + */ +#define MI_BOOTINIT 0x000001fd + +#define MD_CTR 792 /* Data TLB control register */ +#define MD_GPM 0x80000000 /* Set domain manager mode */ +#define MD_PPM 0x40000000 /* Set subpage protection */ +#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */ +#define MD_WTDEF 0x10000000 /* Set writethrough when MMU dis */ +#define MD_RSV4I 0x08000000 /* Reserve 4 TLB entries */ +#define MD_TWAM 0x04000000 /* Use 4K page hardware assist */ +#define MD_PPCS 0x02000000 /* Use MI_RPN prob/priv state */ +#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */ +#define MD_RESETVAL 0x04000000 /* Value of register at reset */ + +#define M_CASID 793 /* Address space ID (context) to match */ +#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */ + +/* These are the Ks and Kp from the ppc books. For proper operation, + * Ks = 0, Kp = 1. + */ +#define MD_AP 794 +#define MD_Ks 0x80000000 /* Should not be set */ +#define MD_Kp 0x40000000 /* Should always be set */ + +/* The effective page number register. When read, contains the information + * about the last instruction TLB miss. When MD_RPN is written, bits in + * this register are used to create the TLB entry. + */ +#define MD_EPN 795 +#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */ +#define MD_EVALID 0x00000200 /* Entry is valid */ +#define MD_ASIDMASK 0x0000000f /* ASID match value */ + /* Reset value is undefined */ + +/* The pointer to the base address of the first level page table. + * During a software tablewalk, reading this register provides the address + * of the entry associated with MD_EPN. + */ +#define M_TWB 796 +#define M_L1TB 0xfffff000 /* Level 1 table base address */ +#define M_L1INDX 0x00000ffc /* Level 1 index, when read */ + /* Reset value is undefined */ + +/* A "level 1" or "segment" or whatever you want to call it register. + * For the data TLB, it contains bits that get loaded into the TLB entry + * when the MD_RPN is written. It is also provides the hardware assist + * for finding the PTE address during software tablewalk. + */ +#define MD_TWC 797 +#define MD_L2TB 0xfffff000 /* Level 2 table base address */ +#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */ +#define MD_APG 0x000001e0 /* Access protection group (0) */ +#define MD_GUARDED 0x00000010 /* Guarded storage */ +#define MD_PSMASK 0x0000000c /* Mask of page size bits */ +#define MD_PS8MEG 0x0000000c /* 8M page size */ +#define MD_PS512K 0x00000004 /* 512K page size */ +#define MD_PS4K_16K 0x00000000 /* 4K or 16K page size */ +#define MD_WT 0x00000002 /* Use writethrough page attribute */ +#define MD_SVALID 0x00000001 /* Segment entry is valid */ + /* Reset value is undefined */ + +/* Real page number. Defined by the pte. Writing this register + * causes a TLB entry to be created for the data TLB, using + * additional information from the MD_EPN, and MD_TWC registers. + */ +#define MD_RPN 798 + +/* This is a temporary storage register that could be used to save + * a processor working register during a tablewalk. + */ +#define M_TW 799 + +/* + * At present, all ppc 400-class processors share a similar TLB + * architecture. The instruction and data sides share a unified, + * 64-entry, fully-associative TLB which is maintained totally under + * software control. In addition, the instruction side has a + * hardware-managed, 4-entry, fully- associative TLB which serves as a + * first level to the shared TLB. These two TLBs are known as the UTLB + * and ITLB, respectively. + */ + +#define PPC4XX_TLB_SIZE 64 + +/* + * TLB entries are defined by a "high" tag portion and a "low" data + * portion. On all architectures, the data portion is 32-bits. + * + * TLB entries are managed entirely under software control by reading, + * writing, and searchoing using the 4xx-specific tlbre, tlbwr, and tlbsx + * instructions. + */ + +/* + * FSL Book-E support + */ + +#define MAS0_TLBSEL_MSK 0x30000000 +#define MAS0_TLBSEL(x) (((x) << 28) & MAS0_TLBSEL_MSK) +#define MAS0_ESEL_MSK 0x0FFF0000 +#define MAS0_ESEL(x) (((x) << 16) & MAS0_ESEL_MSK) +#define MAS0_NV(x) ((x)&0x00000FFF) + +#define MAS1_VALID 0x80000000 +#define MAS1_IPROT 0x40000000 +#define MAS1_TID(x) (((x) << 16) & 0x3FFF0000) +#define MAS1_TS 0x00001000 +#define MAS1_TSIZE(x) (((x) << 7) & 0x00000F80) +#define TSIZE_TO_BYTES(x) (1ULL << ((x) + 10)) + +#define MAS2_EPN 0xFFFFF000 +#define MAS2_X0 0x00000040 +#define MAS2_X1 0x00000020 +#define MAS2_W 0x00000010 +#define MAS2_I 0x00000008 +#define MAS2_M 0x00000004 +#define MAS2_G 0x00000002 +#define MAS2_E 0x00000001 + +#define MAS3_RPN 0xFFFFF000 +#define MAS3_U0 0x00000200 +#define MAS3_U1 0x00000100 +#define MAS3_U2 0x00000080 +#define MAS3_U3 0x00000040 +#define MAS3_UX 0x00000020 +#define MAS3_SX 0x00000010 +#define MAS3_UW 0x00000008 +#define MAS3_SW 0x00000004 +#define MAS3_UR 0x00000002 +#define MAS3_SR 0x00000001 + +#define MAS4_TLBSELD(x) MAS0_TLBSEL(x) +#define MAS4_TIDDSEL 0x000F0000 +#define MAS4_TSIZED(x) MAS1_TSIZE(x) +#define MAS4_X0D 0x00000040 +#define MAS4_X1D 0x00000020 +#define MAS4_WD 0x00000010 +#define MAS4_ID 0x00000008 +#define MAS4_MD 0x00000004 +#define MAS4_GD 0x00000002 +#define MAS4_ED 0x00000001 + +#define MAS6_SPID0 0x3FFF0000 +#define MAS6_SPID1 0x00007FFE +#define MAS6_SAS 0x00000001 +#define MAS6_SPID MAS6_SPID0 + +#define MAS7_RPN 0xFFFFFFFF + +#define FSL_BOOKE_MAS0(tlbsel, esel, nv) \ + (MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel) | MAS0_NV(nv)) +#define FSL_BOOKE_MAS1(v, iprot, tid, ts, tsize) \ + ((((v) << 31) & MAS1_VALID) | \ + (((iprot) << 30) & MAS1_IPROT) | \ + (MAS1_TID(tid)) | \ + (((ts) << 12) & MAS1_TS) | \ + (MAS1_TSIZE(tsize))) +#define FSL_BOOKE_MAS2(epn, wimge) \ + (((epn)&MAS3_RPN) | (wimge)) +#define FSL_BOOKE_MAS3(rpn, user, perms) \ + (((rpn)&MAS3_RPN) | (user) | (perms)) +#define FSL_BOOKE_MAS7(rpn) \ + (((uint64_t)(rpn)) >> 32) + +#define BOOKE_PAGESZ_1K 0 +#define BOOKE_PAGESZ_2K 1 +#define BOOKE_PAGESZ_4K 2 +#define BOOKE_PAGESZ_8K 3 +#define BOOKE_PAGESZ_16K 4 +#define BOOKE_PAGESZ_32K 5 +#define BOOKE_PAGESZ_64K 6 +#define BOOKE_PAGESZ_128K 7 +#define BOOKE_PAGESZ_256K 8 +#define BOOKE_PAGESZ_512K 9 +#define BOOKE_PAGESZ_1M 10 +#define BOOKE_PAGESZ_2M 11 +#define BOOKE_PAGESZ_4M 12 +#define BOOKE_PAGESZ_8M 13 +#define BOOKE_PAGESZ_16M 14 +#define BOOKE_PAGESZ_32M 15 +#define BOOKE_PAGESZ_64M 16 +#define BOOKE_PAGESZ_128M 17 +#define BOOKE_PAGESZ_256M 18 +#define BOOKE_PAGESZ_512M 19 +#define BOOKE_PAGESZ_1G 20 +#define BOOKE_PAGESZ_2G 21 +#define BOOKE_PAGESZ_4G 22 +#define BOOKE_PAGESZ_8G 23 +#define BOOKE_PAGESZ_16GB 24 +#define BOOKE_PAGESZ_32GB 25 +#define BOOKE_PAGESZ_64GB 26 +#define BOOKE_PAGESZ_128GB 27 +#define BOOKE_PAGESZ_256GB 28 +#define BOOKE_PAGESZ_512GB 29 +#define BOOKE_PAGESZ_1TB 30 +#define BOOKE_PAGESZ_2TB 31 + +#define TLBIVAX_ALL 4 +#define TLBIVAX_TLB0 0 +#define TLBIVAX_TLB1 8 + +#ifdef CONFIG_E500 +#ifndef __ASSEMBLY__ +extern void set_tlb(uint8_t tlb, uint32_t epn, uint64_t rpn, uint8_t perms, uint8_t wimge, uint8_t ts, uint8_t esel, uint8_t tsize, uint8_t iprot); +extern void disable_tlb(uint8_t esel); +extern void invalidate_tlb(uint8_t tlb); +extern void init_tlbs(void); +extern int find_tlb_idx(void* addr, uint8_t tlbsel); +extern void init_used_tlb_cams(void); +extern int find_free_tlbcam(void); +extern void print_tlbcam(void); + +extern unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg); +extern void clear_ddr_tlbs(unsigned int memsize_in_meg); + +enum tlb_map_type +{ + TLB_MAP_RAM, + TLB_MAP_IO, +}; + +extern uint64_t tlb_map_range(ulong_t v_addr, phys_addr_t p_addr, uint64_t size, enum tlb_map_type map_type); + +extern void write_tlb(uint32_t _mas0, uint32_t _mas1, uint32_t _mas2, uint32_t _mas3, uint32_t _mas7); + +#define SET_TLB_ENTRY(_tlb, _epn, _rpn, _perms, _wimge, _ts, _esel, _sz, _iprot) \ + { \ + .mas0 = FSL_BOOKE_MAS0(_tlb, _esel, 0), \ + .mas1 = FSL_BOOKE_MAS1(1, _iprot, 0, _ts, _sz), \ + .mas2 = FSL_BOOKE_MAS2(_epn, _wimge), \ + .mas3 = FSL_BOOKE_MAS3(_rpn, 0, _perms), \ + .mas7 = FSL_BOOKE_MAS7(_rpn), \ + } + +struct fsl_e_tlb_entry +{ + uint32_t mas0; + uint32_t mas1; + uint32_t mas2; + uint32_t mas3; + uint32_t mas7; +}; + +extern struct fsl_e_tlb_entry tlb_table[]; +extern int num_tlb_entries; +#endif +#endif + +#ifdef CONFIG_E300 +#define LAWAR_EN 0x80000000 +#define LAWAR_SIZE 0x0000003F + +#define LAWAR_TRGT_IF_PCI 0x00000000 +#define LAWAR_TRGT_IF_PCI1 0x00000000 +#define LAWAR_TRGT_IF_PCIX 0x00000000 +#define LAWAR_TRGT_IF_PCI2 0x00100000 +#define LAWAR_TRGT_IF_PCIE1 0x00200000 +#define LAWAR_TRGT_IF_PCIE2 0x00100000 +#define LAWAR_TRGT_IF_PCIE3 0x00300000 +#define LAWAR_TRGT_IF_LBC 0x00400000 +#define LAWAR_TRGT_IF_CCSR 0x00800000 +#define LAWAR_TRGT_IF_DDR_INTERLEAVED 0x00B00000 +#define LAWAR_TRGT_IF_RIO 0x00c00000 +#define LAWAR_TRGT_IF_DDR 0x00f00000 +#define LAWAR_TRGT_IF_DDR1 0x00f00000 +#define LAWAR_TRGT_IF_DDR2 0x01600000 + +#define LAWAR_SIZE_BASE 0xa +#define LAWAR_SIZE_4K (LAWAR_SIZE_BASE + 1) +#define LAWAR_SIZE_8K (LAWAR_SIZE_BASE + 2) +#define LAWAR_SIZE_16K (LAWAR_SIZE_BASE + 3) +#define LAWAR_SIZE_32K (LAWAR_SIZE_BASE + 4) +#define LAWAR_SIZE_64K (LAWAR_SIZE_BASE + 5) +#define LAWAR_SIZE_128K (LAWAR_SIZE_BASE + 6) +#define LAWAR_SIZE_256K (LAWAR_SIZE_BASE + 7) +#define LAWAR_SIZE_512K (LAWAR_SIZE_BASE + 8) +#define LAWAR_SIZE_1M (LAWAR_SIZE_BASE + 9) +#define LAWAR_SIZE_2M (LAWAR_SIZE_BASE + 10) +#define LAWAR_SIZE_4M (LAWAR_SIZE_BASE + 11) +#define LAWAR_SIZE_8M (LAWAR_SIZE_BASE + 12) +#define LAWAR_SIZE_16M (LAWAR_SIZE_BASE + 13) +#define LAWAR_SIZE_32M (LAWAR_SIZE_BASE + 14) +#define LAWAR_SIZE_64M (LAWAR_SIZE_BASE + 15) +#define LAWAR_SIZE_128M (LAWAR_SIZE_BASE + 16) +#define LAWAR_SIZE_256M (LAWAR_SIZE_BASE + 17) +#define LAWAR_SIZE_512M (LAWAR_SIZE_BASE + 18) +#define LAWAR_SIZE_1G (LAWAR_SIZE_BASE + 19) +#define LAWAR_SIZE_2G (LAWAR_SIZE_BASE + 20) +#define LAWAR_SIZE_4G (LAWAR_SIZE_BASE + 21) +#define LAWAR_SIZE_8G (LAWAR_SIZE_BASE + 22) +#define LAWAR_SIZE_16G (LAWAR_SIZE_BASE + 23) +#define LAWAR_SIZE_32G (LAWAR_SIZE_BASE + 24) +#endif + +#ifdef CONFIG_440 +/* General */ +#define TLB_VALID 0x00000200 + +/* Supported page sizes */ + +#define SZ_1K 0x00000000 +#define SZ_4K 0x00000010 +#define SZ_16K 0x00000020 +#define SZ_64K 0x00000030 +#define SZ_256K 0x00000040 +#define SZ_1M 0x00000050 +#define SZ_16M 0x00000070 +#define SZ_256M 0x00000090 + +/* Storage attributes */ +#define SA_W 0x00000800 /* Write-through */ +#define SA_I 0x00000400 /* Caching inhibited */ +#define SA_M 0x00000200 /* Memory coherence */ +#define SA_G 0x00000100 /* Guarded */ +#define SA_E 0x00000080 /* Endian */ +/* Some additional macros for combinations often used */ +#define SA_IG (SA_I | SA_G) + +/* Access control */ +#define AC_X 0x00000024 /* Execute */ +#define AC_W 0x00000012 /* Write */ +#define AC_R 0x00000009 /* Read */ +/* Some additional macros for combinations often used */ +#define AC_RW (AC_R | AC_W) +#define AC_RWX (AC_R | AC_W | AC_X) + +/* Some handy macros */ + +#define EPN(e) ((e)&0xfffffc00) +#define TLB0(epn, sz) ((EPN((epn)) | (sz) | TLB_VALID)) +#define TLB1(rpn, erpn) (((rpn)&0xfffffc00) | (erpn)) +#define TLB2(a) ((a)&0x00000fbf) + +#define tlbtab_start \ + mflr r1; \ + bl 0f; + +#define tlbtab_end \ + .long 0, 0, 0; \ + 0 : mflr r0; \ + mtlr r1; \ + blr; + +#define tlbentry(epn, sz, rpn, erpn, attr) \ + .long TLB0(epn, sz), TLB1(rpn, erpn), TLB2(attr) + +/*----------------------------------------------------------------------------+ +| TLB specific defines. ++----------------------------------------------------------------------------*/ +#define TLB_256MB_ALIGN_MASK 0xFF0000000ULL +#define TLB_16MB_ALIGN_MASK 0xFFF000000ULL +#define TLB_1MB_ALIGN_MASK 0xFFFF00000ULL +#define TLB_256KB_ALIGN_MASK 0xFFFFC0000ULL +#define TLB_64KB_ALIGN_MASK 0xFFFFF0000ULL +#define TLB_16KB_ALIGN_MASK 0xFFFFFC000ULL +#define TLB_4KB_ALIGN_MASK 0xFFFFFF000ULL +#define TLB_1KB_ALIGN_MASK 0xFFFFFFC00ULL +#define TLB_256MB_SIZE 0x10000000 +#define TLB_16MB_SIZE 0x01000000 +#define TLB_1MB_SIZE 0x00100000 +#define TLB_256KB_SIZE 0x00040000 +#define TLB_64KB_SIZE 0x00010000 +#define TLB_16KB_SIZE 0x00004000 +#define TLB_4KB_SIZE 0x00001000 +#define TLB_1KB_SIZE 0x00000400 + +#define TLB_WORD0_EPN_MASK 0xFFFFFC00 +#define TLB_WORD0_EPN_ENCODE(n) (((unsigned long)(n)) & 0xFFFFFC00) +#define TLB_WORD0_EPN_DECODE(n) (((unsigned long)(n)) & 0xFFFFFC00) +#define TLB_WORD0_V_MASK 0x00000200 +#define TLB_WORD0_V_ENABLE 0x00000200 +#define TLB_WORD0_V_DISABLE 0x00000000 +#define TLB_WORD0_TS_MASK 0x00000100 +#define TLB_WORD0_TS_1 0x00000100 +#define TLB_WORD0_TS_0 0x00000000 +#define TLB_WORD0_SIZE_MASK 0x000000F0 +#define TLB_WORD0_SIZE_1KB 0x00000000 +#define TLB_WORD0_SIZE_4KB 0x00000010 +#define TLB_WORD0_SIZE_16KB 0x00000020 +#define TLB_WORD0_SIZE_64KB 0x00000030 +#define TLB_WORD0_SIZE_256KB 0x00000040 +#define TLB_WORD0_SIZE_1MB 0x00000050 +#define TLB_WORD0_SIZE_16MB 0x00000070 +#define TLB_WORD0_SIZE_256MB 0x00000090 +#define TLB_WORD0_TPAR_MASK 0x0000000F +#define TLB_WORD0_TPAR_ENCODE(n) ((((unsigned long)(n)) & 0x0F) << 0) +#define TLB_WORD0_TPAR_DECODE(n) ((((unsigned long)(n)) >> 0) & 0x0F) + +#define TLB_WORD1_RPN_MASK 0xFFFFFC00 +#define TLB_WORD1_RPN_ENCODE(n) (((unsigned long)(n)) & 0xFFFFFC00) +#define TLB_WORD1_RPN_DECODE(n) (((unsigned long)(n)) & 0xFFFFFC00) +#define TLB_WORD1_PAR1_MASK 0x00000300 +#define TLB_WORD1_PAR1_ENCODE(n) ((((unsigned long)(n)) & 0x03) << 8) +#define TLB_WORD1_PAR1_DECODE(n) ((((unsigned long)(n)) >> 8) & 0x03) +#define TLB_WORD1_PAR1_0 0x00000000 +#define TLB_WORD1_PAR1_1 0x00000100 +#define TLB_WORD1_PAR1_2 0x00000200 +#define TLB_WORD1_PAR1_3 0x00000300 +#define TLB_WORD1_ERPN_MASK 0x0000000F +#define TLB_WORD1_ERPN_ENCODE(n) ((((unsigned long)(n)) & 0x0F) << 0) +#define TLB_WORD1_ERPN_DECODE(n) ((((unsigned long)(n)) >> 0) & 0x0F) + +#define TLB_WORD2_PAR2_MASK 0xC0000000 +#define TLB_WORD2_PAR2_ENCODE(n) ((((unsigned long)(n)) & 0x03) << 30) +#define TLB_WORD2_PAR2_DECODE(n) ((((unsigned long)(n)) >> 30) & 0x03) +#define TLB_WORD2_PAR2_0 0x00000000 +#define TLB_WORD2_PAR2_1 0x40000000 +#define TLB_WORD2_PAR2_2 0x80000000 +#define TLB_WORD2_PAR2_3 0xC0000000 +#define TLB_WORD2_U0_MASK 0x00008000 +#define TLB_WORD2_U0_ENABLE 0x00008000 +#define TLB_WORD2_U0_DISABLE 0x00000000 +#define TLB_WORD2_U1_MASK 0x00004000 +#define TLB_WORD2_U1_ENABLE 0x00004000 +#define TLB_WORD2_U1_DISABLE 0x00000000 +#define TLB_WORD2_U2_MASK 0x00002000 +#define TLB_WORD2_U2_ENABLE 0x00002000 +#define TLB_WORD2_U2_DISABLE 0x00000000 +#define TLB_WORD2_U3_MASK 0x00001000 +#define TLB_WORD2_U3_ENABLE 0x00001000 +#define TLB_WORD2_U3_DISABLE 0x00000000 +#define TLB_WORD2_W_MASK 0x00000800 +#define TLB_WORD2_W_ENABLE 0x00000800 +#define TLB_WORD2_W_DISABLE 0x00000000 +#define TLB_WORD2_I_MASK 0x00000400 +#define TLB_WORD2_I_ENABLE 0x00000400 +#define TLB_WORD2_I_DISABLE 0x00000000 +#define TLB_WORD2_M_MASK 0x00000200 +#define TLB_WORD2_M_ENABLE 0x00000200 +#define TLB_WORD2_M_DISABLE 0x00000000 +#define TLB_WORD2_G_MASK 0x00000100 +#define TLB_WORD2_G_ENABLE 0x00000100 +#define TLB_WORD2_G_DISABLE 0x00000000 +#define TLB_WORD2_E_MASK 0x00000080 +#define TLB_WORD2_E_ENABLE 0x00000080 +#define TLB_WORD2_E_DISABLE 0x00000000 +#define TLB_WORD2_UX_MASK 0x00000020 +#define TLB_WORD2_UX_ENABLE 0x00000020 +#define TLB_WORD2_UX_DISABLE 0x00000000 +#define TLB_WORD2_UW_MASK 0x00000010 +#define TLB_WORD2_UW_ENABLE 0x00000010 +#define TLB_WORD2_UW_DISABLE 0x00000000 +#define TLB_WORD2_UR_MASK 0x00000008 +#define TLB_WORD2_UR_ENABLE 0x00000008 +#define TLB_WORD2_UR_DISABLE 0x00000000 +#define TLB_WORD2_SX_MASK 0x00000004 +#define TLB_WORD2_SX_ENABLE 0x00000004 +#define TLB_WORD2_SX_DISABLE 0x00000000 +#define TLB_WORD2_SW_MASK 0x00000002 +#define TLB_WORD2_SW_ENABLE 0x00000002 +#define TLB_WORD2_SW_DISABLE 0x00000000 +#define TLB_WORD2_SR_MASK 0x00000001 +#define TLB_WORD2_SR_ENABLE 0x00000001 +#define TLB_WORD2_SR_DISABLE 0x00000000 + +/*----------------------------------------------------------------------------+ +| Following instructions are not available in Book E mode of the GNU assembler. ++----------------------------------------------------------------------------*/ +#define DCCCI(ra, rb) .long 0x7c000000 | \ + (ra << 16) | (rb << 11) | (454 << 1) + +#define ICCCI(ra, rb) .long 0x7c000000 | \ + (ra << 16) | (rb << 11) | (966 << 1) + +#define DCREAD(rt, ra, rb) .long 0x7c000000 | (rt << 21) | (ra << 16) | (rb << 11) | (486 << 1) + +#define ICREAD(ra, rb) .long 0x7c000000 | \ + (ra << 16) | (rb << 11) | (998 << 1) + +#define TLBSX(rt, ra, rb) .long 0x7c000000 | (rt << 21) | (ra << 16) | (rb << 11) | (914 << 1) + +#define TLBWE(rs, ra, ws) .long 0x7c000000 | (rs << 21) | (ra << 16) | (ws << 11) | (978 << 1) + +#define TLBRE(rt, ra, ws) .long 0x7c000000 | (rt << 21) | (ra << 16) | (ws << 11) | (946 << 1) + +#define TLBSXDOT(rt, ra, rb) .long 0x7c000001 | (rt << 21) | (ra << 16) | (rb << 11) | (914 << 1) + +#define MSYNC .long 0x7c000000 | \ + (598 << 1) + +#define MBAR_INST .long 0x7c000000 | \ + (854 << 1) + +#ifndef __ASSEMBLY__ +/* Prototypes */ +void mttlb1(unsigned long index, unsigned long value); +void mttlb2(unsigned long index, unsigned long value); +void mttlb3(unsigned long index, unsigned long value); +unsigned long mftlb1(unsigned long index); +unsigned long mftlb2(unsigned long index); +unsigned long mftlb3(unsigned long index); + +void program_tlb(uint64_t phys_addr, uint32_t virt_addr, uint32_t size, uint32_t tlb_word2_i_value); +void remove_tlb(uint32_t vaddr, uint32_t size); +void change_tlb(uint32_t vaddr, uint32_t size, uint32_t tlb_word2_i_value); +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_440 */ +#endif /* _PPC_MMU_H_ */ diff --git a/Kernel/HALKit/RISCV/.keep b/Kernel/HALKit/RISCV/.keep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/RISCV/APM/.gitkeep b/Kernel/HALKit/RISCV/APM/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/RISCV/Hart.hxx b/Kernel/HALKit/RISCV/Hart.hxx new file mode 100644 index 00000000..a77bb5eb --- /dev/null +++ b/Kernel/HALKit/RISCV/Hart.hxx @@ -0,0 +1,18 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Hart.hxx + Purpose: RISC-V hardware threads. + + Revision History: + + 30/01/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +#include + +typedef NewOS::Int32 Rv64HartType; diff --git a/Kernel/HALKit/RISCV/Storage/.gitkeep b/Kernel/HALKit/RISCV/Storage/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/X86S/.gitkeep b/Kernel/HALKit/X86S/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/X86S/ACPI/.gitkeep b/Kernel/HALKit/X86S/ACPI/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/X86S/Storage/.gitkeep b/Kernel/HALKit/X86S/Storage/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/HALKit/compile_flags.txt b/Kernel/HALKit/compile_flags.txt new file mode 100644 index 00000000..26779833 --- /dev/null +++ b/Kernel/HALKit/compile_flags.txt @@ -0,0 +1,6 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I./ +-I../ +-D__NEWOS_AMD64__ diff --git a/Kernel/HintKit/CompilerHint.hxx b/Kernel/HintKit/CompilerHint.hxx new file mode 100644 index 00000000..dee64f95 --- /dev/null +++ b/Kernel/HintKit/CompilerHint.hxx @@ -0,0 +1,23 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __HINTKIT_COMPILER_HINT_HXX__ +#define __HINTKIT_COMPILER_HINT_HXX__ + +#pragma compiler(hint_manifest) + +#define _Input +#define _Output + +#define _Optional + +#define _StrictCheckInput +#define _StrictCheckOutput + +#define _InOut +#define _StrictInOut + +#endif // ifndef __HINTKIT_COMPILER_HINT_HXX__ diff --git a/Kernel/KernelKit/CodeManager.hpp b/Kernel/KernelKit/CodeManager.hpp new file mode 100644 index 00000000..176efcfd --- /dev/null +++ b/Kernel/KernelKit/CodeManager.hpp @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: CodeManager.hpp + Purpose: Code Manager and Shared Objects. + + Revision History: + + 30/01/24: Added file (amlel) + 3/8/24: Add UPP struct. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +#define kUPPNameLen 64 + +namespace NewOS +{ + /// @brief Main process entrypoint. + typedef void (*MainKind)(void); + + /// @brief Executes a new process from a function. kernel code only. + /// @note This sets up a new stack, anything on the main function that calls the kernel will not be accessible. + /// @param main the start of the process. + /// @return if the process was started or not. + bool execute_from_image(MainKind main, const char* processName); +} // namespace NewOS \ No newline at end of file diff --git a/Kernel/KernelKit/DebugOutput.hpp b/Kernel/KernelKit/DebugOutput.hpp new file mode 100644 index 00000000..7fde69aa --- /dev/null +++ b/Kernel/KernelKit/DebugOutput.hpp @@ -0,0 +1,184 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +#define kDebugMaxPorts 16 + +#define kDebugUnboundPort 0x0FEED + +#define kDebugMag0 'H' +#define kDebugMag1 'D' +#define kDebugMag2 'B' +#define kDebugMag3 'G' + +#define kDebugSourceFile 0 +#define kDebugLine 33 +#define kDebugTeam 43 +#define kDebugEOP 49 + +namespace NewOS +{ + // @brief Emulates a VT100 terminal. + class TerminalDevice final : public DeviceInterface + { + public: + TerminalDevice(void (*print)(const Char*), void (*get)(const Char*)) + : DeviceInterface(print, get) + { + } + + virtual ~TerminalDevice() + { + } + + /// @brief returns device name (terminal name) + /// @return string type (const char*) + virtual const char* Name() const override + { + return ("TerminalDevice"); + } + + NEWOS_COPY_DEFAULT(TerminalDevice); + + static TerminalDevice& Shared() noexcept; + }; + + inline TerminalDevice& end_line() + { + TerminalDevice& selfTerm = TerminalDevice::Shared(); + selfTerm << "\r"; + return selfTerm; + } + + inline TerminalDevice& carriage_return() + { + TerminalDevice& selfTerm = TerminalDevice::Shared(); + selfTerm << "\r"; + return selfTerm; + } + + inline TerminalDevice& tabulate() + { + TerminalDevice& selfTerm = TerminalDevice::Shared(); + selfTerm << "\t"; + return selfTerm; + } + + /// @brief emulate a terminal bell, like the VT100 does. + inline TerminalDevice& bell() + { + TerminalDevice& selfTerm = TerminalDevice::Shared(); + selfTerm << "\a"; + return selfTerm; + } + + namespace Detail + { + inline TerminalDevice _write_number(const Long& x, TerminalDevice& term) + { + UInt64 y = (x > 0 ? x : -x) / 10; + UInt64 h = (x > 0 ? x : -x) % 10; + + if (y) + _write_number(y, term); + + /* fail if the number is not base-10 */ + if (h > 9) + { + _write_number('?', term); + return term; + } + + if (y < 0) + y = -y; + + const char NUMBERS[11] = "0123456789"; + + Char buf[2]; + buf[0] = NUMBERS[h]; + buf[1] = 0; + + term << buf; + return term; + } + + inline TerminalDevice _write_number_hex(const Long& x, TerminalDevice& term) + { + UInt64 y = (x > 0 ? x : -x) / 16; + UInt64 h = (x > 0 ? x : -x) % 16; + + if (y) + _write_number_hex(y, term); + + /* fail if the hex number is not base-16 */ + if (h > 15) + { + _write_number_hex('?', term); + return term; + } + + if (y < 0) + y = -y; + + const char NUMBERS[17] = "0123456789ABCDEF"; + + Char buf[2]; + buf[0] = NUMBERS[h]; + buf[1] = 0; + + term << buf; + return term; + } + } // namespace Detail + + inline TerminalDevice& hex_number(const Long& x) + { + TerminalDevice& selfTerm = TerminalDevice::Shared(); + + selfTerm << "0x"; + Detail::_write_number_hex(x, selfTerm); + + return selfTerm; + } + + inline TerminalDevice& number(const Long& x) + { + TerminalDevice& selfTerm = TerminalDevice::Shared(); + + Detail::_write_number(x, selfTerm); + + return selfTerm; + } + + inline TerminalDevice& get_console_in(Char* buf) + { + TerminalDevice& selfTerm = TerminalDevice::Shared(); + selfTerm >> buf; + return selfTerm; + } + + typedef Char rt_debug_type[255]; + + class DebuggerPortHeader final + { + public: + Int16 fPort[kDebugMaxPorts]; + Int16 fBoundCnt; + }; +} // namespace NewOS + +#ifdef kcout +#undef kcout +#endif // ifdef kcout + +#define kcout TerminalDevice::Shared() +#define endl end_line() diff --git a/Kernel/KernelKit/Defines.hpp b/Kernel/KernelKit/Defines.hpp new file mode 100644 index 00000000..b40c5a54 --- /dev/null +++ b/Kernel/KernelKit/Defines.hpp @@ -0,0 +1,12 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +#define KERNELKIT_VERSION "1.01" +#define KERNELKIT_RELEASE "Cairo" diff --git a/Kernel/KernelKit/DeviceManager.hpp b/Kernel/KernelKit/DeviceManager.hpp new file mode 100644 index 00000000..d6a2849d --- /dev/null +++ b/Kernel/KernelKit/DeviceManager.hpp @@ -0,0 +1,131 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/* ------------------------------------------- + + Revision History: + + 31/01/24: Add kDeviceCnt (amlel) + + ------------------------------------------- */ + +#pragma once + +/* NewOS device interface manager. */ +/* @file KernelKit/DeviceManager.hpp */ +/* @brief Device abstraction and I/O buffer. */ + +#include +#include + +#define kDriveManagerCount 4U + +// Last Rev +// Wed, Apr 3, 2024 9:09:41 AM + +namespace NewOS +{ + template + class DeviceInterface; + + template + class DeviceInterface + { + public: + explicit DeviceInterface(void (*Out)(T), void (*In)(T)) + : fOut(Out), fIn(In) + { + } + + virtual ~DeviceInterface() = default; + + public: + DeviceInterface& operator=(const DeviceInterface&) = default; + DeviceInterface(const DeviceInterface&) = default; + + public: + virtual DeviceInterface& operator<<(T Data) + { + fOut(Data); + return *this; + } + + virtual DeviceInterface& operator>>(T Data) + { + fIn(Data); + return *this; + } + + virtual const char* Name() const + { + return "DeviceInterface"; + } + + operator bool() + { + return fOut && fIn; + } + bool operator!() + { + return !fOut && !fIn; + } + + private: + void (*fOut)(T Data); + void (*fIn)(T Data); + }; + + /// + /// @brief Input Output Buffer + /// Used mainly to communicate between hardware. + /// + template + class IOBuf final + { + public: + explicit IOBuf(T Dat) + : fData(Dat) + { + // at least pass something valid when instancating this struct. + MUST_PASS(Dat); + } + + IOBuf& operator=(const IOBuf&) = default; + IOBuf(const IOBuf&) = default; + + ~IOBuf() = default; + + public: + template + R operator->() const + { + return fData; + } + + template + R& operator[](Size index) const + { + return fData[index]; + } + + private: + T fData; + }; + + ///! @brief Device enum types. + enum + { + kDeviceTypeIDE, + kDeviceTypeEthernet, + kDeviceTypeWiFi, + kDeviceTypeRS232, + kDeviceTypeSCSI, + kDeviceTypeSHCI, + kDeviceTypeUSB, + kDeviceTypeMedia, + kDeviceTypeCount, + }; +} // namespace NewOS diff --git a/Kernel/KernelKit/DriveManager.hxx b/Kernel/KernelKit/DriveManager.hxx new file mode 100644 index 00000000..ad77958e --- /dev/null +++ b/Kernel/KernelKit/DriveManager.hxx @@ -0,0 +1,146 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __DRIVE_MANAGER__ +#define __DRIVE_MANAGER__ + +#include +#include +#include +#include +#include +#include + +#define kDriveInvalidID -1 +#define kDriveNameLen 32 + +namespace NewOS +{ + enum + { + kInvalidDrive = -1, + kBlockDevice = 0xAD, + kMassStorage = 0xDA, + kFloppyDisc = 0xCD, + kOpticalDisc = 0xDC, // CD-ROM/DVD-ROM/Blu-Ray + /// combine with below. + kReadOnly = 0x10, // Read only drive + kEPMDrive = 0x11, // Explicit Partition Map. + kEPTDrive = 0x12, // ESP w/ EPM partition. + kMBRDrive = 0x13, // IBM PC classic partition scheme + kDriveCnt = 9, + }; + + typedef Int64 rt_drive_id_type; + + /// @brief Media drive trait type. + struct DriveTrait final + { + Char fName[kDriveNameLen]; // /System, /Boot, //./Devices/USB... + Int32 fKind; // fMassStorage, fFloppy, fOpticalDisc. + rt_drive_id_type fId; // Drive id. + Int32 fFlags; // fReadOnly, fXPMDrive, fXPTDrive + + /// @brief Packet drive (StorageKit compilant.) + struct DrivePacket final + { + VoidPtr fPacketContent; //! packet body. + Char fPacketMime[kDriveNameLen]; //! identify what we're sending. + SizeT fPacketSize; //! packet size + UInt32 fPacketCRC32; //! sanity crc, in case if good is set to false + Boolean fPacketGood; + Lba fLba; + } fPacket; + + Void (*fInput)(DrivePacket* packetPtr); + Void (*fOutput)(DrivePacket* packetPtr); + Void (*fVerify)(DrivePacket* packetPtr); + const Char* (*fDriveKind)(Void); + }; + + ///! drive as a device. + typedef DriveTrait* DriveTraitPtr; + + /** + * @brief Mounted drives interface. + * @note This class has all of it's drive set to nullptr, allocate them using + * GetAddressOf(index). + */ + class MountpointInterface final + { + public: + explicit MountpointInterface() = default; + ~MountpointInterface() = default; + + NEWOS_COPY_DEFAULT(MountpointInterface); + + public: + DriveTrait& A() + { + return mA; + } + DriveTrait& B() + { + return mB; + } + DriveTrait& C() + { + return mC; + } + DriveTrait& D() + { + return mD; + } + + DriveTraitPtr GetAddressOf(Int32 index) + { + DbgLastError() = kErrorSuccess; + + switch (index) + { + case 0: + return &mA; + case 1: + return &mB; + case 2: + return &mC; + case 3: + return &mD; + default: { + DbgLastError() = kErrorNoSuchDisk; + kcout << "New OS: No such disk.\n"; + + break; + } + } + + return nullptr; + } + + private: + DriveTrait mA, mB, mC, mD; + }; + + /// @brief Unimplemented drive. + /// @param pckt + /// @return + Void ke_drv_unimplemented(DriveTrait::DrivePacket* pckt); + + /// @brief Gets the drive kind (ATA, SCSI, AHCI...) + /// @param + /// @return + const Char* ke_drive_kind(Void); + + /// @brief Makes a new drive. + /// @return the new drive. + DriveTrait construct_drive(void) noexcept; + + /// @brief Fetches the main drive. + /// @return the new drive. + DriveTrait construct_main_drive(void) noexcept; +} // namespace NewOS + +#endif /* ifndef __DRIVE_MANAGER__ */ diff --git a/Kernel/KernelKit/FileManager.hpp b/Kernel/KernelKit/FileManager.hpp new file mode 100644 index 00000000..d0843a5e --- /dev/null +++ b/Kernel/KernelKit/FileManager.hpp @@ -0,0 +1,258 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/* ------------------------------------------- + + Revision History: + + 31/01/24: Update documentation (amlel) + + ------------------------------------------- */ + +#pragma once + +#ifdef __FSKIT_NEWFS__ +#include +#endif // __FSKIT_NEWFS__ + +#include +#include +#include +#include + +/// @brief Filesystem abstraction manager. +/// Works like the VFS or IFS. + +#define kBootFolder "/Boot" +#define kBinFolder "/Applications" +#define kShLibsFolder "/Library" +#define kMountFolder "/Mount" + +/// refer to first enum. +#define kFileOpsCount 4 +#define kFileMimeGeneric "application-type/*" + +namespace NewOS +{ + enum + { + kFileWriteAll = 100, + kFileReadAll = 101, + kFileReadChunk = 102, + kFileWriteChunk = 103, + kFileIOCnt = (kFileWriteChunk - kFileWriteAll) + 1, + }; + + typedef VoidPtr NodePtr; + + /** + @brief Filesystem Manager Interface class + @brief Used to provide common I/O for a specific filesystem. +*/ + class FilesystemManagerInterface + { + public: + FilesystemManagerInterface() = default; + virtual ~FilesystemManagerInterface() = default; + + public: + NEWOS_COPY_DEFAULT(FilesystemManagerInterface); + + public: + /// @brief Mounts a new filesystem into an active state. + /// @param interface the filesystem interface + /// @return + static bool Mount(FilesystemManagerInterface* interface); + + /// @brief Unmounts the active filesystem + /// @return + static FilesystemManagerInterface* Unmount(); + + /// @brief Getter, gets the active filesystem. + /// @return + static FilesystemManagerInterface* GetMounted(); + + public: + virtual NodePtr Create(_Input const char* path) = 0; + virtual NodePtr CreateAlias(_Input const char* path) = 0; + virtual NodePtr CreateDirectory(_Input const char* path) = 0; + + public: + virtual bool Remove(_Input const char* path) = 0; + + public: + virtual NodePtr Open(_Input const char* path, _Input const char* r) = 0; + + public: + virtual Void Write(_Input NodePtr node, _Input VoidPtr data, _Input Int32 flags, _Input SizeT size) = 0; + virtual _Output VoidPtr Read(_Input NodePtr node, _Input Int32 flags, _Input SizeT sz) = 0; + + public: + virtual bool Seek(_Input NodePtr node, _Input SizeT off) = 0; + + public: + virtual SizeT Tell(_Input NodePtr node) = 0; + virtual bool Rewind(_Input NodePtr node) = 0; + }; + +/** @brief invalid position. (n-pos) */ +#define kNPos (SizeT)(-1); + +#ifdef __FSKIT_NEWFS__ + /** + * @brief Based of FilesystemManagerInterface, takes care of managing NewFS + * disks. + */ + class NewFilesystemManager final : public FilesystemManagerInterface + { + public: + explicit NewFilesystemManager(); + ~NewFilesystemManager() override; + + public: + NEWOS_COPY_DEFAULT(NewFilesystemManager); + + public: + NodePtr Create(const char* path) override; + NodePtr CreateAlias(const char* path) override; + NodePtr CreateDirectory(const char* path) override; + + public: + bool Remove(const char* path) override; + NodePtr Open(const char* path, const char* r) override; + Void Write(NodePtr node, VoidPtr data, Int32 flags, SizeT sz) override; + VoidPtr Read(NodePtr node, Int32 flags, SizeT sz) override; + bool Seek(NodePtr node, SizeT off); + SizeT Tell(NodePtr node) override; + bool Rewind(NodePtr node) override; + + public: + void SetResourceFork(const char* forkName); + void SetDataFork(const char* forkName); + + NewFSParser* GetImpl() noexcept; + + private: + Char fDataFork[kNewFSForkNameLen] = {0}; + Char fRsrcFork[kNewFSForkNameLen] = {0}; + NewFSParser* fImpl{nullptr}; + }; + +#endif // ifdef __FSKIT_NEWFS__ + + /** + * Usable FileStream + * @tparam Encoding file encoding (char, wchar_t...) + * @tparam FSClass Filesystem contract who takes care of it. + */ + template + class FileStream final + { + public: + explicit FileStream(const Encoding* path, const Encoding* restrict_type); + ~FileStream(); + + public: + FileStream& operator=(const FileStream&); + FileStream(const FileStream&); + + public: + ErrorOr WriteAll(const VoidPtr data) noexcept + { + if (data == nullptr) + return ErrorOr(kErrorInvalidData); + + auto man = FSClass::GetMounted(); + + if (man) + { + man->Write(fFile, data, kFileWriteAll); + return ErrorOr(0); + } + + return ErrorOr(kErrorInvalidData); + } + + VoidPtr Read() noexcept + { + auto man = FSClass::GetMounted(); + + if (man) + { + VoidPtr ret = man->Read(fFile, kFileReadAll, 0); + return ret; + } + + return nullptr; + } + + voidPtr Read(SizeT offset, SizeT sz) + { + auto man = FSClass::GetMounted(); + + if (man) + { + man->Seek(fFile, offset); + auto ret = man->Read(fFile, kFileReadChunk, sz); + + return ret; + } + + return nullptr; + } + + Void Write(SizeT offset, voidPtr data, SizeT sz) + { + auto man = FSClass::GetMounted(); + + if (man) + { + man->Seek(fFile, offset); + man->Write(fFile, data, sz, kFileReadChunk); + } + } + + /// @brief Leak node pointer. + /// @return The node pointer. + NodePtr Leak() + { + return fFile; + } + + public: + char* MIME() noexcept + { + return const_cast(fMime); + } + + private: + NodePtr fFile; + const Char* fMime{kFileMimeGeneric}; + }; + +#define kRestrictR "r" +#define kRestrictRB "rb" +#define kRestrictW "w" +#define kRestrictRW "rw" + + using FileStreamUTF8 = FileStream; + using FileStreamUTF16 = FileStream; + + typedef UInt64 CursorType; + + template + FileStream::FileStream(const Encoding* path, + const Encoding* restrict_type) + : fFile(Class::GetMounted()->Open(path, restrict_type)) + { + } + + template + FileStream::~FileStream() = default; +} // namespace NewOS + +#define node_cast(PTR) reinterpret_cast(PTR) diff --git a/Kernel/KernelKit/Framebuffer.hpp b/Kernel/KernelKit/Framebuffer.hpp new file mode 100644 index 00000000..903a1fa8 --- /dev/null +++ b/Kernel/KernelKit/Framebuffer.hpp @@ -0,0 +1,90 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Framebuffer.hpp + Purpose: Framebuffer object. + +------------------------------------------- */ + +#ifndef __INC_FB_HPP__ +#define __INC_FB_HPP__ + +#include +#include + +namespace NewOS +{ + enum class FramebufferColorKind : UChar + { + RGB32, + RGB16, + RGB8, + INVALID, + }; + + class FramebufferContext final + { + public: + UIntPtr fBase; + UIntPtr fBpp; + UInt fWidth; + UInt fHeight; + }; + + class Framebuffer final + { + public: + explicit Framebuffer(Ref& addr) + : fFrameBufferAddr(addr) + { + } + ~Framebuffer() + { + } + + Framebuffer& operator=(const Framebuffer&) = delete; + Framebuffer(const Framebuffer&) = default; + + volatile UIntPtr* operator[](const UIntPtr& pos); + + operator bool(); + + const FramebufferColorKind& Color( + const FramebufferColorKind& colour = FramebufferColorKind::INVALID); + + Ref& Leak(); + + /// @brief Draws a rectangle inside the fb. + /// @param width the width of it + /// @param height the height of it + /// @param x its x coord. + /// @param y its y coord. + /// @param color the color of it. + /// @return the framebuffer object. + Framebuffer& DrawRect(SizeT width, SizeT height, SizeT x, SizeT y, UInt32 color); + + /// @brief Puts a pixel on the screen. + /// @param x where in X + /// @param y where in Y + /// @param color the color of it. + /// @return the framebuffer object. + Framebuffer& PutPixel(SizeT x, SizeT y, UInt32 color); + + private: + Ref fFrameBufferAddr; + FramebufferColorKind fColour; + }; + + /***********************************************************************************/ + /// Some common colors. + /***********************************************************************************/ + + extern const UInt32 kRgbRed; + extern const UInt32 kRgbGreen; + extern const UInt32 kRgbBlue; + extern const UInt32 kRgbBlack; + extern const UInt32 kRgbWhite; +} // namespace NewOS + +#endif /* ifndef __INC_FB_HPP__ */ diff --git a/Kernel/KernelKit/HError.hpp b/Kernel/KernelKit/HError.hpp new file mode 100644 index 00000000..f4285afb --- /dev/null +++ b/Kernel/KernelKit/HError.hpp @@ -0,0 +1,49 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +namespace NewOS +{ + typedef Int32 HError; + + inline constexpr HError kErrorSuccess = 0; + inline constexpr HError kErrorExecutable = 33; + inline constexpr HError kErrorExecutableLib = 34; // no such library!!! + inline constexpr HError kErrorFileNotFound = 35; + inline constexpr HError kErrorDirectoryNotFound = 36; + inline constexpr HError kErrorDiskReadOnly = 37; + inline constexpr HError kErrorDiskIsFull = 38; + inline constexpr HError kErrorProcessFault = 39; + inline constexpr HError kErrorSocketHangUp = 40; + inline constexpr HError kErrorThreadLocalStorage = 41; + inline constexpr HError kErrorMath = 42; + inline constexpr HError kErrorNoNetwork = 43; + inline constexpr HError kErrorHeapOutOfMemory = 44; + inline constexpr HError kErrorNoSuchDisk = 45; + inline constexpr HError kErrorFileExists = 46; + inline constexpr HError kErrorFormatFailed = 47; + inline constexpr HError kErrorNetworkTimeout = 48; + inline constexpr HError kErrorInternal = 49; + inline constexpr HError kErrorForkAlreadyExists = 50; + inline constexpr HError kErrorOutOfTeamSlot = 51; + inline constexpr HError kErrorHeapNotPresent = 52; + inline constexpr HError kErrorNoEntrypoint = 53; + inline constexpr HError kErrorDiskIsCorrupted = 54; + inline constexpr HError kErrorDisk = 55; + inline constexpr HError kErrorInvalidData = 56; + inline constexpr HError kErrorUnimplemented = 0; + + Boolean ke_bug_check(void) noexcept; +} // namespace NewOS + +#define DbgOk() (kLastError == NewOS::kErrorSuccess) +#define DbgFailed() (kLastError != NewOS::kErrorSuccess) +#define DbgLastError() kLastError + +inline NewOS::HError kLastError = 0; diff --git a/Kernel/KernelKit/KernelHeap.hpp b/Kernel/KernelKit/KernelHeap.hpp new file mode 100644 index 00000000..bb21e981 --- /dev/null +++ b/Kernel/KernelKit/KernelHeap.hpp @@ -0,0 +1,39 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +// last-rev 30/01/24 +// file: KernelHeap.hpp +// description: heap allocation for the kernel. + +#include + +namespace NewOS +{ + + /// @brief Declare pointer as free. + /// @param heapPtr the pointer. + /// @return + Int32 ke_delete_ke_heap(voidPtr allocatedPtr); + + /// @brief Check if pointer is a valid kernel pointer. + /// @param heapPtr the pointer + /// @return if it exists. + Boolean ke_is_valid_heap(VoidPtr ptr); + + /// @brief allocate chunk of memory. + /// @param sz size of pointer + /// @param rw read write (true to enable it) + /// @param user is it accesible by user processes? + /// @return the pointer + voidPtr ke_new_ke_heap(SizeT sz, const bool rw, const bool user); + + /// @brief Protect the heap with a CRC value. + /// @param heapPtr HIB pointer. + /// @return if it valid: point has crc now., otherwise fail. + Boolean ke_protect_ke_heap(VoidPtr heapPtr); +} // namespace NewOS diff --git a/Kernel/KernelKit/LoaderInterface.hpp b/Kernel/KernelKit/LoaderInterface.hpp new file mode 100644 index 00000000..71c90e0c --- /dev/null +++ b/Kernel/KernelKit/LoaderInterface.hpp @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +namespace NewOS +{ + /// @brief This interface is used to make loader contracts (MSCOFF, PEF). + /// @author @Amlal-El-Mahrouss + class LoaderInterface + { + public: + explicit LoaderInterface() = default; + virtual ~LoaderInterface() = default; + + NEWOS_COPY_DEFAULT(LoaderInterface); + + public: + virtual _Output const char* FormatAsString() = 0; + virtual _Output const char* MIME() = 0; + virtual _Output const char* Path() = 0; + virtual _Output ErrorOr FindStart() = 0; + virtual _Output VoidPtr FindSymbol(_Input const char* name, _Input Int32 kind) = 0; + }; +} // namespace NewOS diff --git a/Kernel/KernelKit/LockDelegate.hpp b/Kernel/KernelKit/LockDelegate.hpp new file mode 100644 index 00000000..56a2e17f --- /dev/null +++ b/Kernel/KernelKit/LockDelegate.hpp @@ -0,0 +1,64 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include + +#define kLockDone (200U) /* job is done */ +#define kLockTimedOut (100U) /* job has timed out */ + +namespace NewOS +{ + /// @brief Lock condition pointer. + typedef Boolean* LockPtr; + + /// @brief Locking delegate class, hangs until limit. + /// @tparam N the amount of cycles to wait. + template + class LockDelegate final + { + public: + LockDelegate() = delete; + + public: + explicit LockDelegate(LockPtr expr) + { + auto spin = 0U; + + while (spin != N) + { + if (*expr) + { + fLockStatus | kLockDone; + break; + } + } + + if (spin == N) + fLockStatus | kLockTimedOut; + } + + ~LockDelegate() = default; + + LockDelegate& operator=(const LockDelegate&) = delete; + LockDelegate(const LockDelegate&) = delete; + + bool Done() + { + return fLockStatus[kLockDone] == kLockDone; + } + + bool HasTimedOut() + { + return fLockStatus[kLockTimedOut] != kLockTimedOut; + } + + private: + Atom fLockStatus; + }; +} // namespace NewOS diff --git a/Kernel/KernelKit/MSDOS.hpp b/Kernel/KernelKit/MSDOS.hpp new file mode 100644 index 00000000..8b27ca58 --- /dev/null +++ b/Kernel/KernelKit/MSDOS.hpp @@ -0,0 +1,68 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: MSDOS.hpp + Purpose: MS-DOS header for NewOS. + + Revision History: + + 30/01/24: Added file (amlel) + +------------------------------------------- */ + +#ifndef __MSDOS_EXEC__ +#define __MSDOS_EXEC__ + +#include +#include + +// Last Rev +// Sat Feb 24 CET 2024 + +#define kMagMz0 'M' +#define kMagMz1 'Z' + +typedef NewOS::UInt32 DosWord; +typedef NewOS::Long DosLong; + +typedef struct _DosHeader +{ + NewOS::UInt8 eMagic[2]; + DosWord eMagLen; + DosWord ePagesCount; + DosWord eCrlc; + DosWord eCParHdr; + DosWord eMinAlloc; + DosWord eMaxAlloc; + DosWord eStackSeg; + DosWord eStackPtr; + DosWord eChksum; + DosWord eIp; + DosWord eCs; + DosWord eLfarlc; + DosWord eOvno; + DosWord eRes[4]; + DosWord eOemid; + DosWord eOeminfo; + DosWord eRes2[10]; + DosLong eLfanew; +} DosHeader, *DosHeaderPtr; + +namespace NewOS +{ + /// @brief Find the PE header inside the the blob. + inline auto rt_find_exec_header(DosHeaderPtr ptrDos) -> VoidPtr + { + if (!ptrDos) + return nullptr; + if (ptrDos->eMagic[0] != kMagMz0) + return nullptr; + if (ptrDos->eMagic[1] != kMagMz1) + return nullptr; + + return (VoidPtr)(&ptrDos->eLfanew + 1); + } +} // namespace NewOS + +#endif /* ifndef __MSDOS_EXEC__ */ diff --git a/Kernel/KernelKit/PCI/Database.hpp b/Kernel/KernelKit/PCI/Database.hpp new file mode 100644 index 00000000..002e572a --- /dev/null +++ b/Kernel/KernelKit/PCI/Database.hpp @@ -0,0 +1,38 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ +#pragma once + +#include +#include + +namespace NewOS +{ + namespace Types + { + // https://wiki.osdev.org/PCI + enum class PciDeviceKind : UChar + { + MassStorageController = 0x1, + NetworkController = 0x2, + DisplayController = 0x3, + MultimediaController = 0x4, + MemoryController = 0x5, + Bridge = 0x6, + CommunicationController = 0x7, + GenericSystemPeripheral = 0x8, + InputDeviceController = 0x9, + DockingStation = 0xa, + Processor = 0xb, + SerialBusController = 0xc, + WirelessController = 0xd, + IntelligentController = 0xe, + SatelliteCommunicationsController = 0xf, + CoProcessor = 0x40, + Unassgined = 0xf, + Invalid = Unassgined, + }; + } // namespace Types +} // namespace NewOS diff --git a/Kernel/KernelKit/PCI/Device.hpp b/Kernel/KernelKit/PCI/Device.hpp new file mode 100644 index 00000000..69a99494 --- /dev/null +++ b/Kernel/KernelKit/PCI/Device.hpp @@ -0,0 +1,79 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ +#pragma once + +#include + +namespace NewOS::PCI +{ + enum class PciConfigKind : UShort + { + ConfigAddress = 0xCF8, + ConfigData = 0xCFC, + Invalid = 0xFFF + }; + + class Device final + { + public: + Device() = default; + + public: + explicit Device(UShort bus, UShort device, UShort function, UShort bar); + + Device& operator=(const Device&) = default; + + Device(const Device&) = default; + + ~Device(); + + public: + UInt Read(UInt bar, Size szData); + void Write(UInt bar, UIntPtr data, Size szData); + + public: + operator bool(); + + public: + template + UInt Read(UInt bar) + { + static_assert(sizeof(T) <= 4, "64-bit PCI addressing is unsupported"); + return Read(bar, sizeof(T)); + } + + template + void Write(UInt bar, UIntPtr data) + { + static_assert(sizeof(T) <= 4, "64-bit PCI addressing is unsupported"); + Write(bar, data, sizeof(T)); + } + + public: + UShort DeviceId(); + UShort VendorId(); + UShort InterfaceId(); + UChar Class(); + UChar Subclass(); + UChar ProgIf(); + UChar HeaderType(); + + public: + void EnableMmio(); + void BecomeBusMaster(); // for PCI-DMA, PC-DMA does not need that. + + UShort Vendor(); + + private: + UShort fBus; + UShort fDevice; + UShort fFunction; + UShort fBar; + }; +} // namespace NewOS::PCI + +EXTERN_C void NewOSPCISetCfgTarget(NewOS::UInt bar); +EXTERN_C NewOS::UInt NewOSPCIReadRaw(NewOS::UInt bar); diff --git a/Kernel/KernelKit/PCI/Dma.hpp b/Kernel/KernelKit/PCI/Dma.hpp new file mode 100644 index 00000000..dc7b8601 --- /dev/null +++ b/Kernel/KernelKit/PCI/Dma.hpp @@ -0,0 +1,81 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace NewOS +{ + enum class DmaKind + { + PCI, // Bus mastering is required to be turned on. Basiaclly a request + // control system. 64-Bit access depends on the PAE bit and the device + // (if Double Address Cycle is available) + ISA, // Four DMA channels 0-3; 8 bit transfers and only a megabyte of RAM. + Invalid, + }; + + class DMAWrapper final + { + public: + explicit DMAWrapper() = delete; + + public: + explicit DMAWrapper(nullPtr) = delete; + explicit DMAWrapper(voidPtr Ptr, DmaKind Kind = DmaKind::PCI) + : fAddress(Ptr), fKind(Kind) + { + } + + public: + DMAWrapper& operator=(voidPtr Ptr); + + public: + DMAWrapper& operator=(const DMAWrapper&) = default; + DMAWrapper(const DMAWrapper&) = default; + + public: + ~DMAWrapper() = default; + + template + T* operator->(); + + template + T* Get(const UIntPtr off = 0); + + public: + operator bool(); + bool operator!(); + + public: + bool Write(const UIntPtr& bit, const UIntPtr& offset); + UIntPtr Read(const UIntPtr& offset); + Boolean Check(UIntPtr offset) const; + + public: + UIntPtr operator[](const UIntPtr& offset); + + private: + voidPtr fAddress{nullptr}; + DmaKind fKind{DmaKind::Invalid}; + + private: + friend class DMAFactory; + }; + + class DMAFactory final + { + public: + static OwnPtr> Construct(OwnPtr& dma); + }; +} // namespace NewOS + +#include diff --git a/Kernel/KernelKit/PCI/Dma.inl b/Kernel/KernelKit/PCI/Dma.inl new file mode 100644 index 00000000..53c52802 --- /dev/null +++ b/Kernel/KernelKit/PCI/Dma.inl @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +namespace NewOS +{ + template + T* DMAWrapper::operator->() + { + return fAddress; + } + + template + T* DMAWrapper::Get(const UIntPtr offset) + { + return reinterpret_cast((UIntPtr) fAddress + offset); + } +} diff --git a/Kernel/KernelKit/PCI/Express.hpp b/Kernel/KernelKit/PCI/Express.hpp new file mode 100644 index 00000000..d6266ad2 --- /dev/null +++ b/Kernel/KernelKit/PCI/Express.hpp @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +#define PCI_EXPRESS_BUS_COUNT (4096) diff --git a/Kernel/KernelKit/PCI/IO-Impl-AMD64.inl b/Kernel/KernelKit/PCI/IO-Impl-AMD64.inl new file mode 100644 index 00000000..92a15b8b --- /dev/null +++ b/Kernel/KernelKit/PCI/IO-Impl-AMD64.inl @@ -0,0 +1,47 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: IO-Impl-AMD64.hpp + Purpose: I/O for AMD64. + + Revision History: + + 30/01/24: Add file. (amlel) + 02/02/24: Update I/O routines. (amlel) + +------------------------------------------- */ + +namespace NewOS { +template +template +T IOArray::In(SizeT index) { + switch (sizeof(T)) { + case 4: + return HAL::In32(fPorts[index].Leak()); + case 2: + return HAL::In16(fPorts[index].Leak()); + case 1: + return HAL::In8(fPorts[index].Leak()); + default: + return 0xFFFF; + } +} + +template +template +void IOArray::Out(SizeT index, T value) { + switch (sizeof(T)) { +#ifdef __x86_64__ + case 4: + HAL::Out32(fPorts[index].Leak(), value); + case 2: + HAL::Out16(fPorts[index].Leak(), value); + case 1: + HAL::Out8(fPorts[index].Leak(), value); +#endif + default: + break; + } +} +} // namespace NewOS diff --git a/Kernel/KernelKit/PCI/IO.hpp b/Kernel/KernelKit/PCI/IO.hpp new file mode 100644 index 00000000..0b10f5d0 --- /dev/null +++ b/Kernel/KernelKit/PCI/IO.hpp @@ -0,0 +1,59 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +namespace NewOS +{ + template + class IOArray final + { + public: + IOArray() = delete; + + IOArray(nullPtr) = delete; + + explicit IOArray(Array& ports) + : fPorts(ports) + { + } + ~IOArray() + { + } + + IOArray& operator=(const IOArray&) = default; + + IOArray(const IOArray&) = default; + + operator bool() + { + return !fPorts.Empty(); + } + + public: + template + T In(SizeT index); + + template + void Out(SizeT index, T value); + + private: + Array fPorts; + }; + + using IOArray16 = IOArray<16>; +} // namespace NewOS + +#ifdef __x86_64__ +#include +#else +#error Please provide platform specific code for the I/O +#endif // ifdef __x86_64__ diff --git a/Kernel/KernelKit/PCI/Iterator.hpp b/Kernel/KernelKit/PCI/Iterator.hpp new file mode 100644 index 00000000..278711a7 --- /dev/null +++ b/Kernel/KernelKit/PCI/Iterator.hpp @@ -0,0 +1,38 @@ +#ifndef __PCI_ITERATOR_HPP__ +#define __PCI_ITERATOR_HPP__ + +#include +#include +#include +#include +#include + +#define NEWOS_BUS_COUNT (256) +#define NEWOS_DEVICE_COUNT (33) +#define NEWOS_FUNCTION_COUNT (8) + +namespace NewOS::PCI +{ + class Iterator final + { + public: + Iterator() = delete; + + public: + explicit Iterator(const Types::PciDeviceKind& deviceType); + + Iterator& operator=(const Iterator&) = default; + + Iterator(const Iterator&) = default; + + ~Iterator(); + + public: + Ref operator[](const Size& sz); + + private: + Array fDevices; + }; +} // namespace NewOS::PCI + +#endif // __PCI_ITERATOR_HPP__ diff --git a/Kernel/KernelKit/PCI/PCI.hpp b/Kernel/KernelKit/PCI/PCI.hpp new file mode 100644 index 00000000..2e523d4a --- /dev/null +++ b/Kernel/KernelKit/PCI/PCI.hpp @@ -0,0 +1,58 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ +#pragma once + +#include + +#define PCI_CONFIG_ADDRESS (0xCF8) +#define PCI_CONFIG_DATA (0xCFC) + +#define PCI_DEVICE_COUNT (32) +#define PCI_FUNC_COUNT (8) +#define PCI_BUS_COUNT (255) + +namespace NewOS::PCI +{ + // model + struct DeviceHeader + { + UInt16 VendorId; + UInt16 DeviceId; + UInt8 Command; + UInt8 Status; + UInt8 RevisionId; + UInt8 ProgIf; + UInt8 SubClass; + UInt8 Class; + UInt8 CacheLineSz; + UInt8 LatencyTimer; + UInt8 HeaderType; + UInt8 Bist; + UInt8 Bus; + UInt8 Device; + UInt8 Function; + }; + + namespace Detail + { + class BAR + { + public: + UIntPtr BAR; + SizeT Size; + }; + } // namespace Detail + + class BAR + { + public: + Detail::BAR BAR1; + Detail::BAR BAR2; + Detail::BAR BAR3; + Detail::BAR BAR4; + Detail::BAR BAR5; + }; +} // namespace NewOS::PCI diff --git a/Kernel/KernelKit/PE.hxx b/Kernel/KernelKit/PE.hxx new file mode 100644 index 00000000..5ab40b70 --- /dev/null +++ b/Kernel/KernelKit/PE.hxx @@ -0,0 +1,123 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: PE.hxx + Purpose: Portable Executable for NewOS. + + Revision History: + + 30/01/24: Added file (amlel) + +------------------------------------------- */ + +#ifndef __PE__ +#define __PE__ + +#include + +#define kPeMagic 0x00004550 + +typedef struct ExecHeader final +{ + NewOS::UInt32 mMagic; // PE\0\0 or 0x00004550 + NewOS::UInt16 mMachine; + NewOS::UInt16 mNumberOfSections; + NewOS::UInt32 mTimeDateStamp; + NewOS::UInt32 mPointerToSymbolTable; + NewOS::UInt32 mNumberOfSymbols; + NewOS::UInt16 mSizeOfOptionalHeader; + NewOS::UInt16 mCharacteristics; +} ALIGN(8) ExecHeader, *ExecHeaderPtr; + +#define kMagPE32 0x010b +#define kMagPE64 0x020b + +#define kPEMachineAMD64 0x8664 +#define kPEMachineARM64 0xaa64 + +typedef struct ExecOptionalHeader final +{ + NewOS::UInt16 mMagic; // 0x010b - PE32, 0x020b - PE32+ (64 bit) + NewOS::UChar mMajorLinkerVersion; + NewOS::UChar mMinorLinkerVersion; + NewOS::UIntPtr mSizeOfCode; + NewOS::UIntPtr mSizeOfInitializedData; + NewOS::UIntPtr mSizeOfUninitializedData; + NewOS::UInt32 mAddressOfEntryPoint; + NewOS::UInt32 mBaseOfCode; + NewOS::UIntPtr mImageBase; + NewOS::UInt32 mSectionAlignment; + NewOS::UInt32 mFileAlignment; + NewOS::UInt16 mMajorOperatingSystemVersion; + NewOS::UInt16 mMinorOperatingSystemVersion; + NewOS::UInt16 mMajorImageVersion; + NewOS::UInt16 mMinorImageVersion; + NewOS::UInt16 mMajorSubsystemVersion; + NewOS::UInt16 mMinorSubsystemVersion; + NewOS::UInt32 mWin32VersionValue; + NewOS::UIntPtr mSizeOfImage; + NewOS::UIntPtr mSizeOfHeaders; + NewOS::UInt32 mCheckSum; + NewOS::UInt16 mSubsystem; + NewOS::UInt16 mDllCharacteristics; + NewOS::UIntPtr mSizeOfStackReserve; + NewOS::UIntPtr mSizeOfStackCommit; + NewOS::UIntPtr mSizeOfHeapReserve; + NewOS::UIntPtr mSizeOfHeapCommit; + NewOS::UInt32 mLoaderFlags; + NewOS::UInt32 mNumberOfRvaAndSizes; +} ExecOptionalHeader, *ExecOptionalHeaderPtr; + +typedef struct ExecSectionHeader final +{ + CONST NewOS::UChar mName[8]; + NewOS::UInt32 mVirtualSize; + NewOS::UInt32 mVirtualAddress; + NewOS::UInt32 mSizeOfRawData; + NewOS::UInt32 mPointerToRawData; + NewOS::UInt32 mPointerToRelocations; + NewOS::UInt32 mPointerToLinenumbers; + NewOS::UInt16 mNumberOfRelocations; + NewOS::UInt16 mNumberOfLinenumbers; + NewOS::UInt32 mCharacteristics; +} ExecSectionHeader, *ExecSectionHeaderPtr; + +enum kExecDataDirParams +{ + kExecExport, + kExecImport, + kExecInvalid, + kExecCount, +}; + +typedef struct ExecExportDirectory +{ + NewOS::UInt32 mCharacteristics; + NewOS::UInt32 mTimeDateStamp; + NewOS::UInt16 mMajorVersion; + NewOS::UInt16 mMinorVersion; + NewOS::UInt32 mName; + NewOS::UInt32 mBase; + NewOS::UInt32 mNumberOfFunctions; + NewOS::UInt32 mNumberOfNames; + NewOS::UInt32 mAddressOfFunctions; // export table rva + NewOS::UInt32 mAddressOfNames; + NewOS::UInt32 mAddressOfNameOrdinal; // ordinal table rva +} ExecExportDirectory, *ExecExportDirectoryPtr; + +typedef struct ExecImportDirectory +{ + union { + NewOS::UInt32 mCharacteristics; + NewOS::UInt32 mOriginalFirstThunk; + }; + NewOS::UInt32 mTimeDateStamp; + NewOS::UInt32 mForwarderChain; + NewOS::UInt32 mNameRva; + NewOS::UInt32 mThunkTableRva; +} ExecImportDirectory, *ExecImportDirectoryPtr; + +#define kPeStart "__hcore_subsys_start" + +#endif /* ifndef __PE__ */ diff --git a/Kernel/KernelKit/PECodeManager.hxx b/Kernel/KernelKit/PECodeManager.hxx new file mode 100644 index 00000000..0627617c --- /dev/null +++ b/Kernel/KernelKit/PECodeManager.hxx @@ -0,0 +1,24 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: PECodeManager.hxx + Purpose: PE32+ Code Manager and Shared Objects. + + Revision History: + + 12/02/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +//////////////////////////////////////////////////// + +// LAST REV: Mon Feb 12 13:52:01 CET 2024 + +//////////////////////////////////////////////////// + +#include +#include +#include diff --git a/Kernel/KernelKit/PEF.hpp b/Kernel/KernelKit/PEF.hpp new file mode 100644 index 00000000..77fa4f62 --- /dev/null +++ b/Kernel/KernelKit/PEF.hpp @@ -0,0 +1,114 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: PEF.hpp + Purpose: Preferred Executable Format for NewOS. + + Revision History: + + ?/?/23: Added file (amlel) + +------------------------------------------- */ + +#ifndef __PEF__ +#define __PEF__ + +#include +#include +#include + +#define kPefMagic "Joy!" +#define kPefMagicFat "yoJ!" + +#define kPefMagicLen 5 + +#define kPefVersion 1 +#define kPefNameLen 255 + +namespace NewOS +{ + enum + { + kPefArchIntel86S, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64x0, /* 64x0. ISA */ + kPefArch32x0, /* 32x0. ISA */ + kPefArchPowerPC, + kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, + kPefArchInvalid = 0xFF, + }; + + enum + { + kPefSubArchAMD, + kPefSubArchIntel, + kPefSubArchARM, + kPefSubArchIBM, + }; + + enum + { + kPefKindExec = 1, /* .exe */ + kPefKindSharedObject = 2, /* .lib */ + kPefKindObject = 4, /* .obj */ + kPefKindDebug = 5, /* .dbg */ + kPefKindDriver = 6, + kPefKindCount, + }; + + typedef struct PEFContainer final + { + Char Magic[kPefMagicLen]; + UInt32 Linker; + UInt32 Version; + UInt32 Kind; + UInt32 Abi; + UInt32 Cpu; + UInt32 SubCpu; /* Cpu specific information */ + UIntPtr Start; + SizeT HdrSz; /* Size of header */ + SizeT Count; /* container header count */ + } PACKED PEFContainer; + + /* First PEFCommandHeader starts after PEFContainer */ + /* Last container is __exec_end */ + + /* PEF executable section and commands. */ + + typedef struct PEFCommandHeader final + { + Char Name[kPefNameLen]; /* container name */ + UInt32 Cpu; /* container cpu */ + UInt32 SubCpu; /* container sub-cpu */ + UInt32 Flags; /* container flags */ + UInt16 Kind; /* container kind */ + UIntPtr Offset; /* content offset */ + SizeT Size; /* content Size */ + } PACKED PEFCommandHeader; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + }; +} // namespace NewOS + +#define kPefExt ".exec" +#define kPefDylibExt ".lib" +#define kPefLibExt ".slib" +#define kPefObjectExt ".obj" +#define kPefDebugExt ".dbg" + +// NewOS System Binary Interface. +#define kPefAbi (0x5046) + +#define kPefStart "__ImageStart" + +#define kPefForkKind kPefMagic +#define kPefForkKindFAT kPefMagicFat + +#endif /* ifndef __PEF__ */ diff --git a/Kernel/KernelKit/PEFCodeManager.hxx b/Kernel/KernelKit/PEFCodeManager.hxx new file mode 100644 index 00000000..1dc7c3ac --- /dev/null +++ b/Kernel/KernelKit/PEFCodeManager.hxx @@ -0,0 +1,60 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef _INC_CODE_MANAGER_PEF_ +#define _INC_CODE_MANAGER_PEF_ + +#include +#include +#include + +#define kPefApplicationMime "application/x-newos-exec" + +namespace NewOS +{ + /// + /// \name PEFLoader + /// \brief PEF loader class. + /// + class PEFLoader : public LoaderInterface + { + private: + explicit PEFLoader() = delete; + + public: + explicit PEFLoader(const VoidPtr blob); + explicit PEFLoader(const Char* path); + ~PEFLoader() override; + + public: + NEWOS_COPY_DEFAULT(PEFLoader); + + public: + const char* Path() override; + const char* FormatAsString() override; + const char* MIME() override; + + public: + ErrorOr FindStart() override; + VoidPtr FindSymbol(const char* name, Int32 kind) override; + + public: + bool IsLoaded() noexcept; + + private: + Ref fPath; + VoidPtr fCachedBlob; + bool fFatBinary; + bool fBad; + }; + + namespace Utils + { + bool execute_from_image(PEFLoader& exec, const Int32& procKind) noexcept; + } // namespace Utils +} // namespace NewOS + +#endif // ifndef _INC_CODE_MANAGER_PEF_ diff --git a/Kernel/KernelKit/PEFSharedObject.hxx b/Kernel/KernelKit/PEFSharedObject.hxx new file mode 100644 index 00000000..436145df --- /dev/null +++ b/Kernel/KernelKit/PEFSharedObject.hxx @@ -0,0 +1,112 @@ +/* + * ======================================================== + * + * NewOS + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#ifndef __KERNELKIT_SHARED_OBJECT_HXX__ +#define __KERNELKIT_SHARED_OBJECT_HXX__ + +#include +#include +#include +#include + +namespace NewOS +{ + /// @brief Pure implementation, missing method/function handler. + extern "C" void __mh_purecall(void); + + /** + * @brief Shared Library class + * Load library from this class + */ + class SharedObject final + { + public: + struct SharedObjectTrait final + { + VoidPtr fImageObject; + VoidPtr fImageEntrypointOffset; + }; + + public: + explicit SharedObject() = default; + ~SharedObject() = default; + + public: + NEWOS_COPY_DEFAULT(SharedObject); + + private: + SharedObjectTrait* fMounted{nullptr}; + + public: + SharedObjectTrait** GetAddressOf() + { + return &fMounted; + } + + SharedObjectTrait* Get() + { + return fMounted; + } + + public: + void Mount(SharedObjectTrait* to_mount) + { + if (!to_mount || !to_mount->fImageObject) + return; + + fMounted = to_mount; + + if (fLoader && to_mount) + { + delete fLoader; + fLoader = nullptr; + } + + if (!fLoader) + { + fLoader = new PEFLoader(fMounted->fImageObject); + } + } + + void Unmount() + { + if (fMounted) + fMounted = nullptr; + }; + + template + SymbolType Load(const char* symbol_name, SizeT len, Int32 kind) + { + if (symbol_name == nullptr || *symbol_name == 0) + return nullptr; + if (len > kPathLen || len < 1) + return nullptr; + + auto ret = + reinterpret_cast(fLoader->FindSymbol(symbol_name, kind)); + + if (!ret) + { + if (kind == kPefCode) + return (VoidPtr)__mh_purecall; + + return nullptr; + } + + return ret; + } + + private: + PEFLoader* fLoader{nullptr}; + }; + + typedef SharedObject* SharedObjectPtr; +} // namespace NewOS + +#endif /* ifndef __KERNELKIT_SHARED_OBJECT_HXX__ */ diff --git a/Kernel/KernelKit/PermissionSelector.hxx b/Kernel/KernelKit/PermissionSelector.hxx new file mode 100644 index 00000000..22771bdd --- /dev/null +++ b/Kernel/KernelKit/PermissionSelector.hxx @@ -0,0 +1,57 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef _INC_PERMISSION_SEL_HPP +#define _INC_PERMISSION_SEL_HPP + +#include +#include + +// kernel mode user. +#define kMachineUser "Machine" + +// user mode users. +#define kSuperUser "Admin" +#define kGuestUser "Guest" + +// hash 'user@host:password' -> base64 encoded data +// use this data to then fetch specific data. + +namespace NewOS +{ + enum class RingKind + { + kRingUser = 3, + kRingDriver = 2, + kRingKernel = 0, + kRingUnknown = -1, + kRingCount = 4, + }; + + class PermissionSelector final + { + private: + explicit PermissionSelector(const Int32& sel); + explicit PermissionSelector(const RingKind& kind); + + ~PermissionSelector(); + + public: + NEWOS_COPY_DEFAULT(PermissionSelector) + + public: + bool operator==(const PermissionSelector& lhs); + bool operator!=(const PermissionSelector& lhs); + + public: + const RingKind& Ring() noexcept; + + private: + RingKind fRing; + }; +} // namespace NewOS + +#endif /* ifndef _INC_PERMISSION_SEL_HPP */ diff --git a/Kernel/KernelKit/ProcessScheduler.hpp b/Kernel/KernelKit/ProcessScheduler.hpp new file mode 100644 index 00000000..ba34f9cb --- /dev/null +++ b/Kernel/KernelKit/ProcessScheduler.hpp @@ -0,0 +1,301 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __PROCESS_SCHEDULER__ +#define __PROCESS_SCHEDULER__ + +#include +#include +#include +#include +#include +#include + +#define kSchedMinMicroTime AffinityKind::kHartStandard +#define kSchedInvalidPID (-1) + +#define kSchedProcessLimitPerTeam (100U) + +//////////////////////////////////////////////////// + +// LAST REV: Mon Feb 12 13:52:01 CET 2024 + +//////////////////////////////////////////////////// + +namespace NewOS +{ + class ProcessHeader; + class ProcessTeam; + class ProcessScheduler; + + //! @brief Process identifier. + typedef Int64 ProcessID; + + //! @brief Process name length. + inline constexpr SizeT kProcessLen = 256U; + + //! @brief Forward declaration. + class ProcessHeader; + class ProcessScheduler; + class ProcessHelper; + + //! @brief Process status enum. + enum class ProcessStatus : Int32 + { + kStarting, + kRunning, + kKilled, + kFrozen, + kDead + }; + + //! @brief Affinity is the amount of nano-seconds this process is going + //! to run. + enum class AffinityKind : Int32 + { + kInvalid = 300, + kVeryHigh = 250, + kHigh = 200, + kHartStandard = 150, + kLowUsage = 100, + kVeryLowUsage = 50, + }; + + // operator overloading. + + inline bool operator<(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast(lhs); + Int32 rhs_int = static_cast(rhs); + + return lhs_int < rhs_int; + } + + inline bool operator>(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast(lhs); + Int32 rhs_int = static_cast(rhs); + + return lhs_int > rhs_int; + } + + inline bool operator<=(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast(lhs); + Int32 rhs_int = static_cast(rhs); + + return lhs_int <= rhs_int; + } + + inline bool operator>=(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast(lhs); + Int32 rhs_int = static_cast(rhs); + + return lhs_int >= rhs_int; + } + + // end of operator overloading. + + enum ProcessSubsystemEnum + { + eProcessSubsystemLogin, + eProcessSubsystemNative, + eProcessSubsystemInvalid, + eProcessSubsystemCount, + }; + + using ProcessSubsystem = ProcessSubsystemEnum; + using ProcessTime = UInt64; + using PID = Int64; + + // for permission manager, tells where we run the code. + enum class ProcessSelector : Int + { + kRingUser, /* user ring (or ring 3 in x86) */ + kRingDriver, /* ring 2 in x86, hypervisor privileges in other archs */ + kRingKernel, /* machine privileges */ + }; + + // Helper types. + using ImagePtr = VoidPtr; + using HeapPtr = VoidPtr; + + // @name ProcessHeader + // @brief Process Header (PH) + // Holds information about the running process. + // Thread execution is being abstracted away. + class ProcessHeader final + { + public: + explicit ProcessHeader(VoidPtr startImage = nullptr) + : Image(startImage) + { + MUST_PASS(startImage); + } + + ~ProcessHeader() = default; + + NEWOS_COPY_DEFAULT(ProcessHeader) + + public: + void SetEntrypoint(UIntPtr& imageStart) noexcept; + + public: + Char Name[kProcessLen] = {"NewOS Process"}; + ProcessSubsystem SubSystem{ProcessSubsystem::eProcessSubsystemInvalid}; + ProcessSelector Selector{ProcessSelector::kRingUser}; + HAL::StackFramePtr StackFrame{nullptr}; + AffinityKind Affinity; + ProcessStatus Status; + + // Memory, images. + HeapPtr HeapCursor{nullptr}; + ImagePtr Image{nullptr}; + HeapPtr HeapPtr{nullptr}; + + // memory usage + SizeT UsedMemory{0}; + SizeT FreeMemory{0}; + + enum + { + kUserKind = 3, + kLibKind = 3, + kDriverKind = 0, + kKindCount, + }; + + enum + { + kRingUserKind = 3, + kRingDriverKind = 0, + }; + + ProcessTime PTime; + PID ProcessId{kSchedInvalidPID}; + Int32 Ring{kRingDriverKind}; + Int32 Kind{kUserKind}; + + public: + //! @brief boolean operator, check status. + operator bool() + { + return Status != ProcessStatus::kDead; + } + + //! @brief Crash the app, exits with code ~0. + void Crash(); + + //! @brief Exits app. + void Exit(Int32 exitCode = 0); + + //! @brief TLS Allocate + VoidPtr New(const SizeT& sz); + + //! @brief TLS Free. + Boolean Delete(VoidPtr ptr, const SizeT& sz); + + //! @brief Wakes up threads. + void Wake(const bool wakeup = false); + + // ProcessHeader getters. + public: + //! @brief ProcessHeader name getter, example: "C RunTime" + const Char* GetName(); + + const ProcessSelector& GetSelector(); + const ProcessStatus& GetStatus(); + const AffinityKind& GetAffinity(); + + private: + friend ProcessScheduler; + friend ProcessHelper; + }; + + /// \brief Processs Team (contains multiple processes inside it.) + /// Equivalent to a process batch + class ProcessTeam final + { + public: + explicit ProcessTeam() = default; + ~ProcessTeam() = default; + + NEWOS_COPY_DEFAULT(ProcessTeam); + + MutableArray>& AsArray(); + Ref& AsRef(); + + public: + MutableArray> mProcessList; + Ref mCurrentProcess; + }; + + using ProcessHeaderRef = ProcessHeader*; + + /// @brief ProcessHeader manager class. + /// The main class which you call to schedule an app. + class ProcessScheduler final + { + private: + explicit ProcessScheduler() = default; + + public: + ~ProcessScheduler() = default; + + NEWOS_COPY_DEFAULT(ProcessScheduler) + + operator bool() + { + return mTeam.AsArray().Count() > 0; + } + bool operator!() + { + return mTeam.AsArray().Count() == 0; + } + + ProcessTeam& CurrentTeam() + { + return mTeam; + } + + SizeT Add(Ref& headerRef); + bool Remove(SizeT headerIndex); + + Ref& GetCurrent(); + SizeT Run() noexcept; + + static Ref Shared(); + + private: + ProcessTeam mTeam; + }; + + /* + * Just a helper class, which contains some utilities for the scheduler. + */ + + class ProcessHelper final + { + public: + static bool Switch(HAL::StackFrame* newStack, const PID& newPid); + static bool CanBeScheduled(Ref& process); + static PID& GetCurrentPID(); + static bool StartScheduling(); + }; + + const Int32& rt_get_exit_code() noexcept; +} // namespace NewOS + +#include + +//////////////////////////////////////////////////// + +// END + +//////////////////////////////////////////////////// + +#endif /* ifndef __PROCESS_SCHEDULER__ */ diff --git a/Kernel/KernelKit/SMPManager.hpp b/Kernel/KernelKit/SMPManager.hpp new file mode 100644 index 00000000..3d7a4189 --- /dev/null +++ b/Kernel/KernelKit/SMPManager.hpp @@ -0,0 +1,129 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __SMP_MANAGER__ +#define __SMP_MANAGER__ + +#include +#include +#include + +// Last Rev +// Sat Feb 24 CET 2024 + +#define kMaxHarts 8 + +namespace NewOS +{ + using ThreadID = UInt32; + + enum ThreadKind + { + kHartSystemReserved, // System reserved thread, well user can't use it + kHartStandard, // user thread, cannot be used by kernel + kHartFallback, // fallback thread, cannot be used by user if not clear or + // used by kernel. + kHartBoot, // The core we booted from, the mama. + kInvalidHart, + kHartCount, + }; + + typedef enum ThreadKind SmThreadKind; + typedef ThreadID SmThreadID; + + /// + /// \name HardwareThread + /// @brief CPU Hardware Thread (POWER, x64, or 64x0) + /// + + class HardwareThread final + { + public: + explicit HardwareThread(); + ~HardwareThread(); + + public: + NEWOS_COPY_DEFAULT(HardwareThread) + + public: + operator bool(); + + public: + void Wake(const bool wakeup = false) noexcept; + void Busy(const bool busy = false) noexcept; + + public: + bool Switch(HAL::StackFrame* stack); + bool IsWakeup() noexcept; + + public: + HAL::StackFrame* StackFrame() noexcept; + const ThreadKind& Kind() noexcept; + bool IsBusy() noexcept; + const ThreadID& ID() noexcept; + + private: + HAL::StackFrame* fStack; + ThreadKind fKind; + ThreadID fID; + bool fWakeup; + bool fBusy; + Int64 fPID; + + private: + friend class SMPManager; + }; + + /// + /// \name SMPManager + /// @brief Multi processor manager to manage other cores and dispatch tasks. + /// + + class SMPManager final + { + private: + explicit SMPManager(); + + public: + ~SMPManager(); + + public: + NEWOS_COPY_DEFAULT(SMPManager); + + public: + bool Switch(HAL::StackFrame* the); + HAL::StackFramePtr GetStackFrame() noexcept; + + public: + Ref operator[](const SizeT& idx); + bool operator!() noexcept; + operator bool() noexcept; + + public: + /// @brief Shared instance of the SMP Manager. + /// @return the reference to the smp manager. + static Ref Shared(); + + public: + /// @brief Returns the amount of threads present in the system. + /// @returns SizeT the amount of cores present. + SizeT Count() noexcept; + + private: + Array fThreadList; + ThreadID fCurrentThread{0}; + }; + + /// @brief wakes up thread. + /// wakes up thread from hang. + Void rt_wakeup_thread(HAL::StackFramePtr stack); + + /// @brief makes thread sleep. + /// hooks and hangs thread to prevent code from executing. + Void rt_hang_thread(HAL::StackFramePtr stack); +} // namespace NewOS + +#endif // !__SMP_MANAGER__ diff --git a/Kernel/KernelKit/Semaphore.hpp b/Kernel/KernelKit/Semaphore.hpp new file mode 100644 index 00000000..f12e1282 --- /dev/null +++ b/Kernel/KernelKit/Semaphore.hpp @@ -0,0 +1,42 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace NewOS +{ + class ProcessHeader; + + typedef ProcessHeader* ProcessHeaderRef; + + /// @brief Access control class, which locks a task until one is done. + class Semaphore final + { + public: + explicit Semaphore() = default; + ~Semaphore() = default; + + public: + bool IsLocked() const; + bool Unlock() noexcept; + + public: + void Sync() noexcept; + + public: + bool Lock(ProcessHeader* process); + bool LockOrWait(ProcessHeader* process, const Int64& seconds); + + public: + NEWOS_COPY_DEFAULT(Semaphore); + + private: + ProcessHeaderRef fLockingProcess{nullptr}; + }; +} // namespace NewOS diff --git a/Kernel/KernelKit/ThreadLocalStorage.hxx b/Kernel/KernelKit/ThreadLocalStorage.hxx new file mode 100644 index 00000000..eece3cbc --- /dev/null +++ b/Kernel/KernelKit/ThreadLocalStorage.hxx @@ -0,0 +1,53 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef _KERNELKIT_TLS_HPP +#define _KERNELKIT_TLS_HPP + +#include + +//! @brief TLS implementation in C++ + +#define kCookieMag0 'H' +#define kCookieMag1 'C' +#define kCookieMag2 'R' + +template +T* tls_new_ptr(void); + +template +bool tls_delete_ptr(T* ptr); + +template +T* tls_new_class(Args&&... args); + +#define kTLSCookieLen 3 + +/// @brief Thread Information Block for Local Storage. +/// Located in GS on AMD64, Virtual Address 0x10000 (64x0, 32x0, ARM64) +struct PACKED ThreadInformationBlock final +{ + NewOS::Char Cookie[kTLSCookieLen]; + NewOS::UIntPtr StartCode; // Start Address + NewOS::UIntPtr StartData; // Allocation Heap + NewOS::UIntPtr StartStack; // Stack Pointer. + NewOS::Int32 ThreadID; // Thread execution ID. +}; + +/// @brief TLS install TIB and PIB. +EXTERN_C void rt_install_tib(ThreadInformationBlock* TIB, NewOS::VoidPtr PIB); + +///! @brief Cookie Sanity check. +NewOS::Boolean tls_check_tib(ThreadInformationBlock* Ptr); + +/// @brief TLS check system call +EXTERN_C NewOS::Void tls_check_syscall_impl(NewOS::HAL::StackFramePtr StackPtr) noexcept; + +#include + +// last rev 1/29/24 + +#endif /* ifndef _KERNELKIT_TLS_HPP */ diff --git a/Kernel/KernelKit/ThreadLocalStorage.inl b/Kernel/KernelKit/ThreadLocalStorage.inl new file mode 100644 index 00000000..ae3277eb --- /dev/null +++ b/Kernel/KernelKit/ThreadLocalStorage.inl @@ -0,0 +1,55 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +//! @brief Allocates a pointer from the process's tls. + +#ifndef __PROCESS_MANAGER__ +#include +#endif + +template +inline T* tls_new_ptr(void) +{ + using namespace NewOS; + + MUST_PASS(ProcessScheduler::Shared().Leak().GetCurrent()); + + auto ref_process = ProcessScheduler::Shared().Leak().GetCurrent(); + + T* pointer = (T*)ref_process.Leak().New(sizeof(T)); + return pointer; +} + +//! @brief TLS delete implementation. +template +inline bool tls_delete_ptr(T* ptr) +{ + if (!ptr) + return false; + + using namespace NewOS; + + MUST_PASS(ProcessScheduler::Shared().Leak().GetCurrent()); + + ptr->~T(); + + auto ref_process = ProcessScheduler::Shared().Leak().GetCurrent(); + return ref_process.Leak().Delete(ptr, sizeof(T)); +} + +template +T* tls_new_class(Args&&... args) +{ + T* ptr = tls_new_ptr(); + + if (ptr) + { + *ptr = T(NewOS::forward(args)...); + return ptr; + } + + return nullptr; +} diff --git a/Kernel/KernelKit/Timer.hpp b/Kernel/KernelKit/Timer.hpp new file mode 100644 index 00000000..8b0642c7 --- /dev/null +++ b/Kernel/KernelKit/Timer.hpp @@ -0,0 +1,64 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace NewOS +{ + class HardwareTimer; + class HardwareTimerInterface; + + class HardwareTimerInterface + { + public: + /// @brief Default constructor + explicit HardwareTimerInterface() = default; + virtual ~HardwareTimerInterface() = default; + + public: + NEWOS_COPY_DEFAULT(HardwareTimerInterface); + + public: + virtual Int32 Wait() noexcept; + }; + + class HardwareTimer final : public HardwareTimerInterface + { + public: + explicit HardwareTimer(Int64 seconds); + ~HardwareTimer() override; + + public: + NEWOS_COPY_DEFAULT(HardwareTimer); + + public: + Int32 Wait() noexcept override; + + public: + IntPtr* fDigitalTimer{nullptr}; + Int64 fWaitFor{0}; + }; + + inline Int64 Seconds(Int64 time) + { + if (time < 0) + return 0; + + return 1000 / time; + } + + inline Int64 Milliseconds(Int64 time) + { + if (time < 0) + return 0; + + return 1000 / Seconds(time); + } +} // namespace NewOS diff --git a/Kernel/KernelKit/UserHeap.hpp b/Kernel/KernelKit/UserHeap.hpp new file mode 100644 index 00000000..6197e30d --- /dev/null +++ b/Kernel/KernelKit/UserHeap.hpp @@ -0,0 +1,46 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +/// @version 5/11/23 +/// @file UserHeap.hpp +/// @brief memory heap for user programs. + +#define kUserHeapMaxSz (4096) +#define kUserHeapMag (0xFAF0FEF0) + +namespace NewOS +{ + typedef enum + { + /// @brief Driver only heap. + kUserHeapDriver = 0x2, + /// @brief Shared heap. + kUserHeapShared = 0x4, + /// @brief User and private heap. + kUserHeapUser = 0x6, + /// @brief Read and Write heap. + kUserHeapRw = 0x8, + } kUserHeapFlags; + + /// @brief Allocate a process heap, no zero out is done here. + /// @param flags + /// @return The process's heap. + VoidPtr rt_new_heap(Int32 flags); + + /// @brief Frees the process heap. + /// @param pointer The process heap pointer. + /// @return + Int32 rt_free_heap(voidPtr pointer); +} // namespace NewOS diff --git a/Kernel/KernelKit/XCOFF.hxx b/Kernel/KernelKit/XCOFF.hxx new file mode 100644 index 00000000..2b153918 --- /dev/null +++ b/Kernel/KernelKit/XCOFF.hxx @@ -0,0 +1,38 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: XCOFF.hpp + Purpose: XCOFF for NewOS. + + Revision History: + + 04/07/24: Added file (amlel) + +------------------------------------------- */ + +#ifndef __XCOFF__ +#define __XCOFF__ + +#include + +#define kXCOFF64Magic 0x01F7 + +#define kXCOFFRelFlg 0x0001 +#define kXCOFFExecutable 0x0002 +#define kXCOFFLnno 0x0004 +#define kXCOFFLSyms 0x0008 + +/// @brief XCoff file header, meant for POWER apps. +typedef struct XCoffFileHeader +{ + NewOS::UInt16 fMagic; + NewOS::UInt16 fTarget; + NewOS::UInt16 fNumSecs; + NewOS::UInt32 fTimeDat; + NewOS::UIntPtr fSymPtr; + NewOS::UInt32 fNumSyms; + NewOS::UInt16 fOptHdr; // ?: Number of bytes in optional header +} XCoffFileHeader; + +#endif // ifndef __XCOFF__ diff --git a/Kernel/KernelKit/compile_flags.txt b/Kernel/KernelKit/compile_flags.txt new file mode 100644 index 00000000..a37ae6bf --- /dev/null +++ b/Kernel/KernelKit/compile_flags.txt @@ -0,0 +1,5 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I./ +-I../ diff --git a/Kernel/KernelRsrc.rsrc b/Kernel/KernelRsrc.rsrc new file mode 100644 index 00000000..d8fc6473 --- /dev/null +++ b/Kernel/KernelRsrc.rsrc @@ -0,0 +1,27 @@ +1 ICON "Root/Boot/Icons/kernel-logo.ico" + +#include "CompilerKit/Version.hxx" + +1 VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904E4" + BEGIN + VALUE "CompanyName", "SoftwareLabs" + VALUE "FileDescription", "New OS multiplatform kernel." + VALUE "FileVersion", KERNEL_VERSION + VALUE "InternalName", "NewKernel" + VALUE "LegalCopyright", "SoftwareLabs" + VALUE "OriginalFilename", "NewKernel.exe" + VALUE "ProductName", "NewKernel" + VALUE "ProductVersion", KERNEL_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1252 + END +END diff --git a/Kernel/Linker/16x0.json b/Kernel/Linker/16x0.json new file mode 100644 index 00000000..5851a2d3 --- /dev/null +++ b/Kernel/Linker/16x0.json @@ -0,0 +1,6 @@ +{ + "executable_type": "kernel", + "output_name": "NewKernel.exe", + "start_proc": "__ImageStart", + "format": "PEF" +} diff --git a/Kernel/Linker/32x0.json b/Kernel/Linker/32x0.json new file mode 100644 index 00000000..5851a2d3 --- /dev/null +++ b/Kernel/Linker/32x0.json @@ -0,0 +1,6 @@ +{ + "executable_type": "kernel", + "output_name": "NewKernel.exe", + "start_proc": "__ImageStart", + "format": "PEF" +} diff --git a/Kernel/Linker/64x0.json b/Kernel/Linker/64x0.json new file mode 100644 index 00000000..5851a2d3 --- /dev/null +++ b/Kernel/Linker/64x0.json @@ -0,0 +1,6 @@ +{ + "executable_type": "kernel", + "output_name": "NewKernel.exe", + "start_proc": "__ImageStart", + "format": "PEF" +} diff --git a/Kernel/MoveAll.sh b/Kernel/MoveAll.sh new file mode 100755 index 00000000..664ad472 --- /dev/null +++ b/Kernel/MoveAll.sh @@ -0,0 +1,7 @@ +#! /bin/sh + +for file in *.o; do + mv -- "$file" "${file%.o}.obj" +done + +mv *.obj HALKit/AMD64/*.obj Objects/ \ No newline at end of file diff --git a/Kernel/NetworkKit/IP.hpp b/Kernel/NetworkKit/IP.hpp new file mode 100644 index 00000000..94d0d3be --- /dev/null +++ b/Kernel/NetworkKit/IP.hpp @@ -0,0 +1,83 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +namespace NewOS +{ + class RawIPAddress6; + class RawIPAddress; + class IPFactory; + + class RawIPAddress final + { + private: + explicit RawIPAddress(char bytes[4]); + ~RawIPAddress() = default; + + RawIPAddress& operator=(const RawIPAddress&) = delete; + RawIPAddress(const RawIPAddress&) = default; + + public: + char* Address(); + + char& operator[](const Size& index); + + bool operator==(const RawIPAddress& ipv6); + bool operator!=(const RawIPAddress& ipv6); + + private: + char fAddr[4]; + + friend IPFactory; // it is the one creating these addresses, thus this + // is why the constructors are private. + }; + + /** + * @brief IPv6 address. + */ + class RawIPAddress6 final + { + private: + explicit RawIPAddress6(char Bytes[8]); + ~RawIPAddress6() = default; + + RawIPAddress6& operator=(const RawIPAddress6&) = delete; + RawIPAddress6(const RawIPAddress6&) = default; + + public: + char* Address() + { + return fAddr; + } + + char& operator[](const Size& index); + + bool operator==(const RawIPAddress6& ipv6); + bool operator!=(const RawIPAddress6& ipv6); + + private: + char fAddr[8]; + + friend IPFactory; + }; + + /** + * @brief IP Creation helpers + */ + class IPFactory final + { + public: + static ErrorOr ToStringView(Ref ipv6); + static ErrorOr ToStringView(Ref ipv4); + static bool IpCheckVersion4(const char* ip); + }; +} // namespace NewOS diff --git a/Kernel/NetworkKit/IPCEP.hxx b/Kernel/NetworkKit/IPCEP.hxx new file mode 100644 index 00000000..5c34d47e --- /dev/null +++ b/Kernel/NetworkKit/IPCEP.hxx @@ -0,0 +1,57 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs. + + File: IPCEP.hxx, Purpose: Common IPC protocol. + +------------------------------------------- */ + +#ifndef _INC_IPC_ENDPOINT_HXX_ +#define _INC_IPC_ENDPOINT_HXX_ + +#include +#include + +/// @brief Common IPC Endpoint Protocol (Common IPC for short). + +/// IA separator. +#define kRemoteSeparator "." + +/// Interchange address, consists of domain:namespace. +#define kRemoteInvalid "00.00.00.00:0000" +#define kRemoteBitWidth 96 /* 96-bit address space. */ + +#define kRemoteHeaderMagic 0xFEEDFACE + +namespace NewOS +{ + /// @brief 96-bit number to represent the domain and namespace + struct PACKED IPCEPAddress + { + UInt32 RemoteAddress; + UInt64 RemoteNamespace; + }; + + typedef struct IPCEPAddress IPCEPAddressType; + + enum + { + kIPCEPLittleEndian = 0, + kIPCEPBigEndian = 1 + }; + + /// @brief IPCEP connection header + typedef struct IPCEPConnectionHeader + { + UInt32 IpcHeader; // kRemoteHeaderMagic + UInt8 IpcEndianess; // 0 : LE, 1 : BE + SizeT IpcPacketSize; + IPCEPAddressType IpcFrom; + IPCEPAddressType IpcTo; + UInt32 IpcCRC32; + SizeT IpcDataSize; + Char IpcData[]; + } PACKED IPCEPConnectionHeader; +} // namespace NewOS + +#endif // _INC_IPC_ENDPOINT_HXX_ diff --git a/Kernel/NetworkKit/MAC.hxx b/Kernel/NetworkKit/MAC.hxx new file mode 100644 index 00000000..30a865ac --- /dev/null +++ b/Kernel/NetworkKit/MAC.hxx @@ -0,0 +1,29 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace NewOS +{ + class MacAddressGetter; + + /// \brief This retrieves the MAC address of the device. + /// \note Listens for the current NIC. + class MacAddressGetter final + { + public: + explicit MacAddressGetter() = default; + + public: + StringView& AsString(); + Array& AsBytes(); + }; + +} // namespace NewOS diff --git a/Kernel/NetworkKit/NetworkDevice.hpp b/Kernel/NetworkKit/NetworkDevice.hpp new file mode 100644 index 00000000..b00ce7a6 --- /dev/null +++ b/Kernel/NetworkKit/NetworkDevice.hpp @@ -0,0 +1,65 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __NETWORK_DEVICE__ +#define __NETWORK_DEVICE__ + +#include +#include + +namespace NewOS +{ + struct NetworkDeviceCommand; + class NetworkDevice; + + /** +* \brief Network device interface, establishes a connection to the NIC. +*/ + class NetworkDevice final : public DeviceInterface + { + public: + NetworkDevice(void (*out)(NetworkDeviceCommand), + void (*in)(NetworkDeviceCommand), + void (*onCleanup)(void) = nullptr); + + ~NetworkDevice() override; + + public: + NetworkDevice& operator=(const NetworkDevice&) = default; + NetworkDevice(const NetworkDevice&) = default; + + public: + const char* Name() const override; + + private: + void (*fCleanup)(void); + }; + + struct PACKED NetworkDeviceCommand final + { + UInt32 CommandName; + UInt32 CommandType; + UInt32 CommandFlags; + VoidPtr CommandBuffer; + SizeT CommandSizeBuffer; + }; + + /// @brief TCP device. + using TCPNetworkDevice = NetworkDevice; + + /// @brief UDP device. + using UDPNetworkDevice = NetworkDevice; + + /// @brief PPP device. + using PPPNetworkDevice = NetworkDevice; + + /// @brief HPC device. + using HPCNetworkDevice = NetworkDevice; +} // namespace NewOS + +#include + +#endif // !__NETWORK_DEVICE__ diff --git a/Kernel/NetworkKit/NetworkDevice.inl b/Kernel/NetworkKit/NetworkDevice.inl new file mode 100644 index 00000000..0b927d0e --- /dev/null +++ b/Kernel/NetworkKit/NetworkDevice.inl @@ -0,0 +1,27 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/*** + Dtor and ctors. +*/ + +namespace NewOS { +NetworkDevice::NetworkDevice(void (*out)(NetworkDeviceCommand), + void (*in)(NetworkDeviceCommand), + void (*on_cleanup)(void)) + : DeviceInterface(out, in), fCleanup(on_cleanup) { + kcout << "NK: NetworkDevice initialize.\r"; + + MUST_PASS(out && in && on_cleanup); +} + +NetworkDevice::~NetworkDevice() { + MUST_PASS(fCleanup); + + kcout << "NK: NetworkDevice cleanup.\r"; + if (fCleanup) fCleanup(); +} +} // namespace NewOS diff --git a/Kernel/NetworkKit/compile_flags.txt b/Kernel/NetworkKit/compile_flags.txt new file mode 100644 index 00000000..a37ae6bf --- /dev/null +++ b/Kernel/NetworkKit/compile_flags.txt @@ -0,0 +1,5 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I./ +-I../ diff --git a/Kernel/NewKit/Application.hxx b/Kernel/NewKit/Application.hxx new file mode 100644 index 00000000..19a892d6 --- /dev/null +++ b/Kernel/NewKit/Application.hxx @@ -0,0 +1,31 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +/// +/// @brief Application object, given by the OS to the process. interact with the OS. +/// @file Application.hxx +/// @author Amlal EL Mahrouss +/// + +#include +#include + +/// \brief Application Interface. +/// \author Amlal El Mahrouss +typedef struct _ApplicationInterface final +{ + /// @brief Releases the object exit the process on main object. + NewOS::Void (*Release)(struct _Application* Self, NewOS::Int32 ExitCode); + /// @brief Invoke a function from the application object. + NewOS::IntPtr (*Invoke)(struct _Application* Self, NewOS::Int32 Sel, ...); + /// @brief Query a new application object from a GUID. + /// @note this doesn't query a process, it query a registered object withtin that app. + NewOS::Void (*Query)(struct _Application* Self, NewOS::VoidPtr* Dst, NewOS::SizeT SzDst, NewOS::XRN::GUIDSequence GuidOf); +} ApplicationInterface, *ApplicationInterfaceRef; + +#define app_cast reinterpret_cast diff --git a/Kernel/NewKit/Array.hpp b/Kernel/NewKit/Array.hpp new file mode 100644 index 00000000..623d9860 --- /dev/null +++ b/Kernel/NewKit/Array.hpp @@ -0,0 +1,69 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ +#pragma once + +#include +#include +#include + +namespace NewOS +{ + template + class Array final + { + public: + explicit Array() = default; + ~Array() = default; + + Array& operator=(const Array&) = default; + Array(const Array&) = default; + + ErrorOr operator[](Size At) + { + if (At > N) + return {}; + + kcout << "Returning element\r"; + return ErrorOr(fArray[At]); + } + + Boolean Empty() const + { + for (auto Val : fArray) + { + if (Val) + return false; + } + + return true; + } + + SizeT Count() const + { + SizeT cntElems = 0UL; + for (auto Val : fArray) + { + if (Val) + ++cntElems; + } + + return cntElems; + } + + const T* CData() + { + return fArray; + } + + operator bool() + { + return !Empty(); + } + + private: + T fArray[N]; + }; +} // namespace NewOS diff --git a/Kernel/NewKit/ArrayList.hpp b/Kernel/NewKit/ArrayList.hpp new file mode 100644 index 00000000..7ac47f40 --- /dev/null +++ b/Kernel/NewKit/ArrayList.hpp @@ -0,0 +1,58 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +namespace NewOS +{ + template + class ArrayList final + { + public: + explicit ArrayList(T* list) + : fList(reinterpret_cast(list)) + { + } + + ~ArrayList() = default; + + ArrayList& operator=(const ArrayList&) = default; + ArrayList(const ArrayList&) = default; + + T* Data() + { + return fList; + } + + const T* CData() + { + return fList; + } + + T& operator[](int index) const + { + return fList[index]; + } + + operator bool() + { + return fList; + } + + private: + T* fList; + + friend class InitHelpers; + }; + + template + ArrayList make_list(ValueType val) + { + return ArrayList{val}; + } +} // namespace NewOS diff --git a/Kernel/NewKit/Atom.hpp b/Kernel/NewKit/Atom.hpp new file mode 100644 index 00000000..df7d3dda --- /dev/null +++ b/Kernel/NewKit/Atom.hpp @@ -0,0 +1,46 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ +#pragma once + +#include + +namespace NewOS +{ + template + class Atom final + { + public: + explicit Atom() = default; + ~Atom() = default; + + public: + Atom& operator=(const Atom&) = delete; + Atom(const Atom&) = delete; + + public: + T operator[](Size sz) + { + return (fArrayOfAtoms & sz); + } + void operator|(Size sz) + { + fArrayOfAtoms |= sz; + } + + friend Boolean operator==(Atom& atomic, const T& idx) + { + return atomic[idx] == idx; + } + + friend Boolean operator!=(Atom& atomic, const T& idx) + { + return atomic[idx] == idx; + } + + private: + T fArrayOfAtoms; + }; +} // namespace NewOS diff --git a/Kernel/NewKit/Crc32.hpp b/Kernel/NewKit/Crc32.hpp new file mode 100644 index 00000000..e13aaad5 --- /dev/null +++ b/Kernel/NewKit/Crc32.hpp @@ -0,0 +1,22 @@ +/* + * ======================================================== + * + * NewOS Date Added: 13/02/2023 + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#ifndef __CRC32_H__ +#define __CRC32_H__ + +#include + +#define kCrcCnt (256) + +namespace NewOS +{ + UInt ke_calculate_crc32(const Char* crc, UInt len) noexcept; +} // namespace NewOS + +#endif // !__CRC32_H__ diff --git a/Kernel/NewKit/CxxAbi.hpp b/Kernel/NewKit/CxxAbi.hpp new file mode 100644 index 00000000..92dcbdee --- /dev/null +++ b/Kernel/NewKit/CxxAbi.hpp @@ -0,0 +1,28 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ +#pragma once + +#include + +#ifdef __GNUC__ + +#define kDSOMaxObjects (128) + +struct atexit_func_entry_t +{ + void (*destructor_func)(void*); + void* obj_ptr; + void* dso_handle; +}; + +typedef unsigned uarch_t; + +namespace cxxabiv1 +{ + typedef void* __guard; +} + +#endif // __GNUC__ \ No newline at end of file diff --git a/Kernel/NewKit/Defines.hpp b/Kernel/NewKit/Defines.hpp new file mode 100644 index 00000000..f32e873a --- /dev/null +++ b/Kernel/NewKit/Defines.hpp @@ -0,0 +1,150 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +#define NEWKIT_VERSION "1.01" + +#if !defined(_INC_NO_STDC_HEADERS) && defined(__GNUC__) +#include +#endif + +#ifdef __has_feature +#if !__has_feature(cxx_nullptr) +#if !__has_nullptr +#error You must at least have nullptr featured on your C++ compiler. +#endif +#endif +#endif + +/// @brief NewOS namespace. +namespace NewOS +{ + using voidPtr = void*; + using VoidPtr = void*; + using nullPtr = decltype(nullptr); + using NullPtr = decltype(nullptr); + + using Int = int; + using Int32 = int; + using UShort = unsigned short; + using UInt16 = unsigned short; + using Short = short; + using Int16 = short; + using UInt = unsigned int; + using UInt32 = unsigned int; + using Long = __INT64_TYPE__; + using Int64 = __INT64_TYPE__; + using ULong = __UINT64_TYPE__; + using UInt64 = __UINT64_TYPE__; + using Boolean = bool; + using Bool = bool; + using Char = char; + using UChar = unsigned char; + using UInt8 = unsigned char; + + using SSize = Int64; + using SSizeT = Int64; + using Size = __SIZE_TYPE__; + using SizeT = __SIZE_TYPE__; + using IntPtr = __INTPTR_TYPE__; + using UIntPtr = __UINTPTR_TYPE__; + using IntFast = __INT_FAST32_TYPE__; + using IntFast64 = __INT_FAST64_TYPE__; + using PtrDiff = __PTRDIFF_TYPE__; + + typedef UIntPtr* Ptr64; + typedef UInt32* Ptr32; + + using Utf8Char = char8_t; + using Utf16Char = char16_t; + using WideChar = wchar_t; + using Utf32Char = char32_t; + + using Void = void; + + using Lba = UInt64; + + enum class Endian : UChar + { + kEndianLittle, + kEndianBig, + kEndianMixed, + kCount + }; + + /// @brief Forward object. + /// @tparam Args the object type. + /// @param arg the object. + /// @return object's rvalue + template + inline Args&& forward(Args& arg) + { + return static_cast(arg); + } + + /// @brief Move object. + /// @tparam Args the object type. + /// @param arg the object. + /// @return object's rvalue + template + inline Args&& move(Args&& arg) + { + return static_cast(arg); + } + + /// @brief Encoder class + /// Used to cast A to B or B to A. + class Encoder final + { + public: + explicit Encoder() = default; + ~Encoder() = default; + + Encoder& operator=(const Encoder&) = default; + Encoder(const Encoder&) = default; + + public: + /// @brief Convert type to bytes. + /// @tparam T the type. + /// @param type (a1) the data. + /// @return a1 as Char* + template + Char* AsBytes(T type) noexcept + { + return reinterpret_cast(type); + } + + /// @brief Convert T class to Y class. + /// @tparam T the class type of type. + /// @tparam Y the result class. + /// @param type the class to cast. + /// @return the class as Y. + template + Y As(T type) noexcept + { + return type.template As(); + } + }; +} // namespace NewOS + +#define DEDUCE_ENDIAN(address, value) \ + (((reinterpret_cast(address)[0]) == (value)) \ + ? (NewOS::Endian::kEndianBig) \ + : (NewOS::Endian::kEndianLittle)) + +#define Yes (true) +#define No (false) + +#define VoidStar NewOS::voidPtr + +#ifdef INIT +#undef INIT +#endif // ifdef INIT + +#define INIT(OBJ, TYPE, ...) TYPE OBJ = TYPE(__VA_ARGS__) diff --git a/Kernel/NewKit/ErrorOr.hpp b/Kernel/NewKit/ErrorOr.hpp new file mode 100644 index 00000000..236a2d1c --- /dev/null +++ b/Kernel/NewKit/ErrorOr.hpp @@ -0,0 +1,72 @@ +/* +* ======================================================== +* +* NewOS +* Copyright SoftwareLabs, all rights reserved. +* +* ======================================================== +*/ + +#pragma once + +#include +#include + +namespace NewOS +{ + using ErrorT = UInt; + + template + class ErrorOr final + { + public: + ErrorOr() = default; + ~ErrorOr() = default; + + public: + explicit ErrorOr(Int32 err) + : mId(err) + { + } + + explicit ErrorOr(nullPtr Null) + { + } + + explicit ErrorOr(T Class) + : mRef(Class) + { + } + + ErrorOr& operator=(const ErrorOr&) = default; + ErrorOr(const ErrorOr&) = default; + + ErrorOr& operator=(const Ref& refErr) + { + mRef = refErr; + return *this; + } + + Ref Leak() + { + return mRef; + } + + Int32 Error() + { + return mId; + } + + operator bool() + { + return mRef; + } + + private: + Ref mRef; + Int32 mId{0}; + }; + + using ErrorOrAny = ErrorOr; + +} // namespace NewOS diff --git a/Kernel/NewKit/Function.hpp b/Kernel/NewKit/Function.hpp new file mode 100644 index 00000000..12ae03f3 --- /dev/null +++ b/Kernel/NewKit/Function.hpp @@ -0,0 +1,53 @@ +#ifndef _INC_FUNCTION_HPP__ +#define _INC_FUNCTION_HPP__ + +#include + +namespace NewOS +{ + template + class Function final + { + public: + Function() = default; + + public: + explicit Function(T (*Fn)(Args... args)) + : fFn(Fn) + { + } + + ~Function() = default; + + Function& operator=(const Function&) = default; + Function(const Function&) = default; + + template + T operator()(Args... args) + { + return fFn(args...); + } + + template + T Call(Args... args) + { + return fFn(args...); + } + + operator bool() + { + return fFn; + } + + bool operator!() + { + return !fFn; + } + + private: + T(*fFn) + (Args... args); + }; +} // namespace NewOS + +#endif // !_INC_FUNCTION_HPP__ diff --git a/Kernel/NewKit/Json.hpp b/Kernel/NewKit/Json.hpp new file mode 100644 index 00000000..ebdcc848 --- /dev/null +++ b/Kernel/NewKit/Json.hpp @@ -0,0 +1,118 @@ + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +// last-rev: 30/01/24 + +#include +#include +#include +#include +#include + +namespace NewOS +{ + /// @brief Json value class + class JsonType final + { + public: + explicit JsonType() + : NewOS::JsonType(1, 1) + { + } + + explicit JsonType(SizeT lhsLen, SizeT rhsLen) + : fKey(lhsLen), fValue(rhsLen) + { + } + + ~JsonType() = default; + + NEWOS_COPY_DEFAULT(JsonType); + + private: + StringView fKey; + StringView fValue; + + public: + /// @brief returns the key of the json + /// @return the key as string view. + StringView& AsKey() + { + return fKey; + } + + /// @brief returns the value of the json. + /// @return the key as string view. + StringView& AsValue() + { + return fValue; + } + + static JsonType kUndefined; + }; + + /// @brief Json stream helper class. + struct JsonStreamTrait final + { + JsonType In(const char* full_array) + { + SizeT len = rt_string_len(full_array); + + if (full_array[0] == '\"' && full_array[len - 1] == ',' || + full_array[len - 1] == '\"') + { + Boolean probe_key = true; + + SizeT key_len = 0; + SizeT value_len = 0; + + for (SizeT i = 1; i < len; i++) + { + if (full_array[i] == ' ') + continue; + + JsonType type(kPathLen, kPathLen); + + if (probe_key) + { + type.AsKey().Data()[key_len] = full_array[i]; + ++key_len; + + if (full_array[i] == '\"') + { + probe_key = false; + type.AsKey().Data()[key_len] = 0; + + ++i; + } + } + else + { + type.AsValue().Data()[value_len] = full_array[i]; + ++value_len; + + if (full_array[i] == '\"') + { + type.AsValue().Data()[value_len] = 0; + } + } + } + } + + return JsonType::kUndefined; + } + + JsonType Out(JsonType& out) + { + return out; + } + }; + + using JsonStream = Stream; +} // namespace NewOS diff --git a/Kernel/NewKit/KernelCheck.hpp b/Kernel/NewKit/KernelCheck.hpp new file mode 100644 index 00000000..e6a27834 --- /dev/null +++ b/Kernel/NewKit/KernelCheck.hpp @@ -0,0 +1,63 @@ + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +namespace NewOS +{ + void ke_runtime_check(bool bExpression, const char* file, const char* line); +} + +#define MUST_PASS_COMPILER(EXPR, MSG) static_assert(EXPR, MSG) +#define __MUST_PASS(EXPR, FILE, LINE) \ + NewOS::ke_runtime_check(EXPR, FILE, STRINGIFY(LINE)) +#define MUST_PASS(EXPR) __MUST_PASS(EXPR, __FILE__, __LINE__) +#define assert(EXPR) MUST_PASS(EXPR, RUNTIME_CHECK_EXPRESSION) + +enum RUNTIME_CHECK +{ + RUNTIME_CHECK_FAILED = -1, + RUNTIME_CHECK_POINTER = 0, + RUNTIME_CHECK_EXPRESSION, + RUNTIME_CHECK_FILE, + RUNTIME_CHECK_IPC, + RUNTIME_CHECK_TLS, + RUNTIME_CHECK_HANDSHAKE, + RUNTIME_CHECK_ACPI, + RUNTIME_CHECK_INVALID_PRIVILEGE, + RUNTIME_CHECK_PROCESS, + RUNTIME_CHECK_BAD_BEHAVIOR, + RUNTIME_CHECK_BOOTSTRAP, + RUNTIME_CHECK_UNEXCPECTED, + RUNTIME_CHECK_COUNT, +}; + +namespace NewOS +{ + class DumpManager final + { + public: + static void Dump(void) + { + // TODO: + } + }; + + void ke_stop(const Int& id); +} // namespace NewOS + +#ifdef TRY +#undef TRY +#endif + +#define TRY(FN) \ + if (!FN()) \ + { \ + MUST_PASS(false); \ + } diff --git a/Kernel/NewKit/Macros.hpp b/Kernel/NewKit/Macros.hpp new file mode 100644 index 00000000..7e9dc759 --- /dev/null +++ b/Kernel/NewKit/Macros.hpp @@ -0,0 +1,98 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#ifndef KIB +#define KIB(X) ((X) / 1024) +#endif + +#ifndef MIB +#define MIB(X) ((UInt64)KIB(X) / 1024) +#endif + +#ifndef GIB +#define GIB(X) ((UInt64)MIB(X) / 1024) +#endif + +#ifndef TIB +#define TIB(X) ((UInt64)GIB(X) / 1024) +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) \ + (((sizeof(a) / sizeof(*(a))) / \ + (static_cast(!(sizeof(a) % sizeof(*(a))))))) +#endif + +#ifndef ALIGN +#define ALIGN(X) __attribute__((aligned(X))) +#endif // #ifndef ALIGN + +#ifndef ATTRIBUTE +#define ATTRIBUTE(X) __attribute__((X)) +#endif // #ifndef ATTRIBUTE + +#ifndef __MAHROUSS__ +#define __MAHROUSS__ (202401) +#endif // !__MAHROUSS__ + +#ifndef EXTERN_C +#define EXTERN_C extern "C" +#endif + +#ifndef MAKE_ENUM +#define MAKE_ENUM(NAME) \ + enum NAME \ + { +#endif + +#ifndef END_ENUM +#define END_ENUM() \ + } \ + ; +#endif + +#ifndef MAKE_STRING_ENUM +#define MAKE_STRING_ENUM(NAME) \ + namespace NAME \ + { +#endif + +#ifndef ENUM_STRING +#define ENUM_STRING(NAME, VAL) inline constexpr const char* NAME = VAL +#endif + +#ifndef END_STRING_ENUM +#define END_STRING_ENUM() } +#endif + +#ifndef Alloca +#define Alloca(Sz) __builtin_alloca(Sz) +#endif // #ifndef Alloca + +#ifndef CANT_REACH +#define CANT_REACH() __builtin_unreachable() +#endif + +#define kBadPtr 0xFBFBFBFBFBFBFBFB +#define kMaxAddr 0xFFFFFFFFFFFFFFFF +#define kPathLen 255 + +#define PACKED ATTRIBUTE(packed) +#define NO_EXEC ATTRIBUTE(noexec) + +#define EXTERN extern +#define STATIC static + +#define CONST const + +#define STRINGIFY(X) #X +#define NEWOS_UNUSED(X) ((void)X) + +#ifndef RGB +#define RGB(R, G, B) (UInt32)(0x##R##G##B) +#endif // !RGB diff --git a/Kernel/NewKit/MutableArray.hpp b/Kernel/NewKit/MutableArray.hpp new file mode 100644 index 00000000..0dfed60c --- /dev/null +++ b/Kernel/NewKit/MutableArray.hpp @@ -0,0 +1,232 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ +#pragma once + +#include +#include +#include + +#define TRY_FIND_NODE(NAME, NODE) \ + auto* NAME = NODE; \ + while (NAME) \ + { \ + if (NAME->fIndex == Index) \ + return NAME->fVal; \ + NAME = NAME->fNext; \ + } + +#define TRY_FIND_NODE2(NAME, NODE) \ + auto* NAME = NODE; \ + while (NAME) \ + { \ + if (NAME->fIndex == Index) \ + return Ref{NAME->fVal}; \ + NAME = NAME->fNext; \ + } + +#define TRY_REMOVE_NODE(NODE) \ + if (NODE && NODE->fIndex == Index) \ + { \ + NODE->fUsed = false; \ + NODE->fIndex = 0; \ + \ + return true; \ + } + +// FIXME: this is a shitty algorithm, which is consumer hungry. +// Remove and occurences of that, and remove that class. +namespace NewOS +{ + template + class MutableArray; + + template + class NullableMutableArray; + + template + class MutableLinkedList + { + public: + T fVal; + SizeT fIndex{0}; + Boolean fUsed{false}; + + MutableLinkedList* fPrev{nullptr}; + MutableLinkedList* fNext{nullptr}; + }; + + template + class NullableMutableArray + { + public: + // explicit this. + explicit NullableMutableArray() + : fFirstNode(new MutableLinkedList()) + { + } + + /* + * We free all the nodes allocated by the array + * and store the next one inside "NextIt" + */ + + virtual ~NullableMutableArray() + { + auto* It = fFirstNode; + MutableLinkedList* NextIt = nullptr; + + while (It) + { + NextIt = It->fNext; + delete It; + + It = NextIt; + } + } + + NullableMutableArray& operator=(const NullableMutableArray&) = default; + NullableMutableArray(const NullableMutableArray&) = default; + + operator bool() + { + return Count() > 1; + } + + public: + T operator[](const SizeT& Index) const + { + TRY_FIND_NODE(first, fFirstNode); + TRY_FIND_NODE(last, fLastNode); + + return _PlaceHolderValue; + } + + SizeT Count() const + { + return fNodeCount; + } + + public: + Boolean Remove(const SizeT& Index) + { + TRY_REMOVE_NODE(fFirstNode); + TRY_REMOVE_NODE(fLastNode); + + return false; + } + + Boolean Add(const T val) + { + auto* iterationNode = fFirstNode; + MUST_PASS(iterationNode); + + while (iterationNode) + { + if (!iterationNode->fUsed) + { + iterationNode->fVal = val; + iterationNode->fIndex = 0; + + iterationNode->fUsed = true; + + ++fNodeCount; + + return true; + } + + iterationNode = iterationNode->fNext; + } + + return false; + } + + private: + /* Avoid useless lookups */ + MutableLinkedList* fLastNode{nullptr}; + MutableLinkedList* fFirstNode{nullptr}; + + /* Number of nodes inside of this dynamic array. */ + NewOS::SizeT fNodeCount{0}; + + private: + // don't remove that + friend MutableArray; + }; + + template + class MutableArray : public NullableMutableArray + { + public: + // explicit this. + explicit MutableArray() = default; + virtual ~MutableArray() = default; + + NEWOS_COPY_DEFAULT(MutableArray) + + public: + Boolean Add(const T val) + { + auto* iterationNode = fFirstNode; + MUST_PASS(iterationNode); + + while (iterationNode) + { + if (!iterationNode->fUsed) + { + iterationNode->fVal = val; + iterationNode->fIndex = 0; + + iterationNode->fUsed = true; + + ++fNodeCount; + + return true; + } + + iterationNode = iterationNode->fNext; + } + + return false; + } + + public: + Ref operator[](const SizeT& Index) const + { + TRY_FIND_NODE2(first, fFirstNode); + TRY_FIND_NODE2(last, fLastNode); + + return {}; + } + + SizeT Count() const + { + return fNodeCount; + } + + bool Contains(T& value) noexcept + { + MutableLinkedList* first = fFirstNode; + + while (first) + { + if (first->fVal == value && first->fUsed) + return true; + + first = first->fNext; + } + + return false; + } + + private: + /* Avoid useless lookups */ + MutableLinkedList* fLastNode{nullptr}; + MutableLinkedList* fFirstNode{nullptr}; + + /* Number of nodes inside of this dynamic array. */ + NewOS::SizeT fNodeCount{0}; + }; +} // namespace NewOS diff --git a/Kernel/NewKit/New.hpp b/Kernel/NewKit/New.hpp new file mode 100644 index 00000000..1e80f641 --- /dev/null +++ b/Kernel/NewKit/New.hpp @@ -0,0 +1,18 @@ + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ +#pragma once + +#include + +typedef __SIZE_TYPE__ size_t; // gcc will complain about that + +void* operator new(size_t ptr); +void* operator new[](size_t ptr); + +void operator delete(void* ptr); +void operator delete(void* ptr, unsigned long); +void operator delete[](void* ptr); diff --git a/Kernel/NewKit/NewKit.hpp b/Kernel/NewKit/NewKit.hpp new file mode 100644 index 00000000..273efde2 --- /dev/null +++ b/Kernel/NewKit/NewKit.hpp @@ -0,0 +1,22 @@ + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/Kernel/NewKit/OwnPtr.hpp b/Kernel/NewKit/OwnPtr.hpp new file mode 100644 index 00000000..ca89787a --- /dev/null +++ b/Kernel/NewKit/OwnPtr.hpp @@ -0,0 +1,94 @@ + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace NewOS +{ + template + class OwnPtr; + + template + class NonNullRefPtr; + + template + class OwnPtr final + { + public: + OwnPtr() + { + } + ~OwnPtr() + { + this->Delete(); + } + + OwnPtr& operator=(const OwnPtr&) = default; + OwnPtr(const OwnPtr&) = default; + + public: + template + bool New(Args&&... arg) + { + if (fCls) + { + return false; + } + + fCls = new T(arg...); + return fCls; + } + + void Delete() + { + if (fCls) + delete fCls; + + fCls = nullptr; + } + + T* operator->() const + { + return fCls; + }; + T* Raw() + { + return fCls; + } + + Ref AsRef() + { + return Ref(fCls); + } + + operator bool() + { + return fCls; + } + bool operator!() + { + return !fCls; + } + + private: + T* fCls; + }; + + template + OwnPtr make_ptr(Args... args) + { + OwnPtr ret; + ret.template New(forward(args)...); + MUST_PASS(ret); + + return ret; + } +} // namespace NewOS diff --git a/Kernel/NewKit/PageAllocator.hpp b/Kernel/NewKit/PageAllocator.hpp new file mode 100644 index 00000000..fa92f635 --- /dev/null +++ b/Kernel/NewKit/PageAllocator.hpp @@ -0,0 +1,21 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace NewOS +{ + namespace Detail + { + VoidPtr create_page_wrapper(Boolean rw, Boolean user, SizeT pageSz); + void exec_disable(UIntPtr addr); + bool page_disable(UIntPtr addr); + } // namespace Detail +} // namespace NewOS diff --git a/Kernel/NewKit/PageManager.hpp b/Kernel/NewKit/PageManager.hpp new file mode 100644 index 00000000..7706c9f4 --- /dev/null +++ b/Kernel/NewKit/PageManager.hpp @@ -0,0 +1,81 @@ +// a way to create and find our pages. +// I'm thinking about a separate way of getting a paged area. + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +#ifndef kBadAddress +#define kBadAddress (0) +#endif // #ifndef kBadAddress + +namespace NewOS +{ + class PageManager; + + class PTEWrapper final + { + public: + explicit PTEWrapper(Boolean Rw = false, Boolean User = false, Boolean ExecDisable = false, UIntPtr Address = 0); + + ~PTEWrapper(); + + PTEWrapper& operator=(const PTEWrapper&) = default; + PTEWrapper(const PTEWrapper&) = default; + + public: + const UIntPtr VirtualAddress(); + + void NoExecute(const bool enable = false); + const bool& NoExecute(); + + bool Reclaim(); + bool Shareable(); + bool Present(); + bool Access(); + + private: + Boolean fRw; + Boolean fUser; + Boolean fExecDisable; + UIntPtr fVirtAddr; + Boolean fCache; + Boolean fShareable; + Boolean fWt; + Boolean fPresent; + Boolean fAccessed; + + private: + friend class PageManager; + friend class Pmm; + }; + + struct PageManager final + { + public: + PageManager() = default; + ~PageManager() = default; + + PageManager& operator=(const PageManager&) = default; + PageManager(const PageManager&) = default; + + public: + PTEWrapper Request(Boolean Rw, Boolean User, Boolean ExecDisable, SizeT Sz); + bool Free(Ref& wrapper); + + private: + void FlushTLB(UIntPtr VirtAddr); + + private: + friend PTEWrapper; + friend class Pmm; + }; +} // namespace NewOS diff --git a/Kernel/NewKit/Pair.hpp b/Kernel/NewKit/Pair.hpp new file mode 100644 index 00000000..e5de607d --- /dev/null +++ b/Kernel/NewKit/Pair.hpp @@ -0,0 +1,14 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +namespace NewOS +{ + +} // namespace NewOS diff --git a/Kernel/NewKit/Pmm.hpp b/Kernel/NewKit/Pmm.hpp new file mode 100644 index 00000000..10fd148b --- /dev/null +++ b/Kernel/NewKit/Pmm.hpp @@ -0,0 +1,44 @@ + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace NewOS +{ + class Pmm; + class PTEWrapper; + + class Pmm final + { + public: + explicit Pmm(); + ~Pmm(); + + Pmm& operator=(const Pmm&) = delete; + Pmm(const Pmm&) = default; + + Ref RequestPage(Boolean user = false, Boolean readWrite = false); + Boolean FreePage(Ref refPage); + + Boolean ToggleRw(Ref refPage, Boolean enable = true); + Boolean TogglePresent(Ref refPage, Boolean enable = true); + Boolean ToggleUser(Ref refPage, Boolean enable = true); + Boolean ToggleShare(Ref refPage, Boolean enable = true); + + /// @brief Get the page manager of this. + Ref& Leak() + { + return fPageManager; + } + + private: + Ref fPageManager; + }; +} // namespace NewOS diff --git a/Kernel/NewKit/Ref.hpp b/Kernel/NewKit/Ref.hpp new file mode 100644 index 00000000..356fcad0 --- /dev/null +++ b/Kernel/NewKit/Ref.hpp @@ -0,0 +1,89 @@ + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace NewOS +{ + template + class Ref final + { + public: + Ref() = default; + ~Ref() = default; + + public: + Ref(T cls, const bool& strong = false) + : fClass(cls), fStrong(strong) + { + } + + Ref& operator=(T ref) + { + fClass = ref; + return *this; + } + + public: + T operator->() const + { + return fClass; + } + + T& Leak() + { + return fClass; + } + + T operator*() + { + return fClass; + } + + bool IsStrong() const + { + return fStrong; + } + + operator bool() + { + return fStrong; + } + + private: + T fClass; + bool fStrong{false}; + }; + + template + class NonNullRef final + { + public: + NonNullRef() = delete; + NonNullRef(nullPtr) = delete; + + NonNullRef(T* ref) + : fRef(ref, true) + { + } + + Ref& operator->() + { + MUST_PASS(fRef); + return fRef; + } + + NonNullRef& operator=(const NonNullRef& ref) = delete; + NonNullRef(const NonNullRef& ref) = default; + + private: + Ref fRef{nullptr}; + }; +} // namespace NewOS diff --git a/Kernel/NewKit/Stream.hpp b/Kernel/NewKit/Stream.hpp new file mode 100644 index 00000000..a1074a79 --- /dev/null +++ b/Kernel/NewKit/Stream.hpp @@ -0,0 +1,58 @@ + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace NewOS +{ + template + class Stream final + { + public: + explicit Stream(Ref ref) + : fStream(ref) + { + } + + ~Stream() = default; + + Stream& operator=(const Stream&) = default; + Stream(const Stream&) = default; + + template + friend Stream& operator>>(Stream& Ks, Ref& Buf) + { + Ks.fKind = Ks.fStream->In(Buf); + return *Ks; + } + + template + friend Stream& operator<<(Stream& Ks, Ref& Buf) + { + Ks.fKind = Buf; + Ks.fStream->Out(Buf.Leak()); + return *Ks; + } + + Ref& AsStreamTrait() + { + return fStream; + } + + Ref& AsType() + { + return fKind; + } + + private: + Ref fStream; + Ref fKind; + }; +} // namespace NewOS diff --git a/Kernel/NewKit/String.hpp b/Kernel/NewKit/String.hpp new file mode 100644 index 00000000..6bf5edfd --- /dev/null +++ b/Kernel/NewKit/String.hpp @@ -0,0 +1,76 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace NewOS +{ + class StringView final + { + public: + explicit StringView() = default; + + explicit StringView(Size Sz) + : fSz(Sz) + { + MUST_PASS(Sz > 1); + fData = new Char[Sz]; + MUST_PASS(fData); + } + + ~StringView() + { + if (fData) + delete[] fData; + } + + StringView& operator=(const StringView&) = default; + StringView(const StringView&) = default; + + Char* Data(); + const Char* CData(); + Size Length() const; + + bool operator==(const Char* rhs) const; + bool operator!=(const Char* rhs) const; + + bool operator==(const StringView& rhs) const; + bool operator!=(const StringView& rhs) const; + + StringView& operator+=(const Char* rhs); + StringView& operator+=(const StringView& rhs); + + operator bool() + { + return fData; + } + + bool operator!() + { + return fData; + } + + private: + Char* fData{nullptr}; + Size fSz{0}; + Size fCur{0}; + + friend class StringBuilder; + }; + + struct StringBuilder final + { + static ErrorOr Construct(const Char* data); + static const char* FromInt(const char* fmt, int n); + static const char* FromBool(const char* fmt, bool n); + static const char* Format(const char* fmt, const char* from); + static bool Equals(const char* lhs, const char* rhs); + }; +} // namespace NewOS diff --git a/Kernel/NewKit/Utils.hpp b/Kernel/NewKit/Utils.hpp new file mode 100644 index 00000000..977f5ea7 --- /dev/null +++ b/Kernel/NewKit/Utils.hpp @@ -0,0 +1,29 @@ + +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +namespace NewOS +{ + Int rt_copy_memory(const voidPtr src, voidPtr dst, Size len); + Int rt_move_memory(const voidPtr src, voidPtr dst, Size len); + voidPtr rt_set_memory(voidPtr dst, Char val, Size len); + void rt_zero_memory(voidPtr pointer, Size len); + Int rt_string_cmp(const Char* src, const Char* cmp, Size len); + const Char* alloc_string(const Char* text); + Size rt_string_len(const Char* str); + Size rt_string_len(const Char* str, SizeT _len); + Boolean rt_to_string(Char* buf, Int limit, Int base); + Boolean is_newln(Char chr); + Boolean is_space(Char chr); + Int rt_to_uppercase(Int c); + Int rt_to_lower(Int c); + voidPtr rt_string_in_string(const char* in, const char* needle); + char* rt_string_has_char(char* str, const char chr); +} // namespace NewOS diff --git a/Kernel/NewKit/Variant.hpp b/Kernel/NewKit/Variant.hpp new file mode 100644 index 00000000..a8f6759f --- /dev/null +++ b/Kernel/NewKit/Variant.hpp @@ -0,0 +1,54 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace NewOS +{ + class Variant final + { + public: + enum class VariantKind + { + kString, + kPointer, + kUndefined + }; + + public: + explicit Variant() = delete; + + public: + Variant& operator=(const Variant&) = default; + Variant(const Variant&) = default; + + ~Variant() = default; + + public: + explicit Variant(StringView* stringView) + : fPtr((voidPtr)stringView), fKind(VariantKind::kString) + { + } + explicit Variant(nullPtr) + : fPtr(nullptr), fKind(VariantKind::kUndefined) + { + } + explicit Variant(voidPtr ptr) + : fPtr(ptr), fKind(VariantKind::kPointer) + { + } + + public: + const Char* ToString(); + + private: + voidPtr fPtr{nullptr}; + VariantKind fKind{VariantKind::kUndefined}; + }; +} // namespace NewOS diff --git a/Kernel/NewKit/compile_flags.txt b/Kernel/NewKit/compile_flags.txt new file mode 100644 index 00000000..14c5bc51 --- /dev/null +++ b/Kernel/NewKit/compile_flags.txt @@ -0,0 +1,6 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I./ +-I../ +-I../../../ diff --git a/Kernel/Objects/.hgkeep b/Kernel/Objects/.hgkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/.gitkeep b/Kernel/Root/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/Applications/.gitkeep b/Kernel/Root/Applications/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/Assistants/.gitkeep b/Kernel/Root/Assistants/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/Boot/.gitkeep b/Kernel/Root/Boot/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/Boot/Icons/bonjour-logo.ico b/Kernel/Root/Boot/Icons/bonjour-logo.ico new file mode 100644 index 00000000..568de302 Binary files /dev/null and b/Kernel/Root/Boot/Icons/bonjour-logo.ico differ diff --git a/Kernel/Root/Boot/Icons/boot-logo.ico b/Kernel/Root/Boot/Icons/boot-logo.ico new file mode 100644 index 00000000..a7edcfe8 Binary files /dev/null and b/Kernel/Root/Boot/Icons/boot-logo.ico differ diff --git a/Kernel/Root/Boot/Icons/driver-logo.ico b/Kernel/Root/Boot/Icons/driver-logo.ico new file mode 100644 index 00000000..dbdcdee1 Binary files /dev/null and b/Kernel/Root/Boot/Icons/driver-logo.ico differ diff --git a/Kernel/Root/Boot/Icons/kernel-logo.ico b/Kernel/Root/Boot/Icons/kernel-logo.ico new file mode 100644 index 00000000..00724f48 Binary files /dev/null and b/Kernel/Root/Boot/Icons/kernel-logo.ico differ diff --git a/Kernel/Root/Boot/Icons/settings-icon.ico b/Kernel/Root/Boot/Icons/settings-icon.ico new file mode 100644 index 00000000..4fd36645 Binary files /dev/null and b/Kernel/Root/Boot/Icons/settings-icon.ico differ diff --git a/Kernel/Root/Boot/Icons/update-logo.ico b/Kernel/Root/Boot/Icons/update-logo.ico new file mode 100644 index 00000000..3423d76a Binary files /dev/null and b/Kernel/Root/Boot/Icons/update-logo.ico differ diff --git a/Kernel/Root/Library/.gitkeep b/Kernel/Root/Library/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/Mount/.gitkeep b/Kernel/Root/Mount/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/Support/.gitkeep b/Kernel/Root/Support/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/System/.gitkeep b/Kernel/Root/System/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/System/FileExplorerHome.html b/Kernel/Root/System/FileExplorerHome.html new file mode 100644 index 00000000..f37e6d64 --- /dev/null +++ b/Kernel/Root/System/FileExplorerHome.html @@ -0,0 +1,34 @@ + + + + + + NewOS WebTraveler + + + + + + + + + + + +
+
+ + + diff --git a/Kernel/Root/System/SystemTheme.css b/Kernel/Root/System/SystemTheme.css new file mode 100644 index 00000000..44e38465 --- /dev/null +++ b/Kernel/Root/System/SystemTheme.css @@ -0,0 +1,46 @@ +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 5.9% 10%; + --radius: 0.5rem; + } + + .dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; + } +} diff --git a/Kernel/Root/Users/.gitkeep b/Kernel/Root/Users/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Root/Users/Shared/.gitkeep b/Kernel/Root/Users/Shared/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/Source/AppMain.cxx b/Kernel/Source/AppMain.cxx new file mode 100644 index 00000000..b91d6082 --- /dev/null +++ b/Kernel/Source/AppMain.cxx @@ -0,0 +1,193 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: AppMain.cxx + Purpose: Kernel main loop. + +------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Detail +{ + /// @brief Filesystem auto mounter, additional checks are also done by the + /// class. + class FilesystemWizard final + { + NewOS::NewFilesystemManager* fNewFS{nullptr}; + + public: + explicit FilesystemWizard() + { + if (NewOS::FilesystemManagerInterface::GetMounted()) + { + /// Mounted partition, cool! + NewOS::kcout + << "New OS: No need to create for a NewFS partition here...\r"; + } + else + { + /// Not mounted partition, auto-mount. + ///! Mounts a NewFS block. + fNewFS = new NewOS::NewFilesystemManager(); + + NewOS::FilesystemManagerInterface::Mount(fNewFS); + + if (fNewFS->GetImpl()) + { + constexpr auto cFolderInfo = "Metadata"; + const auto cDirCount = 8; + const char* cDirStr[cDirCount] = { + "/Boot/", "/System/", "/Support/", "/Applications/", + "/Users/", "/Library/", "/Mount/", "/Assistants/"}; + + for (NewOS::SizeT dirIndx = 0UL; dirIndx < cDirCount; ++dirIndx) + { + auto catalogDir = fNewFS->GetImpl()->GetCatalog(cDirStr[dirIndx]); + + if (catalogDir) + { + delete catalogDir; + continue; + } + + catalogDir = fNewFS->GetImpl()->CreateCatalog(cDirStr[dirIndx], 0, + kNewFSCatalogKindDir); + + NewFork theFork{0}; + + const NewOS::Char* cSrcName = cFolderInfo; + + NewOS::rt_copy_memory((NewOS::VoidPtr)(cSrcName), theFork.ForkName, + NewOS::rt_string_len(cSrcName)); + + NewOS::rt_copy_memory((NewOS::VoidPtr)(catalogDir->Name), + theFork.CatalogName, + NewOS::rt_string_len(catalogDir->Name)); + + delete catalogDir; + + theFork.DataSize = kNewFSForkSize; + theFork.ResourceId = 0; + theFork.ResourceKind = NewOS::kNewFSRsrcForkKind; + theFork.Kind = NewOS::kNewFSDataForkKind; + + NewOS::StringView metadataFolder(kNewFSSectorSz); + + metadataFolder += + "

Kind: folder

\r

Created by: system

\r

Edited by: " + "system

\r

Volume Type: New OS Standard

\r"; + + metadataFolder += "

File name: "; + metadataFolder += cDirStr[dirIndx]; + metadataFolder += "

\r"; + + const NewOS::SizeT metadataSz = kNewFSSectorSz; + + auto catalogSystem = fNewFS->GetImpl()->GetCatalog(cDirStr[dirIndx]); + + fNewFS->GetImpl()->CreateFork(catalogSystem, theFork); + + fNewFS->GetImpl()->WriteCatalog( + catalogSystem, (NewOS::VoidPtr)(metadataFolder.CData()), + metadataSz, cFolderInfo); + + delete catalogSystem; + } + } + + NewCatalog* catalogDisk = + this->fNewFS->GetImpl()->GetCatalog("/Mount/This Disk"); + + const NewOS::Char* cSrcName = "DiskInfo"; + + if (catalogDisk) + { + auto bufferInfoDisk = (NewOS::Char*)this->fNewFS->GetImpl()->ReadCatalog(catalogDisk, kNewFSSectorSz, cSrcName); + NewOS::kcout << bufferInfoDisk << NewOS::end_line(); + + delete bufferInfoDisk; + delete catalogDisk; + } + else + { + catalogDisk = + (NewCatalog*)this->Leak()->CreateAlias("/Mount/This Disk"); + + NewOS::StringView diskFolder(kNewFSSectorSz); + + diskFolder += + "

Kind: alias to disk

\r

Created by: system

\r

Edited " + "by: " + "system

\r

Volume Type: New OS Standard

\r"; + + diskFolder += "

Original Path: "; + diskFolder += NewOS::NewFilesystemHelper::Root(); + diskFolder += "

\r"; + + NewFork theDiskFork{0}; + + NewOS::rt_copy_memory((NewOS::VoidPtr)(cSrcName), theDiskFork.ForkName, + NewOS::rt_string_len(cSrcName)); + + NewOS::rt_copy_memory((NewOS::VoidPtr)(catalogDisk->Name), + theDiskFork.CatalogName, + NewOS::rt_string_len(catalogDisk->Name)); + + theDiskFork.DataSize = kNewFSForkSize; + theDiskFork.ResourceId = 0; + theDiskFork.ResourceKind = NewOS::kNewFSRsrcForkKind; + theDiskFork.Kind = NewOS::kNewFSDataForkKind; + + fNewFS->GetImpl()->CreateFork(catalogDisk, theDiskFork); + fNewFS->GetImpl()->WriteCatalog(catalogDisk, + (NewOS::VoidPtr)diskFolder.CData(), + kNewFSSectorSz, cSrcName); + + delete catalogDisk; + } + } + } + + ~FilesystemWizard() + { + delete fNewFS; + } + + NEWOS_COPY_DEFAULT(FilesystemWizard); + + /// Grab the disk's NewFS reference. + NewOS::NewFilesystemManager* Leak() + { + return fNewFS; + } + }; +} // namespace Detail + +/// @file Main microkernel entrypoint. + +EXTERN_C NewOS::Void AppMain(NewOS::Void) +{ + /// Now run kernel loop, until no process are running. + Detail::FilesystemWizard wizard; // automatic. + + while (NewOS::ProcessScheduler::Shared().Leak().Run() > 0) + { + ; + } +} diff --git a/Kernel/Source/Array.cxx b/Kernel/Source/Array.cxx new file mode 100644 index 00000000..618ba9f6 --- /dev/null +++ b/Kernel/Source/Array.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/ArrayList.cxx b/Kernel/Source/ArrayList.cxx new file mode 100644 index 00000000..0f3a1b3a --- /dev/null +++ b/Kernel/Source/ArrayList.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/Atom.cxx b/Kernel/Source/Atom.cxx new file mode 100644 index 00000000..f7ae9416 --- /dev/null +++ b/Kernel/Source/Atom.cxx @@ -0,0 +1,10 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +// @file Atom.cpp +// @brief Atomic primitives diff --git a/Kernel/Source/CodeManager.cxx b/Kernel/Source/CodeManager.cxx new file mode 100644 index 00000000..39917163 --- /dev/null +++ b/Kernel/Source/CodeManager.cxx @@ -0,0 +1,29 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +using namespace NewOS; + +/// @brief Executes a new process from a function. kernel code only. +/// @note This sets up a new stack, anything on the main function that calls the kernel will not be accessible. +/// @param main the start of the process. +/// @return if the process was started or not. +bool execute_from_image(MainKind main, const char* processName) noexcept +{ + if (!main) + return false; + + ProcessHeader proc((VoidPtr)main); + proc.Kind = ProcessHeader::kDriverKind; + rt_copy_memory((VoidPtr)processName, proc.Name, rt_string_len(proc.Name)); + + Ref refProc = proc; + + return ProcessScheduler::Shared().Leak().Add(refProc); +} \ No newline at end of file diff --git a/Kernel/Source/Crc32.cxx b/Kernel/Source/Crc32.cxx new file mode 100644 index 00000000..6ddb5642 --- /dev/null +++ b/Kernel/Source/Crc32.cxx @@ -0,0 +1,74 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +// @file CRC32.cpp +// @brief Check sequence implementation. + +namespace NewOS +{ + /// @brief The CRC32 table. + UInt kCrcTbl[kCrcCnt] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + + /// @brief Calculate CRC32 of p + /// @param p the data to compute. + /// @param len the length of the data. + /// @return the CRC32. + UInt ke_calculate_crc32(const Char* p, UInt len) noexcept + { + UInt crc = 0xffffffff; + + while (len-- != 0) + crc = kCrcTbl[((UInt8)crc ^ *(p++))] ^ (crc >> 8); + + // return (~crc); also works, does the same thing. + return (crc ^ 0xffffffff); + } +} // namespace NewOS diff --git a/Kernel/Source/CxxAbi.cxx b/Kernel/Source/CxxAbi.cxx new file mode 100644 index 00000000..2f9ae6a2 --- /dev/null +++ b/Kernel/Source/CxxAbi.cxx @@ -0,0 +1,87 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +atexit_func_entry_t __atexit_funcs[kDSOMaxObjects]; + +uarch_t __atexit_func_count; + +extern "C" void __cxa_pure_virtual() +{ + NewOS::kcout << "New OS: C++ placeholder method.\n"; +} + +extern "C" void ___chkstk_ms() +{ + while (1) + { + asm("cli"); + asm("hlt"); + } +} + +extern "C" int atexit(void (*f)(void*), void* arg, void* dso) +{ + if (__atexit_func_count >= kDSOMaxObjects) + return -1; + + __atexit_funcs[__atexit_func_count].destructor_func = f; + __atexit_funcs[__atexit_func_count].obj_ptr = arg; + __atexit_funcs[__atexit_func_count].dso_handle = dso; + + __atexit_func_count++; + + return 0; +} + +extern "C" void __cxa_finalize(void* f) +{ + uarch_t i = __atexit_func_count; + if (!f) + { + while (i--) + { + if (__atexit_funcs[i].destructor_func) + { + (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); + }; + } + + return; + } + + while (i--) + { + if (__atexit_funcs[i].destructor_func) + { + (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); + __atexit_funcs[i].destructor_func = 0; + }; + } +} + +namespace cxxabiv1 +{ + extern "C" int __cxa_guard_acquire(__guard* g) + { + (void)g; + return 0; + } + + extern "C" int __cxa_guard_release(__guard* g) + { + *(char*)g = 1; + return 0; + } + + extern "C" void __cxa_guard_abort(__guard* g) + { + (void)g; + } +} // namespace cxxabiv1 diff --git a/Kernel/Source/Defines.cxx b/Kernel/Source/Defines.cxx new file mode 100644 index 00000000..02327f07 --- /dev/null +++ b/Kernel/Source/Defines.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/DeviceManager.cxx b/Kernel/Source/DeviceManager.cxx new file mode 100644 index 00000000..6e45e9da --- /dev/null +++ b/Kernel/Source/DeviceManager.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/DriveManager.cxx b/Kernel/Source/DriveManager.cxx new file mode 100644 index 00000000..c60b2079 --- /dev/null +++ b/Kernel/Source/DriveManager.cxx @@ -0,0 +1,149 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include +#include + +/// @file DriveManager.cxx +/// @brief Kernel drive manager. + +namespace NewOS +{ + static UInt16 kATAIO = 0U; + static UInt8 kATAMaster = 0U; + + /// @brief reads from an ATA drive. + /// @param pckt + /// @return + Void ke_drv_input(DriveTrait::DrivePacket* pckt) + { + if (!pckt) + { + return; + } + + pckt->fPacketGood = false; + +#ifdef __AHCI__ + drv_std_read(pckt->fLba, (Char*)pckt->fPacketContent, kAHCISectorSize, pckt->fPacketSize); +#elif defined(__ATA_PIO__) || defined(__ATA_DMA__) + drv_std_read(pckt->fLba, kATAIO, kATAMaster, (Char*)pckt->fPacketContent, kATASectorSize, pckt->fPacketSize); +#endif + + pckt->fPacketGood = true; + } + + /// @brief Writes to an ATA drive. + /// @param pckt + /// @return + Void ke_drv_output(DriveTrait::DrivePacket* pckt) + { + if (!pckt) + { + return; + } + + pckt->fPacketGood = false; + +#ifdef __AHCI__ + drv_std_write(pckt->fLba, (Char*)pckt->fPacketContent, kATASectorSize, pckt->fPacketSize); +#elif defined(__ATA_PIO__) || defined(__ATA_DMA__) + drv_std_write(pckt->fLba, kATAIO, kATAMaster, (Char*)pckt->fPacketContent, kATASectorSize, pckt->fPacketSize); +#endif + + pckt->fPacketGood = true; + } + + /// @brief Executes a disk check on the ATA drive. + /// @param pckt + /// @return + Void ke_drv_check_disk(DriveTrait::DrivePacket* pckt) + { + if (!pckt) + { + return; + } + + pckt->fPacketGood = false; + +#if defined(__ATA_PIO__) || defined(__ATA_DMA__) + kATAMaster = true; + kATAIO = ATA_PRIMARY_IO; + + MUST_PASS(drv_std_init(kATAIO, kATAMaster, kATAIO, kATAMaster)); +#endif // if defined(__ATA_PIO__) || defined (__ATA_DMA__) + + pckt->fPacketGood = true; + } + +/// @brief Gets the drive kind (ATA, SCSI, AHCI...) +/// @param +/// @return +#ifdef __ATA_PIO__ + const Char* ke_drive_kind(Void) + { + return "ATA-PIO"; + } +#endif + +#ifdef __ATA_DMA__ + const Char* ke_drive_kind(Void) + { + return "ATA-DMA"; + } +#endif + +#ifdef __AHCI__ + const Char* ke_drive_kind(Void) + { + return "AHCI"; + } +#endif + + /// @brief Unimplemented drive. + /// @param pckt + /// @return + Void ke_drv_unimplemented(DriveTrait::DrivePacket* pckt) + { + } + + /// @brief Makes a new drive. + /// @return the new drive. + DriveTrait construct_drive() noexcept + { + DriveTrait trait; + + rt_copy_memory((VoidPtr) "/Mount/Null", trait.fName, rt_string_len("/Mount/Null")); + trait.fKind = kInvalidDrive; + + trait.fInput = ke_drv_unimplemented; + trait.fOutput = ke_drv_unimplemented; + trait.fVerify = ke_drv_unimplemented; + trait.fDriveKind = ke_drive_kind; + + return trait; + } + + /// @brief Fetches the main drive. + /// @return the new drive. + DriveTrait construct_main_drive() noexcept + { + DriveTrait trait; + + rt_copy_memory((VoidPtr) "/Mount/MainDisk/", trait.fName, rt_string_len("/Mount/MainDisk/")); + trait.fKind = kMassStorage | kEPMDrive; + + trait.fInput = ke_drv_input; + trait.fOutput = ke_drv_output; + trait.fVerify = ke_drv_check_disk; + trait.fDriveKind = ke_drive_kind; + + return trait; + } +} // namespace NewOS diff --git a/Kernel/Source/ErrorOr.cxx b/Kernel/Source/ErrorOr.cxx new file mode 100644 index 00000000..7cef9afb --- /dev/null +++ b/Kernel/Source/ErrorOr.cxx @@ -0,0 +1,12 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +/***********************************************************************************/ +/// @file ErrorOr.cxx /// +/// @brief Error Or Value class. /// +/***********************************************************************************/ diff --git a/Kernel/Source/FS/NewFS.cxx b/Kernel/Source/FS/NewFS.cxx new file mode 100644 index 00000000..41869fcd --- /dev/null +++ b/Kernel/Source/FS/NewFS.cxx @@ -0,0 +1,938 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifdef __FSKIT_NEWFS__ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace NewOS; + +///! BUGS: 0 + +/***********************************************************************************/ +/* This file implements the New File System. +/***********************************************************************************/ + +STATIC MountpointInterface sMountpointInterface; + +/// @brief Creates a new fork inside the New filesystem partition. +/// @param catalog it's catalog +/// @param theFork the fork itself. +/// @return the fork +_Output NewFork* NewFSParser::CreateFork(_Input NewCatalog* catalog, + _Input NewFork& theFork) +{ + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return nullptr; + + if (catalog && theFork.ForkName[0] != 0 && + theFork.DataSize == kNewFSForkSize) + { + Lba lba = (theFork.Kind == kNewFSDataForkKind) ? catalog->DataFork + : catalog->ResourceFork; + + kcout << "Fork Lba: " << hex_number(lba) << endl; + + if (lba <= kNewFSCatalogStartAddress) + return nullptr; + + auto drv = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + /// special treatment. + rt_copy_memory((VoidPtr) "fs/newfs-packet", drv->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + NewFork curFork{0}; + NewFork prevFork{0}; + Lba lbaOfPreviousFork = lba; + + /// do not check for anything. Loop until we get what we want, that is a free fork zone. + while (true) + { + if (lba <= kNewFSCatalogStartAddress) + break; + + drv->fPacket.fLba = lba; + drv->fPacket.fPacketSize = sizeof(NewFork); + drv->fPacket.fPacketContent = &curFork; + + drv->fInput(&drv->fPacket); + + kcout << "New OS: Next-Fork: " << hex_number(curFork.NextSibling) << endl; + + if (curFork.Flags == kNewFSFlagCreated) + { + kcout << "New OS: Fork already exists.\r"; + + /// sanity check. + if (StringBuilder::Equals(curFork.ForkName, theFork.ForkName) && + StringBuilder::Equals(curFork.CatalogName, catalog->Name)) + return nullptr; + + kcout << "Next-Fork: " << hex_number(curFork.NextSibling) << endl; + + lbaOfPreviousFork = lba; + lba = curFork.NextSibling; + + prevFork = curFork; + } + else + { + /// This is a check that we have, in order to link the previous fork + /// entry. + if (lba >= kNewFSCatalogStartAddress) + { + drv->fPacket.fLba = lbaOfPreviousFork; + drv->fPacket.fPacketSize = sizeof(NewFork); + drv->fPacket.fPacketContent = &prevFork; + + prevFork.NextSibling = lba; + + /// write to disk. + drv->fOutput(&drv->fPacket); + } + + break; + } + } + + constexpr auto cForkPadding = + 4; /// this value gives us space for the data offset. + + theFork.Flags = kNewFSFlagCreated; + theFork.DataOffset = lba - sizeof(NewFork) * cForkPadding; + theFork.PreviousSibling = lbaOfPreviousFork; + theFork.NextSibling = theFork.DataOffset - theFork.DataSize; + + drv->fPacket.fLba = lba; + drv->fPacket.fPacketSize = sizeof(NewFork); + drv->fPacket.fPacketContent = &theFork; + + drv->fOutput(&drv->fPacket); + + /// log what we have now. + kcout << "New OS: Wrote fork data at: " << hex_number(theFork.DataOffset) + << endl; + + kcout << "New OS: Wrote fork at: " << hex_number(lba) << endl; + + return &theFork; + } + + return nullptr; +} + +/// @brief Find fork inside New filesystem. +/// @param catalog the catalog. +/// @param name the fork name. +/// @return the fork. +_Output NewFork* NewFSParser::FindFork(_Input NewCatalog* catalog, + _Input const Char* name, + Boolean isDataFork) +{ + auto drv = sMountpointInterface.GetAddressOf(this->fDriveIndex); + NewFork* theFork = nullptr; + + Lba lba = isDataFork ? catalog->DataFork : catalog->ResourceFork; + + while (lba != 0) + { + drv->fPacket.fLba = lba; + drv->fPacket.fPacketSize = sizeof(NewFork); + drv->fPacket.fPacketContent = (VoidPtr)theFork; + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drv->fPacket.fPacketMime, 16); + + if (auto res = + fs_newfs_read(&sMountpointInterface, *drv, this->fDriveIndex); + res) + { + switch (res) + { + case 1: + DbgLastError() = kErrorDiskReadOnly; + break; + case 2: + DbgLastError() = kErrorDiskIsFull; + break; + DbgLastError() = kErrorNoSuchDisk; + break; + + default: + break; + } + return nullptr; + } + + if (StringBuilder::Equals(theFork->ForkName, name)) + { + break; + } + + lba = theFork->NextSibling; + } + + return theFork; +} + +/// @brief Simpler factory to create a catalog (assumes you want to create a +/// file.) +/// @param name +/// @return catalog pointer. +_Output NewCatalog* NewFSParser::CreateCatalog(_Input const char* name) +{ + return this->CreateCatalog(name, 0, kNewFSCatalogKindFile); +} + +/// @brief Creates a new catalog into the disk. +/// @param name the catalog name. +/// @param flags the flags of the catalog. +/// @param kind the catalog kind. +/// @return catalog pointer. +_Output NewCatalog* NewFSParser::CreateCatalog(_Input const char* name, + _Input const Int32& flags, + _Input const Int32& kind) +{ + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return nullptr; + + Lba outLba = 0UL; + + /// a directory should have a slash in the end. + if (kind == kNewFSCatalogKindDir && + name[rt_string_len(name) - 1] != NewFilesystemHelper::Separator()) + return nullptr; + + /// a file shouldn't have a slash in the end. + if (kind != kNewFSCatalogKindDir && + name[rt_string_len(name) - 1] == NewFilesystemHelper::Separator()) + return nullptr; + + NewCatalog* checkForCpy = this->FindCatalog(name, outLba); + + if (checkForCpy) + { + return checkForCpy; + } + + char parentName[kNewFSNodeNameLen] = {0}; + + for (SizeT indexName = 0UL; indexName < rt_string_len(name); ++indexName) + { + parentName[indexName] = name[indexName]; + } + + if (*parentName == 0) + { + DbgLastError() = kErrorFileNotFound; + return nullptr; + } + + /// Locate parent catalog, to then allocate right after it. + + for (SizeT indexFill = 0; indexFill < rt_string_len(name); ++indexFill) + { + parentName[indexFill] = name[indexFill]; + } + + SizeT indexReverseCopy = rt_string_len(parentName); + + // zero character. + parentName[--indexReverseCopy] = 0; + + // mandatory / character. + parentName[--indexReverseCopy] = 0; + + while (parentName[indexReverseCopy] != NewFilesystemHelper::Separator()) + { + parentName[indexReverseCopy] = 0; + --indexReverseCopy; + } + + NewCatalog* catalog = this->FindCatalog(parentName, outLba); + + if (catalog && catalog->Kind == kNewFSCatalogKindFile) + { + delete catalog; + return nullptr; + } + else if (!catalog) + { + outLba = kNewFSCatalogStartAddress; + } + + constexpr SizeT cDefaultForkSize = kNewFSForkSize; + + NewCatalog* catalogChild = new NewCatalog(); + + catalogChild->ResourceForkSize = cDefaultForkSize; + catalogChild->DataForkSize = cDefaultForkSize; + + catalogChild->NextSibling = outLba; + catalogChild->PrevSibling = outLba; + catalogChild->Kind = kind; + catalogChild->Flags = kNewFSFlagCreated; + + rt_copy_memory((VoidPtr)name, (VoidPtr)catalogChild->Name, + rt_string_len(name)); + + UInt16 catalogBuf[kNewFSSectorSz] = {0}; + + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + Lba startFree = outLba; + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + drive->fPacket.fPacketContent = catalogBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = startFree; + + drive->fInput(&drive->fPacket); + + NewCatalog* nextSibling = (NewCatalog*)catalogBuf; + + startFree = nextSibling->NextSibling; + + catalogChild->PrevSibling = outLba; + + drive->fPacket.fLba = startFree; + drive->fInput(&drive->fPacket); + + while (drive->fPacket.fPacketGood) + { + nextSibling = (NewCatalog*)catalogBuf; + + if (startFree <= kNewFSAddressAsLba) + { + delete catalogChild; + delete catalog; + + return nullptr; + } + + /// allocation or reallocation or catalog... + if (nextSibling->Flags != kNewFSFlagCreated) + { + Char sectorBufPartBlock[kNewFSSectorSz] = {0}; + + drive->fPacket.fPacketContent = sectorBufPartBlock; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fInput(&drive->fPacket); + + constexpr auto cNewFSCatalogPadding = 4; + + NewPartitionBlock* partBlock = (NewPartitionBlock*)sectorBufPartBlock; + + if (partBlock->FreeCatalog < 1) + { + delete catalogChild; + return nullptr; + } + + catalogChild->DataFork = partBlock->DiskSize - partBlock->StartCatalog; + + catalogChild->ResourceFork = catalogChild->DataFork; + + catalogChild->NextSibling = + startFree + (sizeof(NewCatalog) * cNewFSCatalogPadding); + + drive->fPacket.fPacketContent = catalogChild; + drive->fPacket.fPacketSize = sizeof(NewCatalog); + drive->fPacket.fLba = startFree; + + drive->fOutput(&drive->fPacket); + + drive->fPacket.fPacketContent = catalogBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = + startFree - (sizeof(NewCatalog) * cNewFSCatalogPadding); + + drive->fInput(&drive->fPacket); + + nextSibling->NextSibling = startFree; + + drive->fOutput(&drive->fPacket); + + kcout << "New OS: Create new catalog, status: " + << hex_number(catalogChild->Flags) << endl; + kcout << "New OS: Create new catalog, status: " << catalogChild->Name + << endl; + + drive->fPacket.fPacketContent = sectorBufPartBlock; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fInput(&drive->fPacket); + + partBlock->SectorCount -= 1; + partBlock->CatalogCount += 1; + partBlock->FreeCatalog -= 1; + partBlock->FreeCatalog = catalogChild->NextSibling; + + drive->fOutput(&drive->fPacket); + + delete catalog; + return catalogChild; + } + + constexpr auto cNewFSCatalogPadding = 4; + + //// @note that's how we find the next catalog in the partition block. + startFree = startFree + (sizeof(NewCatalog) * cNewFSCatalogPadding); + + drive->fPacket.fPacketContent = catalogBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = startFree; + + drive->fInput(&drive->fPacket); + } + + delete catalog; + return nullptr; +} + +/// @brief Make a EPM+NewFS drive out of the disk. +/// @param drive The drive to write on. +/// @return If it was sucessful, see DbgLastError(). +bool NewFSParser::Format(_Input _Output DriveTrait* drive) +{ + /// verify disk. + drive->fVerify(&drive->fPacket); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + /// if disk isn't good, then error out. + if (false == drive->fPacket.fPacketGood) + { + DbgLastError() = kErrorDiskIsCorrupted; + return false; + } + + Char sectorBuf[kNewFSSectorSz] = {0}; + + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fInput(&drive->fPacket); + + /// disk isnt faulty and data has been fetched. + if (drive->fPacket.fPacketGood) + { + NewPartitionBlock* partBlock = (NewPartitionBlock*)sectorBuf; + + /// check for an empty partition here. + if (partBlock->PartitionName[0] == 0 && + rt_string_cmp(partBlock->Ident, kNewFSIdent, kNewFSIdentLen)) + { + /// partition is free and valid. + + partBlock->Version = kNewFSVersionInteger; + + const auto cUntitledHD = "New OS HD\0"; + + rt_copy_memory((VoidPtr)kNewFSIdent, (VoidPtr)partBlock->Ident, + kNewFSIdentLen); + + rt_copy_memory((VoidPtr)cUntitledHD, (VoidPtr)partBlock->PartitionName, + rt_string_len(cUntitledHD)); + + SizeT catalogCount = 0; + SizeT sectorCount = drv_std_get_sector_count(); + SizeT diskSize = drv_std_get_drv_size(); + + partBlock->Kind = kNewFSPartitionTypeStandard; + partBlock->StartCatalog = kNewFSCatalogStartAddress; + partBlock->Flags = kNewFSPartitionTypeStandard; + partBlock->CatalogCount = sectorCount / sizeof(NewCatalog); + partBlock->SectorCount = sectorCount; + partBlock->DiskSize = diskSize; + partBlock->FreeCatalog = sectorCount / sizeof(NewCatalog); + + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fOutput(&drive->fPacket); + + kcout << "Drive-Kind: " << drive->fDriveKind() << endl; + + kcout << "Partition-Name: " << partBlock->PartitionName << endl; + kcout << "Start-Catalog: " << hex_number(partBlock->StartCatalog) << endl; + kcout << "Catalog-Count: " << hex_number(partBlock->CatalogCount) << endl; + kcout << "Free-Catalog: " << hex_number(partBlock->FreeCatalog) << endl; + kcout << "Free-Sectors: " << hex_number(partBlock->FreeSectors) << endl; + kcout << "Sector-Size: " << hex_number(partBlock->SectorSize) << endl; + + /// write the root catalog. + this->CreateCatalog(kNewFSRoot, 0, kNewFSCatalogKindDir); + + return true; + } + + kcout << "New OS: PartitionBlock already exists.\r"; + + /// return success as well, do not ignore that partition. + return true; + } + + return false; +} + +/// @brief Writes the data fork into a specific catalog. +/// @param catalog the catalog itself +/// @param data the data. +/// @return if the catalog w rote the contents successfully. +bool NewFSParser::WriteCatalog(_Input _Output NewCatalog* catalog, voidPtr data, SizeT sizeOfData, _Input const char* forkName) +{ + if (sizeOfData > catalog->DataForkSize) + return false; + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return false; + + NewFork* forkData = new NewFork(); + rt_set_memory(forkData, 0, sizeof(NewFork)); + + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + auto startFork = catalog->DataFork; + + rt_copy_memory(catalog->Name, forkData->CatalogName, kNewFSNodeNameLen); + + /// sanity check of the fork position as the condition to run the loop. + while (startFork >= kNewFSCatalogStartAddress) + { + drive->fPacket.fPacketContent = forkData; + drive->fPacket.fPacketSize = sizeof(NewFork); + drive->fPacket.fLba = startFork; + + drive->fInput(&drive->fPacket); + + kcout << "Fork-Name: " << forkData->ForkName << endl; + + /// sanity check the fork. + if (forkData->DataOffset <= kNewFSCatalogStartAddress) + { + DbgLastError() = kErrorDiskIsCorrupted; + + kcout << "New OS: Invalid fork offset.\r"; + + delete forkData; + return false; + } + + if (forkData->Flags != kNewFSFlagUnallocated && + forkData->Flags != kNewFSFlagDeleted && + StringBuilder::Equals(forkData->ForkName, forkName) && + StringBuilder::Equals(forkData->CatalogName, catalog->Name)) + { + drive->fPacket.fPacketContent = data; + drive->fPacket.fPacketSize = sizeOfData; + drive->fPacket.fLba = forkData->DataOffset; + kcout << "Fork-Offset: " << hex_number(forkData->DataOffset) << endl; + + drive->fOutput(&drive->fPacket); + + delete forkData; + return true; + } + else if (auto catalog = this->GetCatalog(forkData->CatalogName); + catalog == nullptr) + { + delete catalog; + drive->fPacket.fPacketContent = data; + drive->fPacket.fPacketSize = sizeOfData; + drive->fPacket.fLba = forkData->DataOffset; + kcout << "Fork-Offset: " << hex_number(forkData->DataOffset) << endl; + + drive->fOutput(&drive->fPacket); + + delete forkData; + return true; + } + + startFork = forkData->NextSibling; + } + + delete forkData; + return false; +} + +/// @brief +/// @param catalogName the catalog name. +/// @return the newly found catalog. +_Output NewCatalog* NewFSParser::FindCatalog(_Input const char* catalogName, + Lba& outLba) +{ + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return nullptr; + + Char* sectorBuf = new Char[sizeof(NewPartitionBlock)]; + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = sizeof(NewPartitionBlock); + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fInput(&drive->fPacket); + + NewPartitionBlock* part = (NewPartitionBlock*)sectorBuf; + + auto startCatalogList = part->StartCatalog; + const auto cCtartCatalogList = part->StartCatalog; + + auto localSearchFirst = false; + + drive->fPacket.fLba = startCatalogList; + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = sizeof(NewCatalog); + + drive->fInput(&drive->fPacket); + + if (!StringBuilder::Equals(catalogName, NewFilesystemHelper::Root())) + { + Char parentName[kNewFSNodeNameLen] = {0}; + + for (SizeT indexFill = 0; indexFill < rt_string_len(catalogName); ++indexFill) + { + parentName[indexFill] = catalogName[indexFill]; + } + + SizeT indexReverseCopy = rt_string_len(parentName); + + // zero character. + parentName[--indexReverseCopy] = 0; + + // mandatory '/' character. + parentName[--indexReverseCopy] = 0; + + while (parentName[indexReverseCopy] != NewFilesystemHelper::Separator()) + { + parentName[indexReverseCopy] = 0; + --indexReverseCopy; + } + + NewCatalog* parentCatalog = this->FindCatalog(parentName, outLba); + + if (parentCatalog && + !StringBuilder::Equals(parentName, NewFilesystemHelper::Root())) + { + startCatalogList = outLba; + delete parentCatalog; + + localSearchFirst = true; + } + else if (parentCatalog) + { + delete parentCatalog; + } + } + +_NewFSSearchThroughCatalogList: + while (drive->fPacket.fPacketGood) + { + NewCatalog* catalog = (NewCatalog*)sectorBuf; + + if (StringBuilder::Equals(catalogName, catalog->Name)) + { + /// ignore unallocated catalog, break + if (catalog->Flags != kNewFSFlagCreated) + { + goto _NewFSContinueSearch; + } + + NewCatalog* catalogPtr = new NewCatalog(); + rt_copy_memory(catalog, catalogPtr, sizeof(NewCatalog)); + + kcout << "New OS: Found catalog at: " << hex_number(startCatalogList) << endl; + + outLba = startCatalogList; + delete[] sectorBuf; + return catalogPtr; + } + + _NewFSContinueSearch: + startCatalogList = catalog->NextSibling; + + if (startCatalogList <= kNewFSAddressAsLba) + break; + + drive->fPacket.fLba = startCatalogList; + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = sizeof(NewCatalog); + + drive->fInput(&drive->fPacket); + } + + if (localSearchFirst) + { + localSearchFirst = false; + startCatalogList = cCtartCatalogList; + + goto _NewFSSearchThroughCatalogList; + } + + outLba = 0UL; + delete[] sectorBuf; + + return nullptr; +} + +/// @brief +/// @param name +/// @return +_Output NewCatalog* NewFSParser::GetCatalog(_Input const char* name) +{ + Lba unused = 0; + return this->FindCatalog(name, unused); +} + +/// @brief +/// @param catalog +/// @return +Boolean NewFSParser::CloseCatalog(_Input _Output NewCatalog* catalog) +{ + if (!catalog) + return false; + + delete catalog; + catalog = nullptr; + + return true; +} + +/// @brief Mark catalog as removed. +/// @param catalog The catalog structure. +/// @return if the catalog was removed or not. +Boolean NewFSParser::RemoveCatalog(_Input const Char* catalogName) +{ + if (!catalogName || + StringBuilder::Equals(catalogName, NewFilesystemHelper::Root())) + { + DbgLastError() = kErrorInternal; + return false; + } + + Lba outLba = 0; + auto catalog = this->FindCatalog(catalogName, outLba); + + if (outLba >= kNewFSCatalogStartAddress || + catalog->Flags == kNewFSFlagCreated) + { + catalog->Flags = kNewFSFlagDeleted; + + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + drive->fPacket.fLba = outLba; // the catalog position. + drive->fPacket.fPacketSize = + sizeof(NewCatalog); // size of catalog. roughly the sector size. + drive->fPacket.fPacketContent = catalog; // the catalog itself. + + drive->fOutput(&drive->fPacket); // send packet. + + Char partitionBlockBuf[sizeof(NewPartitionBlock)] = {0}; + + drive->fPacket.fLba = kNewFSAddressAsLba; + drive->fPacket.fPacketContent = partitionBlockBuf; + drive->fPacket.fPacketSize = sizeof(NewPartitionBlock); + + drive->fInput(&drive->fPacket); + + NewPartitionBlock* partBlock = + reinterpret_cast(partitionBlockBuf); + + ++partBlock->FreeCatalog; + --partBlock->CatalogCount; + + drive->fOutput(&drive->fPacket); + + return true; + } + + delete catalog; + return false; +} + +/// ***************************************************************** /// +/// Reading,Seek,Tell are unimplemented on catalogs, refer to forks I/O instead. +/// ***************************************************************** /// + +/***********************************************************************************/ +/// @brief Read the catalog data fork. +/// @param catalog +/// @param dataSz +/// @return +/***********************************************************************************/ + +VoidPtr NewFSParser::ReadCatalog(_Input _Output NewCatalog* catalog, + _Input SizeT dataSz, + _Input const char* forkName) +{ + if (!catalog) + { + DbgLastError() = kErrorFileNotFound; + return nullptr; + } + + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return nullptr; + + Lba dataForkLba = catalog->DataFork; + Size dataForkSize = catalog->DataForkSize; + + kcout << "Found-Catalog: " << catalog->Name + << ", Data-Fork: " << hex_number(dataForkLba) << endl; + + Char* sectorBuf = new Char[sizeof(NewFork)]; + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + NewFork* forkData = nullptr; + + while (dataForkLba >= kNewFSCatalogStartAddress) + { + drive->fPacket.fLba = dataForkLba; + drive->fPacket.fPacketSize = sizeof(NewFork); + drive->fPacket.fPacketContent = sectorBuf; + + drive->fInput(&drive->fPacket); + + forkData = (NewFork*)sectorBuf; + + kcout << "Fork-Name: " << forkData->ForkName << endl; + + if (forkData->DataOffset <= kNewFSCatalogStartAddress) + { + delete[] sectorBuf; + + kcout << "Fail-Data-Offset: " << hex_number(forkData->DataOffset) << endl; + + return nullptr; + } + + if (StringBuilder::Equals(forkName, forkData->ForkName) && + StringBuilder::Equals(catalog->Name, forkData->CatalogName)) + break; + + dataForkLba = forkData->NextSibling; + } + + if (dataForkLba <= kNewFSCatalogStartAddress) + { + delete[] sectorBuf; + return nullptr; + } + + Char* forkBuf = new Char[dataSz]; + + drive->fPacket.fLba = forkData->DataOffset; + drive->fPacket.fPacketSize = dataSz; + drive->fPacket.fPacketContent = forkBuf; + + drive->fInput(&drive->fPacket); + + delete[] sectorBuf; + return forkBuf; +} + +/***********************************************************************************/ +/// @brief Seek in the data fork. +/// @param catalog the catalog offset. +/// @param off where to seek. +/// @return if the seeking was successful. +/***********************************************************************************/ + +bool NewFSParser::Seek(_Input _Output NewCatalog* catalog, SizeT off) +{ + if (!catalog) + { + DbgLastError() = kErrorFileNotFound; + return false; + } + + DbgLastError() = kErrorUnimplemented; + return false; +} + +/***********************************************************************************/ +/// @brief Tell where we are inside the data fork. +/// @param catalog +/// @return The position on the file. +/***********************************************************************************/ + +SizeT NewFSParser::Tell(_Input _Output NewCatalog* catalog) +{ + if (!catalog) + { + DbgLastError() = kErrorFileNotFound; + return 0; + } + + DbgLastError() = kErrorUnimplemented; + return 0; +} + +namespace NewOS::Detail +{ + /***********************************************************************************/ + /// @brief Construct NewFS drives. + /***********************************************************************************/ + Boolean fs_init_newfs(Void) noexcept + { + sMountpointInterface.A() = construct_main_drive(); + sMountpointInterface.B() = construct_drive(); + sMountpointInterface.C() = construct_drive(); + sMountpointInterface.D() = construct_drive(); + + sMountpointInterface.A().fVerify(&sMountpointInterface.A().fPacket); + + Char partitionBlockBuf[sizeof(NewPartitionBlock)] = {0}; + + sMountpointInterface.A().fPacket.fLba = kNewFSAddressAsLba; + sMountpointInterface.A().fPacket.fPacketContent = partitionBlockBuf; + sMountpointInterface.A().fPacket.fPacketSize = sizeof(NewPartitionBlock); + + sMountpointInterface.A().fInput(&sMountpointInterface.A().fPacket); + + NewPartitionBlock* partBlock = + reinterpret_cast(partitionBlockBuf); + + if (!StringBuilder::Equals(partBlock->Ident, kNewFSIdent)) + { + kcout << "New OS: New FS Partition is corrupt.\r"; + return false; + } + + kcout << "New OS: Read partition: " << partBlock->PartitionName << ", with success!\r"; + + return true; + } +} // namespace NewOS::Detail + +#endif // ifdef __FSKIT_NEWFS__ diff --git a/Kernel/Source/FileManager.cxx b/Kernel/Source/FileManager.cxx new file mode 100644 index 00000000..72ea15a1 --- /dev/null +++ b/Kernel/Source/FileManager.cxx @@ -0,0 +1,183 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +/// BUGS: 0 +//! @brief File manager for NewOS. + +namespace NewOS +{ + static FilesystemManagerInterface* kMounted = nullptr; + + /// @brief FilesystemManager getter. + /// @return The mounted filesystem. + FilesystemManagerInterface* FilesystemManagerInterface::GetMounted() + { + return kMounted; + } + + /// @brief Unmount filesystem. + /// @return The unmounted filesystem. + FilesystemManagerInterface* FilesystemManagerInterface::Unmount() + { + if (kMounted) + { + auto mount = kMounted; + kMounted = nullptr; + + return mount; + } + + return nullptr; + } + + /// @brief Mount filesystem. + /// @param mountPtr The filesystem to mount. + /// @return if it succeeded true, otherwise false. + bool FilesystemManagerInterface::Mount(FilesystemManagerInterface* mountPtr) + { + if (kMounted == nullptr) + { + kMounted = mountPtr; + return true; + } + + return false; + } + +#ifdef __FSKIT_NEWFS__ + /// @brief Opens a new file. + /// @param path + /// @param r + /// @return + NodePtr NewFilesystemManager::Open(const char* path, const char* r) + { + if (!path || *path == 0) + return nullptr; + + if (!r || *r == 0) + return nullptr; + + auto catalog = fImpl->GetCatalog(path); + + if (catalog->Kind != kNewFSCatalogKindFile) + { + fImpl->CloseCatalog(catalog); + return nullptr; + } + + return node_cast(catalog); + } + + /// @brief Writes to a catalog's fork. + /// @param node the node ptr. + /// @param data the data. + /// @param flags the size. + /// @return + Void NewFilesystemManager::Write(NodePtr node, VoidPtr data, Int32 flags, SizeT size) + { + if (!size || + size > kNewFSForkSize) + return; + + if (!data) + return; + + NEWOS_UNUSED(flags); + + const char* cReadAllFork = fDataFork; + + if ((reinterpret_cast(node))->Kind == kNewFSCatalogKindFile) + fImpl->WriteCatalog(reinterpret_cast(node), data, size, + cReadAllFork); + } + + /// @brief Read from filesystem fork. + /// @param node the catalog node. + /// @param flags the flags with it. + /// @param sz the size to read. + /// @return + VoidPtr NewFilesystemManager::Read(NodePtr node, Int32 flags, SizeT sz) + { + if (sz > kNewFSForkSize) + return nullptr; + + if (!sz) + return nullptr; + + NEWOS_UNUSED(flags); + + const char* cReadAllFork = fDataFork; + + if ((reinterpret_cast(node))->Kind == kNewFSCatalogKindFile) + return fImpl->ReadCatalog(reinterpret_cast(node), sz, + cReadAllFork); + + return nullptr; + } + + /// @brief Seek from Catalog. + /// @param node + /// @param off + /// @retval true always returns false, this is unimplemented. + /// @retval false always returns this, it is unimplemented. + + bool NewFilesystemManager::Seek(NodePtr node, SizeT off) + { + if (!node || off == 0) + return false; + + return fImpl->Seek(reinterpret_cast(node), off); + } + + /// @brief Tell where the catalog is. + /// @param node + /// @retval true always returns false, this is unimplemented. + /// @retval false always returns this, it is unimplemented. + + SizeT NewFilesystemManager::Tell(NodePtr node) + { + if (!node) + return kNPos; + + return fImpl->Tell(reinterpret_cast(node)); + } + + /// @brief Rewinds the catalog. + /// @param node + /// @retval true always returns false, this is unimplemented. + /// @retval false always returns this, it is unimplemented. + + bool NewFilesystemManager::Rewind(NodePtr node) + { + if (!node) + return false; + + return this->Seek(node, 0); + } + + /// @brief Returns the filesystem parser. + /// @return the Filesystem parser class. + NewFSParser* NewFilesystemManager::GetImpl() noexcept + { + return fImpl; + } + + void NewFilesystemManager::SetResourceFork(const char* forkName) + { + if (!forkName) return; + rt_copy_memory((VoidPtr)forkName, (VoidPtr)fRsrcFork, rt_string_len(forkName)); + } + + void NewFilesystemManager::SetDataFork(const char* forkName) + { + if (!forkName) return; + rt_copy_memory((VoidPtr)forkName, (VoidPtr)fDataFork, rt_string_len(forkName)); + } +#endif // __FSKIT_NEWFS__ +} // namespace NewOS diff --git a/Kernel/Source/Framebuffer.cxx b/Kernel/Source/Framebuffer.cxx new file mode 100644 index 00000000..7d36c722 --- /dev/null +++ b/Kernel/Source/Framebuffer.cxx @@ -0,0 +1,96 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Framebuffer.cxx + Purpose: Framebuffer object + + Revision History: + + 01/02/24: Added file (amlel) + 02/02/24: Add documentation (amlel) + +------------------------------------------- */ + +#include + +/** + * @brief Framebuffer object implementation. + * + */ + +using namespace NewOS; + +namespace NewOS +{ + const UInt32 kRgbRed = 0x000000FF; + const UInt32 kRgbGreen = 0x0000FF00; + const UInt32 kRgbBlue = 0x00FF0000; + const UInt32 kRgbBlack = 0x00000000; + const UInt32 kRgbWhite = 0xFFFFFFFF; +} // namespace NewOS + +/** + * @brief Get Pixel at + * + * @param pos position of pixel. + * @return volatile* + */ +volatile UIntPtr* Framebuffer::operator[](const UIntPtr& pos) +{ + return (UIntPtr*)(fFrameBufferAddr->fBase * pos); +} + +/// @brief Boolean operator. +Framebuffer::operator bool() +{ + return fFrameBufferAddr.Leak()->fBase != 0 && + fColour != FramebufferColorKind::INVALID && + fFrameBufferAddr.Leak()->fBase != kBadPtr; +} + +/// @brief Set color kind of framebuffer. +/// @param colour +/// @return +const FramebufferColorKind& Framebuffer::Color( + const FramebufferColorKind& colour) +{ + if (fColour != FramebufferColorKind::INVALID && + colour != FramebufferColorKind::INVALID) + { + fColour = colour; + } + + return fColour; +} + +/// @brief Leak framebuffer context. +/// @return The reference of the framebuffer context. +Ref& Framebuffer::Leak() +{ + return this->fFrameBufferAddr; +} + +Framebuffer& Framebuffer::DrawRect(SizeT width, SizeT height, SizeT x, SizeT y, UInt32 color) +{ + for (NewOS::SizeT i = x; i < width + x; ++i) + { + for (NewOS::SizeT u = y; u < height + y; ++u) + { + *(((volatile NewOS::UInt32*)(fFrameBufferAddr.Leak()->fBase + + 4 * fFrameBufferAddr.Leak()->fBpp * i + + 4 * u))) = color; + } + } + + return *this; +} + +Framebuffer& Framebuffer::PutPixel(SizeT x, SizeT y, UInt32 color) +{ + *(((volatile NewOS::UInt32*)(fFrameBufferAddr.Leak()->fBase + + 4 * fFrameBufferAddr.Leak()->fBpp * x + + 4 * y))) = color; + + return *this; +} \ No newline at end of file diff --git a/Kernel/Source/GUIDWizard.cxx b/Kernel/Source/GUIDWizard.cxx new file mode 100644 index 00000000..2e4ffafa --- /dev/null +++ b/Kernel/Source/GUIDWizard.cxx @@ -0,0 +1,65 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: GUIDWizard.cxx + Purpose: GUID helper code + + Revision History: + +------------------------------------------- */ + +#include +#include + +// begin of ascii 'readable' characters. (A, C, C, 1, 2) +#define kAsciiBegin 47 +// @brief Size of UUID. +#define kUUIDSize 37 + +namespace NewOS::XRN::Version1 +{ + auto make_sequence(const ArrayList& uuidSeq) -> Ref + { + GUIDSequence* seq = new GUIDSequence(); + MUST_PASS(seq); + + Ref sequenceReference{seq, true}; + + sequenceReference->fMs1 |= uuidSeq[0]; + sequenceReference->fMs2 |= uuidSeq[1]; + sequenceReference->fMs3 |= uuidSeq[2]; + sequenceReference->fMs3 |= uuidSeq[3]; + + return sequenceReference; + } + + // @brief Tries to make a guid out of a string. + // This function is not complete for now + auto try_guid_to_string(Ref& seq) -> ErrorOr> + { + Char buf[kUUIDSize]; + + for (SizeT index = 0; index < 16; ++index) + { + buf[index] = seq->u8[index] + kAsciiBegin; + } + + for (SizeT index = 16; index < 24; ++index) + { + buf[index] = seq->u16[index] + kAsciiBegin; + } + + for (SizeT index = 24; index < 28; ++index) + { + buf[index] = seq->u32[index] + kAsciiBegin; + } + + auto view = StringBuilder::Construct(buf); + + if (view) + return ErrorOr>{view.Leak()}; + + return ErrorOr>{-1}; + } +} // namespace NewOS::XRN::Version1 diff --git a/Kernel/Source/GUIDWrapper.cxx b/Kernel/Source/GUIDWrapper.cxx new file mode 100644 index 00000000..d8ed28e0 --- /dev/null +++ b/Kernel/Source/GUIDWrapper.cxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS::XRN +{ +} diff --git a/Kernel/Source/HError.cxx b/Kernel/Source/HError.cxx new file mode 100644 index 00000000..bee5a467 --- /dev/null +++ b/Kernel/Source/HError.cxx @@ -0,0 +1,18 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + /// @brief Doea a system wide bug check. + /// @param void no params. + /// @return if error-free: true, otherwise false. + Boolean ke_bug_check(void) noexcept + { + return true; + } +} // namespace NewOS diff --git a/Kernel/Source/IndexableProperty.cxx b/Kernel/Source/IndexableProperty.cxx new file mode 100644 index 00000000..305d0988 --- /dev/null +++ b/Kernel/Source/IndexableProperty.cxx @@ -0,0 +1,57 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +//! @brief Filesystem Indexer. + +#include +#include +#include +#include + +/// @brief File Indexer. +/// BUGS: 0 + +#define kMaxLenIndexer 256 + +namespace NewOS +{ + namespace Indexer + { + IndexProperty& IndexableProperty::LeakProperty() noexcept + { + return fIndex; + } + + void IndexableProperty::AddFlag(Int16 flag) + { + fFlags |= flag; + } + void IndexableProperty::RemoveFlag(Int16 flag) + { + fFlags &= flag; + } + Int16 IndexableProperty::HasFlag(Int16 flag) + { + return fFlags & flag; + } + + /// @brief Index a file into the indexer instance. + /// @param filename path + /// @param filenameLen used bytes in path. + /// @param indexer the filesystem indexer. + /// @return none. + Void fs_index_file(const Char* filename, SizeT filenameLen, IndexableProperty& indexer) + { + if (!indexer.HasFlag(kIndexerClaimed)) + { + indexer.AddFlag(kIndexerClaimed); + rt_copy_memory((VoidPtr)indexer.LeakProperty().Path, (VoidPtr)filename, filenameLen); + + kcout << "New OS: FSKit: index new file: " << filename << endl; + } + } + } // namespace Indexer +} // namespace NewOS diff --git a/Kernel/Source/Json.cxx b/Kernel/Source/Json.cxx new file mode 100644 index 00000000..672c1b39 --- /dev/null +++ b/Kernel/Source/Json.cxx @@ -0,0 +1,12 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +using namespace NewOS; + +/// @brief Undefined object, is null in length. +INIT(NewOS::JsonType::kUndefined, NewOS::JsonType); diff --git a/Kernel/Source/KernelCheck.cxx b/Kernel/Source/KernelCheck.cxx new file mode 100644 index 00000000..e7c43650 --- /dev/null +++ b/Kernel/Source/KernelCheck.cxx @@ -0,0 +1,109 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include + +extern "C" [[noreturn]] void ke_wait_for_debugger() +{ + while (true) + { + NewOS::HAL::rt_cli(); + NewOS::HAL::rt_halt(); + } +} + +/* Each error code is attributed with an ID, which will prompt a string onto the + * screen. Wait for debugger... */ + +namespace NewOS +{ + void ke_stop(const NewOS::Int& id) + { + kcout << "*** STOP *** \r"; + kcout << "*** NewKernel.exe has trigerred a runtime stop. *** \r"; + + switch (id) + { + case RUNTIME_CHECK_PROCESS: { + kcout << "*** CAUSE: RUNTIME_CHECK_PROCESS *** \r"; + kcout << "*** WHAT: BAD DRIVER. *** \r"; + break; + } + case RUNTIME_CHECK_ACPI: { + kcout << "*** CAUSE: RUNTIME_CHECK_ACPI *** \r"; + kcout << "*** WHAT: ACPI ERROR, UNSTABLE STATE. *** \r"; + break; + } + case RUNTIME_CHECK_POINTER: { + kcout << "*** CAUSE: RUNTIME_CHECK_POINTER *** \r"; + kcout << "*** WHAT: HEAP CRC32 ERROR, UNSTABLE STATE. *** \r"; + break; + } + case RUNTIME_CHECK_BAD_BEHAVIOR: { + kcout << "*** CAUSE: RUNTIME_CHECK_BAD_BEHAVIOR *** \r"; + kcout << "*** WHAT: KERNEL BECAME UNSTABLE. *** \r"; + break; + } + case RUNTIME_CHECK_BOOTSTRAP: { + kcout << "*** CAUSE: RUNTIME_CHECK_BOOTSTRAP *** \r"; + kcout << "*** WHAT: INVALID BOOT SEQUENCE. *** \r"; + break; + } + case RUNTIME_CHECK_HANDSHAKE: { + kcout << "*** CAUSE: RUNTIME_CHECK_HANDSHAKE *** \r"; + kcout << "*** WHAT: BAD HANDSHAKE. *** \r"; + break; + } + case RUNTIME_CHECK_IPC: { + kcout << "*** CAUSE: RUNTIME_CHECK_IPC *** \r"; + kcout << "*** WHAT: RICH CALL VIOLATION. *** \r"; + break; + } + case RUNTIME_CHECK_INVALID_PRIVILEGE: { + kcout << "*** CAUSE: RUNTIME_CHECK_INVALID_PRIVILEGE *** \r"; + kcout << "*** WHAT: HYPERVISOR POLICY VIOLATION. *** \r"; + break; + case RUNTIME_CHECK_UNEXCPECTED: { + kcout << "*** CAUSE: RUNTIME_CHECK_UNEXCPECTED *** \r"; + kcout << "*** WHAT: CATASROPHIC FAILURE! *** \r"; + break; + } + case RUNTIME_CHECK_FAILED: { + kcout << "*** CAUSE: RUNTIME_CHECK_FAILED *** \r"; + kcout << "*** WHAT: ASSERTION FAILED! *** \r"; + break; + } + default: { + kcout << "*** CAUSE: RUNTIME_CHECK_GENERIC *** \r"; + break; + } + } + }; + + DumpManager::Dump(); + +#ifdef __DEBUG__ + ke_wait_for_debugger(); +#endif // ifdef __DEBUG__ + } + + void ke_runtime_check(bool expr, const char* file, const char* line) + { + if (!expr) + { +#ifdef __DEBUG__ + kcout << "New Kernel: File: " << file << "\r"; + kcout << "New Kernel: Line: " << line << "\r"; + +#endif // __DEBUG__ + + NewOS::ke_stop(RUNTIME_CHECK_FAILED); // Runtime Check failed + } + } +} // namespace NewOS diff --git a/Kernel/Source/KernelHeap.cxx b/Kernel/Source/KernelHeap.cxx new file mode 100644 index 00000000..d0037ec3 --- /dev/null +++ b/Kernel/Source/KernelHeap.cxx @@ -0,0 +1,169 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include +#include + +//! @file KernelHeap.cxx +//! @brief Kernel allocator. + +#define kKernelHeapMagic (0xD4D7D5) +#define kKernelHeapHeaderPaddingSz (16U) + +namespace NewOS +{ + STATIC SizeT kHeapCount = 0UL; + STATIC PageManager kHeapPageManager; + + namespace Detail + { + /// @brief Kernel heap information block. + /// Located before the address bytes. + /// | HIB | ADDRESS | + struct PACKED HeapInformationBlock final + { + ///! @brief 32-bit value which contains the magic number of the executable. + UInt32 fMagic; + ///! @brief Boolean value which tells if the pointer is allocated. + Boolean fPresent; + ///! @brief 32-bit CRC checksum + UInt32 fCRC32; + /// @brief 64-bit pointer size. + SizeT fTargetPtrSize; + /// @brief 64-bit target pointer. + UIntPtr fTargetPtr; + UInt8 fPadding[kKernelHeapHeaderPaddingSz]; + }; + + typedef HeapInformationBlock* HeapInformationBlockPtr; + } // namespace Detail + + /// @brief allocate chunk of memory. + /// @param sz size of pointer + /// @param rw read write (true to enable it) + /// @param user is it accesible by user processes? + /// @return the pointer + VoidPtr ke_new_ke_heap(SizeT sz, const bool rw, const bool user) + { + if (sz == 0) + ++sz; + + auto wrapper = kHeapPageManager.Request(rw, user, false, sz); + + Detail::HeapInformationBlockPtr heapInfo = + reinterpret_cast( + wrapper.VirtualAddress()); + + heapInfo->fTargetPtrSize = sz; + heapInfo->fMagic = kKernelHeapMagic; + heapInfo->fCRC32 = 0; // dont fill it for now. + heapInfo->fTargetPtr = wrapper.VirtualAddress(); + + ++kHeapCount; + + return reinterpret_cast(wrapper.VirtualAddress() + + sizeof(Detail::HeapInformationBlock)); + } + + /// @brief Declare pointer as free. + /// @param heapPtr the pointer. + /// @return + Int32 ke_delete_ke_heap(VoidPtr heapPtr) + { + if (kHeapCount < 1) + return -kErrorInternal; + if (((IntPtr)heapPtr - sizeof(Detail::HeapInformationBlock)) <= 0) + return -kErrorInternal; + if (((IntPtr)heapPtr - kBadPtr) < 0) + return -kErrorInternal; + + Detail::HeapInformationBlockPtr virtualAddress = + reinterpret_cast( + (UIntPtr)heapPtr - sizeof(Detail::HeapInformationBlock)); + + if (virtualAddress && virtualAddress->fMagic == kKernelHeapMagic) + { + if (!virtualAddress->fPresent) + { + return -kErrorHeapNotPresent; + } + + if (virtualAddress->fCRC32 != 0) + { + if (virtualAddress->fCRC32 != + ke_calculate_crc32((Char*)virtualAddress->fTargetPtr, + virtualAddress->fTargetPtrSize)) + { + ke_stop(RUNTIME_CHECK_POINTER); + } + } + + virtualAddress->fTargetPtrSize = 0UL; + virtualAddress->fPresent = false; + virtualAddress->fTargetPtr = 0; + virtualAddress->fCRC32 = 0; + virtualAddress->fMagic = 0; + + PTEWrapper pageWrapper(false, false, false, (UIntPtr)virtualAddress); + Ref pteAddress{&pageWrapper}; + + kHeapPageManager.Free(pteAddress); + + --kHeapCount; + return 0; + } + + return -kErrorInternal; + } + + /// @brief Check if pointer is a valid kernel pointer. + /// @param heapPtr the pointer + /// @return if it exists. + Boolean ke_is_valid_heap(VoidPtr heapPtr) + { + if (kHeapCount < 1) + return false; + + if (heapPtr) + { + Detail::HeapInformationBlockPtr virtualAddress = + reinterpret_cast( + (UIntPtr)heapPtr - sizeof(Detail::HeapInformationBlock)); + + if (virtualAddress->fPresent && virtualAddress->fMagic == kKernelHeapMagic) + { + return true; + } + } + + return false; + } + + /// @brief Protect the heap with a CRC value. + /// @param heapPtr HIB pointer. + /// @return if it valid: point has crc now., otherwise fail. + Boolean ke_protect_ke_heap(VoidPtr heapPtr) + { + if (heapPtr) + { + Detail::HeapInformationBlockPtr virtualAddress = + reinterpret_cast( + (UIntPtr)heapPtr - sizeof(Detail::HeapInformationBlock)); + + if (virtualAddress->fPresent && kKernelHeapMagic == virtualAddress->fMagic) + { + virtualAddress->fCRC32 = + ke_calculate_crc32((Char*)heapPtr, virtualAddress->fTargetPtrSize); + return true; + } + } + + return false; + } +} // namespace NewOS diff --git a/Kernel/Source/LockDelegate.cxx b/Kernel/Source/LockDelegate.cxx new file mode 100644 index 00000000..70e421f7 --- /dev/null +++ b/Kernel/Source/LockDelegate.cxx @@ -0,0 +1,12 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + /// Leave it empty for now. +} // namespace NewOS \ No newline at end of file diff --git a/Kernel/Source/MutableArray.cxx b/Kernel/Source/MutableArray.cxx new file mode 100644 index 00000000..047a4455 --- /dev/null +++ b/Kernel/Source/MutableArray.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/Network/IP.cxx b/Kernel/Source/Network/IP.cxx new file mode 100644 index 00000000..224f7b2a --- /dev/null +++ b/Kernel/Source/Network/IP.cxx @@ -0,0 +1,126 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +namespace NewOS +{ + char* RawIPAddress::Address() + { + return fAddr; + } + + RawIPAddress::RawIPAddress(char bytes[4]) + { + rt_copy_memory(bytes, fAddr, 4); + } + + bool RawIPAddress::operator==(const RawIPAddress& ipv4) + { + for (Size index = 0; index < 4; ++index) + { + if (ipv4.fAddr[index] != fAddr[index]) + return false; + } + + return true; + } + + bool RawIPAddress::operator!=(const RawIPAddress& ipv4) + { + for (Size index = 0; index < 4; ++index) + { + if (ipv4.fAddr[index] == fAddr[index]) + return false; + } + + return true; + } + + char& RawIPAddress::operator[](const Size& index) + { + kcout << "[RawIPAddress::operator[]] Fetching Index...\r"; + + static char IP_PLACEHOLDER = '0'; + if (index > 4) + return IP_PLACEHOLDER; + + return fAddr[index]; + } + + RawIPAddress6::RawIPAddress6(char bytes[8]) + { + rt_copy_memory(bytes, fAddr, 8); + } + + char& RawIPAddress6::operator[](const Size& index) + { + kcout << "[RawIPAddress6::operator[]] Fetching Index...\r"; + + static char IP_PLACEHOLDER = '0'; + if (index > 8) + return IP_PLACEHOLDER; + + return fAddr[index]; + } + + bool RawIPAddress6::operator==(const RawIPAddress6& ipv6) + { + for (SizeT index = 0; index < 8; ++index) + { + if (ipv6.fAddr[index] != fAddr[index]) + return false; + } + + return true; + } + + bool RawIPAddress6::operator!=(const RawIPAddress6& ipv6) + { + for (SizeT index = 0; index < 8; ++index) + { + if (ipv6.fAddr[index] == fAddr[index]) + return false; + } + + return true; + } + + ErrorOr IPFactory::ToStringView(Ref ipv6) + { + auto str = StringBuilder::Construct(ipv6.Leak().Address()); + return str; + } + + ErrorOr IPFactory::ToStringView(Ref ipv4) + { + auto str = StringBuilder::Construct(ipv4.Leak().Address()); + return str; + } + + bool IPFactory::IpCheckVersion4(const char* ip) + { + int cnter = 0; + + for (Size base = 0; base < rt_string_len(ip); ++base) + { + if (ip[base] == '.') + { + cnter = 0; + } + else + { + if (cnter == 3) + return false; + + ++cnter; + } + } + + return true; + } +} // namespace NewOS diff --git a/Kernel/Source/Network/IPCEP.cxx b/Kernel/Source/Network/IPCEP.cxx new file mode 100644 index 00000000..39f3ea33 --- /dev/null +++ b/Kernel/Source/Network/IPCEP.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/Network/NetworkDevice.cxx b/Kernel/Source/Network/NetworkDevice.cxx new file mode 100644 index 00000000..a2c25782 --- /dev/null +++ b/Kernel/Source/Network/NetworkDevice.cxx @@ -0,0 +1,15 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + const char* NetworkDevice::Name() const + { + return "NetworkDevice"; + } +} // namespace NewOS diff --git a/Kernel/Source/New+Delete.cxx b/Kernel/Source/New+Delete.cxx new file mode 100644 index 00000000..84e3a72d --- /dev/null +++ b/Kernel/Source/New+Delete.cxx @@ -0,0 +1,50 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +void* operator new[](size_t sz) +{ + if (sz == 0) + ++sz; + + return NewOS::ke_new_ke_heap(sz, true, false); +} + +void* operator new(size_t sz) +{ + if (sz == 0) + ++sz; + + return NewOS::ke_new_ke_heap(sz, true, false); +} + +void operator delete[](void* ptr) +{ + if (ptr == nullptr) + return; + + NewOS::ke_delete_ke_heap(ptr); +} + +void operator delete(void* ptr) +{ + if (ptr == nullptr) + return; + + NewOS::ke_delete_ke_heap(ptr); +} + +void operator delete(void* ptr, size_t sz) +{ + if (ptr == nullptr) + return; + + NEWOS_UNUSED(sz); + + NewOS::ke_delete_ke_heap(ptr); +} diff --git a/Kernel/Source/NewFS+FileManager.cxx b/Kernel/Source/NewFS+FileManager.cxx new file mode 100644 index 00000000..bcfc0443 --- /dev/null +++ b/Kernel/Source/NewFS+FileManager.cxx @@ -0,0 +1,89 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +#ifdef __FSKIT_NEWFS__ + +/// @brief NewFS File manager. +/// BUGS: 0 + +namespace NewOS +{ + /// @brief C++ constructor + NewFilesystemManager::NewFilesystemManager() + { + MUST_PASS(Detail::fs_init_newfs()); + fImpl = new NewFSParser(); + } + + NewFilesystemManager::~NewFilesystemManager() + { + if (fImpl) + { + delete fImpl; + } + } + + /// @brief Removes a node from the filesystem. + /// @param fileName The filename + /// @return If it was deleted or not. + bool NewFilesystemManager::Remove(const char* fileName) + { + if (fileName == nullptr || *fileName == 0) + return false; + + return fImpl->RemoveCatalog(fileName); + } + + /// @brief Creates a node with the specified. + /// @param path The filename path. + /// @return The Node pointer. + NodePtr NewFilesystemManager::Create(const char* path) + { + return node_cast(fImpl->CreateCatalog(path, 0, kNewFSCatalogKindFile)); + } + + /// @brief Creates a node with is a directory. + /// @param path The filename path. + /// @return The Node pointer. + NodePtr NewFilesystemManager::CreateDirectory(const char* path) + { + return node_cast(fImpl->CreateCatalog(path, 0, kNewFSCatalogKindDir)); + } + + /// @brief Creates a node with is a alias. + /// @param path The filename path. + /// @return The Node pointer. + NodePtr NewFilesystemManager::CreateAlias(const char* path) + { + return node_cast(fImpl->CreateCatalog(path, 0, kNewFSCatalogKindAlias)); + } + + /// @brief Gets the root directory. + /// @return + const char* NewFilesystemHelper::Root() + { + return kNewFSRoot; + } + + /// @brief Gets the up-dir directory. + /// @return + const char* NewFilesystemHelper::UpDir() + { + return kNewFSUpDir; + } + + /// @brief Gets the separator character. + /// @return + const char NewFilesystemHelper::Separator() + { + return kNewFSSeparator; + } +} // namespace NewOS + +#endif // ifdef __FSKIT_NEWFS__ diff --git a/Kernel/Source/NewFS+IO.cxx b/Kernel/Source/NewFS+IO.cxx new file mode 100644 index 00000000..3235c080 --- /dev/null +++ b/Kernel/Source/NewFS+IO.cxx @@ -0,0 +1,101 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +/************************************************************* + * + * File: NewFS+IO.cxx + * Purpose: Filesystem to mountpoint interface. + * Date: 3/26/24 + * + * Copyright SoftwareLabs, all rights reserved. + * + *************************************************************/ + +#ifdef __FSKIT_NEWFS__ + +#include + +/// Useful macros. + +#define NEWFS_WRITE(DRV, TRAITS, MP) (MP->DRV()).fOutput(&TRAITS) +#define NEWFS_READ(DRV, TRAITS, MP) (MP->DRV()).fInput(&TRAITS) + +using namespace NewOS; + +/// @brief Read from newfs disk. +/// @param Mnt mounted interface. +/// @param DrvTrait drive info +/// @param DrvIndex drive index. +/// @return +Int32 fs_newfs_read(MountpointInterface* Mnt, DriveTrait& DrvTrait, Int32 DrvIndex) +{ + if (!Mnt) + return -1; + + DrvTrait.fPacket.fPacketGood = false; + + switch (DrvIndex) + { + case kNewFSSubDriveA: { + NEWFS_READ(A, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveB: { + NEWFS_READ(B, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveC: { + NEWFS_READ(C, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveD: { + NEWFS_READ(D, DrvTrait.fPacket, Mnt); + break; + } + } + + return DrvTrait.fPacket.fPacketGood; +} + +/// @brief Write to newfs disk. +/// @param Mnt mounted interface. +/// @param DrvTrait drive info +/// @param DrvIndex drive index. +/// @return +Int32 fs_newfs_write(MountpointInterface* Mnt, DriveTrait& DrvTrait, Int32 DrvIndex) +{ + if (!Mnt) + return -1; + + DrvTrait.fPacket.fPacketGood = false; + + switch (DrvIndex) + { + case kNewFSSubDriveA: { + NEWFS_WRITE(A, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveB: { + NEWFS_WRITE(B, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveC: { + NEWFS_WRITE(C, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveD: { + NEWFS_WRITE(D, DrvTrait.fPacket, Mnt); + break; + } + } + + return DrvTrait.fPacket.fPacketGood; +} + +#endif // ifdef __FSKIT_NEWFS__ diff --git a/Kernel/Source/NewFS+Journal.cxx b/Kernel/Source/NewFS+Journal.cxx new file mode 100644 index 00000000..23f42f89 --- /dev/null +++ b/Kernel/Source/NewFS+Journal.cxx @@ -0,0 +1,22 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +#ifdef __FSKIT_NEWFS__ + +///! BUGS: 0 +///! @file NewFS+Journal.cxx +///! @brief Journaling for NewFS. + +namespace NewOS::Journal +{ +} // namespace NewOS::Journal + +using namespace NewOS; + +#endif // ifdef __FSKIT_NEWFS__ diff --git a/Kernel/Source/OwnPtr.cxx b/Kernel/Source/OwnPtr.cxx new file mode 100644 index 00000000..909eacef --- /dev/null +++ b/Kernel/Source/OwnPtr.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/PEFCodeManager.cxx b/Kernel/Source/PEFCodeManager.cxx new file mode 100644 index 00000000..0bab5373 --- /dev/null +++ b/Kernel/Source/PEFCodeManager.cxx @@ -0,0 +1,226 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace NewOS +{ + namespace Detail + { + /// @brief Get the PEF platform signature according to the compiled backebnd + UInt32 rt_get_pef_platform(void) noexcept + { +#ifdef __32x0__ + return kPefArch32x0; +#elif defined(__64x0__) + return kPefArch64x0; +#elif defined(__x86_64__) + return kPefArchAMD64; +#elif defined(__powerpc64__) + return kPefArchPowerPC; +#else + return kPefArchInvalid; +#endif // __32x0__ || __64x0__ || __x86_64__ + } + } // namespace Detail + + /// @brief PEF loader constructor w/ blob. + /// @param blob + PEFLoader::PEFLoader(const VoidPtr blob) + : fCachedBlob(blob) + { + MUST_PASS(fCachedBlob); + fBad = false; + } + + /// @brief PEF loader constructor. + /// @param path the filesystem path. + PEFLoader::PEFLoader(const Char* path) + : fCachedBlob(nullptr), fBad(false), fFatBinary(false) + { + OwnPtr> file; + + file.New(const_cast(path), kRestrictRB); + + if (StringBuilder::Equals(file->MIME(), this->MIME())) + { + fPath = StringBuilder::Construct(path).Leak(); + + fCachedBlob = file->Read(); + + PEFContainer* container = reinterpret_cast(fCachedBlob); + + if (container->Cpu == Detail::rt_get_pef_platform() && + container->Magic[0] == kPefMagic[0] && + container->Magic[1] == kPefMagic[1] && + container->Magic[2] == kPefMagic[2] && + container->Magic[3] == kPefMagic[3] && + container->Magic[4] == kPefMagic[4] && container->Abi == kPefAbi) + { + return; + } + else if (container->Magic[4] == kPefMagic[0] && + container->Magic[3] == kPefMagic[1] && + container->Magic[2] == kPefMagic[2] && + container->Magic[1] == kPefMagic[3] && + container->Magic[0] == kPefMagic[0] && container->Abi == kPefAbi) + { + /// This is a fat binary. + this->fFatBinary = true; + return; + } + + kcout << "CodeManager: Warning: Executable format error!\n"; + fBad = true; + + ke_delete_ke_heap(fCachedBlob); + + fCachedBlob = nullptr; + } + } + + /// @brief PEF destructor. + PEFLoader::~PEFLoader() + { + if (fCachedBlob) + ke_delete_ke_heap(fCachedBlob); + } + + VoidPtr PEFLoader::FindSymbol(const char* name, Int32 kind) + { + if (!fCachedBlob || fBad) + return nullptr; + + PEFContainer* container = reinterpret_cast(fCachedBlob); + + PEFCommandHeader* container_header = reinterpret_cast( + (UIntPtr)fCachedBlob + sizeof(PEFContainer)); + + constexpr auto cMangleCharacter = '$'; + const char* cContainerKinds[] = {".code64", ".data64", ".zero64", nullptr}; + + ErrorOr errOrSym; + + switch (kind) + { + case kPefCode: { + errOrSym = StringBuilder::Construct(cContainerKinds[0]); // code symbol. + break; + } + case kPefData: { + errOrSym = StringBuilder::Construct(cContainerKinds[1]); // data symbol. + break; + } + case kPefZero: { + errOrSym = StringBuilder::Construct(cContainerKinds[2]); // block starting symbol. + break; + } + default: + return nullptr; + } + + char* unconstSymbol = const_cast(name); + + for (SizeT i = 0UL; i < rt_string_len(unconstSymbol, kPefNameLen); ++i) + { + if (unconstSymbol[i] == ' ') + { + unconstSymbol[i] = cMangleCharacter; + } + } + + errOrSym.Leak().Leak() += name; + + for (SizeT index = 0; index < container->Count; ++index) + { + if (StringBuilder::Equals(container_header->Name, + errOrSym.Leak().Leak().CData())) + { + if (container_header->Kind == kind) + { + if (container_header->Cpu != Detail::rt_get_pef_platform()) + { + if (!this->fFatBinary) + return nullptr; + } + + return (VoidPtr)(static_cast(fCachedBlob) + + container_header->Offset); + } + } + } + + return nullptr; + } + + /// @brief Finds the executable entrypoint. + /// @return + ErrorOr PEFLoader::FindStart() + { + if (auto sym = this->FindSymbol(kPefStart, kPefCode); sym) + return ErrorOr(sym); + + return ErrorOr(kErrorExecutable); + } + + /// @brief Tells if the executable is loaded or not. + /// @return + bool PEFLoader::IsLoaded() noexcept + { + return !fBad && fCachedBlob; + } + + namespace Utils + { + bool execute_from_image(PEFLoader& exec, const Int32& procKind) noexcept + { + auto errOrStart = exec.FindStart(); + + if (errOrStart.Error() != 0) + return false; + + ProcessHeader proc(errOrStart.Leak().Leak()); + Ref refProc = proc; + + proc.Kind = procKind; + + return ProcessScheduler::Shared().Leak().Add(refProc); + } + } // namespace Utils + + const char* PEFLoader::Path() + { + return fPath.Leak().CData(); + } + + const char* PEFLoader::FormatAsString() + { +#ifdef __32x0__ + return "32x0 PEF."; +#elif defined(__64x0__) + return "64x0 PEF."; +#elif defined(__x86_64__) + return "x86_64 PEF."; +#elif defined(__powerpc64__) + return "POWER PEF."; +#else + return "Unknown PEF."; +#endif // __32x0__ || __64x0__ || __x86_64__ || __powerpc64__ + } + + const char* PEFLoader::MIME() + { + return kPefApplicationMime; + } +} // namespace NewOS diff --git a/Kernel/Source/PEFSharedObjectRT.cxx b/Kernel/Source/PEFSharedObjectRT.cxx new file mode 100644 index 00000000..810f0480 --- /dev/null +++ b/Kernel/Source/PEFSharedObjectRT.cxx @@ -0,0 +1,107 @@ +/* + * ======================================================== + * + * NewOS + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#include +#include +#include +#include +#include +#include + +/* ------------------------------------------- + + Revision History: + + 01/02/24: Rework shared library ABI, except a rt_library_init and + rt_library_free (amlel) 15/02/24: Breaking changes, changed the name of the + routines. (amlel) + + ------------------------------------------- */ + +using namespace NewOS; + +/***********************************************************************************/ +/// @file SharedObjectRT.cxx +/// @brief Shared Object runtime. +/***********************************************************************************/ + +/***********************************************************************************/ +/* @brief Library runtime initializer. */ +/***********************************************************************************/ + +EXTERN_C SharedObjectPtr rt_library_init(void) +{ + SharedObjectPtr library = tls_new_class(); + + if (!library) + { + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + + return nullptr; + } + + library->Mount(tls_new_class()); + + if (!library->Get()) + { + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + + return nullptr; + } + + library->Get()->fImageObject = + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Image; + + if (!library->Get()->fImageObject) + { + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + + return nullptr; + } + + library->Get()->fImageEntrypointOffset = + library->Load(kPefStart, rt_string_len(kPefStart, 0), kPefCode); + + return library; +} + +/***********************************************************************************/ +/* @brief Ends the library. */ +/* @note Please check if the lib got freed! */ +/* @param SharedObjectPtr the library to free. */ +/***********************************************************************************/ + +EXTERN_C Void rt_library_free(SharedObjectPtr lib, bool* successful) +{ + MUST_PASS(successful); + + // sanity check (will also trigger a bug check if this fails) + if (lib == nullptr) + { + *successful = false; + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + } + + delete lib->Get(); + delete lib; + + lib = nullptr; + + *successful = true; +} + +/***********************************************************************************/ + +/// @brief Unimplemented function (crashes by default) +/// @param +EXTERN_C void __mh_purecall(void) +{ + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + return; +} diff --git a/Kernel/Source/PRDT.cxx b/Kernel/Source/PRDT.cxx new file mode 100644 index 00000000..3f454409 --- /dev/null +++ b/Kernel/Source/PRDT.cxx @@ -0,0 +1,22 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +namespace NewOS +{ + /// @brief constructs a new PRD. + /// @param prd PRD reference. + /// @note This doesnt construct a valid, please fill it by yourself. + void construct_prdt(Ref& prd) + { + prd.Leak().fPhysAddress = 0x0; + prd.Leak().fSectorCount = 0x0; + prd.Leak().fEndBit = 0x0; + } +} // namespace NewOS diff --git a/Kernel/Source/PageAllocator.cxx b/Kernel/Source/PageAllocator.cxx new file mode 100644 index 00000000..bafa5a7e --- /dev/null +++ b/Kernel/Source/PageAllocator.cxx @@ -0,0 +1,52 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +/// @brief Internal namespace, used internally by kernel. +namespace NewOS::Detail +{ + VoidPtr create_page_wrapper(Boolean rw, Boolean user, SizeT pageSz) + { + auto addr = HAL::hal_alloc_page(rw, user, pageSz); + + if (addr == kBadAddress) + { + kcout << "[create_page_wrapper] kBadAddress returned\n"; + ke_stop(RUNTIME_CHECK_POINTER); + } + + return addr; + } + + void exec_disable(UIntPtr VirtualAddr) + { + PTE* VirtualAddrTable = reinterpret_cast(VirtualAddr); + MUST_PASS(!VirtualAddrTable->Accessed); + VirtualAddrTable->ExecDisable = true; + + hal_flush_tlb(); + } + + bool page_disable(UIntPtr VirtualAddr) + { + if (VirtualAddr) + { + auto VirtualAddrTable = (PTE*)(VirtualAddr); + MUST_PASS(!VirtualAddrTable->Accessed); + + VirtualAddrTable->Present = false; + + hal_flush_tlb(); + + return true; + } + + return false; + } +} // namespace NewOS::Detail diff --git a/Kernel/Source/PageManager.cxx b/Kernel/Source/PageManager.cxx new file mode 100644 index 00000000..e1cfdeea --- /dev/null +++ b/Kernel/Source/PageManager.cxx @@ -0,0 +1,118 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +#ifdef __x86_64__ +#include +#endif // ifdef __x86_64__ + +//! null deref will throw (Page Zero detected, aborting app!) +#define kProtectedRegionEnd (512) + +namespace NewOS +{ + PTEWrapper::PTEWrapper(Boolean Rw, Boolean User, Boolean ExecDisable, UIntPtr VirtAddr) + : fRw(Rw), + fUser(User), + fExecDisable(ExecDisable), + fVirtAddr(VirtAddr), + fCache(false), + fShareable(false), + fWt(false), + fPresent(true), + fAccessed(false) + { + } + + PTEWrapper::~PTEWrapper() + { + } + + /// @brief Flush virtual address. + /// @param VirtAddr + void PageManager::FlushTLB(UIntPtr VirtAddr) + { + if (VirtAddr == kBadAddress) + return; + + hal_flush_tlb(); + } + + /// @brief Reclaim freed page. + /// @return + bool PTEWrapper::Reclaim() + { + if (!this->fPresent) + { + this->fPresent = true; + return true; + } + + return false; + } + + /// @brief Request a PTE. + /// @param Rw r/w? + /// @param User user mode? + /// @param ExecDisable disable execution on page? + /// @return + PTEWrapper PageManager::Request(Boolean Rw, Boolean User, Boolean ExecDisable, SizeT Sz) + { + // Store PTE wrapper right after PTE. + VoidPtr ptr = NewOS::HAL::hal_alloc_page(Rw, User, Sz); + + return PTEWrapper{Rw, User, ExecDisable, reinterpret_cast(ptr)}; + } + + /// @brief Disable PTE. + /// @param wrapper the wrapper. + /// @return + bool PageManager::Free(Ref& wrapper) + { + if (wrapper) + { + if (!Detail::page_disable(wrapper->VirtualAddress())) + return false; + return true; + } + + return false; + } + + /// @brief Virtual PTE address. + /// @return The virtual address of the page. + const UIntPtr PTEWrapper::VirtualAddress() + { + return (fVirtAddr); + } + + bool PTEWrapper::Shareable() + { + return fShareable; + } + + bool PTEWrapper::Present() + { + return fPresent; + } + + bool PTEWrapper::Access() + { + return fAccessed; + } + + void PTEWrapper::NoExecute(const bool enable) + { + this->fExecDisable = enable; + } + + const bool& PTEWrapper::NoExecute() + { + return this->fExecDisable; + } +} // namespace NewOS diff --git a/Kernel/Source/PermissionSelector.cxx b/Kernel/Source/PermissionSelector.cxx new file mode 100644 index 00000000..cb44b237 --- /dev/null +++ b/Kernel/Source/PermissionSelector.cxx @@ -0,0 +1,47 @@ +/* + * ======================================================== + * + * NewOS + * Copyright SoftwareLabs, all rights reserved. + * + * File: PermissionSelector.cpp + * Purpose: Permission selectors. + * + * ======================================================== + */ + +#include +#include + +/// bugs 0 + +namespace NewOS +{ + PermissionSelector::PermissionSelector(const Int32& sel) + : fRing((RingKind)sel) + { + MUST_PASS(sel > 0); + } + + PermissionSelector::PermissionSelector(const RingKind& ringKind) + : fRing(ringKind) + { + } + + PermissionSelector::~PermissionSelector() = default; + + bool PermissionSelector::operator==(const PermissionSelector& lhs) + { + return lhs.fRing == this->fRing; + } + + bool PermissionSelector::operator!=(const PermissionSelector& lhs) + { + return lhs.fRing != this->fRing; + } + + const RingKind& PermissionSelector::Ring() noexcept + { + return this->fRing; + } +} // namespace NewOS diff --git a/Kernel/Source/Pmm.cxx b/Kernel/Source/Pmm.cxx new file mode 100644 index 00000000..f60f5b23 --- /dev/null +++ b/Kernel/Source/Pmm.cxx @@ -0,0 +1,85 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +namespace NewOS +{ + Pmm::Pmm() + : fPageManager() + { + kcout << "[PMM] Allocate PageMemoryManager"; + } + + Pmm::~Pmm() = default; + + /* If this returns Null pointer, enter emergency mode */ + Ref Pmm::RequestPage(Boolean user, Boolean readWrite) + { + PTEWrapper pt = fPageManager.Leak().Request(user, readWrite, false, kPTESize); + + if (pt.fPresent) + { + kcout << "[PMM]: Allocation was successful."; + return Ref(pt); + } + + kcout << "[PMM]: Allocation failure."; + + return {}; + } + + Boolean Pmm::FreePage(Ref PageRef) + { + if (!PageRef) + return false; + + PageRef.Leak().fPresent = false; + + return true; + } + + Boolean Pmm::TogglePresent(Ref PageRef, Boolean Enable) + { + if (!PageRef) + return false; + + PageRef.Leak().fPresent = Enable; + + return true; + } + + Boolean Pmm::ToggleUser(Ref PageRef, Boolean Enable) + { + if (!PageRef) + return false; + + PageRef.Leak().fRw = Enable; + + return true; + } + + Boolean Pmm::ToggleRw(Ref PageRef, Boolean Enable) + { + if (!PageRef) + return false; + + PageRef.Leak().fRw = Enable; + + return true; + } + + Boolean Pmm::ToggleShare(Ref PageRef, Boolean Enable) + { + if (!PageRef) + return false; + + PageRef.Leak().fShareable = Enable; + + return true; + } +} // namespace NewOS diff --git a/Kernel/Source/ProcessScheduler.cxx b/Kernel/Source/ProcessScheduler.cxx new file mode 100644 index 00000000..859ce657 --- /dev/null +++ b/Kernel/Source/ProcessScheduler.cxx @@ -0,0 +1,392 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/***********************************************************************************/ +/// @file ProcessScheduler.cxx +/// @brief MicroKernel process scheduler. +/***********************************************************************************/ + +#include +#include +#include +#include +#include + +///! BUGS: 0 + +/***********************************************************************************/ +/* This file handles the process scheduling. +/***********************************************************************************/ + +namespace NewOS +{ + /***********************************************************************************/ + /// @brief Exit Code global + /***********************************************************************************/ + + STATIC Int32 kLastExitCode = 0U; + + /// @brief Gets the latest exit code. + /// @note Not thread-safe. + const Int32& rt_get_exit_code() noexcept + { + return kLastExitCode; + } + + /***********************************************************************************/ + /// @brief crash current process. + /***********************************************************************************/ + + void ProcessHeader::Crash() + { + kcout << this->Name << ": crashed. (id = " << number(39); + kcout << ")\r"; + + if (this->Ring != kRingUserKind) + { + MUST_PASS(ke_bug_check()); + } + + this->Exit(kErrorProcessFault); + } + + void ProcessHeader::Wake(const bool should_wakeup) + { + this->Status = + should_wakeup ? ProcessStatus::kRunning : ProcessStatus::kFrozen; + } + + /***********************************************************************************/ + + VoidPtr ProcessHeader::New(const SizeT& sz) + { + if (this->FreeMemory < 1) + { + DbgLastError() = kErrorHeapOutOfMemory; + this->Crash(); /// out of memory. + + return nullptr; + } + + if (this->HeapCursor) + { + VoidPtr ptr = this->HeapCursor; + this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor + (sizeof(sz))); + + ++this->UsedMemory; + --this->FreeMemory; + + return ptr; + } + + return nullptr; + } + + /***********************************************************************************/ + + /* @brief checks if runtime pointer is in region. */ + bool rt_is_in_pool(VoidPtr pool_ptr, VoidPtr pool, const SizeT& sz) + { + UIntPtr* _pool_ptr = (UIntPtr*)pool_ptr; + UIntPtr* _pool = (UIntPtr*)pool; + + for (SizeT index = sz; _pool[sz] != kUserHeapMag; --index) + { + if (&_pool[index] > &_pool_ptr[sz]) + continue; + + if (_pool[index] == _pool_ptr[index]) + return true; + } + + return false; + } + + /* @brief free pointer from usage. */ + Boolean ProcessHeader::Delete(VoidPtr ptr, const SizeT& sz) + { + if (sz < 1 || this->HeapCursor == this->HeapPtr) + return false; + + // also check for the amount of allocations we've done so far. + if (this->UsedMemory < 1) + return false; + + if (rt_is_in_pool(ptr, this->HeapCursor, this->UsedMemory)) + { + this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor - (sizeof(sz))); + rt_zero_memory(ptr, sz); + + ++this->FreeMemory; + --this->UsedMemory; + + return true; + } + + return false; + } + + /// @brief process name getter. + const Char* ProcessHeader::GetName() + { + return this->Name; + } + + /// @brief process selector getter. + const ProcessSelector& ProcessHeader::GetSelector() + { + return this->Selector; + } + + /// @brief process status getter. + const ProcessStatus& ProcessHeader::GetStatus() + { + return this->Status; + } + + /***********************************************************************************/ + + /** +@brief Affinity is the time slot allowed for the process. +*/ + const AffinityKind& ProcessHeader::GetAffinity() + { + return this->Affinity; + } + + /** +@brief Standard exit proc. +*/ + void ProcessHeader::Exit(Int32 exit_code) + { + if (this->ProcessId != + ProcessScheduler::Shared().Leak().GetCurrent().Leak().ProcessId) + ke_stop(RUNTIME_CHECK_PROCESS); + + if (this->Ring == (Int32)ProcessSelector::kRingKernel && + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Ring > 0) + ke_stop(RUNTIME_CHECK_PROCESS); + + kLastExitCode = exit_code; + + if (this->Ring != (Int32)ProcessSelector::kRingDriver) + { + if (this->HeapPtr) + rt_free_heap(this->HeapPtr); + + this->HeapPtr = nullptr; + this->HeapCursor = nullptr; + + this->FreeMemory = 0UL; + this->UsedMemory = 0UL; + } + + //! Delete image if not done already. + if (this->Image) + ke_delete_ke_heap(this->Image); + if (this->StackFrame) + ke_delete_ke_heap((VoidPtr)this->StackFrame); + + this->Image = nullptr; + this->StackFrame = nullptr; + + ProcessScheduler::Shared().Leak().Remove(this->ProcessId); + } + + SizeT ProcessScheduler::Add(Ref& process) + { + if (!process) + return -1; + + if (!process.Leak().Image) + { + if (process.Leak().Kind != ProcessHeader::kLibKind) + { + return -kErrorNoEntrypoint; + } + } + + if (!mTeam.AsArray().Count() > kSchedProcessLimitPerTeam) + return -kErrorOutOfTeamSlot; + + if (process.Leak().Ring != (Int32)ProcessSelector::kRingKernel) + return -1; + + kcout << "ProcessScheduler::Add(Ref& process)\r"; + + /// Create heap according to type of process. + if (process.Leak().Kind == ProcessHeader::kUserKind) + process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw); + else if (process.Leak().Kind == ProcessHeader::kLibKind) + process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw | kUserHeapShared); + else + process.Leak().HeapPtr = rt_new_heap(kUserHeapDriver | kUserHeapRw); + + process.Leak().StackFrame = reinterpret_cast( + ke_new_ke_heap(sizeof(HAL::StackFrame), true, false)); + + MUST_PASS(process.Leak().StackFrame); + + mTeam.AsArray().Add(process); + + process.Leak().ProcessId = mTeam.AsArray().Count() - 1; + process.Leak().HeapCursor = process.Leak().HeapPtr; + + return mTeam.AsArray().Count() - 1; + } + + bool ProcessScheduler::Remove(SizeT process) + { + if (process > mTeam.AsArray().Count()) + return false; + + kcout << "ProcessScheduler::Remove(SizeT process)\r"; + + return mTeam.AsArray().Remove(process); + } + + SizeT ProcessScheduler::Run() noexcept + { + SizeT processIndex = 0; //! we store this guy to tell the scheduler how many + //! things we have scheduled. + + for (; processIndex < mTeam.AsArray().Count(); ++processIndex) + { + auto process = mTeam.AsArray()[processIndex]; + + MUST_PASS(process); //! no need for a MUST_PASS(process.Leak());, it is + //! recursive because of the nature of the class; + + //! run any process needed to be scheduled. + if (ProcessHelper::CanBeScheduled(process.Leak())) + { + auto unwrapped_process = *process.Leak(); + + unwrapped_process.PTime = 0; + + // set the current process. + mTeam.AsRef() = unwrapped_process; + + // tell helper to find a core to schedule on. + ProcessHelper::Switch(mTeam.AsRef().Leak().StackFrame, + mTeam.AsRef().Leak().ProcessId); + } + else + { + // otherwise increment the P-time. + ++mTeam.AsRef().Leak().PTime; + } + } + + return processIndex; + } + + Ref ProcessScheduler::Shared() + { + static ProcessScheduler ref; + return {ref}; + } + + /// @brief Gets current running process. + /// @return + Ref& ProcessScheduler::GetCurrent() + { + return mTeam.AsRef(); + } + + PID& ProcessHelper::GetCurrentPID() + { + kcout << "ProcessHelper::GetCurrentPID: Leaking ProcessId...\r"; + return ProcessScheduler::Shared().Leak().GetCurrent().Leak().ProcessId; + } + + bool ProcessHelper::CanBeScheduled(Ref& process) + { + if (process.Leak().Status == ProcessStatus::kFrozen || + process.Leak().Status == ProcessStatus::kDead) + return false; + + if (process.Leak().GetStatus() == ProcessStatus::kStarting) + { + if (process.Leak().PTime < static_cast(kSchedMinMicroTime)) + { + process.Leak().Status = ProcessStatus::kRunning; + process.Leak().Affinity = AffinityKind::kHartStandard; + + return true; + } + + ++process.Leak().PTime; + } + + return process.Leak().PTime > static_cast(kSchedMinMicroTime); + } + + /** + * @brief Spin scheduler class. + */ + bool ProcessHelper::StartScheduling() + { + if (ProcessHelper::CanBeScheduled( + ProcessScheduler::Shared().Leak().GetCurrent())) + { + --ProcessScheduler::Shared().Leak().GetCurrent().Leak().PTime; + return false; + } + + auto processRef = ProcessScheduler::Shared().Leak(); + + if (!processRef) + return false; // we have nothing to schedule. simply return. + + SizeT ret = processRef.Run(); + + kcout << StringBuilder::FromInt( + "ProcessHelper::StartScheduling() Iterated over {%} jobs inside team.\r", ret); + + return true; + } + + /** + * \brief Does a context switch in a CPU. + * \param the_stack the stackframe of the running app. + * \param new_pid the process's PID. +*/ + + bool ProcessHelper::Switch(HAL::StackFrame* the_stack, const PID& new_pid) + { + if (!the_stack || new_pid < 0) + return false; + + for (SizeT index = 0UL; index < SMPManager::Shared().Leak().Count(); ++index) + { + if (SMPManager::Shared().Leak()[index].Leak().Kind() == kInvalidHart) + continue; + + if (SMPManager::Shared().Leak()[index].Leak().StackFrame() == the_stack) + { + SMPManager::Shared().Leak()[index].Leak().Busy(false); + continue; + } + + if (SMPManager::Shared().Leak()[index].Leak().IsBusy()) + continue; + + if (SMPManager::Shared().Leak()[index].Leak().Kind() != + ThreadKind::kHartBoot && + SMPManager::Shared().Leak()[index].Leak().Kind() != + ThreadKind::kHartSystemReserved) + { + SMPManager::Shared().Leak()[index].Leak().Busy(true); + ProcessHelper::GetCurrentPID() = new_pid; + + return SMPManager::Shared().Leak()[index].Leak().Switch(the_stack); + } + } + + return false; + } +} // namespace NewOS diff --git a/Kernel/Source/ProcessTeam.cxx b/Kernel/Source/ProcessTeam.cxx new file mode 100644 index 00000000..959402f4 --- /dev/null +++ b/Kernel/Source/ProcessTeam.cxx @@ -0,0 +1,31 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/***********************************************************************************/ +/// @file ProcessTeam.cxx +/// @brief Process teams implementation. +/***********************************************************************************/ + +#include + +namespace NewOS +{ + /// @brief Process list array getter. + /// @return The list of process to schedule. + MutableArray>& ProcessTeam::AsArray() + { + return mProcessList; + } + + /// @brief Current process getter. + /// @return The current process header. + Ref& ProcessTeam::AsRef() + { + return mCurrentProcess; + } +} // namespace NewOS + +// last rev 05-03-24 diff --git a/Kernel/Source/Property.cxx b/Kernel/Source/Property.cxx new file mode 100644 index 00000000..ab4f7bf5 --- /dev/null +++ b/Kernel/Source/Property.cxx @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + bool Property::StringEquals(StringView& name) + { + return fName && this->fName == name; + } + + const PropertyId& Property::GetPropertyById() + { + return fAction; + } +} // namespace NewOS diff --git a/Kernel/Source/Ref.cxx b/Kernel/Source/Ref.cxx new file mode 100644 index 00000000..60f02b69 --- /dev/null +++ b/Kernel/Source/Ref.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/SMPManager.cxx b/Kernel/Source/SMPManager.cxx new file mode 100644 index 00000000..d9aac48e --- /dev/null +++ b/Kernel/Source/SMPManager.cxx @@ -0,0 +1,217 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +///! BUGS: 0 + +///! @file SMPManager.cxx +///! @brief This file handles multi processing in NewOS. +///! @brief Multi processing is needed for multi-tasking operations. + +namespace NewOS +{ + ///! A HardwareThread class takes care of it's owned hardware thread. + ///! It has a stack for it's core. + + ///! @brief constructor + HardwareThread::HardwareThread() = default; + + ///! @brief destructor + HardwareThread::~HardwareThread() = default; + + //! @brief returns the id + + const ThreadID& HardwareThread::ID() noexcept + { + return fID; + } + + //! @brief returns the kind + + const ThreadKind& HardwareThread::Kind() noexcept + { + return fKind; + } + + //! @brief is the core busy? + + bool HardwareThread::IsBusy() noexcept + { + return fBusy; + } + + /// @brief Get processor stack frame. + + HAL::StackFramePtr HardwareThread::StackFrame() noexcept + { + MUST_PASS(fStack); + return fStack; + } + + void HardwareThread::Busy(const bool busy) noexcept + { + fBusy = busy; + } + + HardwareThread::operator bool() + { + return fStack; + } + + /// @brief Wakeup the processor. + + void HardwareThread::Wake(const bool wakeup) noexcept + { + fWakeup = wakeup; + + if (!fWakeup) + rt_hang_thread(fStack); + else + rt_wakeup_thread(fStack); + } + + extern bool rt_check_stack(HAL::StackFramePtr stackPtr); + + bool HardwareThread::Switch(HAL::StackFramePtr stack) + { + if (!rt_check_stack(stack)) + return false; + + fStack = stack; + + rt_do_context_switch(fStack); + return true; + } + + ///! @brief Tells if processor is waked up. + bool HardwareThread::IsWakeup() noexcept + { + return fWakeup; + } + + //! @brief Constructor and destructor + + ///! @brief Default constructor. + SMPManager::SMPManager() = default; + + ///! @brief Default destructor. + SMPManager::~SMPManager() = default; + + /// @brief Shared singleton function + Ref SMPManager::Shared() + { + static SMPManager manager; + return {manager}; + } + + /// @brief Get Stack Frame of Core + HAL::StackFramePtr SMPManager::GetStackFrame() noexcept + { + if (fThreadList[fCurrentThread].Leak() && + ProcessHelper::GetCurrentPID() == + fThreadList[fCurrentThread].Leak().Leak().fPID) + return fThreadList[fCurrentThread].Leak().Leak().fStack; + + return nullptr; + } + + /// @brief Finds and switch to a free core. + bool SMPManager::Switch(HAL::StackFramePtr stack) + { + if (stack == nullptr) + return false; + + for (SizeT idx = 0; idx < kMaxHarts; ++idx) + { + // stack != nullptr -> if core is used, then continue. + if (!fThreadList[idx].Leak() || + !fThreadList[idx].Leak().Leak().IsWakeup() || + fThreadList[idx].Leak().Leak().IsBusy()) + continue; + + // to avoid any null deref. + if (!fThreadList[idx].Leak().Leak().fStack) + continue; + if (fThreadList[idx].Leak().Leak().fStack->Rsp == 0) + continue; + if (fThreadList[idx].Leak().Leak().fStack->Rbp == 0) + continue; + + fThreadList[idx].Leak().Leak().Busy(true); + + fThreadList[idx].Leak().Leak().fID = idx; + + /// I figured out this: + /// Allocate stack + /// Set APIC base to stack + /// Do stuff and relocate stack based on this code. + /// - Amlel + rt_copy_memory(stack, fThreadList[idx].Leak().Leak().fStack, + sizeof(HAL::StackFrame)); + + fThreadList[idx].Leak().Leak().fPID = ProcessHelper::GetCurrentPID(); + + fThreadList[idx].Leak().Leak().Busy(false); + + return true; + } + + return false; + } + + /** + * Index Hardware thread + * @param idx the index + * @return the reference to the hardware thread. + */ + Ref SMPManager::operator[](const SizeT& idx) + { + if (idx == 0) + { + if (fThreadList[idx].Leak().Leak().Kind() != kHartSystemReserved) + { + fThreadList[idx].Leak().Leak().fKind = kHartBoot; + } + } + else if (idx >= kMaxHarts) + { + HardwareThread fakeThread; + fakeThread.fKind = kInvalidHart; + + return {fakeThread}; + } + + return fThreadList[idx].Leak(); + } + + /** + * Check if thread pool isn't empty. + * @return + */ + SMPManager::operator bool() noexcept + { + return !fThreadList.Empty(); + } + + /** + * Reverse operator bool + * @return + */ + bool SMPManager::operator!() noexcept + { + return fThreadList.Empty(); + } + + /// @brief Returns the amount of core present. + /// @return the number of cores. + SizeT SMPManager::Count() noexcept + { + return fThreadList.Count(); + } +} // namespace NewOS diff --git a/Kernel/Source/Semaphore.cxx b/Kernel/Source/Semaphore.cxx new file mode 100644 index 00000000..eebdd210 --- /dev/null +++ b/Kernel/Source/Semaphore.cxx @@ -0,0 +1,53 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +namespace NewOS +{ + bool Semaphore::Unlock() noexcept + { + if (fLockingProcess) + fLockingProcess = nullptr; + + return fLockingProcess == nullptr; + } + + bool Semaphore::Lock(ProcessHeader* process) + { + if (!process || fLockingProcess) + return false; + + fLockingProcess = process; + + return true; + } + + bool Semaphore::IsLocked() const + { + return fLockingProcess; + } + + bool Semaphore::LockOrWait(ProcessHeader* process, const Int64& seconds) + { + if (process == nullptr) + return false; + + HardwareTimer timer(Seconds(seconds)); + timer.Wait(); + + return this->Lock(process); + } + + void Semaphore::Sync() noexcept + { + while (fLockingProcess) + { + } + } +} // namespace NewOS diff --git a/Kernel/Source/Storage/AHCIDeviceInterface.cxx b/Kernel/Source/Storage/AHCIDeviceInterface.cxx new file mode 100644 index 00000000..da25c05d --- /dev/null +++ b/Kernel/Source/Storage/AHCIDeviceInterface.cxx @@ -0,0 +1,35 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +using namespace NewOS; + +/// @brief Class constructor +/// @param Out Disk output +/// @param In Disk input +/// @param Cleanup Disk cleanup. +AHCIDeviceInterface::AHCIDeviceInterface(void (*Out)(MountpointInterface* outpacket), + void (*In)(MountpointInterface* inpacket), + void (*Cleanup)(void)) + : DeviceInterface(Out, In), fCleanup(Cleanup) +{ +} + +/// @brief Class desctructor +AHCIDeviceInterface::~AHCIDeviceInterface() +{ + MUST_PASS(fCleanup); + if (fCleanup) + fCleanup(); +} + +/// @brief Returns the name of the device interface. +/// @return it's name as a string. +const char* AHCIDeviceInterface::Name() const +{ + return "AHCIDeviceInterface"; +} diff --git a/Kernel/Source/Storage/ATADeviceInterface.cxx b/Kernel/Source/Storage/ATADeviceInterface.cxx new file mode 100644 index 00000000..5624dddb --- /dev/null +++ b/Kernel/Source/Storage/ATADeviceInterface.cxx @@ -0,0 +1,88 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +using namespace NewOS; + +/// @brief Class constructor +/// @param Out Disk output +/// @param In Disk input +/// @param Cleanup Disk cleanup. +ATADeviceInterface::ATADeviceInterface( + void (*Out)(MountpointInterface* outpacket), + void (*In)(MountpointInterface* inpacket), + void (*Cleanup)(void)) + : DeviceInterface(Out, In), fCleanup(Cleanup) +{ +} + +/// @brief Class desctructor +ATADeviceInterface::~ATADeviceInterface() +{ + MUST_PASS(fCleanup); + if (fCleanup) + fCleanup(); +} + +/// @brief Returns the name of the device interface. +/// @return it's name as a string. +const char* ATADeviceInterface::Name() const +{ + return "ATADeviceInterface"; +} + +/// @brief Output operator. +/// @param Data +/// @return +ATADeviceInterface& ATADeviceInterface::operator<<(MountpointInterface* Data) +{ + if (!Data) + return *this; + + for (SizeT driveCount = 0; driveCount < kDriveManagerCount; ++driveCount) + { + auto interface = Data->GetAddressOf(driveCount); + if ((interface) && rt_string_cmp((interface)->fDriveKind(), "ATA-", 5) == 0) + { + continue; + } + else if ((interface) && + rt_string_cmp((interface)->fDriveKind(), "ATA-", 5) != 0) + { + return *this; + } + } + + return (ATADeviceInterface&)DeviceInterface::operator<<( + Data); +} + +/// @brief Input operator. +/// @param Data +/// @return +ATADeviceInterface& ATADeviceInterface::operator>>(MountpointInterface* Data) +{ + if (!Data) + return *this; + + for (SizeT driveCount = 0; driveCount < kDriveManagerCount; ++driveCount) + { + auto interface = Data->GetAddressOf(driveCount); + if ((interface) && rt_string_cmp((interface)->fDriveKind(), "ATA-", 5) == 0) + { + continue; + } + else if ((interface) && + rt_string_cmp((interface)->fDriveKind(), "ATA-", 5) != 0) + { + return *this; + } + } + + return (ATADeviceInterface&)DeviceInterface::operator>>( + Data); +} diff --git a/Kernel/Source/Storage/NVMEDeviceInterface.cxx b/Kernel/Source/Storage/NVMEDeviceInterface.cxx new file mode 100644 index 00000000..aaaa3eb0 --- /dev/null +++ b/Kernel/Source/Storage/NVMEDeviceInterface.cxx @@ -0,0 +1,15 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + const char* NVMEDeviceInterface::Name() const + { + return ("NVMEDeviceInterface"); + } +} // namespace NewOS diff --git a/Kernel/Source/Storage/SCSIDeviceInterface.cxx b/Kernel/Source/Storage/SCSIDeviceInterface.cxx new file mode 100644 index 00000000..16105547 --- /dev/null +++ b/Kernel/Source/Storage/SCSIDeviceInterface.cxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +///! @brief ATAPI SCSI packet. +const scsi_packet_type kCDRomPacketTemplate = {0x43, 0, 1, 0, 0, 0, + 0, 12, 0x40, 0, 0}; diff --git a/Kernel/Source/Stream.cxx b/Kernel/Source/Stream.cxx new file mode 100644 index 00000000..134ec586 --- /dev/null +++ b/Kernel/Source/Stream.cxx @@ -0,0 +1,12 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Stream.cxx + Purpose: Stream object + + Revision History: + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/String.cxx b/Kernel/Source/String.cxx new file mode 100644 index 00000000..764ab0d9 --- /dev/null +++ b/Kernel/Source/String.cxx @@ -0,0 +1,248 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +namespace NewOS +{ + Char* StringView::Data() + { + return fData; + } + + const Char* StringView::CData() + { + return fData; + } + + Size StringView::Length() const + { + return rt_string_len(fData); + } + + bool StringView::operator==(const StringView& rhs) const + { + if (rhs.Length() != this->Length()) + return false; + + for (Size index = 0; index < this->Length(); ++index) + { + if (rhs.fData[index] != fData[index]) + return false; + } + + return true; + } + + bool StringView::operator==(const Char* rhs) const + { + if (rt_string_len(rhs) != this->Length()) + return false; + + for (Size index = 0; index < rt_string_len(rhs); ++index) + { + if (rhs[index] != fData[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const StringView& rhs) const + { + if (rhs.Length() != this->Length()) + return false; + + for (Size index = 0; index < rhs.Length(); ++index) + { + if (rhs.fData[index] == fData[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const Char* rhs) const + { + if (rt_string_len(rhs) != this->Length()) + return false; + + for (Size index = 0; index < rt_string_len(rhs); ++index) + { + if (rhs[index] == fData[index]) + return false; + } + + return true; + } + + ErrorOr StringBuilder::Construct(const Char* data) + { + if (!data || *data == 0) + return {}; + + StringView view(rt_string_len(data)); + + view += data; + + return ErrorOr(view); + } + + const char* StringBuilder::FromInt(const char* fmt, int i) + { + if (!fmt) + return ("-1"); + + char* ret = (char*)Alloca(sizeof(char) * 8 + rt_string_len(fmt)); + + if (!ret) + return ("-1"); + + Char result[8]; + + if (!rt_to_string(result, sizeof(int), i)) + { + return ("-1"); + } + + const auto fmt_len = rt_string_len(fmt); + const auto res_len = rt_string_len(result); + + for (Size idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') + { + SizeT result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) + { + ret[result_cnt] = result[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */ + } + + const char* StringBuilder::FromBool(const char* fmt, bool i) + { + if (!fmt) + return ("?"); + + const char* boolean_expr = i ? "true" : "false"; + char* ret = (char*)Alloca((sizeof(char) * i) ? 4 : 5 + rt_string_len(fmt)); + + if (!ret) + return ("?"); + + const auto fmt_len = rt_string_len(fmt); + const auto res_len = rt_string_len(boolean_expr); + + for (Size idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') + { + SizeT result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) + { + ret[result_cnt] = boolean_expr[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + bool StringBuilder::Equals(const char* lhs, const char* rhs) + { + if (rt_string_len(rhs) != rt_string_len(lhs)) + return false; + + for (Size index = 0; index < rt_string_len(rhs); ++index) + { + if (rhs[index] != lhs[index]) + return false; + } + + return true; + } + + const char* StringBuilder::Format(const char* fmt, const char* fmt2) + { + if (!fmt || !fmt2) + return ("?"); + + char* ret = + (char*)Alloca(sizeof(char) * rt_string_len(fmt2) + rt_string_len(fmt2)); + + if (!ret) + return ("?"); + + for (Size idx = 0; idx < rt_string_len(fmt); ++idx) + { + if (fmt[idx] == '%') + { + Size result_cnt = idx; + for (Size y_idx = 0; y_idx < rt_string_len(fmt2); ++y_idx) + { + ret[result_cnt] = fmt2[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + static void string_append(char* lhs, char* rhs, int cur) + { + if (lhs && rhs) + { + SizeT sz_rhs = rt_string_len(rhs); + + if (sz_rhs == 0) + return; + + rt_copy_memory(rhs, lhs + cur, sz_rhs); + } + } + + StringView& StringView::operator+=(const Char* rhs) + { + string_append(this->fData, const_cast(rhs), this->fCur); + this->fCur += rt_string_len(rhs); + + return *this; + } + + StringView& StringView::operator+=(const StringView& rhs) + { + if (rt_string_len(rhs.fData) > rt_string_len(this->fData)) + return *this; + + string_append(this->fData, const_cast(rhs.fData), this->fCur); + this->fCur += rt_string_len(const_cast(rhs.fData)); + + return *this; + } +} // namespace NewOS diff --git a/Kernel/Source/ThreadLocalStorage.cxx b/Kernel/Source/ThreadLocalStorage.cxx new file mode 100644 index 00000000..c31ae1c2 --- /dev/null +++ b/Kernel/Source/ThreadLocalStorage.cxx @@ -0,0 +1,58 @@ +/* + * ======================================================== + * + * NewOS + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#include +#include + +///! BUGS: 0 + +/***********************************************************************************/ +/// @file ThreadLocalStorage.cxx +/// @brief TLS implementation in kernel. +/***********************************************************************************/ + +using namespace NewOS; + +/** + * @brief Check for cookie inside TIB. + * @param tib the TIB to check. + * @return if the cookie is enabled. + */ + +Boolean tls_check_tib(ThreadInformationBlock* tib) +{ + if (!tib) + return false; + + Encoder encoder; + const char* tibAsBytes = encoder.AsBytes(tib); + + kcout << "New OS: Checking for a valid cookie...\r"; + + return tibAsBytes[0] == kCookieMag0 && tibAsBytes[1] == kCookieMag1 && + tibAsBytes[2] == kCookieMag2; +} + +/** + * @brief System call implementation of the TLS check. + * @param stackPtr The call frame. + * @return + */ +EXTERN_C Void tls_check_syscall_impl(NewOS::HAL::StackFramePtr stackPtr) noexcept +{ + ThreadInformationBlock* tib = (ThreadInformationBlock*)stackPtr->Gs; + + if (!tls_check_tib(tib)) + { + kcout << "New OS: Verification failed, Crashing...\r"; + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + } + + kcout << "New OS: Verification succeeded! Keeping on...\r"; +} diff --git a/Kernel/Source/Timer.cxx b/Kernel/Source/Timer.cxx new file mode 100644 index 00000000..3e705c38 --- /dev/null +++ b/Kernel/Source/Timer.cxx @@ -0,0 +1,41 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +///! BUGS: 0 +///! @file Timer.cxx + +using namespace NewOS; + +/// @brief Unimplemented as it is an interface. +Int32 HardwareTimerInterface::Wait() noexcept +{ + return kErrorUnimplemented; +} + +/// @brief HardwareTimer class, meant to be generic. + +HardwareTimer::HardwareTimer(Int64 seconds) + : fWaitFor(seconds) +{ +} +HardwareTimer::~HardwareTimer() +{ + fWaitFor = 0; +} + +Int32 HardwareTimer::Wait() noexcept +{ + if (fWaitFor < 1) + return -1; + + while (*fDigitalTimer < (*fDigitalTimer + fWaitFor)) + { + } + + return 0; +} diff --git a/Kernel/Source/URL.cxx b/Kernel/Source/URL.cxx new file mode 100644 index 00000000..8c11ca55 --- /dev/null +++ b/Kernel/Source/URL.cxx @@ -0,0 +1,96 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +/// BUGS: 0 + +namespace NewOS +{ + URL::URL(StringView& strUrl) + : fUrlView(strUrl, false) + { + } + + URL::~URL() = default; + + /// @brief internal and reserved protocols by kernel. + constexpr const char* kURLProtocols[] = { + "file", // Filesystem protocol + "mup", // Mahrouss update protocol + "param", // Mahrouss parameter protocol. + }; + + constexpr const int kUrlOutSz = 1; //! such as: :// + constexpr const int kProtosCount = 3; + constexpr const int kRangeSz = 4096; + + ErrorOr url_extract_location(const char* url) + { + if (!url || *url == 0 || rt_string_len(url, kRangeSz) > kRangeSz) + return ErrorOr{-1}; + + StringView view(rt_string_len(url)); + + SizeT i = 0; + bool scheme_found = false; + + for (; i < rt_string_len(url); ++i) + { + if (!scheme_found) + { + for (int y = 0; kProtosCount; ++y) + { + if (rt_string_in_string(view.CData(), kURLProtocols[y])) + { + i += rt_string_len(kURLProtocols[y]) + kUrlOutSz; + scheme_found = true; + + break; + } + } + } + + view.Data()[i] = url[i]; + } + + return ErrorOr(view); + } + + ErrorOr url_extract_protocol(const char* url) + { + if (!url || *url == 0 || rt_string_len(url, kRangeSz) > kRangeSz) + return ErrorOr{-1}; + + ErrorOr view{-1}; + + return view; + } + + Ref> URL::Location() noexcept + { + const char* src = fUrlView.Leak().CData(); + auto loc = url_extract_location(src); + + if (!loc) + return {}; + + return Ref>(loc); + } + + Ref> URL::Protocol() noexcept + { + const char* src = fUrlView.Leak().CData(); + auto loc = url_extract_protocol(src); + + if (!loc) + return {}; + + return Ref>(loc); + } +} // namespace NewOS diff --git a/Kernel/Source/UserHeap.cxx b/Kernel/Source/UserHeap.cxx new file mode 100644 index 00000000..9d9cd627 --- /dev/null +++ b/Kernel/Source/UserHeap.cxx @@ -0,0 +1,252 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +#define kHeapHeaderPaddingSz (16U) + +/// @file UserHeap.cxx +/// @brief User Heap Manager, Process heap allocator. +/// @note if you want to look at the kernel allocator, please look for +/// KernelHeap.cxx +/// BUGS: 0 + +namespace NewOS +{ + /** + * @brief Process Heap Header + * @note Allocated per process, it denotes the user's heap. + */ + struct UserHeapHeader final + { + UInt32 fMagic; + Int32 fFlags; + Boolean fFree; + UInt8 fPadding[kHeapHeaderPaddingSz]; + }; + + /** + * @brief User Heap Manager class, takes care of allocating the process pools. + * @note This rely on Virtual Memory! Consider adding good vmem support when + * @note porting to a new arch. + */ + class UserHeapManager final + { + public: + UserHeapManager() = delete; + ~UserHeapManager() = default; + + public: + STATIC SizeT& Count() + { + return s_NumPools; + } + STATIC Ref& Leak() + { + return s_Pmm; + } + STATIC Boolean& IsEnabled() + { + return s_PoolsAreEnabled; + } + STATIC MutableArray>& The() + { + return s_Pool; + } + + private: + STATIC Size s_NumPools; + STATIC Ref s_Pmm; + + private: + STATIC Boolean s_PoolsAreEnabled; + STATIC MutableArray> s_Pool; + }; + + //! declare fields + + SizeT UserHeapManager::s_NumPools = 0UL; + Ref UserHeapManager::s_Pmm; + Boolean UserHeapManager::s_PoolsAreEnabled = true; + MutableArray> UserHeapManager::s_Pool; + + STATIC VoidPtr ke_find_unused_heap(Int32 flags); + STATIC Void ke_free_heap_internal(VoidPtr vaddr); + STATIC VoidPtr ke_make_heap_internal(VoidPtr vaddr, Int32 flags); + STATIC Boolean ke_check_and_free_heap(const SizeT& index, VoidPtr ptr); + + /// @brief Find an unused heap header to allocate on. + /// @param flags the flags to use. + /// @return VoidPtr the heap pointer. + STATIC VoidPtr ke_find_unused_heap(Int32 flags) + { + for (SizeT index = 0; index < kUserHeapMaxSz; ++index) + { + if (UserHeapManager::The()[index] && + !UserHeapManager::The()[index].Leak().Leak().Present()) + { + UserHeapManager::Leak().Leak().TogglePresent( + UserHeapManager::The()[index].Leak().Leak(), true); + kcout << "[ke_find_unused_heap] Done, trying to make a pool now...\r"; + + return ke_make_heap_internal( + (VoidPtr)UserHeapManager::The()[index].Leak().Leak().VirtualAddress(), + flags); + } + } + + return nullptr; + } + + /// @brief Makes a new heap for the process to use. + /// @param virtualAddress the virtual address of the process. + /// @param flags the flags. + /// @return + STATIC VoidPtr ke_make_heap_internal(VoidPtr virtualAddress, Int32 flags) + { + if (virtualAddress) + { + UserHeapHeader* poolHdr = reinterpret_cast(virtualAddress); + + if (!poolHdr->fFree) + { + kcout + << "[ke_make_heap_internal] poolHdr->fFree, HeapPtr already exists\n"; + return nullptr; + } + + poolHdr->fFlags = flags; + poolHdr->fMagic = kUserHeapMag; + poolHdr->fFree = false; + + kcout << "[ke_make_heap_internal] New allocation has been done.\n"; + return reinterpret_cast( + (reinterpret_cast(virtualAddress) + sizeof(UserHeapHeader))); + } + + kcout << "[ke_make_heap_internal] Address is invalid"; + return nullptr; + } + + /// @brief Internally makrs the heap as free. + /// This is done by setting the fFree bit to true + /// @param virtualAddress + /// @return + STATIC Void ke_free_heap_internal(VoidPtr virtualAddress) + { + UserHeapHeader* poolHdr = reinterpret_cast( + reinterpret_cast(virtualAddress) - sizeof(UserHeapHeader)); + + if (poolHdr->fMagic == kUserHeapMag) + { + if (!poolHdr->fFree) + { + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + return; + } + + poolHdr->fFree = true; + poolHdr->fFlags = 0; + + kcout << "[ke_free_heap_internal] Successfully marked header as free!\r"; + } + } + + /** + * @brief Check for the ptr and frees it. + * + * @param index Where to look at. + * @param ptr The ptr to check. + * @return Boolean true if successful. + */ + STATIC Boolean ke_check_and_free_heap(const SizeT& index, VoidPtr ptr) + { + if (UserHeapManager::The()[index]) + { + // ErrorOr<>::operator Boolean + /// if (address matches) + /// -> Free heap. + if (UserHeapManager::The()[index].Leak().Leak().VirtualAddress() == + (UIntPtr)ptr) + { + UserHeapManager::Leak().Leak().FreePage( + UserHeapManager::The()[index].Leak().Leak()); + + --UserHeapManager::Count(); + + ke_free_heap_internal(ptr); + ptr = nullptr; + + return true; + } + } + + return false; + } + + /// @brief Creates a new pool pointer. + /// @param flags the flags attached to it. + /// @return a pool pointer with selected permissions. + VoidPtr rt_new_heap(Int32 flags) + { + if (!UserHeapManager::IsEnabled()) + return nullptr; + + if (UserHeapManager::Count() > kUserHeapMaxSz) + return nullptr; + + if (VoidPtr ret = ke_find_unused_heap(flags)) + return ret; + + // this wasn't set to true + auto ref_page = UserHeapManager::Leak().Leak().RequestPage( + ((flags & kUserHeapUser)), (flags & kUserHeapRw)); + + if (ref_page) + { + ///! reserve page. + UserHeapManager::The()[UserHeapManager::Count()].Leak() = ref_page; + auto& ref = UserHeapManager::Count(); + + ++ref; // increment the number of addresses we have now. + + // finally make the pool address. + return ke_make_heap_internal( + reinterpret_cast(ref_page.Leak().VirtualAddress()), flags); + } + + return nullptr; + } + + /// @brief free a pool pointer. + /// @param ptr The pool pointer to free. + /// @return status code + Int32 rt_free_heap(VoidPtr ptr) + { + if (!UserHeapManager::IsEnabled()) + return -1; + + if (ptr) + { + SizeT base = UserHeapManager::Count(); + + if (ke_check_and_free_heap(base, ptr)) + return 0; + + for (SizeT index = 0; index < kUserHeapMaxSz; ++index) + { + if (ke_check_and_free_heap(index, ptr)) + return 0; + + --base; + } + } + + return -1; + } +} // namespace NewOS diff --git a/Kernel/Source/Utils.cxx b/Kernel/Source/Utils.cxx new file mode 100644 index 00000000..f621594d --- /dev/null +++ b/Kernel/Source/Utils.cxx @@ -0,0 +1,253 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +namespace NewOS +{ + Int rt_string_cmp(const Char* src, const Char* cmp, Size size) + { + Int32 counter = 0; + + for (Size index = 0; index < size; ++index) + { + if (src[index] != cmp[index]) + ++counter; + } + + return counter; + } + + void rt_zero_memory(voidPtr pointer, Size len) + { + rt_set_memory(pointer, 0, len); + } + + Size rt_string_len(const Char* str, SizeT _len) + { + if (*str == '\0') + return 0; + + Size len{0}; + while (str[len] != '\0') + { + if (len > _len) + { + break; + } + + ++len; + } + + return len; + } + + Size rt_string_len(const Char* ptr) + { + if (!ptr) + return 0; + + SizeT cnt = 0; + + while (*ptr != (Char)0) + { + ++ptr; + ++cnt; + } + + return cnt; + } + + voidPtr rt_set_memory(voidPtr src, char value, Size len) + { + if (!src || len < 1) + return nullptr; + char* start = reinterpret_cast(src); + + while (len) + { + *start = value; + ++start; + --len; + } + + return (voidPtr)start; + } + + Int rt_move_memory(const voidPtr src, voidPtr dst, Size len) + { + if (len < 1) + return -2; + if (!src || !dst) + return -1; + + char* srcChr = reinterpret_cast(src); + char* dstChar = reinterpret_cast(dst); + Size index = 0; + + while (index < len) + { + dstChar[index] = srcChr[index]; + srcChr[index] = 0; + + ++index; + } + + return 0; + } + + Int rt_copy_memory(const voidPtr src, voidPtr dst, Size len) + { + if (len < 1) + return -2; + + char* srcChr = reinterpret_cast(src); + char* dstChar = reinterpret_cast(dst); + Size index = 0; + + while (index < len) + { + dstChar[index] = srcChr[index]; + ++index; + } + + return index; + } + + const Char* alloc_string(const Char* text) + { + if (!text) + return nullptr; + + const Char* string = new Char[rt_string_len(text)]; + if (!string) + return nullptr; + + voidPtr vText = reinterpret_cast(const_cast(text)); + voidPtr vStr = reinterpret_cast(const_cast(string)); + rt_copy_memory(vText, vStr, rt_string_len(text)); + + return string; + } + + Int rt_to_uppercase(Int character) + { + if (character >= 'a' && character <= 'z') + return character - 0x20; + + return character; + } + + Int rt_to_lower(Int character) + { + if (character >= 'A' && character <= 'Z') + return character + 0x20; + + return character; + } + + bool rt_to_string(Char* str, Int limit, Int base) + { + if (limit == 0) + return false; + + Int copy_limit = limit; + Int cnt = 0; + Int ret = base; + + while (limit != 1) + { + ret = ret % 10; + str[cnt] = ret; + + ++cnt; + --limit; + --ret; + } + + str[copy_limit] = '\0'; + return true; + } + + Boolean is_space(Char chr) + { + return chr == ' '; + } + + Boolean is_newln(Char chr) + { + return chr == '\n'; + } + + voidPtr rt_string_in_string(const char* in, const char* needle) + { + for (size_t i = 0; i < rt_string_len(in); ++i) + { + if (rt_string_cmp(in + i, needle, rt_string_len(needle)) == 0) + return reinterpret_cast(const_cast(in + i)); + } + + return nullptr; + } + + // @brief Checks for a string start at the character. + + char* rt_string_has_char(char* str, const char chr) + { + while (*str != chr) + { + ++str; + + if (*str == 0) + return nullptr; + } + + return str; + } +} // namespace NewOS + +//////////////////////////////////////////////////////////////////////////////////////// +/// Exported C functions +//////////////////////////////////////////////////////////////////////////////////////// + +/// @brief memset in C++ +EXTERN_C void memset(void* dst, char src, size_t len) +{ + NewOS::rt_set_memory(dst, src, len); +} + +/// @brief memcpy in C++ +EXTERN_C void memcpy(void* dst, void* src, size_t len) +{ + NewOS::rt_copy_memory(src, dst, len); +} + +/// @brief memmove in C++ +EXTERN_C void* memmove(void* dst, void* src, size_t len) +{ + NewOS::rt_copy_memory(src, dst, len); + return dst; +} + +/// @brief strlen definition in C++. +EXTERN_C size_t strlen(const char* whatToCheck) +{ + return NewOS::rt_string_len(whatToCheck); +} + +/// @brief memcmp in C++ +EXTERN_C NewOS::SizeT memcmp(void* dst, void* src, size_t len) +{ + return NewOS::rt_string_cmp((char*)src, (char*)dst, len); +} + +/// @brief strcmp in C++ +EXTERN_C NewOS::SizeT strcmp(char* dst, char* src, size_t len) +{ + return NewOS::rt_string_cmp(src, dst, len); +} diff --git a/Kernel/Source/Variant.cxx b/Kernel/Source/Variant.cxx new file mode 100644 index 00000000..afe66624 --- /dev/null +++ b/Kernel/Source/Variant.cxx @@ -0,0 +1,29 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + const Char* Variant::ToString() + { + if (fPtr == nullptr) + { + return ("Memory:{Nullptr}"); + } + + switch (fKind) + { + case VariantKind::kString: + return ("Class:{String}"); + case VariantKind::kPointer: + return ("Memory:{Pointer}"); + default: + return ("Memory:{Undefined}"); + } + } + +} // namespace NewOS diff --git a/Kernel/Source/compile_flags.txt b/Kernel/Source/compile_flags.txt new file mode 100644 index 00000000..1f54e6fb --- /dev/null +++ b/Kernel/Source/compile_flags.txt @@ -0,0 +1,7 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I../ +-I$(HOME)/ +-D__FSKIT_NEWFS__ +-D__NEWOS_AMD64__ diff --git a/Kernel/StorageKit/AHCI.hpp b/Kernel/StorageKit/AHCI.hpp new file mode 100644 index 00000000..5f8908cb --- /dev/null +++ b/Kernel/StorageKit/AHCI.hpp @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace NewOS +{ + class AHCIDeviceInterface : public DeviceInterface + { + public: + explicit AHCIDeviceInterface(void (*Out)(MountpointInterface* outpacket), + void (*In)(MountpointInterface* inpacket), + void (*Cleanup)(void)); + + virtual ~AHCIDeviceInterface(); + + public: + AHCIDeviceInterface& operator=(const AHCIDeviceInterface&) = default; + AHCIDeviceInterface(const AHCIDeviceInterface&) = default; + + const char* Name() const override; + + private: + void (*fCleanup)(void); + }; +} // namespace NewOS \ No newline at end of file diff --git a/Kernel/StorageKit/ATA.hpp b/Kernel/StorageKit/ATA.hpp new file mode 100644 index 00000000..2cffb092 --- /dev/null +++ b/Kernel/StorageKit/ATA.hpp @@ -0,0 +1,39 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +namespace NewOS +{ + /// @brief ATA device interface type. + class ATADeviceInterface : public DeviceInterface + { + public: + explicit ATADeviceInterface(void (*Out)(MountpointInterface* outpacket), + void (*In)(MountpointInterface* inpacket), + void (*Cleanup)(void)); + + virtual ~ATADeviceInterface(); + + public: + ATADeviceInterface& operator<<(MountpointInterface* Data) override; + ATADeviceInterface& operator>>(MountpointInterface* Data) override; + + public: + ATADeviceInterface& operator=(const ATADeviceInterface&) = default; + ATADeviceInterface(const ATADeviceInterface&) = default; + + const char* Name() const override; + + private: + void (*fCleanup)(void); + }; +} // namespace NewOS \ No newline at end of file diff --git a/Kernel/StorageKit/NVME.hpp b/Kernel/StorageKit/NVME.hpp new file mode 100644 index 00000000..4f1c6362 --- /dev/null +++ b/Kernel/StorageKit/NVME.hpp @@ -0,0 +1,43 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace NewOS +{ + class NVMEDeviceInterface : public DeviceInterface + { + public: + explicit NVMEDeviceInterface(void (*Out)(MountpointInterface* outpacket), + void (*In)(MountpointInterface* inpacket), + void (*Cleanup)(void)) + : DeviceInterface(Out, In), fCleanup(Cleanup) + { + } + + virtual ~NVMEDeviceInterface() + { + if (fCleanup) + fCleanup(); + } + + public: + NVMEDeviceInterface& operator=(const NVMEDeviceInterface&) = default; + NVMEDeviceInterface(const NVMEDeviceInterface&) = default; + + const char* Name() const override; + + public: + OwnPtr operator()(UInt32 dmaLow, UInt32 dmaHigh, SizeT sz); + + private: + void (*fCleanup)(void); + }; +} // namespace NewOS diff --git a/Kernel/StorageKit/PRDT.hpp b/Kernel/StorageKit/PRDT.hpp new file mode 100644 index 00000000..ae6166ce --- /dev/null +++ b/Kernel/StorageKit/PRDT.hpp @@ -0,0 +1,36 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +#define kPrdtTransferSize (sizeof(NewOS::UShort)) + +namespace NewOS +{ + /// @brief Tranfer information about PRD. + enum kPRDTTransfer + { + kPRDTTransferInProgress, + kPRDTTransferIsDone, + kPRDTTransferCount, + }; + + /// @brief Physical Region Descriptor Table. + struct PRDT + { + UInt32 fPhysAddress; + UInt32 fSectorCount; + UInt8 fEndBit; + }; + + void construct_prdt(Ref& prd); + + EXTERN_C Int32 kPRDTTransferStatus; +} // namespace NewOS diff --git a/Kernel/StorageKit/SCSI.hxx b/Kernel/StorageKit/SCSI.hxx new file mode 100644 index 00000000..4a11c6e5 --- /dev/null +++ b/Kernel/StorageKit/SCSI.hxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +extern const scsi_packet_type kCDRomPacketTemplate; diff --git a/Kernel/StorageKit/Storage.hpp b/Kernel/StorageKit/Storage.hpp new file mode 100644 index 00000000..6093a5f0 --- /dev/null +++ b/Kernel/StorageKit/Storage.hpp @@ -0,0 +1,16 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +#define kDriveSectorSizeHDD (512) +#define kDriveSectorSizeSSD (4096) +#define kDriveSectorSizeCDROM (2048) diff --git a/Kernel/compile_flags.txt b/Kernel/compile_flags.txt new file mode 100644 index 00000000..de13f8f6 --- /dev/null +++ b/Kernel/compile_flags.txt @@ -0,0 +1,6 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I./ +-I$(HOME)/ +-D__NEWOS_AMD64__ diff --git a/Kernel/makefile b/Kernel/makefile new file mode 100644 index 00000000..61eb9dfe --- /dev/null +++ b/Kernel/makefile @@ -0,0 +1,87 @@ +################################################## +# (C) SoftwareLabs, all rights reserved. +# This is the microkernel makefile. +################################################## + +CC = x86_64-w64-mingw32-gcc +LD = x86_64-w64-mingw32-ld +CCFLAGS = -c -fPIC -ffreestanding -D__NEWOS_AMD64__ -mno-red-zone -fno-rtti -fno-exceptions \ + -std=c++20 -D__FSKIT_NEWFS__ -D__KERNEL__ -D__HAVE_MAHROUSS_APIS__ -D__MAHROUSS__ -I../ -I./ \ + -DBLEND2D_NO_STDCXX -DBLEND2D_NO_TLS -DBLEND2D_EMBED + +ASM = nasm + +ifneq ($(ATA_PIO_SUPPORT), ) +DISKDRIVER = -D__ATA_PIO__ +endif + +ifneq ($(ATA_DMA_SUPPORT), ) +DISKDRIVER = -D__ATA_DMA__ +endif + +ifneq ($(AHCI_SUPPORT), ) +DISKDRIVER = -D__AHCI__ +endif + +ifneq ($(DEBUG_SUPPORT), ) +DEBUG = -D__DEBUG__ +endif + +COPY = cp + +# Add assembler, linker, and object files variables. +ASMFLAGS = -f win64 + +# NewOS subsystem is 17 and entrypoint is __ImageStart +LDFLAGS = -e __ImageStart --subsystem=17 +LDOBJ = Objects/*.obj + +# This file is the kernel, responsible of task management and memory. +KERNEL = NewKernel.exe + +# The kernel entrypoint +SCRIPT = --script=Linker/Platforms/PC.lds + +.PHONY: error +error: + @echo "=== ERROR ===" + @echo "=> Use a specific target." + +MOVEALL=./MoveAll.sh +WINDRES=x86_64-w64-mingw32-windres + +.PHONY: newos-amd64-epm +newos-amd64-epm: clean + $(WINDRES) KernelRsrc.rsrc -O coff -o KernelRsrc.obj + $(CC) $(CCFLAGS) $(DISKDRIVER) $(DEBUG) $(wildcard Source/*.cxx) \ + $(wildcard Source/FS/*.cxx) $(wildcard HALKit/AMD64/Storage/*.cxx) \ + $(wildcard HALKit/AMD64/PCI/*.cxx) $(wildcard Source/Network/*.cxx) $(wildcard Source/Storage/*.cxx) \ + $(wildcard HALKit/AMD64/*.cxx) $(wildcard HALKit/AMD64/*.cpp) \ + $(wildcard HALKit/AMD64/*.s) + + $(ASM) $(ASMFLAGS) HALKit/AMD64/HalInterruptAPI.asm + $(ASM) $(ASMFLAGS) HALKit/AMD64/HalSMPCoreManager.asm + $(ASM) $(ASMFLAGS) HALKit/AMD64/HalNewBoot.asm + $(ASM) $(ASMFLAGS) HALKit/AMD64/HalInstallTIB.asm + $(MOVEALL) + +OBJCOPY=x86_64-w64-mingw32-objcopy + +.PHONY: link-amd64-epm +link-amd64-epm: + $(LD) $(LDFLAGS) $(LDOBJ) -o $(KERNEL) + +.PHONY: all +all: newos-amd64-epm link-amd64-epm + @echo "NewKernel => OK." + +.PHONY: help +help: + @echo "=== HELP ===" + @echo "all: Build kernel and link it." + @echo "link-amd64-epm: Link kernel. (EPM AMD64)" + @echo "newos-amd64-epm: Build kernel. (EPM AMD64)" + +.PHONY: clean +clean: + rm -f $(LDOBJ) $(KERNEL) -- cgit v1.2.3