feat(kernel/driver): implement built-in driver support

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
EnderIce2 2025-03-02 21:34:16 +00:00
parent 426499090e
commit f824df9aad
No known key found for this signature in database
GPG Key ID: 2EE20AF089811A5A
12 changed files with 200 additions and 30 deletions

View File

@ -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 = .);

View File

@ -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 = .);

View File

@ -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 = .);

View File

@ -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 = .);

View File

@ -15,6 +15,7 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#define NO_API_IN_HEADER 1
#include <driver.hpp>
#include <interface/driver.h>
#include <interface/fs.h>

View File

@ -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 = "<builtin>";
drvObj.InterruptHandlers = new std::unordered_map<uint8_t, void *>();
drvObj.DeviceOperations = new std::unordered_map<dev_t, DriverHandlers>();
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<uint8_t, void *>(),
.DeviceOperations = new std::unordered_map<dev_t, DriverHandlers>(),
.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<uint8_t, void *>();
drvObj.DeviceOperations = new std::unordered_map<dev_t, DriverHandlers>();
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());

View File

@ -38,6 +38,51 @@
#include <io.h>
#include <list>
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<InputReport> *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<uint8_t, void *> *InterruptHandlers;
std::unordered_map<dev_t, DriverHandlers> *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__

View File

@ -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

View File

@ -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__

View File

@ -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__

View File

@ -239,6 +239,8 @@ typedef struct
};
} InputReport;
#ifndef __kernel__
EXTERNC int ReportInputEvent(InputReport *Report);
#endif // !__kernel__
#endif // !__FENNIX_API_INPUT_H__

View File

@ -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
}