From f824df9aad43c2597d66a72e93c2b80190b5fa38 Mon Sep 17 00:00:00 2001 From: EnderIce2 Date: Sun, 2 Mar 2025 21:34:16 +0000 Subject: [PATCH] feat(kernel/driver): implement built-in driver support Signed-off-by: EnderIce2 --- Kernel/arch/aarch64/linker.ld | 8 ++ Kernel/arch/amd64/linker.ld | 8 ++ Kernel/arch/arm/linker.ld | 8 ++ Kernel/arch/i386/linker.ld | 8 ++ Kernel/core/driver/api.cpp | 1 + Kernel/core/driver/driver.cpp | 48 +++++++++-- Kernel/include/driver.hpp | 136 +++++++++++++++++++++++++----- Kernel/include/interface/aip.h | 4 +- Kernel/include/interface/device.h | 3 + Kernel/include/interface/fs.h | 2 + Kernel/include/interface/input.h | 2 + Kernel/include/interface/pci.h | 2 + 12 files changed, 200 insertions(+), 30 deletions(-) diff --git a/Kernel/arch/aarch64/linker.ld b/Kernel/arch/aarch64/linker.ld index ab159b65..9565b00b 100644 --- a/Kernel/arch/aarch64/linker.ld +++ b/Kernel/arch/aarch64/linker.ld @@ -77,6 +77,14 @@ SECTIONS *(.rodata .rodata.*) } :rodata + .builtin_drivers ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.builtin_drivers) - KERNEL_VMA) + { + __kernel_builtin_drivers_start = .; + KEEP(*(SORT(.builtin_drivers.*))) + KEEP(*(.builtin_drivers)) + __kernel_builtin_drivers_end = .; + } :rodata + .init_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.init_array) - KERNEL_VMA) { PROVIDE_HIDDEN(__init_array_start = .); diff --git a/Kernel/arch/amd64/linker.ld b/Kernel/arch/amd64/linker.ld index 09070393..8fa2e21e 100644 --- a/Kernel/arch/amd64/linker.ld +++ b/Kernel/arch/amd64/linker.ld @@ -80,6 +80,14 @@ SECTIONS *(.rodata .rodata.*) } :rodata + .builtin_drivers ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.builtin_drivers) - KERNEL_VMA) + { + __kernel_builtin_drivers_start = .; + KEEP(*(SORT(.builtin_drivers.*))) + KEEP(*(.builtin_drivers)) + __kernel_builtin_drivers_end = .; + } :rodata + .init_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.init_array) - KERNEL_VMA) { PROVIDE_HIDDEN(__init_array_start = .); diff --git a/Kernel/arch/arm/linker.ld b/Kernel/arch/arm/linker.ld index da726905..8b8a083e 100644 --- a/Kernel/arch/arm/linker.ld +++ b/Kernel/arch/arm/linker.ld @@ -58,6 +58,14 @@ SECTIONS } . = ALIGN(4096); + .builtin_drivers : + { + __kernel_builtin_drivers_start = .; + KEEP(*(SORT(.builtin_drivers.*))) + KEEP(*(.builtin_drivers)) + __kernel_builtin_drivers_end = .; + } + .init_array : { PROVIDE_HIDDEN(__init_array_start = .); diff --git a/Kernel/arch/i386/linker.ld b/Kernel/arch/i386/linker.ld index a87da925..5ae6632d 100644 --- a/Kernel/arch/i386/linker.ld +++ b/Kernel/arch/i386/linker.ld @@ -80,6 +80,14 @@ SECTIONS *(.rodata .rodata.*) } :rodata + .builtin_drivers ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.builtin_drivers) - KERNEL_VMA) + { + __kernel_builtin_drivers_start = .; + KEEP(*(SORT(.builtin_drivers.*))) + KEEP(*(.builtin_drivers)) + __kernel_builtin_drivers_end = .; + } :rodata + .init_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.init_array) - KERNEL_VMA) { PROVIDE_HIDDEN(__init_array_start = .); diff --git a/Kernel/core/driver/api.cpp b/Kernel/core/driver/api.cpp index 44cd0f6d..834ae1de 100644 --- a/Kernel/core/driver/api.cpp +++ b/Kernel/core/driver/api.cpp @@ -15,6 +15,7 @@ along with Fennix Kernel. If not, see . */ +#define NO_API_IN_HEADER 1 #include #include #include diff --git a/Kernel/core/driver/driver.cpp b/Kernel/core/driver/driver.cpp index 80e9e9e2..5607f7d9 100644 --- a/Kernel/core/driver/driver.cpp +++ b/Kernel/core/driver/driver.cpp @@ -37,6 +37,36 @@ namespace Driver void Manager::PreloadDrivers() { debug("Initializing driver manager"); + + auto &bs = __kernel_builtin_drivers_start; + auto &be = __kernel_builtin_drivers_end; + for (const BuiltInDriver *drv = bs; drv < be; ++drv) + { + debug("Loading built-in driver %s", drv->Name); + + DriverObject drvObj = {}; + strncpy(drvObj.Name, drv->Name, sizeof(drvObj.Name)); + strncpy(drvObj.Description, drv->Description, sizeof(drvObj.Description)); + strncpy(drvObj.Author, drv->Author, sizeof(drvObj.Author)); + drvObj.Version.Major = drv->Version.Major; + drvObj.Version.Minor = drv->Version.Minor; + drvObj.Version.Patch = drv->Version.Patch; + drvObj.Entry = drv->Entry; + drvObj.Final = drv->Final; + drvObj.Panic = drv->Panic; + drvObj.Probe = drv->Probe; + + drvObj.IsBuiltIn = true; + drvObj.BaseAddress = 0; + drvObj.EntryPoint = drv->EntryPoint; + drvObj.vma = new Memory::VirtualMemoryArea(thisProcess->PageTable); + drvObj.Path = ""; + drvObj.InterruptHandlers = new std::unordered_map(); + drvObj.DeviceOperations = new std::unordered_map(); + drvObj.ID = DriverIDCounter; + Drivers.insert({DriverIDCounter++, drvObj}); + } + const char *DriverDirectory = Config.DriverDirectory; FileNode *drvDirNode = fs->GetByPath(DriverDirectory, nullptr); if (!drvDirNode) @@ -58,13 +88,15 @@ namespace Driver continue; } - DriverObject drvObj = {.BaseAddress = 0, - .EntryPoint = 0, - .vma = new Memory::VirtualMemoryArea(thisProcess->PageTable), - .Path = drvNode->Path, - .InterruptHandlers = new std::unordered_map(), - .DeviceOperations = new std::unordered_map(), - .ID = DriverIDCounter}; + DriverObject drvObj = {}; + drvObj.IsBuiltIn = false; + drvObj.BaseAddress = 0; + drvObj.EntryPoint = 0; + drvObj.vma = new Memory::VirtualMemoryArea(thisProcess->PageTable); + drvObj.Path = drvNode->Path; + drvObj.InterruptHandlers = new std::unordered_map(); + drvObj.DeviceOperations = new std::unordered_map(); + drvObj.ID = DriverIDCounter; int err = this->LoadDriverFile(drvObj, drvNode); debug("err = %d (%s)", err, strerror(err)); @@ -111,7 +143,7 @@ namespace Driver continue; } - KPrint("Loading driver %s", Drv.Name); + KPrint("Loading driver %s (%d)", Drv.Name, Drv.ID); debug("Calling Probe()=%#lx on driver %s", Drv.Probe, Drv.Path.c_str()); diff --git a/Kernel/include/driver.hpp b/Kernel/include/driver.hpp index 6bb77f8a..733866cd 100644 --- a/Kernel/include/driver.hpp +++ b/Kernel/include/driver.hpp @@ -38,6 +38,51 @@ #include #include +struct BuiltInDriver +{ + char Name[32] = {'\0'}; + char Description[64] = {'\0'}; + char Author[32] = {'\0'}; + struct + { + int Major, Minor, Patch; + } Version = {0, 0, 0}; + char License[32] = {'\0'}; + bool Initialized = false; + int ErrorCode = 0; + + int (*Entry)() = nullptr; + int (*Final)() = nullptr; + int (*Panic)() = nullptr; + int (*Probe)() = nullptr; + uintptr_t EntryPoint = 0; +}; + +extern const BuiltInDriver __kernel_builtin_drivers_start[]; +extern const BuiltInDriver __kernel_builtin_drivers_end[]; + +#define REGISTER_BUILTIN_DRIVER(driverName, desc, auth, maj, min, patch, \ + entryFunc, finalFunc, panicFunc, initFunc) \ + int __builtin_driver_start_##driverName(dev_t id) \ + { \ + DriverID = id; \ + return 0; \ + } \ + static const BuiltInDriver __builtin_driver_##driverName \ + __attribute__((section(".builtin_drivers"), used)) = { \ + #driverName, \ + desc, \ + auth, \ + {maj, min, patch}, \ + "", \ + false, \ + 0, \ + entryFunc, \ + finalFunc, \ + panicFunc, \ + initFunc, \ + (uintptr_t)__builtin_driver_start_##driverName} + namespace Driver { char GetScanCode(uint8_t ScanCode, bool Upper); @@ -50,10 +95,10 @@ namespace Driver RingBuffer *InputReports; }; - struct DriverObject + struct DriverObject : BuiltInDriver { + bool IsBuiltIn = false; uintptr_t BaseAddress = 0; - uintptr_t EntryPoint = 0; Memory::VirtualMemoryArea *vma; /* Path has the same pointer as in the Node */ @@ -61,22 +106,6 @@ namespace Driver std::unordered_map *InterruptHandlers; std::unordered_map *DeviceOperations; dev_t ID = 0; - - char Name[32] = {'\0'}; - char Description[64] = {'\0'}; - char Author[32] = {'\0'}; - struct - { - int Major, Minor, Patch; - } Version = {0, 0, 0}; - char License[32] = {'\0'}; - bool Initialized = false; - int ErrorCode = 0; - - int (*Entry)() = nullptr; - int (*Final)() = nullptr; - int (*Panic)() = nullptr; - int (*Probe)() = nullptr; }; class Manager @@ -93,7 +122,6 @@ namespace Driver FileNode *devNode = nullptr; FileNode *devInputNode = nullptr; - int LoadDriverFile(DriverObject &Drv, FileNode *File); void ReloadDriver(dev_t driverID); @@ -153,7 +181,6 @@ namespace Driver dev_t RegisterDevice(dev_t DriverID, DeviceType Type, const InodeOperations *Operations); int ReportInputEvent(dev_t DriverID, InputReport *Report); - int UnregisterDevice(dev_t DriverID, dev_t Device); void *AllocateMemory(dev_t DriverID, size_t Pages); @@ -168,4 +195,73 @@ namespace Driver void *GetSymbolByName(const char *Name, int Version); +#ifndef NO_API_IN_HEADER +namespace v0 +{ + typedef int CriticalState; + + void KernelPrint(dev_t DriverID, const char *Format, va_list args); + void KernelLog(dev_t DriverID, const char *Format, va_list args); + + CriticalState EnterCriticalSection(dev_t DriverID); + void LeaveCriticalSection(dev_t DriverID, CriticalState PreviousState); + + int RegisterInterruptHandler(dev_t DriverID, uint8_t IRQ, void *Handler); + int OverrideInterruptHandler(dev_t DriverID, uint8_t IRQ, void *Handler); + int UnregisterInterruptHandler(dev_t DriverID, uint8_t IRQ, void *Handler); + int UnregisterAllInterruptHandlers(dev_t DriverID, void *Handler); + + dev_t RegisterFileSystem(dev_t DriverID, FileSystemInfo *Info, struct Inode *Root); + int UnregisterFileSystem(dev_t DriverID, dev_t Device); + + pid_t CreateKernelProcess(dev_t DriverID, const char *Name); + pid_t CreateKernelThread(dev_t DriverID, pid_t pId, const char *Name, void *EntryPoint, void *Argument); + pid_t GetCurrentProcess(dev_t DriverID); + int KillProcess(dev_t DriverID, pid_t pId, int ExitCode); + int KillThread(dev_t DriverID, pid_t tId, pid_t pId, int ExitCode); + void Yield(dev_t DriverID); + void Sleep(dev_t DriverID, uint64_t Milliseconds); + + void PIC_EOI(dev_t DriverID, uint8_t IRQ); + void IRQ_MASK(dev_t DriverID, uint8_t IRQ); + void IRQ_UNMASK(dev_t DriverID, uint8_t IRQ); + + void PS2Wait(dev_t DriverID, const bool Output); + void PS2WriteCommand(dev_t DriverID, uint8_t Command); + void PS2WriteData(dev_t DriverID, uint8_t Data); + uint8_t PS2ReadData(dev_t DriverID); + uint8_t PS2ReadStatus(dev_t DriverID); + uint8_t PS2ReadAfterACK(dev_t DriverID); + void PS2ClearOutputBuffer(dev_t DriverID); + int PS2ACKTimeout(dev_t DriverID); + + void *AllocateMemory(dev_t DriverID, size_t Pages); + void FreeMemory(dev_t DriverID, void *Pointer, size_t Pages); + void *MemoryCopy(dev_t DriverID, void *Destination, const void *Source, size_t Length); + void *MemorySet(dev_t DriverID, void *Destination, int Value, size_t Length); + void *MemoryMove(dev_t DriverID, void *Destination, const void *Source, size_t Length); + size_t StringLength(dev_t DriverID, const char String[]); + char *_strstr(dev_t DriverID, const char *Haystack, const char *Needle); + + void MapPages(dev_t MajorID, void *PhysicalAddress, void *VirtualAddress, size_t Pages, uint32_t Flags); + void UnmapPages(dev_t MajorID, void *VirtualAddress, size_t Pages); + void AppendMapFlag(dev_t MajorID, void *Address, PageMapFlags Flag); + void RemoveMapFlag(dev_t MajorID, void *Address, PageMapFlags Flag); + + void *Znwm(size_t Size); + void ZdlPvm(void *Pointer, size_t Size); + + __PCIArray *GetPCIDevices(dev_t DriverID, uint16_t _Vendors[], uint16_t _Devices[]); + void InitializePCI(dev_t DriverID, void *_Header); + uint32_t GetBAR(dev_t DriverID, uint8_t i, void *_Header); + uint8_t iLine(dev_t DriverID, PCI::PCIDevice *Device); + uint8_t iPin(dev_t DriverID, PCI::PCIDevice *Device); + + dev_t CreateDeviceFile(dev_t DriverID, const char *name, mode_t mode, const InodeOperations *Operations); + dev_t RegisterDevice(dev_t DriverID, DeviceType Type, const InodeOperations *Operations); + int UnregisterDevice(dev_t DriverID, dev_t Device); + int ReportInputEvent(dev_t DriverID, InputReport *Report); +} +#endif // !NO_API_IN_HEADER + #endif // !__FENNIX_KERNEL_DRIVER_H__ diff --git a/Kernel/include/interface/aip.h b/Kernel/include/interface/aip.h index 6189291b..94813c1a 100644 --- a/Kernel/include/interface/aip.h +++ b/Kernel/include/interface/aip.h @@ -103,6 +103,7 @@ typedef union uint8_t Raw; } PS2_OUTPUT_PORT; +#ifndef __kernel__ void PIC_EOI(uint8_t IRQ); void IRQ_MASK(uint8_t IRQ); void IRQ_UNMASK(uint8_t IRQ); @@ -114,11 +115,11 @@ uint8_t PS2ReadStatus(); uint8_t PS2ReadAfterACK(); void PS2ClearOutputBuffer(); int PS2ACKTimeout(); +#endif // !__kernel__ #define WaitOutput PS2Wait(DriverID, true) #define WaitInput PS2Wait(DriverID, false) - #define PS2_KBD_CMD_SET_LEDS 0xED #define PS2_KBD_CMD_ECHO 0xEE #define PS2_KBD_CMD_SCAN_CODE_SET 0xF0 @@ -189,7 +190,6 @@ typedef union uint8_t Raw; } PS2_KBD_TYPEMATIC; - #define PS2_MOUSE_CMD_SET_SCALING_1_1 0xE6 #define PS2_MOUSE_CMD_SET_SCALING_2_1 0xE7 #define PS2_MOUSE_CMD_SET_RESOLUTION 0xE8 diff --git a/Kernel/include/interface/device.h b/Kernel/include/interface/device.h index 925a76e2..d89aed41 100644 --- a/Kernel/include/interface/device.h +++ b/Kernel/include/interface/device.h @@ -69,7 +69,10 @@ typedef enum BLOCK_TYPE_FLOPPY = DEVICE_TYPE_BLOCK + 128, } DeviceType; +#ifndef __kernel__ +EXTERNC dev_t CreateDeviceFile(const char *name, mode_t mode, const struct InodeOperations *Operations); EXTERNC dev_t RegisterDevice(DeviceType Type, const struct InodeOperations *Operations); EXTERNC int UnregisterDevice(dev_t Device); +#endif // !__kernel__ #endif // !__FENNIX_API_DEVICE_H__ diff --git a/Kernel/include/interface/fs.h b/Kernel/include/interface/fs.h index 23e19f14..0a3f1905 100644 --- a/Kernel/include/interface/fs.h +++ b/Kernel/include/interface/fs.h @@ -377,7 +377,9 @@ struct FileSystemInfo void *PrivateData; } __attribute__((packed)); +#ifndef __kernel__ dev_t RegisterFileSystem(struct FileSystemInfo *Info, struct Inode *Root); int UnregisterFileSystem(dev_t Device); +#endif // !__kernel__ #endif // !__FENNIX_API_FILESYSTEM_H__ diff --git a/Kernel/include/interface/input.h b/Kernel/include/interface/input.h index ff40a071..0618de0c 100644 --- a/Kernel/include/interface/input.h +++ b/Kernel/include/interface/input.h @@ -239,6 +239,8 @@ typedef struct }; } InputReport; +#ifndef __kernel__ EXTERNC int ReportInputEvent(InputReport *Report); +#endif // !__kernel__ #endif // !__FENNIX_API_INPUT_H__ diff --git a/Kernel/include/interface/pci.h b/Kernel/include/interface/pci.h index bfeedea0..bd5537de 100644 --- a/Kernel/include/interface/pci.h +++ b/Kernel/include/interface/pci.h @@ -171,11 +171,13 @@ extern "C" { #endif +#ifndef __kernel__ PCIArray *GetPCIDevices(uint16_t Vendors[], uint16_t Devices[]); void InitializePCI(PCIDevice *Device); uint32_t GetBAR(uint8_t Index, PCIDevice *Device); uint8_t iLine(PCIDevice *Device); uint8_t iPin(PCIDevice *Device); +#endif // !__kernel__ #ifdef __cplusplus }