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
+219
-73
@@ -16,6 +16,7 @@
|
||||
#include <kernel/ob_object.h>
|
||||
#include <kernel/ke_process.h>
|
||||
#include <kernel/ke_power.h>
|
||||
#include <kernel/ke_firmware.h>
|
||||
#include <kernel/mm_file_cache.h>
|
||||
#include <kernel/ke_thread.h>
|
||||
#include <kernel/ke_sched.h>
|
||||
@@ -43,6 +44,8 @@
|
||||
#include <kernel/ke_audio.h>
|
||||
#include <kernel/ke_settings.h>
|
||||
#include <kernel/ke_work.h>
|
||||
#include <kernel/ke_event.h>
|
||||
#include <ntlite/atomic.h>
|
||||
#include <kernel/ke_system_root.h>
|
||||
#include <kernel/se_security.h>
|
||||
#include <kernel/ke_system_service.h>
|
||||
@@ -134,7 +137,6 @@ static void KiInitializeSwapFromSettings(void) {
|
||||
// HAL pointer cached at boot for subsystems that still need platform services.
|
||||
static const HAL_API* gKmainHal;
|
||||
|
||||
// Implements the page In Bootloader Region operation.
|
||||
static bool KiPageInBootloaderRegion(const BOOT_INFO* bootInfo, PHYSICAL_ADDRESS page) {
|
||||
for (uint32_t i = 0; i < bootInfo->MemoryMap.RegionCount; i++) {
|
||||
const MEMORY_REGION* r = &bootInfo->MemoryMap.Regions[i];
|
||||
@@ -178,6 +180,24 @@ static void KiReclaimBootloaderMemory(const BOOT_INFO* bootInfo) {
|
||||
KiReclaimBootBlob(bootInfo, bootInfo->DriversIni.PhysicalBase, bootInfo->DriversIni.PageCount);
|
||||
}
|
||||
|
||||
// Runs the shared module prepare/publication sequence for both image sources.
|
||||
static KSTATUS KiStartLoadedDriver(const DM_DRIVER_CONFIG* driver, uintptr_t base) {
|
||||
KSTATUS status = LdrResolveImports(base);
|
||||
LDR_KERNEL_MODULE* reservation = (LDR_KERNEL_MODULE*)0;
|
||||
bool canReleaseImage = true;
|
||||
if (KSUCCESS(status))
|
||||
status = LdrRegisterModule(driver->Image, base, &reservation);
|
||||
if (KSUCCESS(status)) status = DmPrepareLoadedDriver(driver->Id, base, &canReleaseImage);
|
||||
if (KSUCCESS(status)) {
|
||||
DmCommitLoadedDriver(base, reservation);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
LdrDiscardModule(reservation);
|
||||
if (canReleaseImage) LdrReleaseKernelImage(base);
|
||||
else DbgPrint("driver: failed image retained for callback lifetime %s\n", driver->Image);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Loads a runtime image from the selected system root, keeping PE identity separate
|
||||
// from the configured module id used for lifecycle and dependency accounting.
|
||||
static KSTATUS KiLoadRuntimeDriver(const DM_DRIVER_CONFIG* driver) {
|
||||
@@ -210,14 +230,7 @@ static KSTATUS KiLoadRuntimeDriver(const DM_DRIVER_CONFIG* driver) {
|
||||
status = LdrLoadKernelImage(memory, (size_t)size, &base);
|
||||
MmFreePool(memory);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
status = LdrResolveImports(base);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
status = LdrRegisterModule(driver->Image, base);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
status = DmStartLoadedDriver(driver->Id, base);
|
||||
if (KSUCCESS(status))
|
||||
status = LdrSetModuleExportsAvailable(driver->Image, true);
|
||||
return status;
|
||||
return KiStartLoadedDriver(driver, base);
|
||||
}
|
||||
|
||||
// Starts a preloaded boot driver by its configuration identity, not array position.
|
||||
@@ -237,14 +250,7 @@ static KSTATUS KiLoadBootDriver(const BOOT_INFO* bootInfo,
|
||||
KSTATUS status = LdrLoadKernelImage(
|
||||
(const void*)(bootInfo->PhysicalMapBase + found->PhysicalBase), found->Length, &base);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
status = LdrResolveImports(base);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
status = LdrRegisterModule(driver->Image, base);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
status = DmStartLoadedDriver(driver->Id, base);
|
||||
if (KSUCCESS(status))
|
||||
status = LdrSetModuleExportsAvailable(driver->Image, true);
|
||||
return status;
|
||||
return KiStartLoadedDriver(driver, base);
|
||||
}
|
||||
|
||||
// Validates that the firmware preloaded exactly the configured boot modules.
|
||||
@@ -266,54 +272,195 @@ static bool KiCheckBootDriverHandoff(const BOOT_INFO* bootInfo, const DM_CONFIG*
|
||||
return expected == bootInfo->BootDrivers.Count;
|
||||
}
|
||||
|
||||
// Starts the lexicographically first eligible driver, independent of INI order.
|
||||
// Failed providers block requires= dependents, while after= waits for settlement.
|
||||
// Bounded workers execute independent driver starts while the coordinator owns graph state.
|
||||
#define KI_DRIVER_START_WORKERS 4u
|
||||
|
||||
typedef enum KI_DRIVER_WORK_STATE {
|
||||
KiDriverWorkIdle,
|
||||
KiDriverWorkQueued,
|
||||
KiDriverWorkRunning,
|
||||
KiDriverWorkFinished,
|
||||
KiDriverWorkExit,
|
||||
KiDriverWorkExited
|
||||
} KI_DRIVER_WORK_STATE;
|
||||
|
||||
typedef struct KI_DRIVER_START_WORKER {
|
||||
EVENT* Wake;
|
||||
EVENT* Completion;
|
||||
THREAD* Thread;
|
||||
const DM_CONFIG* Config;
|
||||
const BOOT_INFO* BootInfo;
|
||||
volatile int32_t State;
|
||||
uint32_t Index;
|
||||
KSTATUS Status;
|
||||
} KI_DRIVER_START_WORKER;
|
||||
|
||||
static void KiDriverStartWorker(void* argument) {
|
||||
KI_DRIVER_START_WORKER* worker = (KI_DRIVER_START_WORKER*)argument;
|
||||
for (;;) {
|
||||
EVENT* wake = worker->Wake;
|
||||
if (!wake)
|
||||
KePanic(KE_PANIC_CODE_INIT,
|
||||
"Driver worker: null wake worker=0x%016llx index=%u state=%d\n",
|
||||
(uint64_t)(uintptr_t)worker, worker->Index,
|
||||
NtlAtomicLoad32(&worker->State));
|
||||
KSTATUS status = KeWaitForEvent(wake, false);
|
||||
if (!KSUCCESS(status)) {
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
KePanic(KE_PANIC_CODE_INIT,
|
||||
"Driver worker wait status=0x%x worker=0x%016llx index=%u state=%d\n"
|
||||
" wake=0x%016llx currentWake=0x%016llx thread=0x%016llx\n"
|
||||
" waitStatus=0x%x threadState=%u waitObject=0x%016llx\n",
|
||||
status, (uint64_t)(uintptr_t)worker, worker->Index,
|
||||
NtlAtomicLoad32(&worker->State),
|
||||
(uint64_t)(uintptr_t)wake,
|
||||
(uint64_t)(uintptr_t)worker->Wake,
|
||||
(uint64_t)(uintptr_t)self,
|
||||
self ? self->WaitStatus : 0u,
|
||||
self ? (unsigned)self->State : 0u,
|
||||
self ? (uint64_t)(uintptr_t)self->WaitObject : 0ull);
|
||||
}
|
||||
// A wake alone does not claim work; stale signals may arrive after completion.
|
||||
int32_t prior = NtlAtomicCompareExchange32(&worker->State,
|
||||
KiDriverWorkRunning, KiDriverWorkQueued);
|
||||
if (prior == KiDriverWorkExit) {
|
||||
NtlAtomicExchange32(&worker->State, KiDriverWorkExited);
|
||||
return;
|
||||
}
|
||||
if (prior != KiDriverWorkQueued) continue;
|
||||
uint32_t index = worker->Index;
|
||||
if (index >= worker->Config->DriverCount)
|
||||
KePanic(KE_PANIC_CODE_INIT, "Driver worker: invalid assignment %u\n", index);
|
||||
const DM_DRIVER_CONFIG* driver = &worker->Config->Drivers[index];
|
||||
DbgPrint("driver: start id=%s image=%s\n", driver->Id, driver->Image);
|
||||
worker->Status = driver->Phase == DmStartBoot ?
|
||||
KiLoadBootDriver(worker->BootInfo, driver) : KiLoadRuntimeDriver(driver);
|
||||
NtlAtomicExchange32(&worker->State, KiDriverWorkFinished);
|
||||
KeSignalEvent(worker->Completion);
|
||||
}
|
||||
}
|
||||
|
||||
static int KiSelectEligibleDriver(const DM_CONFIG* config, DM_START_PHASE phase) {
|
||||
int selected = -1;
|
||||
for (uint32_t i = 0; i < config->DriverCount; ++i) {
|
||||
const DM_DRIVER_CONFIG* d = &config->Drivers[i];
|
||||
if (d->Phase != phase || !DmDriverCanStart(config, i)) continue;
|
||||
if (selected < 0 || strcmp(d->Id, config->Drivers[selected].Id) < 0)
|
||||
selected = (int)i;
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
static void KiRunDriverPhase(DM_CONFIG* config, const BOOT_INFO* bootInfo,
|
||||
DM_START_PHASE phase) {
|
||||
config->ActivePhase = phase;
|
||||
EVENT* completion = (EVENT*)0;
|
||||
KSTATUS status = KeEventCreate(EventAutoReset, false, &completion);
|
||||
if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: completion event failed\n");
|
||||
|
||||
// Worker threads retain these records until their exit has been acknowledged.
|
||||
KI_DRIVER_START_WORKER* workers = (KI_DRIVER_START_WORKER*)
|
||||
MmAllocatePoolTag(sizeof(KI_DRIVER_START_WORKER) * KI_DRIVER_START_WORKERS,
|
||||
MM_POOL_TAG('d', 'r', 'w', 'k'));
|
||||
if (!workers)
|
||||
KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: worker allocation failed\n");
|
||||
memset(workers, 0, sizeof(KI_DRIVER_START_WORKER) * KI_DRIVER_START_WORKERS);
|
||||
for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) {
|
||||
KI_DRIVER_START_WORKER* worker = &workers[i];
|
||||
worker->Index = UINT32_MAX;
|
||||
worker->Config = config;
|
||||
worker->BootInfo = bootInfo;
|
||||
worker->Completion = completion;
|
||||
status = KeEventCreate(EventAutoReset, false, &worker->Wake);
|
||||
if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: work event failed\n");
|
||||
const KE_THREAD_CREATE_PARAMETERS parameters =
|
||||
KE_THREAD_CREATE_NAMED_NORMAL(PriorityNormal, "driver.start");
|
||||
status = KeCreateKernelThread((uintptr_t)KiDriverStartWorker,
|
||||
(uintptr_t)worker, ¶meters, &worker->Thread);
|
||||
if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: worker failed\n");
|
||||
}
|
||||
|
||||
uint32_t active = 0;
|
||||
for (;;) {
|
||||
int selected = -1;
|
||||
for (uint32_t i = 0; i < config->DriverCount; ++i) {
|
||||
const DM_DRIVER_CONFIG* d = &config->Drivers[i];
|
||||
if (d->Phase != phase || !DmDriverCanStart(config, i)) continue;
|
||||
if (selected < 0 || strcmp(d->Id, config->Drivers[selected].Id) < 0)
|
||||
selected = (int)i;
|
||||
}
|
||||
if (selected >= 0) {
|
||||
DM_DRIVER_CONFIG* d = &config->Drivers[selected];
|
||||
DbgPrint("Driver manager: starting %s (%s)\n", d->Id, d->Image);
|
||||
KSTATUS status = phase == DmStartBoot
|
||||
? KiLoadBootDriver(bootInfo, d) : KiLoadRuntimeDriver(d);
|
||||
d->State = KSUCCESS(status) ? DmRunStarted : DmRunFailed;
|
||||
if (!KSUCCESS(status)) {
|
||||
DbgPrint("Driver manager: failed %s, status=0x%x\n", d->Id, status);
|
||||
if (d->Critical)
|
||||
KePanic(KE_PANIC_CODE_INIT,
|
||||
"Critical driver %s failed (0x%x)\n", d->Id, status);
|
||||
for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) {
|
||||
KI_DRIVER_START_WORKER* worker = &workers[i];
|
||||
if (NtlAtomicCompareExchange32(&worker->State,
|
||||
KiDriverWorkIdle, KiDriverWorkFinished) !=
|
||||
KiDriverWorkFinished) continue;
|
||||
uint32_t index = worker->Index;
|
||||
if (index >= config->DriverCount)
|
||||
KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: invalid completion %u\n", index);
|
||||
DM_DRIVER_CONFIG* driver = &config->Drivers[index];
|
||||
driver->State = KSUCCESS(worker->Status) ? DmRunStarted : DmRunFailed;
|
||||
if (!KSUCCESS(worker->Status)) {
|
||||
DbgPrint("driver: failed id=%s status=0x%x\n", driver->Id, worker->Status);
|
||||
if (driver->Critical)
|
||||
KePanic(KE_PANIC_CODE_INIT, "Critical driver %s failed (0x%x)\n",
|
||||
driver->Id, worker->Status);
|
||||
}
|
||||
worker->Index = UINT32_MAX;
|
||||
--active;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) {
|
||||
KI_DRIVER_START_WORKER* worker = &workers[i];
|
||||
if (NtlAtomicLoad32(&worker->State) != KiDriverWorkIdle) continue;
|
||||
int selected = KiSelectEligibleDriver(config, phase);
|
||||
if (selected < 0) break;
|
||||
DM_DRIVER_CONFIG* driver = &config->Drivers[selected];
|
||||
driver->State = DmRunStarting;
|
||||
worker->Index = (uint32_t)selected;
|
||||
NtlAtomicExchange32(&worker->State, KiDriverWorkQueued);
|
||||
++active;
|
||||
KeSignalEvent(worker->Wake);
|
||||
}
|
||||
|
||||
if (active) {
|
||||
status = KeWaitForEvent(completion, false);
|
||||
if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: wait failed\n");
|
||||
continue;
|
||||
}
|
||||
bool changed = false;
|
||||
uint32_t waiting = 0;
|
||||
for (uint32_t i = 0; i < config->DriverCount; ++i) {
|
||||
DM_DRIVER_CONFIG* d = &config->Drivers[i];
|
||||
if (d->Phase != phase || d->State != DmRunWaiting) continue;
|
||||
DM_DRIVER_CONFIG* driver = &config->Drivers[i];
|
||||
if (driver->Phase != phase || driver->State != DmRunWaiting) continue;
|
||||
++waiting;
|
||||
if (DmDriverIsBlocked(config, i)) {
|
||||
d->State = DmRunBlocked;
|
||||
DbgPrint("Driver manager: blocked %s by unsatisfied dependency\n", d->Id);
|
||||
if (d->Critical)
|
||||
KePanic(KE_PANIC_CODE_INIT, "Critical driver %s blocked\n", d->Id);
|
||||
changed = true;
|
||||
}
|
||||
if (!DmDriverIsBlocked(config, i)) continue;
|
||||
driver->State = DmRunBlocked;
|
||||
DbgPrint("driver: blocked id=%s dependency failed\n", driver->Id);
|
||||
if (driver->Critical)
|
||||
KePanic(KE_PANIC_CODE_INIT, "Critical driver %s blocked\n", driver->Id);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) continue;
|
||||
if (waiting)
|
||||
KePanic(KE_PANIC_CODE_INIT,
|
||||
"Driver manager: no eligible drivers in phase %u (waiting=%u)\n",
|
||||
"Driver manager: deadlocked phase=%u waiting=%u\n",
|
||||
(unsigned)phase, waiting);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) {
|
||||
if (NtlAtomicCompareExchange32(&workers[i].State,
|
||||
KiDriverWorkExit, KiDriverWorkIdle) != KiDriverWorkIdle)
|
||||
KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: worker still active at shutdown\n");
|
||||
KeSignalEvent(workers[i].Wake);
|
||||
}
|
||||
for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) {
|
||||
status = KeWaitForEvent(workers[i].Thread->ExitEvent, false);
|
||||
if (!KSUCCESS(status))
|
||||
KePanic(KE_PANIC_CODE_INIT,
|
||||
"Driver scheduler: worker %u exit wait failed (0x%x)\n", i, status);
|
||||
if (NtlAtomicLoad32(&workers[i].State) != KiDriverWorkExited)
|
||||
KePanic(KE_PANIC_CODE_INIT,
|
||||
"Driver scheduler: worker %u exited without acknowledgment (state=%d)\n",
|
||||
i, NtlAtomicLoad32(&workers[i].State));
|
||||
ObDereferenceObject(&workers[i].Thread->Header);
|
||||
ObDereferenceObject(&workers[i].Wake->Header);
|
||||
}
|
||||
ObDereferenceObject(&completion->Header);
|
||||
MmFreePool(workers);
|
||||
}
|
||||
|
||||
static DM_CONFIG* gDriverConfig;
|
||||
@@ -359,7 +506,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
// Kernel-launched user images are rooted at the selected system volume.
|
||||
s = KeOpenSystemRootFile(filePath, &f);
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
DbgPrint("Failed to load system file: \"%s\" (status %d)!\n", filePath, s);
|
||||
DbgPrint("process: image load failed path=%s status=0x%x\n", filePath, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -376,13 +523,13 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
IoCloseFile(f);
|
||||
return 0;
|
||||
}
|
||||
DbgPrint("Created process (PID %u) with command line: %s\n", proc->ProcessId, (args && args[0]) ? args : filePath);
|
||||
DbgPrint("process: created pid=%u image=%s\n", proc->ProcessId, filePath);
|
||||
|
||||
s = KeSetupUserProcessEnvironment(proc,
|
||||
SysSvFromCstr(filePath),
|
||||
SysSvFromCstr(args));
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KiLaunchUserProcess: Failed to build user process environment. Status: %d\n", s);
|
||||
DbgPrint("process: environment failed status=0x%x\n", s);
|
||||
IoCloseFile(f);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return 0;
|
||||
@@ -461,7 +608,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
}
|
||||
}
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KiLaunchUserProcess: Failed to create bootstrap startup capabilities. Status: %d\n", s);
|
||||
DbgPrint("process: bootstrap capabilities failed status=0x%x\n", s);
|
||||
IoCloseFile(f);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return 0;
|
||||
@@ -476,7 +623,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
};
|
||||
s = KeSetProcessStartupCapabilities(proc, startupCapabilities, 6);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KiLaunchUserProcess: Failed to install startup capabilities. Status: %d\n", s);
|
||||
DbgPrint("process: capability install failed status=0x%x\n", s);
|
||||
IoCloseFile(f);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return 0;
|
||||
@@ -487,7 +634,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
s = LdrLoadImageFileForProcess(proc, f, &imageBase);
|
||||
IoCloseFile(f);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KiLaunchUserProcess: LdrLoadImageFileForProcess failed with status: %d\n", s);
|
||||
DbgPrint("process: image map failed status=0x%x\n", s);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return 0;
|
||||
}
|
||||
@@ -501,7 +648,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
|
||||
s = LdrProtectImageForProcess(proc, imageBase, true);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KiLaunchUserProcess: Failed to protect EXE image for %s (status %d)\n", filePath, s);
|
||||
DbgPrint("process: image protect failed path=%s status=0x%x\n", filePath, s);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return 0;
|
||||
}
|
||||
@@ -520,14 +667,12 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
s = KeCreateThread(proc, (uintptr_t)entryPoint, 0, &threadParameters, &thread);
|
||||
if (!KSUCCESS(s)) {
|
||||
KePowerSetInitProcess((PROCESS*)0);
|
||||
DbgPrint("KiLaunchUserProcess: Failed to create thread. Status: %d\n", s);
|
||||
DbgPrint("process: thread creation failed status=0x%x\n", s);
|
||||
proc->ImageBase = 0;
|
||||
proc->ImageSize = 0;
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return 0;
|
||||
}
|
||||
uint32_t tid = thread->ThreadId;
|
||||
DbgPrint("KiLaunchUserProcess: Thread created and queued! TID=%u\n", tid);
|
||||
ObDereferenceObject(&thread->Header);
|
||||
|
||||
// Caller owns the reference returned by KeCreateProcess.
|
||||
@@ -548,19 +693,15 @@ static void KiFlushRegisteredDisks(const char* phase) {
|
||||
DbgPrint("shutdown: %s disk enumeration failed 0x%x\n", phase, st);
|
||||
}
|
||||
|
||||
// Implements the system Init Thread operation.
|
||||
void SystemInitThread(void* arg) {
|
||||
SYSTEM_INIT_ARGS* args = (SYSTEM_INIT_ARGS*)arg;
|
||||
|
||||
DbgPrint("SystemInitThread: Thread started. Igniting the system...\n");
|
||||
|
||||
KiInitializeDrivers(args->BootInfo, args->Hal);
|
||||
|
||||
KSTATUS powerStatus = KePowerInitialize();
|
||||
if (!KSUCCESS(powerStatus))
|
||||
KePanic(KE_PANIC_CODE_INIT, "Power coordinator failed (0x%x)\n", powerStatus);
|
||||
|
||||
KePowerInitializeButton(args->Hal);
|
||||
KiInitializeDrivers(args->BootInfo, args->Hal);
|
||||
KePowerInitializePolicy();
|
||||
KeTimeReloadSettings();
|
||||
|
||||
KiInitializeSwapFromSettings();
|
||||
@@ -571,7 +712,7 @@ void SystemInitThread(void* arg) {
|
||||
KiRunKernelSelfTests();
|
||||
|
||||
// Launch the bootstrap service manager. Its allocated PID is not a system contract.
|
||||
PROCESS* initProcess = KiLaunchUserProcess("system/init.exe", args->BootConfig.CommandLine);
|
||||
PROCESS* initProcess = KiLaunchUserProcess("system/init.exe", "");
|
||||
if (!initProcess) {
|
||||
DbgPrint("SystemInitThread: Failed to start system/init.exe.\n");
|
||||
KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: Failed to start system/init.exe.\n");
|
||||
@@ -588,7 +729,7 @@ void SystemInitThread(void* arg) {
|
||||
if (exitCode != 0) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: init.exe exited with code %d.\n", exitCode);
|
||||
}
|
||||
DbgPrint("SystemInitThread: power commit accepted; init exited with code %d.\n", exitCode);
|
||||
DbgPrint("shutdown: init exit=%d\n", exitCode);
|
||||
uint32_t action = KePowerCommittedAction();
|
||||
if (!action) KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: missing power action\n");
|
||||
KSTATUS flush = MmFileCacheFlushAll();
|
||||
@@ -604,12 +745,19 @@ void SystemInitThread(void* arg) {
|
||||
flush = MmFileCacheFlushAll();
|
||||
if (!KSUCCESS(flush)) DbgPrint("shutdown: final cache flush status 0x%x\n", flush);
|
||||
KiFlushRegisteredDisks("final");
|
||||
// Firmware preparation runs while platform drivers can still execute methods.
|
||||
KSTATUS firmwarePrepare = KePowerPrepareFirmware(action);
|
||||
if (!KSUCCESS(firmwarePrepare) && firmwarePrepare != NTLSTATUS_NOT_SUPPORTED)
|
||||
DbgPrint("shutdown: firmware prepare failed 0x%x; using HAL fallback\n", firmwarePrepare);
|
||||
KSTATUS prepare = DmPrepareShutdown();
|
||||
if (!KSUCCESS(prepare)) DbgPrint("shutdown: prepare status 0x%x\n", prepare);
|
||||
KSTATUS pnpShutdown = IoPnpShutdown(10000u);
|
||||
if (!KSUCCESS(pnpShutdown))
|
||||
DbgPrint("shutdown: device stop status 0x%x\n", pnpShutdown);
|
||||
DmCommitShutdown();
|
||||
KSTATUS firmwareEnter = KePowerEnterFirmware(action);
|
||||
if (firmwareEnter != NTLSTATUS_NOT_SUPPORTED)
|
||||
DbgPrint("shutdown: firmware transition returned 0x%x; using HAL fallback\n", firmwareEnter);
|
||||
if (action == SYS_POWER_ACTION_RESTART) {
|
||||
if (!gKmainHal->Power.Reset)
|
||||
KePanic(KE_PANIC_CODE_INIT, "shutdown: reset HAL callback unavailable\n");
|
||||
@@ -741,9 +889,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
KeInitializeGdt();
|
||||
KeInitializeIdt();
|
||||
|
||||
// Register boot modules (Allows LdrGetExport to work for drivers and the HAL)
|
||||
// Note: Kept to a single call here to avoid the duplicate in your original code.
|
||||
|
||||
// Register boot exports before resolving driver imports.
|
||||
KSTATUS moduleRegistryStatus = LdrRegisterModulesFromBootInfo(bootInfo);
|
||||
if (!KSUCCESS(moduleRegistryStatus))
|
||||
KeStopProcessor();
|
||||
@@ -773,9 +919,11 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
KeStopProcessor();
|
||||
|
||||
IoInitializeDdk(hal, bootInfo->PhysicalMapBase);
|
||||
KeFirmwareInitialize(bootInfo);
|
||||
gKmainHal = hal;
|
||||
|
||||
KeInitDebug(hal, KSUCCESS(bootConfigStatus) ? bootConfig.Debug : 0);
|
||||
KeFirmwareLog();
|
||||
if (!KSUCCESS(bootConfigStatus)) {
|
||||
KePanic(KE_PANIC_CODE_INIT,
|
||||
"boot.ini: malformed or missing mandatory configuration, status=0x%x\n",
|
||||
@@ -786,7 +934,6 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
// Bind IRQ dispatch while IF remains clear. Interrupt sources are armed
|
||||
// later, after their kernel consumers have registered.
|
||||
KeIrqInitialize(hal);
|
||||
DbgPrint("CPU: PAT owns WB/WC/UC policy; MTRR default=WB fixed=off variable=off.\n");
|
||||
KeTimeInitialize(bootInfo, hal);
|
||||
KeDisplayInitialize(hal);
|
||||
|
||||
@@ -805,7 +952,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
|
||||
KeInputInitialize(hal);
|
||||
|
||||
KeIrqRegister(hal->Timer.IrqNumber, hal->Timer.HandleInterrupt);
|
||||
KeIrqRegisterLocalTimerHandler(hal->Timer.HandleInterrupt);
|
||||
|
||||
KeSyscallInit(hal);
|
||||
|
||||
@@ -822,7 +969,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
// Scheduler Prep & Status Update.
|
||||
|
||||
KeInitializeScheduler();
|
||||
KeIrqRegister(hal->Timer.IrqNumber, KeSchedulerTick);
|
||||
KeIrqRegisterLocalTimerHandler(KeSchedulerTick);
|
||||
KeConfigureCurrentProcessorTimer();
|
||||
|
||||
KSTATUS volumeManagerStatus = IoInitializeVolumeManager();
|
||||
@@ -873,7 +1020,6 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
if (!KSUCCESS(st)) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "KernelMain: Failed to create SystemInitThread (status 0x%x)\n", st);
|
||||
}
|
||||
DbgPrint("KernelMain: Handing over to scheduler...\n");
|
||||
|
||||
// The bootstrap CPU becomes the scheduler idle context once interrupts are enabled.
|
||||
while (true)
|
||||
|
||||
Reference in new issue
Block a user