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
@@ -1,18 +1,22 @@
|
||||
// Native service-manager control protocol.
|
||||
// Native service-manager control protocol. Names determine exported handle identity.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <ntlite/port.h>
|
||||
#include <ntlite/status.h>
|
||||
|
||||
#define NTL_SERVICE_CONTROL_VERSION 2u
|
||||
#define NTL_SERVICE_CONTROL_VERSION 3u
|
||||
#define NTL_SERVICE_CONTROL_READY 1u
|
||||
#define NTL_SERVICE_CONTROL_STOP 2u
|
||||
#define NTL_SERVICE_EXPORT_NAME_MAX 31u
|
||||
|
||||
#define NTL_SERVICE_CONTROL_READY 1u
|
||||
#define NTL_SERVICE_CONTROL_STOP 2u
|
||||
|
||||
// Service-control messages are notifications over a private Port connection.
|
||||
// READY transfers ExportCount service-defined handles whose meaning is fixed by
|
||||
// the service type known to the manager. Other operations transfer no handles.
|
||||
// READY transfers one handle for each named entry in ExportNames. The entry at
|
||||
// index i names the handle at transfer index i; its position has no semantic
|
||||
// meaning. STOP transfers zero handles and carries only zeroed export names.
|
||||
// Each message is wholly self-contained so the Port cannot retain user pointers.
|
||||
typedef struct NTL_SERVICE_CONTROL_MESSAGE {
|
||||
uint32_t Size;
|
||||
uint32_t Version;
|
||||
@@ -20,4 +24,73 @@ typedef struct NTL_SERVICE_CONTROL_MESSAGE {
|
||||
uint32_t ExportCount;
|
||||
KSTATUS Status;
|
||||
uint32_t Reserved[3];
|
||||
char ExportNames[SYS_PORT_MAX_TRANSFER_HANDLES][NTL_SERVICE_EXPORT_NAME_MAX + 1u];
|
||||
} NTL_SERVICE_CONTROL_MESSAGE;
|
||||
|
||||
// Accepts the deliberately restricted, case-sensitive capability-name grammar.
|
||||
static inline bool NtlServiceExportNameValid(const char* name) {
|
||||
if (!name || !name[0]) return false;
|
||||
for (uint32_t i = 0; i <= NTL_SERVICE_EXPORT_NAME_MAX; ++i) {
|
||||
char c = name[i];
|
||||
if (!c) return i != 0;
|
||||
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') || c == '_' || c == '-' || c == '.'))
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Labels an already counted READY transfer without assigning authority to its name.
|
||||
static inline bool NtlServiceControlNameExport(NTL_SERVICE_CONTROL_MESSAGE* message,
|
||||
uint32_t index, const char* name) {
|
||||
if (!message || message->Operation != NTL_SERVICE_CONTROL_READY ||
|
||||
index >= message->ExportCount || index >= SYS_PORT_MAX_TRANSFER_HANDLES ||
|
||||
!NtlServiceExportNameValid(name))
|
||||
return false;
|
||||
memset(message->ExportNames[index], 0, sizeof(message->ExportNames[index]));
|
||||
size_t length = strlen(name);
|
||||
memcpy(message->ExportNames[index], name, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validates wire size, exact transfer count, export names, and zeroed unused entries.
|
||||
static inline bool NtlServiceControlValid(const NTL_SERVICE_CONTROL_MESSAGE* message,
|
||||
uint32_t operation, uint32_t handleCount) {
|
||||
if (!message || message->Size != sizeof(*message) ||
|
||||
message->Version != NTL_SERVICE_CONTROL_VERSION || message->Operation != operation ||
|
||||
(operation != NTL_SERVICE_CONTROL_READY && operation != NTL_SERVICE_CONTROL_STOP) ||
|
||||
message->ExportCount != handleCount || handleCount > SYS_PORT_MAX_TRANSFER_HANDLES ||
|
||||
message->Reserved[0] || message->Reserved[1] || message->Reserved[2])
|
||||
return false;
|
||||
if (operation == NTL_SERVICE_CONTROL_STOP &&
|
||||
(handleCount != 0u || message->Status != NTLSTATUS_SUCCESS))
|
||||
return false;
|
||||
for (uint32_t i = 0; i < SYS_PORT_MAX_TRANSFER_HANDLES; ++i) {
|
||||
const char* name = message->ExportNames[i];
|
||||
if (i >= handleCount) {
|
||||
for (uint32_t j = 0; j <= NTL_SERVICE_EXPORT_NAME_MAX; ++j)
|
||||
if (name[j]) return false;
|
||||
continue;
|
||||
}
|
||||
if (!NtlServiceExportNameValid(name)) return false;
|
||||
// The complete fixed-size wire representation has one canonical encoding.
|
||||
uint32_t end = 0;
|
||||
while (name[end]) ++end;
|
||||
for (uint32_t j = end + 1u; j <= NTL_SERVICE_EXPORT_NAME_MAX; ++j)
|
||||
if (name[j]) return false;
|
||||
for (uint32_t earlier = 0; earlier < i; ++earlier)
|
||||
if (strcmp(name, message->ExportNames[earlier]) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Finds the transfer index for a validated named READY export.
|
||||
static inline int32_t NtlServiceControlFindExport(const NTL_SERVICE_CONTROL_MESSAGE* message,
|
||||
const char* name) {
|
||||
if (!message || !NtlServiceExportNameValid(name) ||
|
||||
message->ExportCount > SYS_PORT_MAX_TRANSFER_HANDLES)
|
||||
return -1;
|
||||
for (uint32_t i = 0; i < message->ExportCount; ++i)
|
||||
if (strcmp(message->ExportNames[i], name) == 0) return (int32_t)i;
|
||||
return -1;
|
||||
}
|
||||
Reference in new issue
Block a user