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:
maksw committed 2026-10-26 10:08:03 +01:00
1 parent c0ad63c27f
commit d36f19509c
160 files changed
+6563 -7366

No files matched your search

File diff suppressed because it is too large. Load diff
+27
View File
@@ -0,0 +1,27 @@
// Service restart budget: three automatic attempts in any sliding five-minute interval.
#pragma once
#include <stdbool.h>
#include <stdint.h>
typedef struct INIT_RESTART_BUDGET {
uint64_t Attempts[3];
uint32_t Count;
} INIT_RESTART_BUDGET;
static inline bool InitConsumeRestartBudget(INIT_RESTART_BUDGET* budget,
uint64_t now, uint64_t frequency) {
if (!budget || !frequency || budget->Count > 3u ||
frequency > UINT64_MAX / 300u) return false;
uint64_t window = frequency * 300u;
uint32_t keep = 0;
for (uint32_t i = 0; i < budget->Count; ++i) {
uint64_t started = budget->Attempts[i];
if (now >= started && now - started < window)
budget->Attempts[keep++] = started;
}
budget->Count = keep;
if (keep == 3u) return false;
budget->Attempts[budget->Count++] = now;
return true;
}
+128 -61
View File
@@ -1,12 +1,12 @@
// Init service-configuration parser. Malformed or ambiguous service policy is rejected at boot.
#include "service_config.h"
#include <ntlite/bootstrap_capabilities.h>
#include <stddef.h>
#include <string.h>
#include <ntlite/status.h>
#define INIT_SERVICE_KEY_TYPE 0x00000001u
#define INIT_SERVICE_KEY_IMAGE 0x00000002u
#define INIT_SERVICE_KEY_START 0x00000004u
#define INIT_SERVICE_KEY_CRITICAL 0x00000008u
@@ -14,7 +14,9 @@
#define INIT_SERVICE_KEY_READY_TIMEOUT 0x00000020u
#define INIT_SERVICE_KEY_STOP_TIMEOUT 0x00000040u
#define INIT_SERVICE_KEY_REQUIRES 0x00000080u
#define INIT_SERVICE_REQUIRED_KEYS 0x000000FFu
#define INIT_SERVICE_KEY_GRANTS 0x00000100u
#define INIT_SERVICE_KEY_EXPORTS 0x00000200u
#define INIT_SERVICE_REQUIRED_KEYS 0x000003FEu
typedef struct INIT_PARSED_SERVICE {
INIT_SERVICE_DESCRIPTOR Descriptor;
@@ -155,17 +157,65 @@ static bool parse_requires(char* value, INIT_PARSED_SERVICE* service) {
return true;
}
// Parses explicit capability-source names without associating them with service roles.
static bool parse_grants(char* value, INIT_PARSED_SERVICE* service) {
service->Descriptor.GrantCount = 0;
if (!*value) return true;
char* cursor = value;
for (;;) {
char* comma = strchr(cursor, ',');
if (comma) *comma = '\0';
char* name = trim_left(cursor);
trim_right(name);
size_t length = strlen(name);
if (length == 0 || length > INIT_SERVICE_GRANT_NAME_MAX ||
service->Descriptor.GrantCount >= INIT_SERVICE_GRANT_MAX) return false;
for (size_t i = 0; i < length; ++i)
if (!is_service_id_char(name[i])) return false;
if (!strchr(name, '.') || name[0] == '.' || name[length - 1u] == '.') return false;
if (strcmp(name, "service.control") == 0 || strncmp(name, "publish.", 8u) == 0)
return false;
for (uint32_t i = 0; i < service->Descriptor.GrantCount; ++i)
if (strcmp(service->Descriptor.Grants[i], name) == 0) return false;
if (!copy_bounded(service->Descriptor.Grants[service->Descriptor.GrantCount],
sizeof(service->Descriptor.Grants[0]), name)) return false;
++service->Descriptor.GrantCount;
if (!comma) break;
cursor = comma + 1;
if (!*cursor) return false;
}
return true;
}
// Reads the declared READY export names, which are an exact startup contract.
static bool parse_exports(char* value, INIT_PARSED_SERVICE* service) {
service->Descriptor.ExportCount = 0;
if (!*value) return true;
char* cursor = value;
for (;;) {
char* comma = strchr(cursor, ',');
if (comma) *comma = '\0';
char* name = trim_left(cursor);
trim_right(name);
if (!NtlServiceExportNameValid(name) ||
service->Descriptor.ExportCount >= INIT_SERVICE_EXPORT_MAX) return false;
for (uint32_t i = 0; i < service->Descriptor.ExportCount; ++i)
if (strcmp(name, service->Descriptor.Exports[i]) == 0) return false;
if (!copy_bounded(service->Descriptor.Exports[service->Descriptor.ExportCount],
sizeof(service->Descriptor.Exports[0]), name)) return false;
++service->Descriptor.ExportCount;
if (!comma) break;
cursor = comma + 1;
if (!*cursor) return false;
}
return true;
}
// Applies one known key to the current service and rejects duplicates or invalid values.
static bool parse_service_key(INIT_PARSED_SERVICE* service, char* key, char* value) {
uint32_t bit = 0;
if (strcmp(key, "type") == 0) {
bit = INIT_SERVICE_KEY_TYPE;
if (strcmp(value, "resource") == 0) service->Descriptor.Type = InitServiceTypeResource;
else if (strcmp(value, "dwm") == 0) service->Descriptor.Type = InitServiceTypeDwm;
else if (strcmp(value, "generic") == 0) service->Descriptor.Type = InitServiceTypeGeneric;
else return false;
} else if (strcmp(key, "image") == 0) {
if (strcmp(key, "image") == 0) {
bit = INIT_SERVICE_KEY_IMAGE;
if (!validate_image_path(value) ||
!copy_bounded(service->Descriptor.ImagePath, sizeof(service->Descriptor.ImagePath), value))
@@ -192,6 +242,12 @@ static bool parse_service_key(INIT_PARSED_SERVICE* service, char* key, char* val
} else if (strcmp(key, "requires") == 0) {
bit = INIT_SERVICE_KEY_REQUIRES;
if (!parse_requires(value, service)) return false;
} else if (strcmp(key, "grants") == 0) {
bit = INIT_SERVICE_KEY_GRANTS;
if (!parse_grants(value, service)) return false;
} else if (strcmp(key, "exports") == 0) {
bit = INIT_SERVICE_KEY_EXPORTS;
if (!parse_exports(value, service)) return false;
} else {
return false;
}
@@ -270,7 +326,8 @@ static KSTATUS parse_services_ini(char* buffer, uint32_t* serviceCountOut, uint3
line = saved ? end + 1u : end;
}
if (serviceCount == 0) return NTLSTATUS_INVALID_PARAMETER;
if (serviceCount == 0)
return NTLSTATUS_INVALID_PARAMETER;
*serviceCountOut = serviceCount;
return NTLSTATUS_SUCCESS;
}
@@ -279,14 +336,59 @@ static KSTATUS parse_services_ini(char* buffer, uint32_t* serviceCountOut, uint3
static KSTATUS validate_services(uint32_t serviceCount,
INIT_SERVICE_CONFIG* configOut,
uint32_t* errorLineOut) {
uint32_t resourceCount = 0;
uint16_t resourceIndex = 0;
uint32_t dwmCount = 0;
uint16_t dwmIndex = UINT16_MAX;
memset(configOut, 0, sizeof(*configOut));
configOut->ResourceServiceIndex = UINT16_MAX;
configOut->DwmServiceIndex = UINT16_MAX;
static const char* const bootGrants[] = {
NTL_BOOT_CAP_NAMESPACE_ROOT, NTL_BOOT_CAP_VOLUME_MANAGER, NTL_BOOT_CAP_INPUT_MANAGER,
NTL_BOOT_CAP_DISPLAY_POLICY, NTL_BOOT_CAP_DISPLAY_PRESENT, NTL_BOOT_CAP_RESOURCE_REGISTRATION
};
for (uint32_t i = 0; i < serviceCount; ++i) {
INIT_SERVICE_DESCRIPTOR* descriptor = &gParsedServices[i].Descriptor;
for (uint32_t g = 0; g < descriptor->GrantCount; ++g) {
const char* name = descriptor->Grants[g];
bool known = false;
for (uint32_t b = 0; b < sizeof(bootGrants) / sizeof(bootGrants[0]); ++b)
if (strcmp(name, bootGrants[b]) == 0) known = true;
if (known) continue;
if (strncmp(name, "boot.", 5u) == 0) {
if (errorLineOut) *errorLineOut = gParsedServices[i].SectionLine;
return NTLSTATUS_INVALID_PARAMETER;
}
// Service export sources require an explicit dependency; the longest
// matching service ID owns a qualified export name.
int32_t provider = -1;
size_t prefixLength = 0;
for (uint32_t j = 0; j < serviceCount; ++j) {
const char* id = gParsedServices[j].Descriptor.Id;
size_t length = strlen(id);
if (length > prefixLength && strncmp(name, id, length) == 0 &&
name[length] == '.' && name[length + 1u] != '\0') {
provider = (int32_t)j;
prefixLength = length;
}
}
bool declaredDependency = false;
if (provider >= 0 && (uint32_t)provider != i &&
gParsedServices[provider].Descriptor.StartPolicy == InitServiceStartAuto) {
for (uint32_t d = 0; d < gParsedServices[i].DependencyCount; ++d)
if (strcmp(gParsedServices[i].DependencyIds[d],
gParsedServices[provider].Descriptor.Id) == 0)
declaredDependency = true;
}
if (declaredDependency) {
const char* exportName = name + prefixLength + 1u;
bool declaredExport = false;
const INIT_SERVICE_DESCRIPTOR* source = &gParsedServices[provider].Descriptor;
for (uint32_t e = 0; e < source->ExportCount; ++e)
if (strcmp(source->Exports[e], exportName) == 0) declaredExport = true;
if (!declaredExport) declaredDependency = false;
}
if (!declaredDependency) {
if (errorLineOut) *errorLineOut = gParsedServices[i].SectionLine;
return NTLSTATUS_INVALID_PARAMETER;
}
}
}
for (uint32_t i = 0; i < serviceCount; ++i) {
INIT_PARSED_SERVICE* parsed = &gParsedServices[i];
@@ -297,6 +399,13 @@ static KSTATUS validate_services(uint32_t serviceCount,
INIT_SERVICE_DESCRIPTOR* descriptor = &configOut->Services[i];
*descriptor = parsed->Descriptor;
for (uint32_t e = 0; e < descriptor->ExportCount; ++e) {
if (strlen(descriptor->Id) + 1u + strlen(descriptor->Exports[e]) >
INIT_SERVICE_GRANT_NAME_MAX) {
if (errorLineOut) *errorLineOut = parsed->SectionLine;
return NTLSTATUS_NAME_TOO_LONG;
}
}
descriptor->DependencyCount = parsed->DependencyCount;
for (uint32_t d = 0; d < parsed->DependencyCount; ++d) {
int32_t dependency = find_parsed_service(gParsedServices, serviceCount, parsed->DependencyIds[d]);
@@ -306,48 +415,6 @@ static KSTATUS validate_services(uint32_t serviceCount,
}
descriptor->Dependencies[d] = (uint16_t)dependency;
}
if (descriptor->Type == InitServiceTypeResource) {
++resourceCount;
resourceIndex = (uint16_t)i;
} else if (descriptor->Type == InitServiceTypeDwm) {
++dwmCount;
dwmIndex = (uint16_t)i;
}
}
if (resourceCount != 1u || dwmCount > 1u) return NTLSTATUS_INVALID_PARAMETER;
INIT_SERVICE_DESCRIPTOR* resource = &configOut->Services[resourceIndex];
if (resource->StartPolicy != InitServiceStartAuto || !resource->Critical ||
resource->RestartPolicy != InitServiceRestartNever || resource->DependencyCount != 0u) {
if (errorLineOut) *errorLineOut = gParsedServices[resourceIndex].SectionLine;
return NTLSTATUS_INVALID_PARAMETER;
}
if (dwmCount == 1u) {
INIT_SERVICE_DESCRIPTOR* dwm = &configOut->Services[dwmIndex];
bool requiresResource = false;
for (uint32_t d = 0; d < dwm->DependencyCount; ++d)
if (dwm->Dependencies[d] == resourceIndex) requiresResource = true;
if (dwm->StartPolicy == InitServiceStartAuto &&
(dwm->Critical || dwm->RestartPolicy != InitServiceRestartNever || !requiresResource)) {
if (errorLineOut) *errorLineOut = gParsedServices[dwmIndex].SectionLine;
return NTLSTATUS_INVALID_PARAMETER;
}
}
// The generic adapter publishes READY listeners through RSSRV, so automatic generic services require it.
for (uint32_t i = 0; i < serviceCount; ++i) {
INIT_SERVICE_DESCRIPTOR* generic = &configOut->Services[i];
if (generic->Type != InitServiceTypeGeneric || generic->StartPolicy != InitServiceStartAuto) continue;
bool requiresResource = false;
for (uint32_t d = 0; d < generic->DependencyCount; ++d)
if (generic->Dependencies[d] == resourceIndex) requiresResource = true;
if (generic->Critical || generic->RestartPolicy != InitServiceRestartNever || !requiresResource) {
if (errorLineOut) *errorLineOut = gParsedServices[i].SectionLine;
return NTLSTATUS_INVALID_PARAMETER;
}
}
for (uint32_t i = 0; i < serviceCount; ++i) {
@@ -406,8 +473,8 @@ static KSTATUS validate_services(uint32_t serviceCount,
}
configOut->ServiceCount = serviceCount;
configOut->ResourceServiceIndex = resourceIndex;
configOut->DwmServiceIndex = dwmIndex;
if (configOut->StartupCount + 2u > SYS_WAIT_MANY_MAX_HANDLES)
return NTLSTATUS_LIMIT_REACHED;
return NTLSTATUS_SUCCESS;
}
+8 -9
View File
@@ -5,18 +5,16 @@
#include <stdbool.h>
#include <stdint.h>
#include <ntlite/syscall.h>
#include <ntlite/service_control.h>
#define INIT_SERVICES_PATH "system/services.ini"
#define INIT_SERVICES_MAX_FILE_BYTES (64u * 1024u)
#define INIT_SERVICE_MAX_COUNT 32u
#define INIT_SERVICE_ID_MAX 31u
#define INIT_SERVICE_DEPENDENCY_MAX 8u
typedef enum INIT_SERVICE_TYPE {
InitServiceTypeResource = 0,
InitServiceTypeDwm,
InitServiceTypeGeneric,
} INIT_SERVICE_TYPE;
#define INIT_SERVICE_GRANT_MAX 8u
#define INIT_SERVICE_GRANT_NAME_MAX SYS_STARTUP_CAPABILITY_NAME_MAX
#define INIT_SERVICE_EXPORT_MAX 8u
typedef enum INIT_SERVICE_START_POLICY {
InitServiceStartAuto = 0,
@@ -31,7 +29,6 @@ typedef enum INIT_SERVICE_RESTART_POLICY {
typedef struct INIT_SERVICE_DESCRIPTOR {
char Id[INIT_SERVICE_ID_MAX + 1u];
char ImagePath[SYS_PATH_MAX];
INIT_SERVICE_TYPE Type;
INIT_SERVICE_START_POLICY StartPolicy;
bool Critical;
INIT_SERVICE_RESTART_POLICY RestartPolicy;
@@ -39,6 +36,10 @@ typedef struct INIT_SERVICE_DESCRIPTOR {
uint32_t StopTimeoutMilliseconds;
uint32_t DependencyCount;
uint16_t Dependencies[INIT_SERVICE_DEPENDENCY_MAX];
uint32_t GrantCount;
char Grants[INIT_SERVICE_GRANT_MAX][INIT_SERVICE_GRANT_NAME_MAX + 1u];
uint32_t ExportCount;
char Exports[INIT_SERVICE_EXPORT_MAX][NTL_SERVICE_EXPORT_NAME_MAX + 1u];
} INIT_SERVICE_DESCRIPTOR;
typedef struct INIT_SERVICE_CONFIG {
@@ -46,8 +47,6 @@ typedef struct INIT_SERVICE_CONFIG {
uint16_t StartupOrder[INIT_SERVICE_MAX_COUNT];
uint32_t ServiceCount;
uint32_t StartupCount;
uint16_t ResourceServiceIndex;
uint16_t DwmServiceIndex;
} INIT_SERVICE_CONFIG;
// Loads, strictly parses, and validates services.ini beneath the bootstrap system volume.