mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-17 02:01:44 +00:00
Restructured and rewritten entire codebase
This commit is contained in:
27
core/module/api.hpp
Normal file
27
core/module/api.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_MODULE_API_H__
|
||||
#define __FENNIX_KERNEL_MODULE_API_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include "../../mapi.hpp"
|
||||
|
||||
extern KernelAPI KernelAPITemplate;
|
||||
|
||||
#endif // !__FENNIX_KERNEL_MODULE_API_H__
|
347
core/module/module.cpp
Normal file
347
core/module/module.cpp
Normal file
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <module.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../modules/mod.hpp"
|
||||
#include "../../kernel.h"
|
||||
#include "../../mapi.hpp"
|
||||
#include "../../Fex.hpp"
|
||||
#include "api.hpp"
|
||||
|
||||
using vfs::RefNode;
|
||||
|
||||
namespace Module
|
||||
{
|
||||
void Module::Panic()
|
||||
{
|
||||
debug("%ld modules loaded, [modUIDs: %ld]", Modules.size(), modUIDs - 1);
|
||||
|
||||
foreach (auto Drv in Modules)
|
||||
{
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
ModuleManager->IOCB(Drv.modUniqueID, &callback);
|
||||
|
||||
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||
{
|
||||
if (!Drv.InterruptHook[j])
|
||||
continue;
|
||||
|
||||
Drv.InterruptHook[j]->Disable();
|
||||
debug("Interrupt hook %#lx disabled", Drv.InterruptHook[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Module::UnloadAllModules()
|
||||
{
|
||||
debug("%ld modules loaded, [modUIDs: %ld]", Modules.size(), modUIDs - 1);
|
||||
|
||||
foreach (auto Drv in Modules)
|
||||
{
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
debug("Stopping & unloading module %ld [%#lx]", Drv.modUniqueID, Drv.Address);
|
||||
ModuleManager->IOCB(Drv.modUniqueID, &callback);
|
||||
|
||||
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||
{
|
||||
if (!Drv.InterruptHook[j])
|
||||
continue;
|
||||
|
||||
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
|
||||
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
|
||||
}
|
||||
|
||||
if (Drv.vma)
|
||||
delete Drv.vma, Drv.vma = nullptr;
|
||||
}
|
||||
Modules.clear();
|
||||
}
|
||||
|
||||
bool Module::UnloadModule(unsigned long id)
|
||||
{
|
||||
debug("Searching for module %ld", id);
|
||||
|
||||
forItr(Drv, Modules)
|
||||
{
|
||||
if (Drv->modUniqueID != id)
|
||||
continue;
|
||||
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
debug("Stopping & unloading module %ld [%#lx]", Drv->modUniqueID, Drv->Address);
|
||||
this->IOCB(Drv->modUniqueID, &callback);
|
||||
|
||||
for (size_t j = 0; j < sizeof(Drv->InterruptHook) / sizeof(Drv->InterruptHook[0]); j++)
|
||||
{
|
||||
if (!Drv->InterruptHook[j])
|
||||
continue;
|
||||
|
||||
debug("Interrupt hook %#lx", Drv->InterruptHook[j]);
|
||||
delete Drv->InterruptHook[j], Drv->InterruptHook[j] = nullptr;
|
||||
}
|
||||
|
||||
if (Drv->vma)
|
||||
delete Drv->vma, Drv->vma = nullptr;
|
||||
|
||||
Modules.erase(Drv);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Module::IOCB(unsigned long id, void *KCB)
|
||||
{
|
||||
foreach (auto Drv in Modules)
|
||||
{
|
||||
if (Drv.modUniqueID != id)
|
||||
continue;
|
||||
|
||||
FexExtended *fexE = (FexExtended *)Drv.ExtendedHeaderAddress;
|
||||
return ((int (*)(void *))((uintptr_t)fexE->Module.Callback + (uintptr_t)Drv.Address))(KCB);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ModuleCode Module::CallModuleEntryPoint(void *fex, bool BuiltIn)
|
||||
{
|
||||
ModuleCode ret{};
|
||||
KernelAPI modKAPI = KernelAPITemplate;
|
||||
|
||||
modKAPI.Info.modUniqueID = modUIDs++;
|
||||
modKAPI.Info.KernelDebug = DebuggerIsAttached;
|
||||
|
||||
debug("Calling module entry point ( %#lx %ld )", (unsigned long)fex, modKAPI.Info.modUniqueID);
|
||||
|
||||
if (!BuiltIn)
|
||||
{
|
||||
modKAPI.Info.Offset = (unsigned long)fex;
|
||||
|
||||
debug("MODULE: %s HAS MODULE ID %ld",
|
||||
((FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS))->Module.Name,
|
||||
modKAPI.Info.modUniqueID);
|
||||
ret = ((ModuleCode(*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)&modKAPI));
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("MODULE: BUILTIN HAS MODULE ID %ld", modKAPI.Info.modUniqueID);
|
||||
ret = ((ModuleCode(*)(KernelAPI *))((uintptr_t)fex))(((KernelAPI *)&modKAPI));
|
||||
}
|
||||
|
||||
if (ModuleCode::OK != ret)
|
||||
{
|
||||
modUIDs--;
|
||||
return ret;
|
||||
}
|
||||
return ModuleCode::OK;
|
||||
}
|
||||
|
||||
ModuleCode Module::LoadModule(vfs::Node *fildes)
|
||||
{
|
||||
Fex DrvHdr;
|
||||
fildes->read((uint8_t *)&DrvHdr, sizeof(Fex), 0);
|
||||
|
||||
if (DrvHdr.Magic[0] != 'F' || DrvHdr.Magic[1] != 'E' || DrvHdr.Magic[2] != 'X' || DrvHdr.Magic[3] != '\0')
|
||||
return ModuleCode::INVALID_FEX_HEADER;
|
||||
|
||||
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr.Magic, DrvHdr.Type, DrvHdr.OS, DrvHdr.EntryPoint);
|
||||
|
||||
if (DrvHdr.Type != FexFormatType::FexFormatType_Module)
|
||||
return ModuleCode::NOT_MODULE;
|
||||
|
||||
FexExtended fexE;
|
||||
fildes->read((uint8_t *)&fexE, sizeof(FexExtended), EXTENDED_SECTION_ADDRESS);
|
||||
|
||||
debug("Name: \"%s\"; Type: %d; Callback: %#lx", fexE.Module.Name, fexE.Module.Type, fexE.Module.Callback);
|
||||
|
||||
Memory::SmartHeap ModuleAddress(fildes->Size);
|
||||
fildes->read(ModuleAddress, fildes->Size, 0);
|
||||
|
||||
switch (fexE.Module.Bind.Type)
|
||||
{
|
||||
case ModuleBindType::BIND_PCI:
|
||||
return this->ModuleLoadBindPCI(ModuleAddress, fildes->Size);
|
||||
case ModuleBindType::BIND_INTERRUPT:
|
||||
return this->ModuleLoadBindInterrupt(ModuleAddress, fildes->Size);
|
||||
case ModuleBindType::BIND_PROCESS:
|
||||
return this->ModuleLoadBindProcess(ModuleAddress, fildes->Size);
|
||||
case ModuleBindType::BIND_INPUT:
|
||||
return this->ModuleLoadBindInput(ModuleAddress, fildes->Size);
|
||||
default:
|
||||
{
|
||||
error("Unknown module bind type: %d", fexE.Module.Bind.Type);
|
||||
return ModuleCode::UNKNOWN_MODULE_BIND_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Module::LoadModules()
|
||||
{
|
||||
SmartCriticalSection(ModuleInitLock);
|
||||
|
||||
const char *ModuleConfigFile = new char[256];
|
||||
assert(strlen(Config.ModuleDirectory) < 255 - 12);
|
||||
strcpy((char *)ModuleConfigFile, Config.ModuleDirectory);
|
||||
strcat((char *)ModuleConfigFile, "/config.ini");
|
||||
fixme("Loading module config file: %s", ModuleConfigFile);
|
||||
delete[] ModuleConfigFile;
|
||||
|
||||
debug("Loading built-in modules");
|
||||
StartBuiltInModules();
|
||||
|
||||
RefNode *ModuleDirectory = fs->Open(Config.ModuleDirectory);
|
||||
if (!ModuleDirectory)
|
||||
{
|
||||
KPrint("\eE85230Failed to open %s: %d)",
|
||||
Config.ModuleDirectory, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Loading modules from %s", Config.ModuleDirectory);
|
||||
foreach (auto DrvFile in ModuleDirectory->node->Children)
|
||||
{
|
||||
if (DrvFile->Type != vfs::NodeType::FILE)
|
||||
continue;
|
||||
|
||||
if (cwk_path_has_extension(DrvFile->Name))
|
||||
{
|
||||
const char *extension;
|
||||
size_t extension_length;
|
||||
cwk_path_get_extension(DrvFile->Name, &extension, &extension_length);
|
||||
debug("File: %s; Extension: %s", DrvFile->Name, extension);
|
||||
if (strcmp(extension, ".fex") == 0)
|
||||
{
|
||||
uintptr_t ret = this->LoadModule(DrvFile);
|
||||
char *RetString = new char[256];
|
||||
if (ret == ModuleCode::OK)
|
||||
strcpy(RetString, "\e058C19OK");
|
||||
else if (ret == ModuleCode::NOT_AVAILABLE)
|
||||
strcpy(RetString, "\eFF7900NOT AVAILABLE");
|
||||
else
|
||||
strcpy(RetString, "\eE85230FAILED");
|
||||
KPrint("%s %s %#lx", DrvFile->Name, RetString, ret);
|
||||
delete[] RetString;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete ModuleDirectory;
|
||||
}
|
||||
|
||||
Module::Module() {}
|
||||
|
||||
Module::~Module()
|
||||
{
|
||||
debug("Destructor called");
|
||||
this->UnloadAllModules();
|
||||
}
|
||||
|
||||
#if defined(a64)
|
||||
SafeFunction void ModuleInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||
#elif defined(a32)
|
||||
SafeFunction void ModuleInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
||||
#elif defined(aa64)
|
||||
SafeFunction void ModuleInterruptHook::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
|
||||
#endif
|
||||
{
|
||||
SmartLock(DriverInterruptLock); /* Lock in case of multiple interrupts firing at the same time */
|
||||
if (!this->Enabled)
|
||||
{
|
||||
debug("Interrupt hook is not enabled (%#lx, IRQ%d)",
|
||||
Frame->InterruptNumber,
|
||||
Frame->InterruptNumber - 32);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Handle.InterruptCallback)
|
||||
{
|
||||
#if defined(a86)
|
||||
uint64_t IntNum = Frame->InterruptNumber - 32;
|
||||
#elif defined(aa64)
|
||||
uint64_t IntNum = Frame->InterruptNumber;
|
||||
#endif
|
||||
warn("Interrupt callback for %ld is not set for module %ld!",
|
||||
IntNum, Handle.modUniqueID);
|
||||
return;
|
||||
}
|
||||
CPURegisters regs;
|
||||
#if defined(a64)
|
||||
regs.r15 = Frame->r15;
|
||||
regs.r14 = Frame->r14;
|
||||
regs.r13 = Frame->r13;
|
||||
regs.r12 = Frame->r12;
|
||||
regs.r11 = Frame->r11;
|
||||
regs.r10 = Frame->r10;
|
||||
regs.r9 = Frame->r9;
|
||||
regs.r8 = Frame->r8;
|
||||
|
||||
regs.rbp = Frame->rbp;
|
||||
regs.rdi = Frame->rdi;
|
||||
regs.rsi = Frame->rsi;
|
||||
regs.rdx = Frame->rdx;
|
||||
regs.rcx = Frame->rcx;
|
||||
regs.rbx = Frame->rbx;
|
||||
regs.rax = Frame->rax;
|
||||
|
||||
regs.InterruptNumber = Frame->InterruptNumber;
|
||||
regs.ErrorCode = Frame->ErrorCode;
|
||||
regs.rip = Frame->rip;
|
||||
regs.cs = Frame->cs;
|
||||
regs.rflags = Frame->rflags.raw;
|
||||
regs.rsp = Frame->rsp;
|
||||
regs.ss = Frame->ss;
|
||||
#elif defined(a32)
|
||||
regs.edi = Frame->edi;
|
||||
regs.esi = Frame->esi;
|
||||
regs.ebp = Frame->ebp;
|
||||
regs.esp = Frame->esp;
|
||||
regs.ebx = Frame->ebx;
|
||||
regs.edx = Frame->edx;
|
||||
regs.ecx = Frame->ecx;
|
||||
regs.eax = Frame->eax;
|
||||
|
||||
regs.InterruptNumber = Frame->InterruptNumber;
|
||||
regs.ErrorCode = Frame->ErrorCode;
|
||||
regs.eip = Frame->eip;
|
||||
regs.cs = Frame->cs;
|
||||
regs.eflags = Frame->eflags.raw;
|
||||
regs.r3_esp = Frame->r3_esp;
|
||||
regs.r3_ss = Frame->r3_ss;
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
((int (*)(void *))(Handle.InterruptCallback))(®s);
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
ModuleInterruptHook::ModuleInterruptHook(int Interrupt, ModuleFile Handle) : Interrupts::Handler(Interrupt)
|
||||
{
|
||||
this->Handle = Handle;
|
||||
#if defined(a86)
|
||||
trace("Interrupt %d hooked to module %ld", Interrupt, Handle.modUniqueID);
|
||||
#elif defined(aa64)
|
||||
trace("Interrupt %d hooked to module %ld", Interrupt, Handle.modUniqueID);
|
||||
#endif
|
||||
}
|
||||
}
|
226
core/module/module_api.cpp
Normal file
226
core/module/module_api.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <module.hpp>
|
||||
|
||||
#include <dumper.hpp>
|
||||
#include <lock.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
#include "api.hpp"
|
||||
|
||||
// show debug messages
|
||||
// #define DEBUG_MODULE_API 1
|
||||
|
||||
#ifdef DEBUG_MODULE_API
|
||||
#define modbg(m, ...) debug(m, ##__VA_ARGS__)
|
||||
#else
|
||||
#define modbg(m, ...)
|
||||
#endif
|
||||
|
||||
NewLock(ModuleDisplayPrintLock);
|
||||
|
||||
void ModuleDebugPrint(char *String, __UINT64_TYPE__ modUniqueID)
|
||||
{
|
||||
trace("[%ld] %s", modUniqueID, String);
|
||||
}
|
||||
|
||||
void ModuleDisplayPrint(char *String)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
for (__UINT64_TYPE__ i = 0; i < strlen(String); i++)
|
||||
Display->Print(String[i], 0, true);
|
||||
}
|
||||
|
||||
void *RequestPage(__UINT64_TYPE__ Size)
|
||||
{
|
||||
void *ret = KernelAllocator.RequestPages(size_t(Size + 1));
|
||||
modbg("Allocated %ld pages (%#lx-%#lx)",
|
||||
Size, (__UINT64_TYPE__)ret,
|
||||
(__UINT64_TYPE__)ret + FROM_PAGES(Size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreePage(void *Page, __UINT64_TYPE__ Size)
|
||||
{
|
||||
modbg("Freeing %ld pages (%#lx-%#lx)",
|
||||
Size, (__UINT64_TYPE__)Page,
|
||||
(__UINT64_TYPE__)Page + FROM_PAGES(Size));
|
||||
KernelAllocator.FreePages(Page, size_t(Size + 1));
|
||||
}
|
||||
|
||||
void MapMemory(void *VirtualAddress, void *PhysicalAddress, __UINT64_TYPE__ Flags)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Mapping %#lx to %#lx with flags %#lx...",
|
||||
(__UINT64_TYPE__)VirtualAddress,
|
||||
(__UINT64_TYPE__)PhysicalAddress, Flags);
|
||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||
}
|
||||
|
||||
void UnmapMemory(void *VirtualAddress)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Unmapping %#lx...",
|
||||
(__UINT64_TYPE__)VirtualAddress);
|
||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||
}
|
||||
|
||||
void *Modulememcpy(void *Destination, void *Source, __UINT64_TYPE__ Size)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
|
||||
(__UINT64_TYPE__)Source, (__UINT64_TYPE__)Source + Size,
|
||||
(__UINT64_TYPE__)Destination, (__UINT64_TYPE__)Destination + Size);
|
||||
return memcpy(Destination, Source, size_t(Size));
|
||||
}
|
||||
|
||||
void *Modulememset(void *Destination, int Value, __UINT64_TYPE__ Size)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
|
||||
(__UINT64_TYPE__)Destination,
|
||||
(__UINT64_TYPE__)Destination + Size, Size);
|
||||
return memset(Destination, Value, size_t(Size));
|
||||
}
|
||||
|
||||
void ModuleNetSend(__UINT32_TYPE__ ModuleID,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT16_TYPE__ Size)
|
||||
{
|
||||
// This is useless I guess...
|
||||
if (NIManager)
|
||||
NIManager->DrvSend(ModuleID, Data, Size);
|
||||
}
|
||||
|
||||
void ModuleNetReceive(__UINT32_TYPE__ ModuleID,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT16_TYPE__ Size)
|
||||
{
|
||||
if (NIManager)
|
||||
NIManager->DrvReceive(ModuleID, Data, Size);
|
||||
}
|
||||
|
||||
void ModuleAHCIDiskRead(__UINT32_TYPE__ ModuleID,
|
||||
__UINT64_TYPE__ Sector,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT32_TYPE__ SectorCount,
|
||||
__UINT8_TYPE__ Port)
|
||||
{
|
||||
DumpData("ModuleDiskRead", Data, SectorCount * 512);
|
||||
UNUSED(ModuleID);
|
||||
UNUSED(Sector);
|
||||
UNUSED(Port);
|
||||
}
|
||||
|
||||
void ModuleAHCIDiskWrite(__UINT32_TYPE__ ModuleID,
|
||||
__UINT64_TYPE__ Sector,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT32_TYPE__ SectorCount,
|
||||
__UINT8_TYPE__ Port)
|
||||
{
|
||||
DumpData("ModuleDiskWrite",
|
||||
Data, SectorCount * 512);
|
||||
UNUSED(ModuleID);
|
||||
UNUSED(Sector);
|
||||
UNUSED(Port);
|
||||
}
|
||||
|
||||
char *ModulePCIGetDeviceName(__UINT32_TYPE__ VendorID,
|
||||
__UINT32_TYPE__ DeviceID)
|
||||
{
|
||||
UNUSED(VendorID);
|
||||
UNUSED(DeviceID);
|
||||
return (char *)"Unknown";
|
||||
}
|
||||
|
||||
__UINT32_TYPE__ ModuleGetWidth()
|
||||
{
|
||||
return Display->GetBuffer(0)->Width;
|
||||
}
|
||||
|
||||
__UINT32_TYPE__ ModuleGetHeight()
|
||||
{
|
||||
return Display->GetBuffer(0)->Height;
|
||||
}
|
||||
|
||||
void ModuleSleep(__UINT64_TYPE__ Milliseconds)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Sleeping for %ld milliseconds...", Milliseconds);
|
||||
if (TaskManager)
|
||||
TaskManager->Sleep(Milliseconds);
|
||||
else
|
||||
TimeManager->Sleep(size_t(Milliseconds),
|
||||
Time::Units::Milliseconds);
|
||||
}
|
||||
|
||||
int Modulesprintf(char *Buffer, const char *Format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
int ret = vsprintf(Buffer, Format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
KernelAPI KernelAPITemplate = {
|
||||
.Version = {
|
||||
.Major = 0,
|
||||
.Minor = 0,
|
||||
.Patch = 1},
|
||||
.Info = {
|
||||
.Offset = 0,
|
||||
.modUniqueID = 0,
|
||||
.KernelDebug = false,
|
||||
},
|
||||
.Memory = {
|
||||
.PageSize = PAGE_SIZE,
|
||||
.RequestPage = RequestPage,
|
||||
.FreePage = FreePage,
|
||||
.Map = MapMemory,
|
||||
.Unmap = UnmapMemory,
|
||||
},
|
||||
.PCI = {
|
||||
.GetDeviceName = ModulePCIGetDeviceName,
|
||||
},
|
||||
.Util = {
|
||||
.DebugPrint = ModuleDebugPrint,
|
||||
.DisplayPrint = ModuleDisplayPrint,
|
||||
.memcpy = Modulememcpy,
|
||||
.memset = Modulememset,
|
||||
.Sleep = ModuleSleep,
|
||||
.sprintf = Modulesprintf,
|
||||
},
|
||||
.Command = {
|
||||
.Network = {
|
||||
.SendPacket = ModuleNetSend,
|
||||
.ReceivePacket = ModuleNetReceive,
|
||||
},
|
||||
.Disk = {
|
||||
.AHCI = {
|
||||
.ReadSector = ModuleAHCIDiskRead,
|
||||
.WriteSector = ModuleAHCIDiskWrite,
|
||||
},
|
||||
},
|
||||
},
|
||||
.Display = {
|
||||
.GetWidth = ModuleGetWidth,
|
||||
.GetHeight = ModuleGetHeight,
|
||||
},
|
||||
};
|
42
core/module/module_binding/bind_input.cpp
Normal file
42
core/module/module_binding/bind_input.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../api.hpp"
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../mapi.hpp"
|
||||
#include "../../../Fex.hpp"
|
||||
|
||||
namespace Module
|
||||
{
|
||||
ModuleCode Module::ModuleLoadBindInput(uintptr_t ModuleAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
stub;
|
||||
UNUSED(ModuleAddress);
|
||||
UNUSED(Size);
|
||||
UNUSED(IsBuiltIn);
|
||||
return ModuleCode::NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
118
core/module/module_binding/bind_interrupt.cpp
Normal file
118
core/module/module_binding/bind_interrupt.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../api.hpp"
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../mapi.hpp"
|
||||
#include "../../../Fex.hpp"
|
||||
|
||||
namespace Module
|
||||
{
|
||||
ModuleCode Module::ModuleLoadBindInterrupt(uintptr_t ModuleAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
Memory::VirtualMemoryArea *vma = new Memory::VirtualMemoryArea(nullptr);
|
||||
|
||||
BuiltInModuleInfo *bidi = (BuiltInModuleInfo *)ModuleAddress;
|
||||
Fex *fex = nullptr;
|
||||
if (!IsBuiltIn)
|
||||
{
|
||||
fex = (Fex *)vma->RequestPages(TO_PAGES(Size + 1));
|
||||
memcpy(fex, (void *)ModuleAddress, Size);
|
||||
debug("Module allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||
}
|
||||
else
|
||||
fex = (Fex *)bidi->EntryPoint;
|
||||
ModuleCode ret = CallModuleEntryPoint(fex, IsBuiltIn);
|
||||
if (ret != ModuleCode::OK)
|
||||
{
|
||||
delete vma;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IsBuiltIn)
|
||||
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||
|
||||
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
|
||||
debug("Starting driver %s", fexE->Module.Name);
|
||||
|
||||
switch (fexE->Module.Type)
|
||||
{
|
||||
case FexModuleType::FexModuleType_Generic:
|
||||
case FexModuleType::FexModuleType_Display:
|
||||
case FexModuleType::FexModuleType_Network:
|
||||
case FexModuleType::FexModuleType_Storage:
|
||||
case FexModuleType::FexModuleType_FileSystem:
|
||||
case FexModuleType::FexModuleType_Input:
|
||||
case FexModuleType::FexModuleType_Audio:
|
||||
{
|
||||
FexExtended *DriverExtendedHeader = (FexExtended *)vma->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
|
||||
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
|
||||
|
||||
ModuleFile DrvFile = {
|
||||
.Enabled = true,
|
||||
.BuiltIn = IsBuiltIn,
|
||||
.modUniqueID = this->modUIDs - 1,
|
||||
.Address = (void *)fex,
|
||||
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
|
||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Module.InterruptCallback),
|
||||
.vma = vma,
|
||||
};
|
||||
|
||||
if (fexE->Module.InterruptCallback)
|
||||
{
|
||||
for (uint16_t i = 0; i < sizeof(fexE->Module.Bind.Interrupt.Vector) / sizeof(fexE->Module.Bind.Interrupt.Vector[0]); i++)
|
||||
{
|
||||
if (fexE->Module.Bind.Interrupt.Vector[i] == 0)
|
||||
break;
|
||||
DrvFile.InterruptHook[i] = new ModuleInterruptHook(fexE->Module.Bind.Interrupt.Vector[i], DrvFile);
|
||||
}
|
||||
}
|
||||
|
||||
KernelCallback KCallback{};
|
||||
KCallback.RawPtr = nullptr;
|
||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
||||
ModuleCode CallbackRet = ((ModuleCode(*)(KernelCallback *))((uintptr_t)fexE->Module.Callback + (uintptr_t)fex))(&KCallback);
|
||||
|
||||
if (CallbackRet != ModuleCode::OK)
|
||||
{
|
||||
error("Module %s returned error %d", fexE->Module.Name, CallbackRet);
|
||||
delete vma;
|
||||
return CallbackRet;
|
||||
}
|
||||
|
||||
Modules.push_back(DrvFile);
|
||||
return ModuleCode::OK;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("Unknown driver type: %d", fexE->Module.Type);
|
||||
delete vma;
|
||||
return ModuleCode::UNKNOWN_MODULE_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
145
core/module/module_binding/bind_pci.cpp
Normal file
145
core/module/module_binding/bind_pci.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../api.hpp"
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../mapi.hpp"
|
||||
#include "../../../Fex.hpp"
|
||||
|
||||
namespace Module
|
||||
{
|
||||
ModuleCode Module::ModuleLoadBindPCI(uintptr_t ModuleAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
FexExtended *DrvExtHdr = (FexExtended *)(ModuleAddress + EXTENDED_SECTION_ADDRESS);
|
||||
if (IsBuiltIn)
|
||||
DrvExtHdr = (FexExtended *)(((BuiltInModuleInfo *)ModuleAddress)->ExtendedHeader);
|
||||
|
||||
uint16_t SizeOfVendorID = sizeof(DrvExtHdr->Module.Bind.PCI.VendorID) /
|
||||
sizeof(DrvExtHdr->Module.Bind.PCI.VendorID[0]);
|
||||
uint16_t SizeOfDeviceID = sizeof(DrvExtHdr->Module.Bind.PCI.DeviceID) /
|
||||
sizeof(DrvExtHdr->Module.Bind.PCI.DeviceID[0]);
|
||||
|
||||
for (uint16_t vID = 0; vID < SizeOfVendorID; vID++)
|
||||
{
|
||||
for (uint16_t dID = 0; dID < SizeOfDeviceID; dID++)
|
||||
{
|
||||
if (DrvExtHdr->Module.Bind.PCI.VendorID[vID] == 0 ||
|
||||
DrvExtHdr->Module.Bind.PCI.DeviceID[dID] == 0)
|
||||
continue;
|
||||
|
||||
std::vector<PCI::PCIDevice> devices =
|
||||
PCIManager->FindPCIDevice(DrvExtHdr->Module.Bind.PCI.VendorID[vID],
|
||||
DrvExtHdr->Module.Bind.PCI.DeviceID[dID]);
|
||||
if (devices.size() == 0)
|
||||
continue;
|
||||
|
||||
foreach (auto Device in devices)
|
||||
{
|
||||
debug("[%ld] VendorID: %#x; DeviceID: %#x",
|
||||
devices.size(), Device.Header->VendorID,
|
||||
Device.Header->DeviceID);
|
||||
|
||||
Memory::VirtualMemoryArea *vma = new Memory::VirtualMemoryArea(nullptr);
|
||||
|
||||
BuiltInModuleInfo *bidi = (BuiltInModuleInfo *)ModuleAddress;
|
||||
Fex *fex = nullptr;
|
||||
if (!IsBuiltIn)
|
||||
{
|
||||
fex = (Fex *)vma->RequestPages(TO_PAGES(Size + 1));
|
||||
memcpy(fex, (void *)ModuleAddress, Size);
|
||||
debug("Module allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||
}
|
||||
else
|
||||
fex = (Fex *)bidi->EntryPoint;
|
||||
ModuleCode ret = CallModuleEntryPoint(fex, IsBuiltIn);
|
||||
if (ret != ModuleCode::OK)
|
||||
{
|
||||
delete vma;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IsBuiltIn)
|
||||
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||
|
||||
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
debug("Starting driver %s", fexE->Module.Name);
|
||||
|
||||
PCIManager->MapPCIAddresses(Device);
|
||||
|
||||
switch (fexE->Module.Type)
|
||||
{
|
||||
case FexModuleType::FexModuleType_Generic:
|
||||
case FexModuleType::FexModuleType_Display:
|
||||
case FexModuleType::FexModuleType_Network:
|
||||
case FexModuleType::FexModuleType_Storage:
|
||||
case FexModuleType::FexModuleType_FileSystem:
|
||||
case FexModuleType::FexModuleType_Input:
|
||||
case FexModuleType::FexModuleType_Audio:
|
||||
{
|
||||
FexExtended *DriverExtendedHeader = (FexExtended *)vma->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
|
||||
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
|
||||
|
||||
ModuleFile DrvFile = {
|
||||
.Enabled = true,
|
||||
.BuiltIn = IsBuiltIn,
|
||||
.modUniqueID = this->modUIDs - 1,
|
||||
.Address = (void *)fex,
|
||||
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
|
||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Module.InterruptCallback),
|
||||
.vma = vma,
|
||||
};
|
||||
|
||||
if (fexE->Module.InterruptCallback)
|
||||
DrvFile.InterruptHook[0] = new ModuleInterruptHook(((int)((PCI::PCIHeader0 *)Device.Header)->InterruptLine), DrvFile);
|
||||
|
||||
KernelCallback KCallback{};
|
||||
KCallback.RawPtr = Device.Header;
|
||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
||||
ModuleCode CallbackRet = ((ModuleCode(*)(KernelCallback *))((uintptr_t)fexE->Module.Callback + (uintptr_t)fex))(&KCallback);
|
||||
|
||||
if (CallbackRet != ModuleCode::OK)
|
||||
{
|
||||
error("Module %s returned error %d", fexE->Module.Name, CallbackRet);
|
||||
delete vma;
|
||||
return CallbackRet;
|
||||
}
|
||||
|
||||
Modules.push_back(DrvFile);
|
||||
return ModuleCode::OK;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("Unknown driver type: %d", fexE->Module.Type);
|
||||
delete vma;
|
||||
return ModuleCode::UNKNOWN_MODULE_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ModuleCode::PCI_DEVICE_NOT_FOUND;
|
||||
}
|
||||
}
|
42
core/module/module_binding/bind_process.cpp
Normal file
42
core/module/module_binding/bind_process.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../api.hpp"
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../mapi.hpp"
|
||||
#include "../../../Fex.hpp"
|
||||
|
||||
namespace Module
|
||||
{
|
||||
ModuleCode Module::ModuleLoadBindProcess(uintptr_t ModuleAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
stub;
|
||||
UNUSED(ModuleAddress);
|
||||
UNUSED(Size);
|
||||
UNUSED(IsBuiltIn);
|
||||
return ModuleCode::NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user