replace ad hoc driver loading with a proper driver manager, new DDK, new PnP manager with device matching, asynchronous startup, resource ownership and removal, add shared PCI capability helpers, replace typed, rigid services with a proper service manager, implement proper system shutdown and restart, shutting down unloads drivers and shuts down services, add simple power button, remove heavyweight boot self-tests and SMP stress runs, add monotonic timestamps to kernel debug output, fruitless USB and PS/2 fixes, make test builds opt in.
This commit is contained in:
1 parent
c0ad63c27f
commit
d36f19509c
160 files changed
+6563
-7366
No files matched your search
+243
-216
@@ -2,10 +2,12 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <ntlite/bootstrap_capabilities.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_disable)
|
||||
#include <ntlite/boot_info.h>
|
||||
#include <ntlite/syscall.h>
|
||||
#include <kernel/ke_hal.h>
|
||||
#include <kernel/mm_phys.h>
|
||||
#include <kernel/mm_pfn.h>
|
||||
@@ -13,6 +15,8 @@
|
||||
#include <kernel/mm_swap.h>
|
||||
#include <kernel/ob_object.h>
|
||||
#include <kernel/ke_process.h>
|
||||
#include <kernel/ke_power.h>
|
||||
#include <kernel/mm_file_cache.h>
|
||||
#include <kernel/ke_thread.h>
|
||||
#include <kernel/ke_sched.h>
|
||||
#include <kernel/ke_cpu.h>
|
||||
@@ -23,6 +27,9 @@
|
||||
#include <ntlite/ddi/net_device.h>
|
||||
#include <kernel/ke_debug.h>
|
||||
#include <kernel/ldr_image.h>
|
||||
#include <kernel/driver_module.h>
|
||||
#include <kernel/io_pnp.h>
|
||||
#include <kernel/dm_config.h>
|
||||
#include <kernel/hal/hal_api.h>
|
||||
#include <kernel/io_file.h>
|
||||
#include <kernel/io_volume.h>
|
||||
@@ -38,6 +45,7 @@
|
||||
#include <kernel/ke_work.h>
|
||||
#include <kernel/ke_system_root.h>
|
||||
#include <kernel/se_security.h>
|
||||
#include <kernel/ke_system_service.h>
|
||||
#include <kernel/ke_boot_config.h>
|
||||
|
||||
typedef struct {
|
||||
@@ -123,8 +131,6 @@ static void KiInitializeSwapFromSettings(void) {
|
||||
}
|
||||
}
|
||||
|
||||
typedef KSTATUS (*DRIVER_ENTRY_FN)(const NTL_DDK* ddk, NTL_DRIVER_INIT* init);
|
||||
|
||||
// HAL pointer cached at boot for subsystems that still need platform services.
|
||||
static const HAL_API* gKmainHal;
|
||||
|
||||
@@ -168,231 +174,179 @@ static void KiReclaimBootloaderMemory(const BOOT_INFO* bootInfo) {
|
||||
KiReclaimBootBlob(bootInfo, list->FilesPhysical, list->PageCount);
|
||||
if (bootInfo->BootIni.PhysicalBase && bootInfo->BootIni.PageCount)
|
||||
KiReclaimBootBlob(bootInfo, bootInfo->BootIni.PhysicalBase, bootInfo->BootIni.PageCount);
|
||||
if (bootInfo->DriversIni.PhysicalBase && bootInfo->DriversIni.PageCount)
|
||||
KiReclaimBootBlob(bootInfo, bootInfo->DriversIni.PhysicalBase, bootInfo->DriversIni.PageCount);
|
||||
}
|
||||
|
||||
// Returns whether one drivers.ini line character is horizontal whitespace.
|
||||
static bool KiDriverConfigSpace(char c) {
|
||||
return c == ' ' || c == '\t' || c == '\r';
|
||||
}
|
||||
|
||||
// Trims horizontal whitespace from one immutable drivers.ini line span.
|
||||
static void KiDriverConfigTrim(const char** begin, const char** end) {
|
||||
while (*begin < *end && KiDriverConfigSpace(**begin))
|
||||
++*begin;
|
||||
while (*end > *begin && KiDriverConfigSpace((*end)[-1]))
|
||||
--*end;
|
||||
}
|
||||
|
||||
// Returns whether one immutable drivers.ini span exactly matches an ASCII string.
|
||||
static bool KiDriverConfigSpanEquals(const char* begin, const char* end, const char* text) {
|
||||
while (begin < end && *text) {
|
||||
if (*begin++ != *text++)
|
||||
return false;
|
||||
}
|
||||
return begin == end && *text == '\0';
|
||||
}
|
||||
|
||||
// Loads one runtime driver filename from the system-root drivers directory.
|
||||
static KSTATUS KiLoadRuntimeDriverByName(const char* name, const NTL_DDK* ddk) {
|
||||
char relative[512];
|
||||
size_t length = strlen(name);
|
||||
if (length + 9u > sizeof(relative))
|
||||
return NTLSTATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
// 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) {
|
||||
char relative[DM_IMAGE_MAX + 8u];
|
||||
size_t length = strlen(driver->Image);
|
||||
memcpy(relative, "drivers/", 8);
|
||||
memcpy(relative + 8, name, length + 1);
|
||||
memcpy(relative + 8, driver->Image, length + 1);
|
||||
FILE_OBJECT* file = NULL;
|
||||
KSTATUS status = KeOpenSystemRootFile(relative, &file);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
uint64_t driverSize = IoGetFileSize(file);
|
||||
if (driverSize == 0 || driverSize > SIZE_MAX) {
|
||||
uint64_t size = IoGetFileSize(file);
|
||||
if (!size || size > SIZE_MAX) {
|
||||
IoCloseFile(file);
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
void* driverMemory = MmAllocatePool((size_t)driverSize);
|
||||
if (!driverMemory) {
|
||||
void* memory = MmAllocatePool((size_t)size);
|
||||
if (!memory) {
|
||||
IoCloseFile(file);
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
size_t got = 0;
|
||||
status = IoReadFile(file, driverMemory, (size_t)driverSize, &got);
|
||||
status = IoReadFile(file, memory, (size_t)size, &got);
|
||||
IoCloseFile(file);
|
||||
if (!KSUCCESS(status) || got != (size_t)driverSize) {
|
||||
MmFreePool(driverMemory);
|
||||
if (!KSUCCESS(status) || got != (size_t)size) {
|
||||
MmFreePool(memory);
|
||||
return KSUCCESS(status) ? NTLSTATUS_FAILURE : status;
|
||||
}
|
||||
|
||||
uintptr_t mappedBase = 0;
|
||||
status = LdrLoadKernelImage(driverMemory, (size_t)driverSize, &mappedBase);
|
||||
MmFreePool(driverMemory);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
status = LdrResolveImports(mappedBase);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
status = LdrRegisterModule(name, mappedBase);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
DRIVER_ENTRY_FN entry = (DRIVER_ENTRY_FN)LdrGetEntryPoint(mappedBase);
|
||||
if (!entry)
|
||||
return NTLSTATUS_FAILURE;
|
||||
|
||||
NTL_DRIVER_INIT init = {0};
|
||||
return entry(ddk, &init);
|
||||
uintptr_t base = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
// Scans only the [runtime] section of drivers.ini and loads each filename immediately.
|
||||
static KSTATUS KiLoadRuntimeDriversFromConfig(const char* text, size_t length, const NTL_DDK* ddk) {
|
||||
int inRuntime = 0;
|
||||
size_t offset = 0;
|
||||
|
||||
while (offset < length) {
|
||||
size_t lineStart = offset;
|
||||
while (offset < length && text[offset] != '\n')
|
||||
++offset;
|
||||
size_t lineEnd = offset;
|
||||
if (offset < length)
|
||||
++offset;
|
||||
|
||||
const char* begin = text + lineStart;
|
||||
const char* end = text + lineEnd;
|
||||
KiDriverConfigTrim(&begin, &end);
|
||||
if (begin == end || *begin == ';' || *begin == '#')
|
||||
continue;
|
||||
|
||||
if (*begin == '[') {
|
||||
if (end[-1] != ']')
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
const char* sectionBegin = begin + 1;
|
||||
const char* sectionEnd = end - 1;
|
||||
KiDriverConfigTrim(§ionBegin, §ionEnd);
|
||||
inRuntime = KiDriverConfigSpanEquals(sectionBegin, sectionEnd, "runtime");
|
||||
continue;
|
||||
// Starts a preloaded boot driver by its configuration identity, not array position.
|
||||
static KSTATUS KiLoadBootDriver(const BOOT_INFO* bootInfo,
|
||||
const DM_DRIVER_CONFIG* driver) {
|
||||
const BOOT_FILE* files = (const BOOT_FILE*)(bootInfo->PhysicalMapBase +
|
||||
bootInfo->BootDrivers.FilesPhysical);
|
||||
const BOOT_FILE* found = NULL;
|
||||
for (uint32_t i = 0; i < bootInfo->BootDrivers.Count; ++i) {
|
||||
if (!strcmp(files[i].DriverId, driver->Id)) {
|
||||
found = &files[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!inRuntime)
|
||||
continue;
|
||||
|
||||
size_t nameLength = (size_t)(end - begin);
|
||||
if (nameLength == 0 || nameLength >= BOOT_FILE_NAME_MAX)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
for (const char* p = begin; p < end; ++p) {
|
||||
if (*p == '=' || *p == '/' || *p == '\\')
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
char name[BOOT_FILE_NAME_MAX];
|
||||
memcpy(name, begin, nameLength);
|
||||
name[nameLength] = '\0';
|
||||
DbgPrint("Found runtime driver: %s\n", name);
|
||||
|
||||
KSTATUS status = KiLoadRuntimeDriverByName(name, ddk);
|
||||
if (!KSUCCESS(status))
|
||||
DbgPrint("KiInitializeDrivers: runtime driver %s failed, status=0x%x\n", name, status);
|
||||
}
|
||||
|
||||
return NTLSTATUS_SUCCESS;
|
||||
if (!found || strcmp(found->Image, driver->Image)) return NTLSTATUS_INVALID_PARAMETER;
|
||||
uintptr_t base = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
// Initializes drivers.
|
||||
// Validates that the firmware preloaded exactly the configured boot modules.
|
||||
static bool KiCheckBootDriverHandoff(const BOOT_INFO* bootInfo, const DM_CONFIG* config) {
|
||||
const BOOT_FILE* files = (const BOOT_FILE*)(bootInfo->PhysicalMapBase +
|
||||
bootInfo->BootDrivers.FilesPhysical);
|
||||
uint32_t expected = 0;
|
||||
for (uint32_t i = 0; i < config->DriverCount; ++i) {
|
||||
const DM_DRIVER_CONFIG* driver = &config->Drivers[i];
|
||||
if (driver->Phase != DmStartBoot) continue;
|
||||
++expected;
|
||||
uint32_t occurrences = 0;
|
||||
for (uint32_t j = 0; j < bootInfo->BootDrivers.Count; ++j) {
|
||||
if (!strcmp(files[j].DriverId, driver->Id) &&
|
||||
!strcmp(files[j].Image, driver->Image)) ++occurrences;
|
||||
}
|
||||
if (occurrences != 1) return false;
|
||||
}
|
||||
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.
|
||||
static void KiRunDriverPhase(DM_CONFIG* config, const BOOT_INFO* bootInfo,
|
||||
DM_START_PHASE phase) {
|
||||
config->ActivePhase = phase;
|
||||
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);
|
||||
}
|
||||
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;
|
||||
++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 (changed) continue;
|
||||
if (waiting)
|
||||
KePanic(KE_PANIC_CODE_INIT,
|
||||
"Driver manager: no eligible drivers in phase %u (waiting=%u)\n",
|
||||
(unsigned)phase, waiting);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static DM_CONFIG* gDriverConfig;
|
||||
|
||||
static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
(void)hal;
|
||||
const NTL_DDK* ddk = IoGetDdk();
|
||||
DbgPrint("KiInitializeDrivers: Initializing drivers...\n");
|
||||
|
||||
// Boot drivers are page-backed raw files supplied by the bootloader.
|
||||
const BOOT_FILE* bootFiles = bootInfo->BootDrivers.FilesPhysical
|
||||
? (const BOOT_FILE*)(bootInfo->PhysicalMapBase + bootInfo->BootDrivers.FilesPhysical)
|
||||
: NULL;
|
||||
DM_CONFIG* config = (DM_CONFIG*)MmAllocatePool(sizeof(*config));
|
||||
if (!config)
|
||||
KePanic(KE_PANIC_CODE_INIT, "Driver manager: configuration allocation failed\n");
|
||||
const char* text = (const char*)(bootInfo->PhysicalMapBase +
|
||||
bootInfo->DriversIni.PhysicalBase);
|
||||
char error[96] = {0};
|
||||
if (!DmConfigParse(config, text, bootInfo->DriversIni.Length, error, sizeof(error)))
|
||||
KePanic(KE_PANIC_CODE_INIT, "Driver manager: invalid drivers.ini: %s\n", error);
|
||||
if (!KiCheckBootDriverHandoff(bootInfo, config))
|
||||
KePanic(KE_PANIC_CODE_INIT, "Driver manager: boot preloads do not match drivers.ini\n");
|
||||
|
||||
for (uint32_t i = 0; bootFiles && i < bootInfo->BootDrivers.Count; ++i) {
|
||||
const BOOT_FILE* file = &bootFiles[i];
|
||||
if (!file->PhysicalBase || !file->Length) {
|
||||
DbgPrint("KiInitializeDrivers: invalid boot driver descriptor at index %u\n", i);
|
||||
continue;
|
||||
}
|
||||
KSTATUS pnpStatus = IoPnpInitialize();
|
||||
if (!KSUCCESS(pnpStatus))
|
||||
KePanic(KE_PANIC_CODE_INIT, "PnP initialization failed (0x%x)\n", pnpStatus);
|
||||
|
||||
DbgPrint("KiInitializeDrivers: Loading boot driver %s\n", file->Name);
|
||||
void* rawPeBuffer = (void*)(bootInfo->PhysicalMapBase + file->PhysicalBase);
|
||||
KiRunDriverPhase(config, bootInfo, DmStartBoot);
|
||||
pnpStatus = IoPnpWaitForIdle(30000u);
|
||||
if (!KSUCCESS(pnpStatus))
|
||||
KePanic(KE_PANIC_CODE_INIT, "PnP boot startup did not settle (0x%x)\n", pnpStatus);
|
||||
|
||||
uintptr_t mappedBase = 0;
|
||||
KSTATUS st = LdrLoadKernelImage(rawPeBuffer, file->Length, &mappedBase);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("ERROR: Failed to map driver %s (0x%X)\n", file->Name, st);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!KSUCCESS(LdrResolveImports(mappedBase))) {
|
||||
DbgPrint("ERROR: Failed to resolve imports for %s\n", file->Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
KSTATUS registerStatus = LdrRegisterModule(file->Name, mappedBase);
|
||||
if (!KSUCCESS(registerStatus)) {
|
||||
DbgPrint("ERROR: Failed to register driver %s (0x%X)\n", file->Name, registerStatus);
|
||||
continue;
|
||||
}
|
||||
|
||||
DRIVER_ENTRY_FN entry = (DRIVER_ENTRY_FN)LdrGetEntryPoint(mappedBase);
|
||||
if (entry) {
|
||||
NTL_DRIVER_INIT init = {0};
|
||||
KSTATUS ds = entry(ddk, &init);
|
||||
if (!KSUCCESS(ds))
|
||||
DbgPrint("WARNING: Driver %s returned failure status 0x%X\n", file->Name, ds);
|
||||
}
|
||||
}
|
||||
|
||||
// runtime drivers.
|
||||
KSTATUS s;
|
||||
FILE_OBJECT* f;
|
||||
|
||||
s = KeInitializeSystemRootVolume();
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "KiInitializeDrivers: Failed to find system root volume (status %d)\n", s);
|
||||
}
|
||||
|
||||
|
||||
s = KeOpenSystemRootFile("drivers/drivers.ini", &f);
|
||||
if (s != NTLSTATUS_SUCCESS) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "KiInitializeDrivers: Failed to open drivers.ini on system root (status %d)\n", s);
|
||||
}
|
||||
|
||||
uint64_t fileSize = IoGetFileSize(f);
|
||||
if (fileSize == 0 || fileSize >= SIZE_MAX) {
|
||||
IoCloseFile(f);
|
||||
KePanic(KE_PANIC_CODE_INIT, "KiInitializeDrivers: drivers.ini has an invalid size.\n");
|
||||
}
|
||||
|
||||
size_t size = (size_t)fileSize;
|
||||
char* mem = (char*)MmAllocatePool(size + 1u);
|
||||
if (!mem) {
|
||||
IoCloseFile(f);
|
||||
KePanic(KE_PANIC_CODE_INIT, "KiInitializeDrivers: Failed to allocate drivers.ini buffer.\n");
|
||||
}
|
||||
|
||||
size_t got = 0;
|
||||
KSTATUS readStatus = IoReadFile(f, mem, size, &got);
|
||||
IoCloseFile(f);
|
||||
if (!KSUCCESS(readStatus) || got != size) {
|
||||
MmFreePool(mem);
|
||||
KePanic(KE_PANIC_CODE_INIT, "KiInitializeDrivers: Failed to read drivers.ini.\n");
|
||||
}
|
||||
mem[got] = '\0';
|
||||
|
||||
KSTATUS runtimeStatus = KiLoadRuntimeDriversFromConfig(mem, got, ddk);
|
||||
MmFreePool(mem);
|
||||
if (!KSUCCESS(runtimeStatus)) {
|
||||
KePanic(KE_PANIC_CODE_INIT,
|
||||
"KiInitializeDrivers: drivers.ini [runtime] is malformed, status=0x%x\n",
|
||||
runtimeStatus);
|
||||
}
|
||||
// Root volume readiness depends on real devices, not the driver module state.
|
||||
KSTATUS status = KeInitializeSystemRootVolume();
|
||||
if (!KSUCCESS(status))
|
||||
KePanic(KE_PANIC_CODE_INIT, "Driver manager: no system root (0x%x)\n", status);
|
||||
KiRunDriverPhase(config, bootInfo, DmStartRuntime);
|
||||
// Retain the authoritative graph and module states for the shutdown slice.
|
||||
gDriverConfig = config;
|
||||
}
|
||||
|
||||
// Phase Helper: Load and launch a process from the filesystem.
|
||||
@@ -442,6 +396,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
SYS_HANDLE volumeManagerHandle = SYS_HANDLE_INVALID;
|
||||
SYS_HANDLE inputManagerHandle = SYS_HANDLE_INVALID;
|
||||
SYS_HANDLE displayManagerHandle = SYS_HANDLE_INVALID;
|
||||
SYS_HANDLE registrationAuthorityHandle = SYS_HANDLE_INVALID;
|
||||
s = KeReferenceSystemRootVolume(&systemVolume);
|
||||
if (KSUCCESS(s)) {
|
||||
s = KeCreateHandle(proc, &systemVolume->Header,
|
||||
@@ -493,20 +448,33 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
ObDereferenceObject(&displayManager->Header);
|
||||
}
|
||||
}
|
||||
if (KSUCCESS(s)) {
|
||||
OBJECT* authority = (OBJECT*)0;
|
||||
s = KeSystemServiceCreateRegistrationAuthority(SYS_SERVICE_RESOURCE, &authority);
|
||||
if (KSUCCESS(s)) {
|
||||
s = KeCreateHandle(proc, authority,
|
||||
SYS_RIGHT_DUPLICATE | SYS_RIGHT_DERIVE | SYS_RIGHT_TRANSFER |
|
||||
SYS_RIGHT_QUERY | SYS_SERVICE_REGISTRATION_RIGHT_REGISTER |
|
||||
SYS_SERVICE_REGISTRATION_RIGHT_UNREGISTER,
|
||||
®istrationAuthorityHandle);
|
||||
ObDereferenceObject(authority);
|
||||
}
|
||||
}
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KiLaunchUserProcess: Failed to create bootstrap startup capabilities. Status: %d\n", s);
|
||||
IoCloseFile(f);
|
||||
ObDereferenceObject(&proc->Header);
|
||||
return 0;
|
||||
}
|
||||
SYS_STARTUP_CAPABILITY startupCapabilities[5] = {
|
||||
{ SYS_STARTUP_CAP_SYSTEM_VOLUME, systemVolumeHandle },
|
||||
{ SYS_STARTUP_CAP_SYSTEM_VOLUME_NAMESPACE, namespaceVolumeHandle },
|
||||
{ SYS_STARTUP_CAP_VOLUME_MANAGER, volumeManagerHandle },
|
||||
{ SYS_STARTUP_CAP_INPUT_MANAGER, inputManagerHandle },
|
||||
{ SYS_STARTUP_CAP_DISPLAY_MANAGER, displayManagerHandle },
|
||||
SYS_STARTUP_CAPABILITY startupCapabilities[6] = {
|
||||
{ NTL_BOOT_CAP_SYSTEM_VOLUME, systemVolumeHandle },
|
||||
{ NTL_BOOT_CAP_NAMESPACE_ROOT, namespaceVolumeHandle },
|
||||
{ NTL_BOOT_CAP_VOLUME_MANAGER, volumeManagerHandle },
|
||||
{ NTL_BOOT_CAP_INPUT_MANAGER, inputManagerHandle },
|
||||
{ NTL_BOOT_CAP_DISPLAY_POLICY, displayManagerHandle },
|
||||
{ NTL_BOOT_CAP_RESOURCE_REGISTRATION, registrationAuthorityHandle },
|
||||
};
|
||||
s = KeSetProcessStartupCapabilities(proc, startupCapabilities, 5);
|
||||
s = KeSetProcessStartupCapabilities(proc, startupCapabilities, 6);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("KiLaunchUserProcess: Failed to install startup capabilities. Status: %d\n", s);
|
||||
IoCloseFile(f);
|
||||
@@ -538,16 +506,20 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
proc->Flags |= KE_PROCESS_FLAG_TERMINATION_PROTECTED;
|
||||
proc->ImageBase = imageBase;
|
||||
proc->ImageSize = LdrGetMappedImageSize(proc, imageBase);
|
||||
|
||||
uintptr_t entryPoint = LdrGetEntryPoint(imageBase);
|
||||
|
||||
KePowerSetInitProcess(proc);
|
||||
|
||||
// Create the main thread last. KeCreateThread queues it before returning.
|
||||
const KE_THREAD_CREATE_PARAMETERS threadParameters =
|
||||
KE_THREAD_CREATE_NAMED_NORMAL(PriorityNormal, proc->Name);
|
||||
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);
|
||||
proc->ImageBase = 0;
|
||||
proc->ImageSize = 0;
|
||||
@@ -562,16 +534,33 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) {
|
||||
return proc;
|
||||
}
|
||||
|
||||
static void KiFlushRegisteredDisk(uint8_t disk, DEVICE_OBJECT* device, void* context) {
|
||||
(void)device;
|
||||
const char* phase = (const char*)context;
|
||||
KSTATUS st = IoFlushDisk(disk);
|
||||
if (!KSUCCESS(st) && st != NTLSTATUS_NOT_FOUND)
|
||||
DbgPrint("shutdown: %s disk %u flush status 0x%x\n", phase, (unsigned)disk, st);
|
||||
}
|
||||
|
||||
static void KiFlushRegisteredDisks(const char* phase) {
|
||||
KSTATUS st = IoEnumerateDiskDevices(KiFlushRegisteredDisk, (void*)phase);
|
||||
if (!KSUCCESS(st))
|
||||
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");
|
||||
|
||||
KiRunEarlyKernelSelfTests();
|
||||
|
||||
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);
|
||||
KeTimeReloadSettings();
|
||||
|
||||
KiInitializeSwapFromSettings();
|
||||
@@ -579,7 +568,7 @@ void SystemInitThread(void* arg) {
|
||||
KiReclaimBootloaderMemory(args->BootInfo);
|
||||
|
||||
if (args->BootConfig.Debug & KE_DEBUG_SELFTEST)
|
||||
KiRunKernelSelfTests(args->Hal);
|
||||
KiRunKernelSelfTests();
|
||||
|
||||
// Launch the bootstrap service manager. Its allocated PID is not a system contract.
|
||||
PROCESS* initProcess = KiLaunchUserProcess("system/init.exe", args->BootConfig.CommandLine);
|
||||
@@ -588,12 +577,23 @@ void SystemInitThread(void* arg) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: Failed to start system/init.exe.\n");
|
||||
}
|
||||
|
||||
KeWaitForEvent(initProcess->ExitEvent, 0);
|
||||
EVENT* exits[2] = { KePowerCompletionEvent(), initProcess->ExitEvent };
|
||||
uint32_t signaled = 0;
|
||||
KSTATUS waitStatus = KeWaitForMultipleEvents(exits, 2u, false,
|
||||
SYS_WAIT_TIMEOUT_INFINITE, &signaled);
|
||||
if (!KSUCCESS(waitStatus) || signaled != 0u)
|
||||
KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: init exited without power commit\n");
|
||||
(void)KeWaitForEvent(initProcess->ExitEvent, false);
|
||||
int exitCode = initProcess->ExitCode;
|
||||
if (exitCode != 0) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: init.exe exited with code %d.\n", exitCode);
|
||||
}
|
||||
DbgPrint("SystemInitThread: init.exe exited with code %d.\n", exitCode);
|
||||
DbgPrint("SystemInitThread: power commit accepted; init exited with code %d.\n", exitCode);
|
||||
uint32_t action = KePowerCommittedAction();
|
||||
if (!action) KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: missing power action\n");
|
||||
KSTATUS flush = MmFileCacheFlushAll();
|
||||
if (!KSUCCESS(flush)) DbgPrint("shutdown: cache flush status 0x%x\n", flush);
|
||||
KiFlushRegisteredDisks("initial");
|
||||
ObDereferenceObject(&initProcess->Header);
|
||||
|
||||
if (args->BootConfig.Debug & (KE_DEBUG_CONSOLE | KE_DEBUG_FILE_LOG)) {
|
||||
@@ -601,6 +601,20 @@ void SystemInitThread(void* arg) {
|
||||
if (!KSUCCESS(logStatus))
|
||||
DbgPrint("debuglog: shutdown flush failed st=0x%x\n", logStatus);
|
||||
}
|
||||
flush = MmFileCacheFlushAll();
|
||||
if (!KSUCCESS(flush)) DbgPrint("shutdown: final cache flush status 0x%x\n", flush);
|
||||
KiFlushRegisteredDisks("final");
|
||||
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();
|
||||
if (action == SYS_POWER_ACTION_RESTART) {
|
||||
if (!gKmainHal->Power.Reset)
|
||||
KePanic(KE_PANIC_CODE_INIT, "shutdown: reset HAL callback unavailable\n");
|
||||
gKmainHal->Power.Reset();
|
||||
}
|
||||
gKmainHal->Power.Shutdown();
|
||||
MmFreePool(args);
|
||||
}
|
||||
@@ -620,9 +634,11 @@ static bool KiValidateBootFile(const BOOT_FILE* file) {
|
||||
return false;
|
||||
|
||||
uint64_t capacity = (uint64_t)file->PageCount * PAGE_SIZE;
|
||||
if ((uint64_t)file->Length + 1u > capacity || file->Name[0] == '\0')
|
||||
if ((uint64_t)file->Length + 1u > capacity)
|
||||
return false;
|
||||
return memchr(file->Name, '\0', sizeof(file->Name)) != NULL;
|
||||
return file->DriverId[0] != '\0' && file->Image[0] != '\0' &&
|
||||
memchr(file->DriverId, '\0', sizeof(file->DriverId)) &&
|
||||
memchr(file->Image, '\0', sizeof(file->Image));
|
||||
}
|
||||
|
||||
// Returns whether one fixed core-image descriptor fits inside its page-backed physical allocation.
|
||||
@@ -657,10 +673,20 @@ static bool KiValidateBootInfo(const BOOT_INFO* bootInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t driverIniCapacity = (uint64_t)bootInfo->DriversIni.PageCount * PAGE_SIZE;
|
||||
if (!KiValidateBootPageRange(bootInfo->DriversIni.PhysicalBase,
|
||||
bootInfo->DriversIni.PageCount) ||
|
||||
bootInfo->DriversIni.Length == 0 ||
|
||||
bootInfo->DriversIni.Length > DM_CONFIG_MAX_BYTES ||
|
||||
(uint64_t)bootInfo->DriversIni.Length + 1u > driverIniCapacity ||
|
||||
bootInfo->DriversIni.PhysicalBase > UINTPTR_MAX - bootInfo->PhysicalMapBase)
|
||||
return false;
|
||||
|
||||
uint64_t driverListCapacity = (uint64_t)bootInfo->BootDrivers.PageCount * PAGE_SIZE;
|
||||
uint64_t driverListBytes = (uint64_t)bootInfo->BootDrivers.Count * sizeof(BOOT_FILE);
|
||||
if (!KiValidateBootPageRange(bootInfo->BootDrivers.FilesPhysical, bootInfo->BootDrivers.PageCount) ||
|
||||
bootInfo->BootDrivers.Count == 0 || driverListBytes > driverListCapacity ||
|
||||
bootInfo->BootDrivers.Count == 0 || bootInfo->BootDrivers.Count > DM_MAX_DRIVERS ||
|
||||
driverListBytes > driverListCapacity ||
|
||||
bootInfo->BootDrivers.FilesPhysical > UINTPTR_MAX - bootInfo->PhysicalMapBase) {
|
||||
return false;
|
||||
}
|
||||
@@ -825,7 +851,8 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
KePanic(KE_PANIC_CODE_INIT, "SMP: failed to admit APs to scheduler, status=0x%x\n", smpSchedStatus);
|
||||
}
|
||||
|
||||
KiRunCoreHardeningSelfTests();
|
||||
if (bootConfig.Debug & KE_DEBUG_SELFTEST)
|
||||
KiCheckBootState();
|
||||
|
||||
// Pack the arguments for the init thread.
|
||||
SYSTEM_INIT_ARGS* initArgs = MmAllocatePool(sizeof(SYSTEM_INIT_ARGS));
|
||||
|
||||
Reference in new issue
Block a user