colonel.exe 🤑, refactor all include directives, AHCI is now interrupt driven, upgrades to IDE, implemented I/O Request Packets, fix numerous keyboard issues, change all for (;;) and while (1) to while (true), DbgPrint guarded by spinlock, fix KeSignalEvent, major KernelMain refactor, added SystemInitThread because of new blocking I/O, replace memcpy manouvers with strncpy and strncat, add: run for ide, runa for ahci, rund for debug and ide, runad for debug and ahci.
This commit is contained in:
1 parent
7f4052f41c
commit
9fa2a7e0db
61 files changed
+1311
-456
No files matched your search
+114
-83
@@ -1,22 +1,22 @@
|
||||
// main.c - kernel entry point
|
||||
#include "boot_info.h"
|
||||
#include "mm_phys.h"
|
||||
#include "mm_virt.h"
|
||||
#include "ob_object.h"
|
||||
#include "ke_process.h"
|
||||
#include "ke_thread.h"
|
||||
#include "ke_sched.h"
|
||||
#include "ke_idt.h"
|
||||
#include "ke_irq.h"
|
||||
#include "ke_syscall.h"
|
||||
#include "ke_debug.h"
|
||||
#include "ldr_image.h"
|
||||
#include "hal_api.h"
|
||||
#include "io_file.h"
|
||||
#include "ini_parser.h"
|
||||
// kmain.c - kernel entry point
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
#include <boot_info.h>
|
||||
#include <mm_phys.h>
|
||||
#include <mm_virt.h>
|
||||
#include <ob_object.h>
|
||||
#include <ke_process.h>
|
||||
#include <ke_thread.h>
|
||||
#include <ke_sched.h>
|
||||
#include <ke_idt.h>
|
||||
#include <ke_irq.h>
|
||||
#include <ke_syscall.h>
|
||||
#include <ke_debug.h>
|
||||
#include <ldr_image.h>
|
||||
#include <hal_api.h>
|
||||
#include <io_file.h>
|
||||
#include <ini_parser.h>
|
||||
|
||||
// dynamic arrays bitch
|
||||
typedef struct {
|
||||
@@ -72,6 +72,11 @@ typedef struct {
|
||||
|
||||
#define arr_free(arr) MmFreePool((Header*)(arr) - 1)
|
||||
|
||||
typedef struct {
|
||||
BOOT_INFO* bootInfo;
|
||||
const HAL_API* hal;
|
||||
} SYSTEM_INIT_ARGS;
|
||||
|
||||
typedef KSTATUS (*DRIVER_ENTRY_FN)(const HAL_API *);
|
||||
|
||||
// HAL pointer cached at boot so kernel threads can reach it without
|
||||
@@ -107,7 +112,7 @@ static void DriversIniCb(const char* section, const char* key,
|
||||
}
|
||||
|
||||
static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
DbgPrint("KernelMain: Initializing drivers...\n");
|
||||
DbgPrint("InitializeDrivers: Initializing drivers...\n");
|
||||
|
||||
// boot drivers (provided by the bootloader)
|
||||
for (uint32_t i = 0; i < bootInfo->ModuleCount; i++) {
|
||||
@@ -117,13 +122,13 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
size_t len = strlen(name);
|
||||
if (len < 4 || strcmp(name + len - 4, ".sys")) continue;
|
||||
|
||||
DbgPrint("KernelMain: Executing DriverEntry for %s\n", name);
|
||||
DbgPrint("InitializeDrivers: Executing DriverEntry for %s\n", name);
|
||||
|
||||
DRIVER_ENTRY_FN entry = (DRIVER_ENTRY_FN)(LdrGetEntryPoint(bootInfo->Modules[i].VirtBase));
|
||||
|
||||
KSTATUS ds = entry(hal);
|
||||
if (!KSUCCESS(ds)) {
|
||||
DbgPrint("KernelMain: Driver %s failed to init!\n", name);
|
||||
DbgPrint("InitializeDrivers: Driver %s failed to init!\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,17 +138,17 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
|
||||
s = IoOpenFile("drivers\\drivers.ini", &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
DbgPrint("KernelMain: Failed to open drivers.ini\n");
|
||||
_disable(); while(1) __halt();
|
||||
DbgPrint("InitializeDrivers: Failed to open drivers.ini\n");
|
||||
_disable(); while(true) __halt();
|
||||
}
|
||||
|
||||
uint64_t size = IoGetFileSize(f) + 1;
|
||||
char* mem = MmAllocatePool(size);
|
||||
size_t got;
|
||||
if (!KSUCCESS(IoReadFile(f, mem, size, &got))) {
|
||||
DbgPrint("KernelMain: Failed to read drivers.ini\n");
|
||||
DbgPrint("InitializeDrivers: Failed to read drivers.ini\n");
|
||||
IoCloseFile(f);
|
||||
_disable(); while(1) __halt();
|
||||
_disable(); while(true) __halt();
|
||||
}
|
||||
mem[got] = '\0';
|
||||
|
||||
@@ -159,17 +164,18 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
size_t len = strlen(runtimeKeys[i]);
|
||||
char* path = MmAllocatePool(len + 10);
|
||||
if (!path) {
|
||||
DbgPrint("KernelMain: Failed to allocate memory for driver path. How?\n");
|
||||
DbgPrint("InitializeDrivers: Failed to allocate memory for driver path. How?\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// memcpy manouvers
|
||||
memcpy(path, "drivers\\", 8);
|
||||
memcpy(path + 8, runtimeKeys[i], len + 1);
|
||||
// Assemble the path
|
||||
strncpy(path, "drivers\\", sizeof(path) - 1);
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
strncat(path, runtimeKeys[i], sizeof(path) - strlen(path) - 1);
|
||||
|
||||
s = IoOpenFile(path, &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
DbgPrint("KernelMain: Failed to open runtime driver: %s\n", runtimeKeys[i]);
|
||||
DbgPrint("InitializeDrivers: Failed to open runtime driver: %s\n", runtimeKeys[i]);
|
||||
continue; // Skip this driver but keep going with others
|
||||
}
|
||||
|
||||
@@ -178,7 +184,7 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
uint64_t drvSize = IoGetFileSize(f);
|
||||
void* drvMem = MmAllocatePool(drvSize);
|
||||
if (!KSUCCESS(IoReadFile(f, drvMem, drvSize, &got))) {
|
||||
DbgPrint("KernelMain: Failed to read runtime driver: %s\n", runtimeKeys[i]);
|
||||
DbgPrint("InitializeDrivers: Failed to read runtime driver: %s\n", runtimeKeys[i]);
|
||||
IoCloseFile(f);
|
||||
continue;
|
||||
}
|
||||
@@ -186,7 +192,7 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
|
||||
uintptr_t mappedBase = 0;
|
||||
if (!KSUCCESS(LdrLoadImage(drvMem, drvSize, &mappedBase, false))) { // Load into kernel space
|
||||
DbgPrint("KernelMain: Failed to load runtime driver: %s\n", runtimeKeys[i]);
|
||||
DbgPrint("InitializeDrivers: Failed to load runtime driver: %s\n", runtimeKeys[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -194,7 +200,7 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
|
||||
KSTATUS ds = entry(hal);
|
||||
if (!KSUCCESS(ds)) {
|
||||
DbgPrint("KernelMain: Driver %s failed to init!\n", runtimeKeys[i]);
|
||||
DbgPrint("InitializeDrivers: Driver %s failed to init!\n", runtimeKeys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +229,7 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
// Read the DLL from disk
|
||||
s = IoOpenFile(filename, &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
DbgPrint("KernelMain: Failed to open DLL: %s\n", filename);
|
||||
DbgPrint("LoadAndRegisterDll: Failed to open DLL: %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -231,7 +237,7 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
void* mem = MmAllocatePool(size); // Temporary pool for the raw file
|
||||
size_t got;
|
||||
if (!KSUCCESS(IoReadFile(f, mem, size, &got))) {
|
||||
DbgPrint("KernelMain: Failed to read %s\n", filename);
|
||||
DbgPrint("LoadAndRegisterDll: Failed to read %s\n", filename);
|
||||
IoCloseFile(f);
|
||||
return;
|
||||
}
|
||||
@@ -242,7 +248,7 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
uintptr_t mappedBase = 0;
|
||||
s = LdrLoadImage(mem, size, &mappedBase, true);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KernelMain: Failed to map %s\n", filename);
|
||||
DbgPrint("LoadAndRegisterDll: Failed to map %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -262,23 +268,23 @@ static PROCESS* LaunchUserProcess(const char* filePath) {
|
||||
|
||||
// Read the executable file into a raw buffer
|
||||
s = IoOpenFile(filePath, &f);
|
||||
DbgPrint("KernelMain: IoOpenFile: %d\n", s);
|
||||
DbgPrint("LaunchUserProcess: IoOpenFile: %d\n", s);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
DbgPrint("Failed to load file: \"%s\"!\n", filePath);
|
||||
return (PROCESS*)0;
|
||||
}
|
||||
|
||||
uint64_t size = IoGetFileSize(f);
|
||||
DbgPrint("KernelMain: IoGetFileSize: %llu\n", size);
|
||||
DbgPrint("LaunchUserProcess: IoGetFileSize: %llu\n", size);
|
||||
|
||||
void* mem = MmAllocateUserMemory(size);
|
||||
DbgPrint("KernelMain: MmAllocateUserMemory: 0x%llX\n", mem);
|
||||
DbgPrint("LaunchUserProcess: MmAllocateUserMemory: 0x%llX\n", mem);
|
||||
|
||||
size_t got;
|
||||
s = IoReadFile(f, mem, size, &got);
|
||||
DbgPrint("KernelMain: IoReadFile: %d\n", s);
|
||||
DbgPrint("LaunchUserProcess: IoReadFile: %d\n", s);
|
||||
IoCloseFile(f);
|
||||
DbgPrint("KernelMain: IoCloseFile\n");
|
||||
DbgPrint("LaunchUserProcess: IoCloseFile\n");
|
||||
|
||||
// Create the process object
|
||||
PROCESS* proc;
|
||||
@@ -295,17 +301,17 @@ static PROCESS* LaunchUserProcess(const char* filePath) {
|
||||
uintptr_t imageBase = 0;
|
||||
s = LdrLoadImage(mem, size, &imageBase, true);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KernelMain: LdrLoadImage failed with status: %d\n", s);
|
||||
DbgPrint("LaunchUserProcess: LdrLoadImage failed with status: %d\n", s);
|
||||
}
|
||||
uintptr_t entryPoint = LdrGetEntryPoint(imageBase);
|
||||
DbgPrint("KernelMain: PE Image mapped! Base 0x%llx, Entry 0x%llX\n", imageBase, entryPoint);
|
||||
DbgPrint("LaunchUserProcess: PE Image mapped! Base 0x%llx, Entry 0x%llX\n", imageBase, entryPoint);
|
||||
|
||||
// Create the main thread, pointing it to the PE Entry Point
|
||||
s = KeCreateThread(proc, (uintptr_t)entryPoint, 0, PriorityNormal, &thread);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KernelMain: Failed to create thread. Status: %d\n", s);
|
||||
DbgPrint("LaunchUserProcess: Failed to create thread. Status: %d\n", s);
|
||||
}
|
||||
DbgPrint("KernelMain: Thread created and queued!\n");
|
||||
DbgPrint("LaunchUserProcess: Thread created and queued!\n");
|
||||
|
||||
// Caller owns the reference returned by KeCreateProcess.
|
||||
return proc;
|
||||
@@ -318,11 +324,11 @@ static PROCESS* LaunchUserProcess(const char* filePath) {
|
||||
static void ProcessWatcherThread(void* arg) {
|
||||
PROCESS* proc = (PROCESS*)arg;
|
||||
KeWaitForEvent(proc->ExitEvent);
|
||||
DbgPrint("KernelMain: Process \"%s\" (PID %u) exited with code %d.\n",
|
||||
DbgPrint("ProcessWatcherThread: Process \"%s\" (PID %u) exited with code %d.\n",
|
||||
proc->Name, proc->ProcessId, proc->ExitCode);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
|
||||
DbgPrint("KernelMain: Shutting down.\n");
|
||||
DbgPrint("ProcessWatcherThread: Shutting down.\n");
|
||||
gKmainHal->Power.Shutdown(); // does not return
|
||||
}
|
||||
|
||||
@@ -345,6 +351,47 @@ static void PrintProcessList() {
|
||||
}
|
||||
}
|
||||
|
||||
void SystemInitThread(void* arg) {
|
||||
SYSTEM_INIT_ARGS* args = (SYSTEM_INIT_ARGS*)arg;
|
||||
|
||||
DbgPrint("SystemInitThread: Thread started. Igniting the system...\n");
|
||||
|
||||
InitializeDrivers(args->bootInfo, args->hal);
|
||||
|
||||
ResolveSystemImports(args->bootInfo);
|
||||
|
||||
DbgPrint("SystemInitThread: Loading system DLLs...\n");
|
||||
LoadAndRegisterDll("syscall.dll");
|
||||
LoadAndRegisterDll("win32.dll");
|
||||
LoadAndRegisterDll("bink2w64.dll");
|
||||
|
||||
// Now that they are in memory and registered, we link them together
|
||||
// (e.g., win32.dll resolving its imports against syscall.dll)
|
||||
ResolveSystemImports(args->bootInfo);
|
||||
|
||||
// Print memory status now that the system is fully alive
|
||||
DbgPrint("Memory Status:\n");
|
||||
DbgPrint(" -> Free (PMM): %.2f MB\n", (float)MmFreeFrameCount() * PAGE_SIZE / (1024.0f * 1024.0f));
|
||||
DbgPrint(" -> Kernel Pool: %.2f MB\n", (float)MmGetKernelPoolUsage() / (1024.0f * 1024.0f));
|
||||
DbgPrint(" -> User Heap: %.2f MB\n", (float)MmGetUserHeapUsage() / (1024.0f * 1024.0f));
|
||||
|
||||
args->hal->Screen.Clear(0x000000);
|
||||
|
||||
// Launch User-Mode Shell (this will trigger AHCI & FAT32 which CAN safely block now)
|
||||
PROCESS* shellProc = LaunchUserProcess(args->bootInfo->CommandLine);
|
||||
|
||||
if (shellProc) {
|
||||
KSTATUS ws = KeCreateKernelThread((uintptr_t)ProcessWatcherThread,
|
||||
(uintptr_t)shellProc,
|
||||
PriorityNormal, (THREAD**)0);
|
||||
if (!KSUCCESS(ws)) {
|
||||
DbgPrint("SystemInitThread: Failed to create watcher thread (%d) -- leaking proc ref.\n", ws);
|
||||
}
|
||||
}
|
||||
|
||||
MmFreePool(args);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Main Kernel Entry
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -381,7 +428,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
.DebugEnabled = bootInfo->DebugEnabled
|
||||
};
|
||||
KSTATUS s = HalInitialize(&halParams);
|
||||
if (!KSUCCESS(s)) for (;;) __halt(); // there's nothing we can do.
|
||||
if (!KSUCCESS(s)) while (true) __halt(); // there's nothing we can do.
|
||||
const HAL_API* hal = HalGetApi();
|
||||
gKmainHal = hal;
|
||||
|
||||
@@ -400,53 +447,37 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
// Dynamic Linking & Driver Execution
|
||||
//
|
||||
ResolveSystemImports(bootInfo);
|
||||
InitializeDrivers(bootInfo, hal);
|
||||
//InitializeDrivers(bootInfo, hal);
|
||||
|
||||
//
|
||||
// Scheduler Prep & Status Update
|
||||
//
|
||||
KeInitializeScheduler();
|
||||
hal->Screen.Clear(0x000000);
|
||||
|
||||
DbgPrint("KernelMain: Loading system DLLs...\n");
|
||||
LoadAndRegisterDll("syscall.dll");
|
||||
LoadAndRegisterDll("win32.dll");
|
||||
LoadAndRegisterDll("bink2w64.dll");
|
||||
// Pack the arguments for the init thread
|
||||
SYSTEM_INIT_ARGS* initArgs = MmAllocatePool(sizeof(SYSTEM_INIT_ARGS));
|
||||
initArgs->bootInfo = bootInfo;
|
||||
initArgs->hal = hal;
|
||||
|
||||
// Now that they are in memory and registered, we link them together
|
||||
// (e.g., win32.dll resolving its imports against syscall.dll)
|
||||
ResolveSystemImports(bootInfo);
|
||||
|
||||
//
|
||||
// User-Mode Launch
|
||||
//
|
||||
PROCESS* shellProc = LaunchUserProcess(bootInfo->CommandLine);
|
||||
|
||||
// Spawn a kernel thread that blocks on the process exit event and prints
|
||||
// when it fires. The watcher takes ownership of the LaunchUserProcess
|
||||
// reference so we do not hold a dangling pointer in KernelMain.
|
||||
if (shellProc) {
|
||||
KSTATUS ws = KeCreateKernelThread((uintptr_t)ProcessWatcherThread,
|
||||
(uintptr_t)shellProc,
|
||||
PriorityNormal, (THREAD**)0);
|
||||
if (!KSUCCESS(ws)) {
|
||||
DbgPrint("KernelMain: Failed to create watcher thread (%d) -- leaking proc ref.\n", ws);
|
||||
}
|
||||
// Ownership of shellProc transferred to watcher; do not use it below.
|
||||
// Spawn the Initialization Thread
|
||||
THREAD* initThread = (THREAD*)0;
|
||||
KSTATUS st = KeCreateKernelThread((uintptr_t)SystemInitThread,
|
||||
(uintptr_t)initArgs,
|
||||
PriorityNormal, &initThread);
|
||||
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("KernelMain: PANIC - Failed to create SystemInitThread! (0x%x)\n", st);
|
||||
_disable();
|
||||
for(;;) __halt();
|
||||
}
|
||||
|
||||
//
|
||||
// Ignite the System
|
||||
//
|
||||
DbgPrint("KernelMain: Starting scheduler... Handing over control.\n");
|
||||
DbgPrint("KernelMain: Handing over to scheduler...\n");
|
||||
|
||||
// Ignite the system
|
||||
_enable();
|
||||
|
||||
DbgPrint("Memory Status:\n");
|
||||
DbgPrint(" -> Free (PMM): %.2f MB\n", (float)MmFreeFrameCount() * PAGE_SIZE / (1024.0f * 1024.0f));
|
||||
DbgPrint(" -> Kernel Pool: %.2f MB\n", (float)MmGetKernelPoolUsage() / (1024.0f * 1024.0f));
|
||||
DbgPrint(" -> User Heap: %.2f MB\n", (float)MmGetUserHeapUsage() / (1024.0f * 1024.0f));
|
||||
|
||||
while (1) {
|
||||
KeYield(); // nothing to do
|
||||
// The Idle Loop: The CPU rests here whenever all other threads are waiting on events.
|
||||
while (true) {
|
||||
__halt();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user