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
}