move keyboard and mouse out of HAL into a standalone ps2.sys driver, implement usb stack with xhci controller discovery, hid keyboard/mouse, and bulk-only mass storage, add pci msi support with capability chain walking and software irq vector allocation (slots 16-23), rewrite user virtual memory as a USER_VA_REGION descriptor arena with per-process ownership tracking and guard page support, replacing the old bump allocator and top-down image region, add MmCreateUserRegion/MmDestroyAllUserRegions so process teardown reclaims all user va in one pass, allocate a pool-backed shadow framebuffer in hal_screen to fix cursor tearing and scroll corruption, reserve ap trampoline page below 1mb in uefi bootloader before boot services exit, rewrite memset/memcpy/memmove/memcmp with __stosq/__movsq intrinsics, promote driver flag literals to macros and add multi-tu STANDALONE_DRIVERS table to build.c, split rtl8139/rtl816x into header+source, rename KbReadScancode to KbReadKey, improve page fault output with MmDebugDescribeAddress and user region dump, fix %p to %016llX throughout.

This commit is contained in:
maksw committed 2026-06-02 00:01:20 +02:00
1 parent b970d7f59c
commit b838f8d83d
130 files changed
+8137 -2932

No files matched your search

+61 -51
View File
@@ -42,6 +42,16 @@
#include <kernel/ke_apc.h>
#include <kernel/ke_queue.h>
#include <kernel/ke_debug.h>
#ifndef PROCESS_LAUNCH_DEBUG
#define PROCESS_LAUNCH_DEBUG 0
#endif
#if PROCESS_LAUNCH_DEBUG
#define ProcDbg(...) DbgPrint(__VA_ARGS__)
#else
#define ProcDbg(...) ((void)0)
#endif
#include <kernel/mm_virt.h>
#include <kernel/ldr_image.h>
#include <kernel/syscall_nr.h>
@@ -49,6 +59,7 @@
#include <kernel/io_file.h>
#include <kernel/net_socket.h>
#include <kernel/ke_trap.h>
#include <kernel/ke_input.h>
#include <ntlite/syscall.h>
// ---------------------------------------------------------------------------
@@ -121,7 +132,7 @@ static KSTATUS KiAllocHandleForCurrentWithRights(OBJECT* obj, uint32_t rights, u
KSTATUS s = KeAllocateHandleWithRights(proc, obj, rights, handleOut);
// Most syscall create/open paths receive a fresh creator reference from the
// subsystem. The handle table takes its own reference; this helper always
// subsystem. The handle table takes its own reference; this helper always
// drops the creator reference so the object is owned only by the returned
// handle (and any subsystem-internal refs).
ObDereferenceObject(obj);
@@ -752,7 +763,7 @@ static void SyscallUserAsyncKernelRoutine(KAPC* apc,
(void)systemArgument2;
SYS_USER_ASYNC_APC_CONTEXT* ctx = CONTAINING_RECORD(apc, SYS_USER_ASYNC_APC_CONTEXT, KernelApc);
DbgPrint("USER/APC async: kernel routine ctx=0x%llX iosb=0x%llX status=%u info=%llu irql=%u\n",
DbgPrint("USER/APC async: kernel routine ctx=0x%016llX iosb=0x%016llX status=%u info=%llu irql=%u\n",
(uint64_t)ctx,
(uint64_t)(uintptr_t)apc->SystemArgument1,
(uint32_t)(uintptr_t)apc->SystemArgument2,
@@ -1150,81 +1161,72 @@ static uint64_t SyscallScreenPutChar(uint64_t a0, uint64_t a1, uint64_t a2,
}
// ---------------------------------------------------------------------------
// SYS_KB_POLL (40) -> 1 or 0
// SYS_KB_POLL (64) -> next INPUT_KEY or INPUT_KEY_NONE
// ---------------------------------------------------------------------------
static uint64_t SyscallKbPoll(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
if (!gHal) return 0;
return gHal->Keyboard.Poll();
return (uint64_t)KeInputKbPoll();
}
// ---------------------------------------------------------------------------
// SYS_KB_IS_KEY_DOWN (41) a0=scancode a1=extended -> 1 or 0
// SYS_KB_IS_KEY_DOWN (65) a0=INPUT_KEY -> 1 or 0
// ---------------------------------------------------------------------------
static uint64_t SyscallKbIsKeyDown(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a2; (void)a3; (void)a4; (void)a5;
// Check gHal and ensure the HAL struct actually has the new function pointer
if (!gHal || !gHal->Keyboard.IsKeyDown) return 0;
return gHal->Keyboard.IsKeyDown((uint8_t)a0, (bool)a1) ? 1u : 0u;
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
return KeInputIsKeyDown((INPUT_KEY)a0) ? 1u : 0u;
}
// ---------------------------------------------------------------------------
// SYS_KB_READ_CHAR (42) -> char (blocks, yields while waiting)
// SYS_KB_READ_CHAR (66) -> char (blocks, yields while waiting)
// ---------------------------------------------------------------------------
static uint64_t SyscallKbReadChar(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
if (!gHal) return 0;
while (!gHal->Keyboard.Poll()) KeYield();
return (uint64_t)(uint8_t)gHal->Keyboard.ReadChar();
while (!KeInputKbPoll()) KeYield();
return (uint64_t)(uint8_t)KeInputReadChar();
}
// ---------------------------------------------------------------------------
// SYS_KB_READ_SCANCODE (43) -> uint8_t (blocks, yields while waiting)
// SYS_KB_READ_KEY (67) -> INPUT_KEY (blocks, yields while waiting)
// ---------------------------------------------------------------------------
static uint64_t SyscallKbReadScancode(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
static uint64_t SyscallKbReadKey(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
if (!gHal) return 0;
while (!gHal->Keyboard.Poll()) KeYield();
return (uint64_t)gHal->Keyboard.ReadScancode();
while (!KeInputKbPoll()) KeYield();
return (uint64_t)KeInputReadKey();
}
// ---------------------------------------------------------------------------
// SYS_KB_GET_MODIFIERS (44) -> uint32_t
// SYS_KB_GET_MODIFIERS (68) -> uint32_t INPUT_MOD_* flags
// ---------------------------------------------------------------------------
static uint64_t SyscallKbGetModifiers(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
if (!gHal) return 0;
return (uint64_t)gHal->Keyboard.GetModifiers();
return (uint64_t)KeInputGetModifiers();
}
// ---------------------------------------------------------------------------
// SYS_MOUSE_POLL (45) -> 1 or 0
// SYS_MOUSE_POLL (69) -> 1 or 0
// ---------------------------------------------------------------------------
static uint64_t SyscallMousePoll(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
if (!gHal) return 0;
return gHal->Mouse.Poll() ? 1u : 0u;
return KeInputMousePoll() ? 1u : 0u;
}
// ---------------------------------------------------------------------------
// SYS_MOUSE_READ (46) a0=*dx a1=*dy a2=*buttons -> 1 or 0
// SYS_MOUSE_READ (70) a0=*dx a1=*dy a2=*buttons -> 1 or 0
// ---------------------------------------------------------------------------
static uint64_t SyscallMouseRead(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a3; (void)a4; (void)a5;
if (!gHal || !a0 || !a1 || !a2) return 0;
if (!a0 || !a1 || !a2) return 0;
int dx = 0, dy = 0;
uint8_t buttons = 0;
if (!gHal->Mouse.Read(&dx, &dy, &buttons)) return 0;
if (!KeInputMouseRead(&dx, &dy, &buttons)) return 0;
if (!KSUCCESS(CopyToUser((void*)(uintptr_t)a0, &dx, sizeof(dx)))) return 0;
if (!KSUCCESS(CopyToUser((void*)(uintptr_t)a1, &dy, sizeof(dy)))) return 0;
@@ -1233,15 +1235,15 @@ static uint64_t SyscallMouseRead(uint64_t a0, uint64_t a1, uint64_t a2,
}
// ---------------------------------------------------------------------------
// SYS_MOUSE_GET_POS (47) a0=*x a1=*y
// SYS_MOUSE_GET_POS (71) a0=*x a1=*y
// ---------------------------------------------------------------------------
static uint64_t SyscallMouseGetPos(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
(void)a2; (void)a3; (void)a4; (void)a5;
if (!gHal || !a0 || !a1) return STATUS_INVALID_PARAMETER;
if (!a0 || !a1) return STATUS_INVALID_PARAMETER;
int x = 0, y = 0;
gHal->Mouse.GetPosition(&x, &y);
KeInputMouseGetPosition(&x, &y);
KSTATUS s = KiCopyIntToUser(a0, x);
if (!KSUCCESS(s)) return s;
return KiCopyIntToUser(a1, y);
@@ -1334,22 +1336,25 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
// Read the executable from disk.
FILE_OBJECT* f;
ProcDbg("CreateProcess: path='%v' cmd='%v' callerPid=%u\n", path, cmdlineView, KeGetCurrentProcess() ? KeGetCurrentProcess()->ProcessId : 0);
s = IoOpenFile(path, &f);
if (!KSUCCESS(s)) return s;
if (!KSUCCESS(s)) { ProcDbg("CreateProcess: IoOpenFile failed st=%d\n", s); return s; }
uint64_t size = IoGetFileSize(f);
ProcDbg("CreateProcess: fileSize=%llu\n", size);
void* mem = MmAllocatePool(size);
if (!mem) { IoCloseFile(f); return STATUS_NO_MEMORY; }
if (!mem) { IoCloseFile(f); ProcDbg("CreateProcess: raw image pool alloc failed size=%llu\n", size); return STATUS_NO_MEMORY; }
size_t got;
s = IoReadFile(f, mem, size, &got);
IoCloseFile(f);
if (!KSUCCESS(s)) { MmFreePool(mem); return s; }
if (!KSUCCESS(s)) { ProcDbg("CreateProcess: IoReadFile failed st=%d got=%llu\n", s, (unsigned long long)got); MmFreePool(mem); return s; }
// Create the process object.
PROCESS* proc;
s = KeCreateProcess(pathBuf, &proc);
if (!KSUCCESS(s)) { MmFreePool(mem); return s; }
if (!KSUCCESS(s)) { ProcDbg("CreateProcess: KeCreateProcess failed st=%d\n", s); MmFreePool(mem); return s; }
ProcDbg("CreateProcess: created pid=%u name=%s\n", proc->ProcessId, proc->Name);
// Inherit CWD from parent
PROCESS* parent = KeGetCurrentProcess();
@@ -1368,34 +1373,37 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
path,
cmdlineView,
SysSvFromParts(proc->CurrentDirectory, proc->CurrentDirectoryLength));
if (!KSUCCESS(s)) { MmFreePool(mem); ObDereferenceObject(&proc->Header); return s; }
if (!KSUCCESS(s)) { ProcDbg("CreateProcess: env setup failed st=%d\n", s); MmFreePool(mem); ObDereferenceObject(&proc->Header); return s; }
// Map the PE image into memory.
uintptr_t imageBase = 0;
s = LdrLoadImage(mem, size, &imageBase, true);
s = LdrLoadImageForProcess(proc, mem, size, &imageBase);
MmFreePool(mem);
if (!KSUCCESS(s)) { ObDereferenceObject(&proc->Header); return s; }
if (!KSUCCESS(s)) { ProcDbg("CreateProcess: LdrLoadImage failed st=%d\n", s); ObDereferenceObject(&proc->Header); return s; }
ProcDbg("CreateProcess: image mapped pid=%u base=%016llx size=%llx\n", proc->ProcessId, (unsigned long long)imageBase, (unsigned long long)LdrGetMappedImageSize(proc, imageBase));
s = LdrResolveImportsForProcess(proc, imageBase);
if (!KSUCCESS(s)) {
MmFreeUserImage((void*)imageBase, LdrGetImageSize(imageBase));
ProcDbg("CreateProcess: resolve imports failed st=%d pid=%u image=%016llx\n", s, proc->ProcessId, (unsigned long long)imageBase);
MmDebugDumpUserRegions(proc);
ObDereferenceObject(&proc->Header);
return s;
}
ProcDbg("CreateProcess: imports resolved pid=%u modules=%u\n", proc->ProcessId, proc->ModuleCount);
s = LdrProtectImage(imageBase, true);
s = LdrProtectImageForProcess(proc, imageBase, true);
if (!KSUCCESS(s)) {
MmFreeUserImage((void*)imageBase, LdrGetImageSize(imageBase));
ProcDbg("CreateProcess: protect image failed st=%d pid=%u\n", s, proc->ProcessId);
MmDebugDumpUserRegions(proc);
ObDereferenceObject(&proc->Header);
return s;
}
proc->ImageBase = imageBase;
proc->ImageSize = LdrGetImageSize(imageBase);
proc->ImageSize = LdrGetMappedImageSize(proc, imageBase);
PROCESS* caller = KeGetCurrentProcess();
if (!caller) {
MmFreeUserImage((void*)imageBase, LdrGetImageSize(imageBase));
ObDereferenceObject(&proc->Header);
return STATUS_FAILURE;
}
@@ -1405,7 +1413,6 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
if (!KSUCCESS(s)) {
proc->ImageBase = 0;
proc->ImageSize = 0;
MmFreeUserImage((void*)imageBase, LdrGetImageSize(imageBase));
ObDereferenceObject(&proc->Header);
return s;
}
@@ -1414,10 +1421,13 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
uintptr_t entryPoint = LdrGetEntryPoint(imageBase);
s = KeCreateThread(proc, entryPoint, 0, PriorityNormal, &thread);
if (!KSUCCESS(s)) {
ProcDbg("CreateProcess: KeCreateThread failed st=%d pid=%u entry=%016llx\n", s, proc->ProcessId, (unsigned long long)entryPoint);
MmDebugDumpUserRegions(proc);
KeCloseHandle(caller, handle);
ObDereferenceObject(&proc->Header);
return s;
}
ProcDbg("CreateProcess: thread created pid=%u tid=%llu entry=%016llx handle=%u\n", proc->ProcessId, (unsigned long long)thread->ThreadId, (unsigned long long)entryPoint, handle);
s = KiCopyHandleToUser((uint64_t)(uintptr_t)req.HandleOut, handle);
if (!KSUCCESS(s)) {
@@ -1427,7 +1437,7 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2,
return s;
}
// Drop the creator's local reference. The returned handle and live thread
// Drop the creator's local reference. The returned handle and live thread
// references now own the process lifetime.
ObDereferenceObject(&proc->Header);
return STATUS_SUCCESS;
@@ -1666,7 +1676,7 @@ static uint64_t SyscallGetProcessPid(uint64_t a0, uint64_t a1, uint64_t a2,
// Named Queue Registry
//
// A flat, fixed-size table of { name -> QUEUE* } pairs protected by a
// spinlock. The registry holds one reference to each published queue for
// spinlock. The registry holds one reference to each published queue for
// the lifetime of the entry, so the queue object cannot be destroyed while
// it is registered even if every process closes its own handle to it.
//
@@ -1747,7 +1757,7 @@ static uint64_t SyscallPublishQueue(uint64_t a0, uint64_t a1, uint64_t a2,
// SYS_OPEN_NAMED_QUEUE (61) a0=*name a1=*handleOut
//
// Looks up 'name' in the registry and allocates a handle to the queue in the
// calling process's handle table. Returns STATUS_NOT_FOUND if no match.
// calling process's handle table. Returns STATUS_NOT_FOUND if no match.
// Callers that race against the publisher should retry on NOT_FOUND.
// ---------------------------------------------------------------------------
static uint64_t SyscallOpenNamedQueue(uint64_t a0, uint64_t a1, uint64_t a2,
@@ -2629,7 +2639,7 @@ static const SYSCALL_HANDLER gSyscallTable[SYS_MAX] = {
/* 64 SYS_KB_POLL */ SyscallKbPoll,
/* 65 SYS_KB_IS_KEY_DOWN */ SyscallKbIsKeyDown,
/* 66 SYS_KB_READ_CHAR */ SyscallKbReadChar,
/* 67 SYS_KB_READ_SCANCODE */ SyscallKbReadScancode,
/* 67 SYS_KB_READ_KEY */ SyscallKbReadKey,
/* 68 SYS_KB_GET_MODIFIERS */ SyscallKbGetModifiers,
/* 69 SYS_MOUSE_POLL */ SyscallMousePoll,
/* 70 SYS_MOUSE_READ */ SyscallMouseRead,