fix the return value of LdrLoadImage, make use of __declspec(dllexport), speed up blitting, add dummy TEB, redesign the syscall interface, fix stack alignent so movaps doesn't crash, implement a shitload of win32, implement a simple shell, add bink as video.exe 😎, minor kmain.c cleanup, HAL now supports power-off events, implemented \b in hal_screen.c, fix many deadlocks, add wait for exit event for processes, completely new error codes, small readme changes.
This commit is contained in:
1 parent
c13dd99150
commit
7f4052f41c
33 files changed
+6396
-735
No files matched your search
+64
-32
@@ -74,6 +74,10 @@ typedef struct {
|
||||
|
||||
typedef KSTATUS (*DRIVER_ENTRY_FN)(const HAL_API *);
|
||||
|
||||
// HAL pointer cached at boot so kernel threads can reach it without
|
||||
// threading a parameter through every call chain.
|
||||
static const HAL_API* gKmainHal;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Phase Helper: Resolve Imports for all registered modules
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -210,7 +214,7 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Phase Helper: Load a DLL from disk and register it as a system module
|
||||
// Phase Helper: Load a DLL from disk and register it
|
||||
// ---------------------------------------------------------------------------
|
||||
static void LoadAndRegisterDll(const char* filename) {
|
||||
KSTATUS s;
|
||||
@@ -219,8 +223,8 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
// Read the DLL from disk
|
||||
s = IoOpenFile(filename, &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
DbgPrint("KernelMain: Failed to open critical system DLL: %s\n", filename);
|
||||
_disable(); while(1) __halt();
|
||||
DbgPrint("KernelMain: Failed to open DLL: %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t size = IoGetFileSize(f);
|
||||
@@ -229,7 +233,7 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
if (!KSUCCESS(IoReadFile(f, mem, size, &got))) {
|
||||
DbgPrint("KernelMain: Failed to read %s\n", filename);
|
||||
IoCloseFile(f);
|
||||
_disable(); while(1) __halt();
|
||||
return;
|
||||
}
|
||||
IoCloseFile(f);
|
||||
|
||||
@@ -239,7 +243,7 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
s = LdrLoadImage(mem, size, &mappedBase, true);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KernelMain: Failed to map %s\n", filename);
|
||||
_disable(); while(1) __halt();
|
||||
return;
|
||||
}
|
||||
|
||||
MmFreePool(mem); // Free the raw file buffer, we only need the mapped image now
|
||||
@@ -248,18 +252,20 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Phase Helper: Load and launch the init process from the filesystem
|
||||
// Phase Helper: Load and launch a process from the filesystem.
|
||||
// Returns the new PROCESS* with one reference owned by the caller.
|
||||
// Returns NULL on failure.
|
||||
// ---------------------------------------------------------------------------
|
||||
static void LaunchInitProcess(BOOT_INFO* bootInfo) {
|
||||
static PROCESS* LaunchUserProcess(const char* filePath) {
|
||||
KSTATUS s;
|
||||
FILE_OBJECT* f;
|
||||
|
||||
// Read the executable file into a raw buffer
|
||||
s = IoOpenFile(bootInfo->CommandLine, &f);
|
||||
s = IoOpenFile(filePath, &f);
|
||||
DbgPrint("KernelMain: IoOpenFile: %d\n", s);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
DbgPrint("Failed to load file: \"%s\"!\n", bootInfo->CommandLine);
|
||||
_disable(); while(1) __halt();
|
||||
DbgPrint("Failed to load file: \"%s\"!\n", filePath);
|
||||
return (PROCESS*)0;
|
||||
}
|
||||
|
||||
uint64_t size = IoGetFileSize(f);
|
||||
@@ -278,29 +284,46 @@ static void LaunchInitProcess(BOOT_INFO* bootInfo) {
|
||||
PROCESS* proc;
|
||||
THREAD* thread;
|
||||
|
||||
s = KeCreateProcess("init", &proc);
|
||||
s = KeCreateProcess(filePath, &proc);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("Failed to create init process. System halted.\n");
|
||||
_disable(); while(1) __halt();
|
||||
DbgPrint("Failed to create process. System halted.\n");
|
||||
return (PROCESS*)0;
|
||||
}
|
||||
DbgPrint("Created init process (PID %u) with command line: %s\n", proc->ProcessId, bootInfo->CommandLine);
|
||||
DbgPrint("Created process (PID %u) with command line: %s\n", proc->ProcessId, filePath);
|
||||
|
||||
// Parse the raw PE file and map it into executable memory
|
||||
uintptr_t entryPoint = 0;
|
||||
s = LdrLoadImage(mem, size, &entryPoint, true);
|
||||
uintptr_t imageBase = 0;
|
||||
s = LdrLoadImage(mem, size, &imageBase, true);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KernelMain: LdrLoadImage failed with status: %d\n", s);
|
||||
_disable(); while(1) __halt();
|
||||
}
|
||||
DbgPrint("KernelMain: PE Image mapped! Entry point at 0x%llX\n", (void*)entryPoint);
|
||||
uintptr_t entryPoint = LdrGetEntryPoint(imageBase);
|
||||
DbgPrint("KernelMain: 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 init thread. Status: %d\n", s);
|
||||
_disable(); while(1) __halt();
|
||||
DbgPrint("KernelMain: Failed to create thread. Status: %d\n", s);
|
||||
}
|
||||
DbgPrint("KernelMain: Thread created and queued!\n");
|
||||
|
||||
// Caller owns the reference returned by KeCreateProcess.
|
||||
return proc;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Kernel thread: wait for a process to exit, then log a message and shut down.
|
||||
// Takes ownership of the PROCESS* reference passed as arg; releases it on exit.
|
||||
// ---------------------------------------------------------------------------
|
||||
static void ProcessWatcherThread(void* arg) {
|
||||
PROCESS* proc = (PROCESS*)arg;
|
||||
KeWaitForEvent(proc->ExitEvent);
|
||||
DbgPrint("KernelMain: Process \"%s\" (PID %u) exited with code %d.\n",
|
||||
proc->Name, proc->ProcessId, proc->ExitCode);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
|
||||
DbgPrint("KernelMain: Shutting down.\n");
|
||||
gKmainHal->Power.Shutdown(); // does not return
|
||||
}
|
||||
|
||||
static void PrintProcessList() {
|
||||
@@ -360,6 +383,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
KSTATUS s = HalInitialize(&halParams);
|
||||
if (!KSUCCESS(s)) for (;;) __halt(); // there's nothing we can do.
|
||||
const HAL_API* hal = HalGetApi();
|
||||
gKmainHal = hal;
|
||||
|
||||
KeInitDebug(hal->Screen.PrintChar, bootInfo->DebugEnabled); // Enable debug
|
||||
|
||||
@@ -382,11 +406,12 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
// Scheduler Prep & Status Update
|
||||
//
|
||||
KeInitializeScheduler();
|
||||
// hal->Screen.Clear(0x000000);
|
||||
hal->Screen.Clear(0x000000);
|
||||
|
||||
DbgPrint("KernelMain: 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)
|
||||
@@ -395,7 +420,20 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
//
|
||||
// User-Mode Launch
|
||||
//
|
||||
LaunchInitProcess(bootInfo);
|
||||
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.
|
||||
}
|
||||
|
||||
//
|
||||
// Ignite the System
|
||||
@@ -403,18 +441,12 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
DbgPrint("KernelMain: Starting scheduler... Handing over control.\n");
|
||||
_enable();
|
||||
|
||||
float freeMB = (float)MmFreeFrameCount() * PAGE_SIZE / (1024.0f * 1024.0f);
|
||||
float kernelMB = (float)MmGetKernelPoolUsage() / (1024.0f * 1024.0f);
|
||||
float userMB = (float)MmGetUserHeapUsage() / (1024.0f * 1024.0f);
|
||||
|
||||
DbgPrint("Memory Status:\n");
|
||||
DbgPrint(" -> Free (PMM): %.2f MB\n", freeMB);
|
||||
DbgPrint(" -> Kernel Pool: %.2f MB\n", kernelMB);
|
||||
DbgPrint(" -> User Heap: %.2f MB\n", userMB);
|
||||
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) {
|
||||
//DbgPrint("KernelMain: Idle loop. Free memory: %.2f MB.\n",
|
||||
//(float)(MmFreeFrameCount() * PAGE_SIZE) / (1024.0f * 1024.0f));
|
||||
__halt(); // nothing to do
|
||||
KeYield(); // nothing to do
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user