replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code.
This commit is contained in:
1 parent
d36f19509c
commit
36eef8f58d
696 files changed
+147281
-7530
No files matched your search
+82
-58
@@ -9,6 +9,7 @@
|
||||
#include <kernel/io_file.h>
|
||||
#include <kernel/mm_virt.h>
|
||||
#include <kernel/ke_debug.h>
|
||||
#include <kernel/ke_spinlock.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
#ifndef LDR_DEBUG_VERBOSE
|
||||
@@ -89,12 +90,10 @@ typedef struct {
|
||||
uint32_t Characteristics;
|
||||
} SECTION_HEADER;
|
||||
|
||||
// Implements the align Pe Size operation.
|
||||
static size_t KiAlignPeSize(size_t value) {
|
||||
return (value + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
}
|
||||
|
||||
// Implements the compute Required Image Size operation.
|
||||
static KSTATUS KiComputeRequiredImageSize(const PE_HEADER* pe, size_t fileSize, size_t* outSize) {
|
||||
if (!pe || !outSize) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
@@ -166,15 +165,16 @@ typedef struct {
|
||||
// Global kernel-module registry. Entries are allocated as modules arrive so boot-driver count is not an ABI limit.
|
||||
#define LDR_KERNEL_MODULE_NAME_MAX 64u
|
||||
|
||||
typedef struct MODULE_ENTRY {
|
||||
typedef struct LDR_KERNEL_MODULE {
|
||||
char Name[LDR_KERNEL_MODULE_NAME_MAX];
|
||||
uintptr_t Base;
|
||||
size_t Size;
|
||||
bool ExportsAvailable;
|
||||
struct MODULE_ENTRY* Next;
|
||||
} MODULE_ENTRY;
|
||||
struct LDR_KERNEL_MODULE* Next;
|
||||
} LDR_KERNEL_MODULE;
|
||||
|
||||
static MODULE_ENTRY* gModules;
|
||||
static LDR_KERNEL_MODULE* gModules;
|
||||
static SPINLOCK gModuleLock = SPINLOCK_INIT;
|
||||
|
||||
// Ensures a user image page is privately writable before the kernel patches it.
|
||||
static KSTATUS KiEnsureUserImageWrite(PROCESS* process, bool user, uintptr_t address, size_t size) {
|
||||
@@ -182,66 +182,82 @@ static KSTATUS KiEnsureUserImageWrite(PROCESS* process, bool user, uintptr_t add
|
||||
return MmVadMakeImageRangePrivate(process, (void*)address, size);
|
||||
}
|
||||
|
||||
// Allocates and inserts one global kernel-module registry entry.
|
||||
// Reserves an exact module identity before exposing its exports.
|
||||
static KSTATUS KiRegisterGlobalModule(const char* name, uintptr_t base, size_t size,
|
||||
bool exportsAvailable) {
|
||||
bool exportsAvailable, LDR_KERNEL_MODULE** out) {
|
||||
if (!name || !*name || !base || !size)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (out) *out = (LDR_KERNEL_MODULE*)0;
|
||||
|
||||
size_t nameLength = 0;
|
||||
while (nameLength < LDR_KERNEL_MODULE_NAME_MAX && name[nameLength]) nameLength++;
|
||||
if (nameLength == 0 || nameLength >= LDR_KERNEL_MODULE_NAME_MAX ||
|
||||
while (nameLength < LDR_KERNEL_MODULE_NAME_MAX && name[nameLength]) ++nameLength;
|
||||
if (!nameLength || nameLength >= LDR_KERNEL_MODULE_NAME_MAX ||
|
||||
!SysSvIsUtf8Text(SysSvFromParts(name, nameLength)))
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
MODULE_ENTRY* entry = (MODULE_ENTRY*)MmAllocatePool(sizeof(MODULE_ENTRY));
|
||||
if (!entry)
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
|
||||
LDR_KERNEL_MODULE* entry = (LDR_KERNEL_MODULE*)MmAllocatePool(sizeof(*entry));
|
||||
if (!entry) return NTLSTATUS_NO_MEMORY;
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
memcpy(entry->Name, name, nameLength);
|
||||
entry->Name[nameLength] = '\0';
|
||||
entry->Base = base;
|
||||
entry->Size = size;
|
||||
entry->ExportsAvailable = exportsAvailable;
|
||||
entry->Next = gModules;
|
||||
gModules = entry;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Registers the two fixed bootstrap images described explicitly by BOOT_INFO.
|
||||
KSTATUS LdrRegisterModulesFromBootInfo(const BOOT_INFO* bootInfo) {
|
||||
if (!bootInfo)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = KiRegisterGlobalModule("kernel.exe",
|
||||
bootInfo->KernelImage.VirtualBase,
|
||||
bootInfo->KernelImage.ImageSize, true);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
return KiRegisterGlobalModule("hal.dll",
|
||||
bootInfo->HalImage.VirtualBase,
|
||||
bootInfo->HalImage.ImageSize, true);
|
||||
}
|
||||
|
||||
// Registers one loaded kernel module without imposing a fixed registry capacity.
|
||||
KSTATUS LdrRegisterModule(const char* name, uintptr_t base) {
|
||||
size_t size = base ? LdrGetImageSize(base) : 0;
|
||||
return KiRegisterGlobalModule(name, base, size, false);
|
||||
}
|
||||
|
||||
// Makes an initialized module's exports visible to future import resolution.
|
||||
// Failed images remain mapped for diagnostics but must not provide exports.
|
||||
KSTATUS LdrSetModuleExportsAvailable(const char* name, bool available) {
|
||||
if (!name) return NTLSTATUS_INVALID_PARAMETER;
|
||||
for (MODULE_ENTRY* entry = gModules; entry; entry = entry->Next) {
|
||||
if (_stricmp(entry->Name, name) == 0) {
|
||||
entry->ExportsAvailable = available;
|
||||
return NTLSTATUS_SUCCESS;
|
||||
KSTATUS status = NTLSTATUS_SUCCESS;
|
||||
uintptr_t flags = KeAcquireSpinlock(&gModuleLock);
|
||||
for (LDR_KERNEL_MODULE* it = gModules; it; it = it->Next) {
|
||||
if (_stricmp(it->Name, name) == 0 || it->Base == base) {
|
||||
status = NTLSTATUS_ALREADY_EXISTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
if (KSUCCESS(status)) {
|
||||
entry->Next = gModules;
|
||||
gModules = entry;
|
||||
if (out) *out = entry;
|
||||
}
|
||||
KeReleaseSpinlock(&gModuleLock, flags);
|
||||
if (!KSUCCESS(status)) MmFreePool(entry);
|
||||
return status;
|
||||
}
|
||||
|
||||
KSTATUS LdrRegisterModulesFromBootInfo(const BOOT_INFO* bootInfo) {
|
||||
if (!bootInfo) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = KiRegisterGlobalModule("kernel.exe",
|
||||
bootInfo->KernelImage.VirtualBase,
|
||||
bootInfo->KernelImage.ImageSize, true, (LDR_KERNEL_MODULE**)0);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
return KiRegisterGlobalModule("hal.dll", bootInfo->HalImage.VirtualBase,
|
||||
bootInfo->HalImage.ImageSize, true, (LDR_KERNEL_MODULE**)0);
|
||||
}
|
||||
|
||||
KSTATUS LdrRegisterModule(const char* name, uintptr_t base, LDR_KERNEL_MODULE** out) {
|
||||
size_t size = base ? LdrGetImageSize(base) : 0;
|
||||
if (!out) return NTLSTATUS_INVALID_PARAMETER;
|
||||
return KiRegisterGlobalModule(name, base, size, false, out);
|
||||
}
|
||||
|
||||
// Only the owner of the reservation can publish or discard it.
|
||||
void LdrPublishModule(LDR_KERNEL_MODULE* module) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gModuleLock);
|
||||
module->ExportsAvailable = true;
|
||||
KeReleaseSpinlock(&gModuleLock, flags);
|
||||
}
|
||||
|
||||
void LdrDiscardModule(LDR_KERNEL_MODULE* module) {
|
||||
if (!module) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&gModuleLock);
|
||||
LDR_KERNEL_MODULE** link = &gModules;
|
||||
while (*link && *link != module) link = &(*link)->Next;
|
||||
if (*link && !module->ExportsAvailable) *link = module->Next;
|
||||
else module = (LDR_KERNEL_MODULE*)0;
|
||||
KeReleaseSpinlock(&gModuleLock, flags);
|
||||
if (module) MmFreePool(module);
|
||||
}
|
||||
|
||||
void LdrReleaseKernelImage(uintptr_t imageBase) {
|
||||
if (imageBase) MmFreePool((void*)imageBase);
|
||||
}
|
||||
|
||||
// Finds the loaded kernel module that owns an address.
|
||||
@@ -249,7 +265,9 @@ const char* LdrFindKernelModuleByAddress(uintptr_t address, uintptr_t* baseOut,
|
||||
if (baseOut) *baseOut = 0;
|
||||
if (sizeOut) *sizeOut = 0;
|
||||
|
||||
for (MODULE_ENTRY* module = gModules; module; module = module->Next) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gModuleLock);
|
||||
for (LDR_KERNEL_MODULE* module = gModules; module; module = module->Next) {
|
||||
if (!module->ExportsAvailable) continue;
|
||||
uintptr_t base = module->Base;
|
||||
size_t size = module->Size;
|
||||
if (!base || !size || base > UINTPTR_MAX - size)
|
||||
@@ -257,20 +275,28 @@ const char* LdrFindKernelModuleByAddress(uintptr_t address, uintptr_t* baseOut,
|
||||
if (address >= base && address < base + size) {
|
||||
if (baseOut) *baseOut = base;
|
||||
if (sizeOut) *sizeOut = size;
|
||||
return module->Name;
|
||||
const char* name = module->Name;
|
||||
KeReleaseSpinlock(&gModuleLock, flags);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinlock(&gModuleLock, flags);
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
// Returns the loaded global kernel module base for one exact module name.
|
||||
static uintptr_t KiFindGlobalModuleBase(const char* name) {
|
||||
if (!name) return 0;
|
||||
for (MODULE_ENTRY* module = gModules; module; module = module->Next) {
|
||||
if (module->ExportsAvailable && _stricmp(module->Name, name) == 0)
|
||||
return module->Base;
|
||||
uintptr_t base = 0;
|
||||
uintptr_t flags = KeAcquireSpinlock(&gModuleLock);
|
||||
for (LDR_KERNEL_MODULE* module = gModules; module; module = module->Next) {
|
||||
if (module->ExportsAvailable && _stricmp(module->Name, name) == 0) {
|
||||
base = module->Base;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
KeReleaseSpinlock(&gModuleLock, flags);
|
||||
return base;
|
||||
}
|
||||
|
||||
// Returns export At Base.
|
||||
@@ -313,7 +339,6 @@ void* LdrGetExport(const char* moduleName, const char* functionName) {
|
||||
return KiGetExportAtBase(base, functionName);
|
||||
}
|
||||
|
||||
// Implements the ldr Get Image Size operation.
|
||||
size_t LdrGetImageSize(uintptr_t base) {
|
||||
if (!base) return 0;
|
||||
uint32_t peOffset = *(uint32_t*)(base + 0x3C);
|
||||
@@ -322,7 +347,6 @@ size_t LdrGetImageSize(uintptr_t base) {
|
||||
return (size_t)pe->OptionalHeader.SizeOfImage;
|
||||
}
|
||||
|
||||
// Implements the ldr Get Mapped Image Size operation.
|
||||
size_t LdrGetMappedImageSize(PROCESS* process, uintptr_t base) {
|
||||
if (!base) return 0;
|
||||
if (process) {
|
||||
|
||||
Reference in new issue
Block a user