introduce a stable NTL_DDK driver ABI to replace direct HAL_API and kernel-header access in drivers, add code/kernel/io_ddk.c and code/public/ntlite/ddk/ headers, change DriverEntry to take (const NTL_DDK*, NTL_DRIVER_INIT*), update kmain to build the DDK once via IoInitializeDdk/IoGetDdk and hand it to both boot and runtime drivers, downgrade code/public/ntlite/ddi/io_driver.h to a legacy I/O model header pulling from ntlite/ddk instead of kernel internals, move code/third_party/lwip into code/drivers/net/lwip/third_party, fix up lwip_sources.txt and build.c include paths to match, split build.c's single CFLAGS macro into COMMON/KERNEL/USER/BOOT/DRIVER cflags.

This commit is contained in:
maksw committed 2026-07-01 23:19:11 +02:00
1 parent 08329516ba
commit 485a6bbfe7
385 files changed
+1822 -1079

No files matched your search

+4 -54
View File
@@ -3,61 +3,11 @@
#pragma once
// io_async.h - waitable asynchronous I/O request objects.
// Async request objects own the common completion, APC, wait, query, and
// cancellation surface used by file and socket I/O.
// cancellation surface used by file and socket I/O. The shared request layout is
// currently DDK-visible for legacy kernel-mode drivers; this private header owns
// only the kernel implementation entry points.
#include <stddef.h>
#include <stdint.h>
#include <kernel/ke_list.h>
#include <kernel/ob_object.h>
#include <ntlite/status.h>
struct EVENT;
struct KAPC;
struct IRP;
typedef struct MM_LOCKED_USER_BUFFER MM_LOCKED_USER_BUFFER;
// Completion status visible to async callers.
typedef struct IO_STATUS_BLOCK {
volatile KSTATUS Status;
volatile size_t Information;
} IO_STATUS_BLOCK;
typedef enum IO_ASYNC_REQUEST_STATE {
IoAsyncRequestQueued = 0,
IoAsyncRequestRunning = 1,
IoAsyncRequestCompleted = 2,
IoAsyncRequestCancelled = 3,
} IO_ASYNC_REQUEST_STATE;
typedef struct IO_ASYNC_REQUEST_OBJECT IO_ASYNC_REQUEST_OBJECT;
typedef void (*IO_ASYNC_REQUEST_CLEANUP_ROUTINE)(IO_ASYNC_REQUEST_OBJECT* request,
void* context);
typedef KSTATUS (*IO_ASYNC_REQUEST_CANCEL_ROUTINE)(IO_ASYNC_REQUEST_OBJECT* request,
void* context);
// Common waitable async I/O request object.
struct IO_ASYNC_REQUEST_OBJECT {
OBJECT Header;
LIST_ENTRY Link;
IO_ASYNC_REQUEST_STATE State;
uint8_t CancelRequested;
struct EVENT* WaitEvent;
struct EVENT* CompletionEvent;
struct KAPC* CompletionApc;
IO_STATUS_BLOCK* Iosb;
IO_STATUS_BLOCK IosbSnapshot;
MM_LOCKED_USER_BUFFER* LockedBuffer;
MM_LOCKED_USER_BUFFER* LockedIosb;
struct IRP* Irp;
IO_ASYNC_REQUEST_CLEANUP_ROUTINE CleanupRoutine;
void* CleanupContext;
IO_ASYNC_REQUEST_CANCEL_ROUTINE CancelRoutine;
void* CancelContext;
};
#include <ntlite/ddk/async.h>
__declspec(dllexport) KSTATUS IoCreateAsyncRequest(size_t objectSize,
IO_ASYNC_REQUEST_CLEANUP_ROUTINE cleanupRoutine,
+14
View File
@@ -0,0 +1,14 @@
// Kernel DDK-table provider declarations.
#pragma once
#include <ntlite/ddk/ddk.h>
struct HAL_API;
typedef struct HAL_API HAL_API;
// Initializes the kernel-owned DDK table from platform services.
void IoInitializeDdk(const HAL_API* hal);
// Returns the kernel-owned DDK table passed to driver entrypoints.
const NTL_DDK* IoGetDdk(void);
+46 -233
View File
@@ -1,240 +1,53 @@
// Kernel io file declarations shared by implementation files and kernel clients.
// Kernel I/O file declarations shared by filesystem, cache, and syscall code.
#pragma once
// io_file.h - VFS layer
// Filesystem drivers register an IO_FILESYSTEM vtable via IoRegisterFilesystem.
// Kernel and user code open files through IoOpenFile.
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <ntlite/status.h>
#include <kernel/ob_object.h>
#include <kernel/ke_spinlock.h>
// io_file.h - VFS and filesystem provider interface.
// Current kernel-mode filesystem drivers still use the legacy file-provider
// layout. The shared declarations live in the DDK while the real provider split
// is being designed; this private header adds kernel-only async and lock entry
// points without redefining the shared types.
#include <ntlite/ddk/file.h>
#include <kernel/io_async.h>
#include <ntlite/string_view.h>
#include <ntlite/dirent.h>
#include <ntlite/file_stat.h>
// Kernel/filesystem code uses the public directory-entry ABI directly.
typedef SYS_DIR_ENTRY KDIR_ENTRY;
#define KDIR_NAME_MAX SYS_DIR_NAME_MAX
struct PROCESS;
// Native asynchronous filesystem completion. Filesystems that provide
// ReadAsync/WriteAsync accept the operation, return NTLSTATUS_PENDING, and later
// call Complete(CompleteContext, status, information). Filesystems without
// these callbacks fall back to the generic VFS async worker.
typedef void (*IO_FS_ASYNC_COMPLETE)(void* completeContext,
KSTATUS status,
size_t information);
// Filesystem-level cache and traversal statistics.
// Drivers map private metadata work onto these generic counters.
typedef struct IO_FILESYSTEM_STATS {
uint64_t PathLookups;
uint64_t PathCacheHits;
uint64_t PathCacheMisses;
uint64_t PathCacheStores;
uint64_t PathCacheInvalidations;
uint64_t PathCacheGeneration;
uint64_t DirectorySearches;
uint64_t DirectoryBlocksRead;
uint64_t DirectoryEntriesScanned;
uint64_t DataReadRuns;
uint64_t DataReadSectors;
uint64_t DataReadRunMerges;
uint64_t MaxDataReadSpanSectors;
} IO_FILESYSTEM_STATS;
// Stable identity for a file on a mounted filesystem.
// Filesystems that can provide this let higher layers cache file-backed
// objects by file identity instead of by one FILE_OBJECT instance.
typedef struct IO_FILE_IDENTITY {
uint64_t VolumeId;
uint64_t FileId;
uint64_t Generation;
uint64_t Size;
} IO_FILE_IDENTITY;
// Filesystem driver vtable - filled in by a filesystem driver.
typedef struct IO_FILESYSTEM {
// Open a file by absolute path (e.g. "apps\\shell.exe").
// Returns an opaque per-file driver cookie in* fileCtx.
KSTATUS (*Open)(struct IO_FILESYSTEM* fs,
SYS_STRING_VIEW path, void **fileCtx);
// Read up to 'size' bytes at 'offset' into 'buf'.
// Sets* bytesRead to actual bytes copied.
KSTATUS (*Read)(struct IO_FILESYSTEM* fs, void* fileCtx,
uint64_t offset, void* buf,
size_t size, size_t* bytesRead);
KSTATUS (*Write)(struct IO_FILESYSTEM* fs, void* fileCtx,
uint64_t offset, const void* buf,
size_t size, size_t* bytesWritten);
KSTATUS (*ReadAsync)(struct IO_FILESYSTEM* fs, void* fileCtx,
uint64_t offset, void* buf, size_t size,
IO_FS_ASYNC_COMPLETE complete,
void* completeContext);
KSTATUS (*WriteAsync)(struct IO_FILESYSTEM* fs, void* fileCtx,
uint64_t offset, const void* buf, size_t size,
IO_FS_ASYNC_COMPLETE complete,
void* completeContext);
// Create a new file at 'path'; returns an open fileCtx on success.
KSTATUS (*Create)(struct IO_FILESYSTEM* fs, SYS_STRING_VIEW path,
void** fileCtx);
// Delete the file at 'path'.
KSTATUS (*Delete)(struct IO_FILESYSTEM* fs, SYS_STRING_VIEW path);
// Rename or move a file/directory within the same filesystem.
KSTATUS (*Rename)(struct IO_FILESYSTEM* fs,
SYS_STRING_VIEW oldPath, SYS_STRING_VIEW newPath);
// Create or remove directories.
KSTATUS (*CreateDir)(struct IO_FILESYSTEM* fs, SYS_STRING_VIEW path);
KSTATUS (*RemoveDir)(struct IO_FILESYSTEM* fs, SYS_STRING_VIEW path);
// Truncate or extend the file to exactly 'newSize' bytes.
KSTATUS (*Truncate)(struct IO_FILESYSTEM* fs, void* fileCtx,
uint64_t newSize, uint32_t fileFlags);
// Return the file size in bytes.
uint64_t (*GetSize)(struct IO_FILESYSTEM* fs, void* fileCtx);
// Query metadata for an open file or path.
KSTATUS (*QueryInfo)(struct IO_FILESYSTEM* fs, void* fileCtx,
SYS_FILE_STAT* out);
KSTATUS (*Stat)(struct IO_FILESYSTEM* fs, SYS_STRING_VIEW path,
SYS_FILE_STAT* out);
// Return a stable file identity for caches that outlive one open handle.
KSTATUS (*QueryIdentity)(struct IO_FILESYSTEM* fs, void* fileCtx,
IO_FILE_IDENTITY* out);
// Release any resources the driver allocated for fileCtx.
void (*Close)(struct IO_FILESYSTEM* fs, void* fileCtx);
// Query cache and traversal statistics exposed through kernel stats.
void (*QueryStats)(struct IO_FILESYSTEM* fs, IO_FILESYSTEM_STATS* out);
// Optional driver-private data.
void* DriverCtx;
// Open a directory iterator for 'dirPath' (relative or drive-prefixed).
// Returns an opaque per-iteration driver cookie in *dirCtx.
KSTATUS (*OpenDir)(struct IO_FILESYSTEM* fs,
SYS_STRING_VIEW dirPath, void** dirCtx);
// Advance to the next entry.
// Fills 'out' with name, attributes, and size.
// Returns NTLSTATUS_NO_MORE_FILES when the directory is exhausted.
KSTATUS (*ReadDir)(struct IO_FILESYSTEM* fs, void* dirCtx,
KDIR_ENTRY* out);
// Release resources allocated by OpenDir.
void (*CloseDir)(struct IO_FILESYSTEM* fs, void* dirCtx);
} IO_FILESYSTEM;
struct EVENT;
struct KAPC;
typedef struct MM_LOCKED_USER_BUFFER MM_LOCKED_USER_BUFFER;
typedef struct IO_ASYNC_FILE_REQUEST_OBJECT IO_ASYNC_FILE_REQUEST_OBJECT;
// FILE_OBJECT - the kernel object returned to callers.
#define IO_FILE_FLAG_NO_CACHE 0x00000001u
#define IO_FILE_FLAG_SKIP_ZERO_EXTEND 0x00000002u
#define IO_FILE_FLAG_APPEND 0x00000004u
typedef struct FILE_OBJECT {
OBJECT Header; // must be first
IO_FILESYSTEM* Fs;
void* FileCtx; // driver cookie
SPINLOCK Lock; // protects cached Size/Offset updates
uint64_t Size;
uint64_t Offset; // current position for sequential reads
uint32_t Flags; // IO_FILE_FLAG_*
uint32_t ReadaheadScore;
uint64_t ReadaheadNextOffset;
uint64_t ReadaheadIssuedUntil;
uint64_t ReadaheadSuppressedUntil;
} FILE_OBJECT;
// DIR_OBJECT - kernel object for an open directory iterator.
typedef struct DIR_OBJECT {
OBJECT Header; // must be first
IO_FILESYSTEM* Fs;
void* DirCtx; // driver cookie (opaque iteration state)
} DIR_OBJECT;
typedef struct IO_VOLUME_PARAMS {
uint8_t DiskIndex; // registered disk DEVICE_OBJECT index
uint64_t PartitionLba; // starting LBA of this partition
uint64_t PartitionSize; // sectors, for bounds checking
} IO_VOLUME_PARAMS;
// Registration - called by fat32.sys from DriverEntry
// driveIndex matches the index passed to IoRegisterDiskDevice.
__declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t driveIndex, IO_FILESYSTEM* fs, const IO_VOLUME_PARAMS *vol);
__declspec(dllexport) KSTATUS IoUnregisterFilesystem(uint8_t driveIndex);
__declspec(dllexport) KSTATUS IoUnregisterFilesystemsForDisk(uint8_t diskIndex);
__declspec(dllexport) bool IoFilesystemPresent(uint8_t driveIndex);
__declspec(dllexport) void IoQueryFilesystemStats(IO_FILESYSTEM_STATS* out);
// Kernel-side API.
__declspec(dllexport) KSTATUS IoOpenFile(SYS_STRING_VIEW path, FILE_OBJECT **out);
__declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf,
size_t size, size_t* bytesRead);
__declspec(dllexport) KSTATUS IoReadFileAt(FILE_OBJECT* file, uint64_t offset,
void* buf, size_t size, size_t* bytesRead);
__declspec(dllexport) KSTATUS IoWriteFile (FILE_OBJECT* file, const void* buf,
size_t size, size_t* bytesWritten);
__declspec(dllexport) KSTATUS IoWriteFileAt(FILE_OBJECT* file, uint64_t offset,
const void* buf, size_t size,
size_t* bytesWritten);
__declspec(dllexport) KSTATUS IoFlushFile(FILE_OBJECT* file);
__declspec(dllexport) KSTATUS IoReadFileAsyncKernel(FILE_OBJECT* file, void* buf,
size_t size, uint64_t offset, IO_STATUS_BLOCK* iosb,
struct EVENT* completionEvent, struct KAPC* completionApc,
MM_LOCKED_USER_BUFFER* lockedBuffer,
MM_LOCKED_USER_BUFFER* lockedIosb,
IO_ASYNC_FILE_REQUEST_OBJECT** requestOut);
__declspec(dllexport) KSTATUS IoWriteFileAsyncKernel(FILE_OBJECT* file, const void* buf,
size_t size, uint64_t offset, IO_STATUS_BLOCK* iosb,
struct EVENT* completionEvent, struct KAPC* completionApc,
MM_LOCKED_USER_BUFFER* lockedBuffer,
MM_LOCKED_USER_BUFFER* lockedIosb,
IO_ASYNC_FILE_REQUEST_OBJECT** requestOut);
__declspec(dllexport) OBJECT* IoAsyncFileRequestObject(IO_ASYNC_FILE_REQUEST_OBJECT* request);
__declspec(dllexport) KSTATUS IoWaitAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* request,
uint32_t flags);
__declspec(dllexport) KSTATUS IoReadFileAsyncKernel(FILE_OBJECT* file,
void* buf,
size_t size,
uint64_t offset,
IO_STATUS_BLOCK* iosb,
struct EVENT* completionEvent,
struct KAPC* completionApc,
MM_LOCKED_USER_BUFFER* lockedBuffer,
MM_LOCKED_USER_BUFFER* lockedIosb,
IO_ASYNC_FILE_REQUEST_OBJECT** requestOut);
__declspec(dllexport) KSTATUS IoWriteFileAsyncKernel(FILE_OBJECT* file,
const void* buf,
size_t size,
uint64_t offset,
IO_STATUS_BLOCK* iosb,
struct EVENT* completionEvent,
struct KAPC* completionApc,
MM_LOCKED_USER_BUFFER* lockedBuffer,
MM_LOCKED_USER_BUFFER* lockedIosb,
IO_ASYNC_FILE_REQUEST_OBJECT** requestOut);
__declspec(dllexport) OBJECT* IoAsyncFileRequestObject(IO_ASYNC_FILE_REQUEST_OBJECT* request);
__declspec(dllexport) KSTATUS IoWaitAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* request,
uint32_t flags);
__declspec(dllexport) struct EVENT* IoGetAsyncFileRequestWaitEvent(IO_ASYNC_FILE_REQUEST_OBJECT* request);
__declspec(dllexport) KSTATUS IoCancelAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* request);
__declspec(dllexport) KSTATUS IoQueryAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* request,
IO_STATUS_BLOCK* iosbOut);
__declspec(dllexport) KSTATUS IoCreateFile (SYS_STRING_VIEW path, FILE_OBJECT** out);
__declspec(dllexport) KSTATUS IoDeleteFile (SYS_STRING_VIEW path);
__declspec(dllexport) KSTATUS IoRenameFile (SYS_STRING_VIEW oldPath, SYS_STRING_VIEW newPath);
__declspec(dllexport) KSTATUS IoCreateDir (SYS_STRING_VIEW path);
__declspec(dllexport) KSTATUS IoRemoveDir (SYS_STRING_VIEW path);
__declspec(dllexport) KSTATUS IoTruncateFile(FILE_OBJECT* file, uint64_t newSize);
__declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset);
__declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file);
__declspec(dllexport) KSTATUS IoGetFileStat(FILE_OBJECT* file, SYS_FILE_STAT* out);
__declspec(dllexport) KSTATUS IoStatFile(SYS_STRING_VIEW path, SYS_FILE_STAT* out);
__declspec(dllexport) KSTATUS IoQueryFileIdentity(FILE_OBJECT* file, IO_FILE_IDENTITY* out);
__declspec(dllexport) KSTATUS IoLockFile(FILE_OBJECT* file, struct PROCESS* owner, uint32_t mode, uint64_t offset, uint64_t length, uint64_t timeoutMilliseconds);
__declspec(dllexport) KSTATUS IoUnlockFile(FILE_OBJECT* file, struct PROCESS* owner, uint64_t offset, uint64_t length);
__declspec(dllexport) void IoReleaseFileLocksForProcess(struct PROCESS* owner);
__declspec(dllexport) void IoCloseFile(FILE_OBJECT* file);
__declspec(dllexport) KSTATUS IoCancelAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* request);
__declspec(dllexport) KSTATUS IoQueryAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* request,
IO_STATUS_BLOCK* iosbOut);
// Directory enumeration API.
__declspec(dllexport) KSTATUS IoOpenDir (SYS_STRING_VIEW dirPath, DIR_OBJECT** out);
__declspec(dllexport) KSTATUS IoReadDir (DIR_OBJECT* dir, KDIR_ENTRY* entryOut);
__declspec(dllexport) void IoCloseDir(DIR_OBJECT* dir);
// Current Working Directory.
__declspec(dllexport) KSTATUS IoSetCwd(SYS_STRING_VIEW path);
__declspec(dllexport) KSTATUS IoRealPath(SYS_STRING_VIEW path, char* buffer, size_t bufferSize, size_t* requiredSizeOut);
__declspec(dllexport) KSTATUS IoLockFile(FILE_OBJECT* file,
struct PROCESS* owner,
uint32_t mode,
uint64_t offset,
uint64_t length,
uint64_t timeoutMilliseconds);
__declspec(dllexport) KSTATUS IoUnlockFile(FILE_OBJECT* file,
struct PROCESS* owner,
uint64_t offset,
uint64_t length);
__declspec(dllexport) void IoReleaseFileLocksForProcess(struct PROCESS* owner);
+1 -11
View File
@@ -8,6 +8,7 @@
#include <ntlite/status.h>
#include <ntlite/string_view.h>
#include <ntlite/ddi/hal_api.h>
#include <ntlite/ddk/debug.h>
#define KE_DEBUG_CONSOLE 0x00000001u
#define KE_DEBUG_SELFTEST 0x00000002u
@@ -29,17 +30,6 @@ __declspec(dllexport) void DbgPrint(const char* fmt, ...);
__declspec(dllexport) void KePrintConsole(const char* buf, size_t len);
__declspec(dllexport) KSTATUS KeFlushDebugLogToFile(SYS_STRING_VIEW path);
typedef enum KE_PANIC_CODE {
KE_PANIC_CODE_GENERIC = 0,
KE_PANIC_CODE_FAULT = 1,
KE_PANIC_CODE_IRQL = 2,
KE_PANIC_CODE_SELFTEST = 3,
KE_PANIC_CODE_TRAP = 4,
KE_PANIC_CODE_DRIVER = 5,
KE_PANIC_CODE_INIT = 6,
KE_PANIC_CODE_SCHEDULER= 7,
} KE_PANIC_CODE;
__declspec(dllexport) _Noreturn void KePanic(int code, const char* fmt, ...);
__declspec(dllexport) int KeHandleNmiIpi(void);
+1 -48
View File
@@ -1,10 +1,6 @@
// Kernel ke display declarations shared by implementation files and kernel clients.
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <ntlite/status.h>
#include <ntlite/ddi/hal_api.h>
#ifndef DISPLAY_API
@@ -14,50 +10,7 @@
#define DISPLAY_API __declspec(dllimport)
#endif
#endif
#include <ntlite/ddi/display.h>
typedef struct KE_CONSOLE_INFO {
uint32_t Columns;
uint32_t Rows;
uint32_t CursorX;
uint32_t CursorY;
uint16_t Attribute;
} KE_CONSOLE_INFO;
typedef struct KE_DISPLAY_INFO {
char PrimaryName[32];
DISPLAY_MODE Mode;
uint32_t Caps;
uint32_t DeviceCount;
DISPLAY_STATS ManagerStats;
DISPLAY_STATS DeviceStats;
} KE_DISPLAY_INFO;
#include <ntlite/ddk/display.h>
void KeDisplayInitialize(const HAL_API* hal);
DISPLAY_API KSTATUS KeDisplayRegisterDevice(DISPLAY_DEVICE* device);
DISPLAY_API KSTATUS KeDisplaySetPrimary(DISPLAY_DEVICE* device);
DISPLAY_API void KeDisplaySuspendConsole(bool suspend);
DISPLAY_API KSTATUS KeDisplayGetMode(DISPLAY_MODE* outMode);
DISPLAY_API KSTATUS KeDisplayGetSize(int* outWidth, int* outHeight);
typedef KSTATUS (*KE_DISPLAY_ROW_SOURCE)(void* context, int rowIndex, uint32_t* scratch, size_t pixelCount);
DISPLAY_API KSTATUS KeDisplayBlit(int x, int y, int w, int h, const uint32_t* pixels);
DISPLAY_API KSTATUS KeDisplayBlitRows(int x, int y, int w, int h, KE_DISPLAY_ROW_SOURCE source, void* context, uint32_t* scratch);
DISPLAY_API KSTATUS KeDisplayFillRect(int x, int y, int w, int h, uint32_t color);
DISPLAY_API KSTATUS KeDisplayClear(uint32_t color);
DISPLAY_API KSTATUS KeDisplayCopyRect(int dstX, int dstY, int srcX, int srcY, int w, int h);
DISPLAY_API KSTATUS KeDisplayScroll(int lines);
DISPLAY_API KSTATUS KeDisplayPutChar(char c, int x, int y, uint32_t fg, uint32_t bg);
DISPLAY_API KSTATUS KeDisplayPrintChar(char c, uint32_t fg, uint32_t bg);
DISPLAY_API KSTATUS KeDisplayGetConsoleInfo(KE_CONSOLE_INFO* outInfo);
DISPLAY_API KSTATUS KeDisplaySetConsoleCursor(int col, int row);
DISPLAY_API KSTATUS KeDisplayFillConsoleChars(char c, int col, int row, size_t length, size_t* writtenOut);
DISPLAY_API KSTATUS KeDisplayFillConsoleAttrs(uint16_t attr, int col, int row, size_t length, size_t* writtenOut);
DISPLAY_API KSTATUS KeDisplayPresent(const DISPLAY_RECT* rects, size_t rectCount);
DISPLAY_API KSTATUS KeDisplaySync(void);
DISPLAY_API KSTATUS KeDisplayQueryInfo(KE_DISPLAY_INFO* outInfo);
DISPLAY_API KSTATUS KeDisplaySetCursorImage(int width, int height, int hotX, int hotY, const uint32_t* argbPixels);
DISPLAY_API KSTATUS KeDisplaySetCursorPosition(int x, int y);
DISPLAY_API KSTATUS KeDisplayShowCursor(bool show);
+4 -34
View File
@@ -1,46 +1,16 @@
// Kernel ke dpc declarations shared by implementation files and kernel clients.
#pragma once
// ke_dpc.h - deferred procedure calls
// ke_dpc.h - deferred procedure calls.
// DPCs are the kernel's bottom-half mechanism. Hardware ISRs can queue a DPC
// after acknowledging/capturing device state; the DPC then runs later at
// DISPATCH_LEVEL from the common interrupt-exit path. DPC routines must not
// wait, block, or call PASSIVE_LEVEL-only code.
// DISPATCH_LEVEL from the common interrupt-exit path. The legacy storage layout
// is DDK-visible while kernel-mode drivers are being moved behind the real DDK.
#include <stdint.h>
#include <stdbool.h>
#include <kernel/ke_list.h>
#include <kernel/ke_spinlock.h>
typedef struct KDPC KDPC;
typedef void (*KDEFERRED_ROUTINE)(KDPC* dpc,
void* context,
void* systemArgument1,
void* systemArgument2);
struct KDPC {
LIST_ENTRY Link;
KDEFERRED_ROUTINE Routine;
void* Context;
void* SystemArgument1;
void* SystemArgument2;
volatile long Inserted;
};
#include <ntlite/ddk/dpc.h>
// Called during kernel bring-up before interrupts are enabled.
void KeInitializeDpcSystem(void);
__declspec(dllexport) void KeInitializeDpc(KDPC* dpc,
KDEFERRED_ROUTINE routine,
void* context);
// Queue a DPC if it is not already queued. Returns false if the DPC was
// already pending or the arguments are invalid.
__declspec(dllexport) bool KeInsertQueueDpc(KDPC* dpc,
void* systemArgument1,
void* systemArgument2);
// Internal: drain queued DPCs at DISPATCH_LEVEL. Called from interrupt exit.
void KiDrainDpcQueue(void);
+3 -22
View File
@@ -2,26 +2,7 @@
#pragma once
// ke_event.h - auto-reset and manual-reset events.
#include <stdint.h>
#include <kernel/ob_object.h>
#include <kernel/ke_spinlock.h>
#include <kernel/ke_list.h>
#include <ntlite/status.h>
// Event layout is DDK-visible during the legacy driver cleanup. This private
// header intentionally reuses the shared declaration instead of redefining it.
typedef enum EVENT_TYPE { EventAutoReset, EventManualReset } EVENT_TYPE;
typedef struct EVENT {
OBJECT Header;
SPINLOCK Lock;
EVENT_TYPE Type;
uint32_t Signaled;
LIST_ENTRY WaitList;
LIST_ENTRY MultiWaitList;
} EVENT;
__declspec(dllexport) KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out);
__declspec(dllexport) void KeSignalEvent(EVENT* event);
__declspec(dllexport) void KeClearEvent(EVENT* event);
__declspec(dllexport) KSTATUS KeWaitForEvent(EVENT* event, uint8_t alertable);
__declspec(dllexport) KSTATUS KeTryWaitEvent(EVENT* event);
__declspec(dllexport) KSTATUS KeWaitForMultipleEvents(EVENT** events, uint32_t count, uint8_t alertable, uint64_t timeoutMs, uint32_t* signaledIndexOut);
#include <ntlite/ddk/event.h>
+3 -195
View File
@@ -1,200 +1,8 @@
// Kernel ke irp declarations shared by implementation files and kernel clients.
#pragma once
// ke_irp.h - I/O Request Packet and remove-lock primitives
// IRPs are stack-based. A caller builds an IRP with one or more
// IO_STACK_LOCATION entries, submits it to a DEVICE_OBJECT, and the I/O
// manager/driver stack advances CurrentLocation as the IRP is forwarded.
// ke_irp.h - kernel-private include path for the current IRP API.
// The legacy layout is DDK-visible until the opaque IRP accessor work lands.
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <kernel/ke_list.h>
#include <kernel/ke_spinlock.h>
#include <kernel/ke_irql.h>
#include <ntlite/status.h>
struct EVENT;
struct SEMAPHORE;
struct KAPC;
typedef struct DEVICE_OBJECT DEVICE_OBJECT;
// IRP major/minor functions.
typedef enum IO_MAJOR_FUNCTION {
IRP_MJ_CREATE = 0,
IRP_MJ_CLOSE = 1,
IRP_MJ_READ = 2,
IRP_MJ_WRITE = 3,
IRP_MJ_DEVICE_CONTROL = 4,
IRP_MJ_INTERNAL_DEVICE_CONTROL = 5,
IRP_MJ_PNP = 6,
IRP_MJ_POWER = 7,
IRP_MJ_MAXIMUM_FUNCTION = 8,
} IO_MAJOR_FUNCTION;
typedef enum IO_PNP_MINOR_FUNCTION {
IRP_MN_START_DEVICE = 0,
IRP_MN_QUERY_REMOVE_DEVICE = 1,
IRP_MN_CANCEL_REMOVE_DEVICE = 2,
IRP_MN_SURPRISE_REMOVAL = 3,
IRP_MN_REMOVE_DEVICE = 4,
IRP_MN_QUERY_DEVICE_RELATIONS = 5,
IRP_MN_QUERY_ID = 6,
IRP_MN_QUERY_CAPABILITIES = 7,
} IO_PNP_MINOR_FUNCTION;
typedef enum IO_DEVICE_RELATION_TYPE {
IoBusRelations = 0,
IoRemovalRelations = 1,
} IO_DEVICE_RELATION_TYPE;
// IRP flags.
#define IRP_FLAG_PRIORITY (1u << 0) // insert at head of a driver queue
#define IRP_FLAG_CANCELLED (1u << 1)
#define IRP_FLAG_COMPLETED (1u << 2)
// IRP stack parameters.
typedef struct IO_STACK_LOCATION {
IO_MAJOR_FUNCTION MajorFunction;
uint8_t MinorFunction;
DEVICE_OBJECT* DeviceObject;
union {
struct {
uint64_t ByteOffset;
uint32_t Length;
} ReadWrite;
struct {
uint32_t IoControlCode;
void* InputBuffer;
uint32_t InputLength;
void* OutputBuffer;
uint32_t OutputLength;
} DeviceIoControl;
struct {
IO_DEVICE_RELATION_TYPE RelationType;
} QueryDeviceRelations;
struct {
uint32_t IdType;
} QueryId;
} Parameters;
} IO_STACK_LOCATION;
// Forward declaration / callbacks.
typedef struct IRP IRP;
typedef void (*IRP_COMPLETION_FN)(IRP* irp, void* ctx);
typedef void (*IRP_CANCEL_ROUTINE)(DEVICE_OBJECT* device, IRP* irp);
// I/O Request Packet.
typedef struct IRP {
LIST_ENTRY Link;
volatile KSTATUS Status;
volatile size_t Information;
uint32_t Flags;
volatile bool Cancel;
SPINLOCK CancelLock;
KIRQL CancelIrql;
IRP_CANCEL_ROUTINE CancelRoutine;
struct EVENT* CompletionEvent;
struct KAPC* CompletionApc;
IRP_COMPLETION_FN CompletionFn;
void* CompletionCtx;
void* UserBuffer;
void* SystemBuffer;
uint8_t StackCount;
uint8_t CurrentLocation;
// Driver-owned scratch fields. They are deliberately not interpreted by
// the I/O manager and are preserved across queueing/completion.
uint8_t HwSlot;
void* DriverCtx;
IO_STACK_LOCATION Stack[1];
} IRP;
// Remove lock.
typedef struct IO_REMOVE_LOCK {
SPINLOCK Lock;
volatile long IoCount;
bool Removing;
struct EVENT* RemovedEvent;
} IO_REMOVE_LOCK;
__declspec(dllexport) KSTATUS IoInitializeRemoveLock(IO_REMOVE_LOCK* lock);
__declspec(dllexport) void IoDestroyRemoveLock(IO_REMOVE_LOCK* lock);
__declspec(dllexport) KSTATUS IoAcquireRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp);
__declspec(dllexport) void IoReleaseRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp);
__declspec(dllexport) void IoReleaseRemoveLockAndWait(IO_REMOVE_LOCK* lock, IRP* removeIrp);
// IRP_QUEUE (per-device, driver-internal).
typedef struct IRP_QUEUE {
SPINLOCK Lock;
LIST_ENTRY Head;
struct SEMAPHORE* Semaphore;
} IRP_QUEUE;
__declspec(dllexport) void IrpQueueInit (IRP_QUEUE* q, struct SEMAPHORE* sem);
__declspec(dllexport) void IrpQueueEnqueue (IRP_QUEUE* q, IRP* irp);
__declspec(dllexport) IRP* IrpQueueDequeue (IRP_QUEUE* q);
typedef void (*IRP_QUEUE_CANCEL_CALLBACK)(IRP* irp, void* context);
__declspec(dllexport) void IrpQueueCancelAllEx(IRP_QUEUE* q,
KSTATUS status,
IRP_QUEUE_CANCEL_CALLBACK callback,
void* context);
__declspec(dllexport) void IrpQueueCancelAll(IRP_QUEUE* q, KSTATUS status);
// IRP allocation / stack helpers.
__declspec(dllexport) KSTATUS IoAllocateIrp(uint8_t stackCount, IRP** outIrp);
__declspec(dllexport) void IoFreeIrp(IRP* irp);
__declspec(dllexport) void IoInitializeIrp(IRP* irp, uint8_t stackCount);
__declspec(dllexport) IO_STACK_LOCATION* IoGetCurrentIrpStackLocation(IRP* irp);
__declspec(dllexport) IO_STACK_LOCATION* IoGetNextIrpStackLocation(IRP* irp);
__declspec(dllexport) void IoSkipCurrentIrpStackLocation(IRP* irp);
__declspec(dllexport) void IoCopyCurrentIrpStackLocationToNext(IRP* irp);
__declspec(dllexport) void IoSetCompletionRoutine(IRP* irp, IRP_COMPLETION_FN fn, void* ctx);
__declspec(dllexport) IRP_CANCEL_ROUTINE IoSetCancelRoutine(IRP* irp, IRP_CANCEL_ROUTINE routine);
__declspec(dllexport) void IoCancelIrp(IRP* irp);
__declspec(dllexport) void IoBuildReadWriteIrp(IRP* irp,
IO_MAJOR_FUNCTION major,
uint64_t byteOffset,
uint32_t length,
void* buffer);
__declspec(dllexport) void IoBuildPnpIrp(IRP* irp,
IO_PNP_MINOR_FUNCTION minor);
__declspec(dllexport) void IoBuildDeviceIoControlIrp(IRP* irp,
IO_MAJOR_FUNCTION major,
uint32_t ioControlCode,
void* inputBuffer,
uint32_t inputLength,
void* outputBuffer,
uint32_t outputLength);
// Complete an IRP exactly once: publish status/information, signal the
// optional completion event, queue the optional APC, then invoke the optional
// completion callback.
__declspec(dllexport) KSTATUS IoCompleteRequest(IRP* irp, KSTATUS status, size_t information);
// Submit to a specific top-of-stack device object. The current stack location
// is stamped with the target device before dispatch.
__declspec(dllexport) KSTATUS IoSubmitIrp(DEVICE_OBJECT* device, IRP* irp);
__declspec(dllexport) KSTATUS IoSubmitIrpSync(DEVICE_OBJECT* device, IRP* irp);
#include <ntlite/ddk/irp.h>
+15 -21
View File
@@ -1,36 +1,30 @@
// Kernel ke irql declarations shared by implementation files and kernel clients.
#pragma once
// ke_irql.h - software IRQL skeleton
// This is intentionally small for the first IRQL/APC bring-up step. It does
// not yet program interrupt hardware or replace the spinlock interrupt-disable
// path. It gives the kernel one authoritative execution-level state plus
// assertions so blocking code can reject illegal callers early.
// ke_irql.h - software IRQL skeleton.
// The level constants are DDK-visible because current synchronization and IRP
// layouts expose KIRQL. Kernel routines remain declared here.
#include <stdint.h>
typedef uint8_t KIRQL;
#define PASSIVE_LEVEL ((KIRQL)0)
#define APC_LEVEL ((KIRQL)1)
#define DISPATCH_LEVEL ((KIRQL)2)
#define DIRQL_BASE ((KIRQL)16)
#define HIGH_LEVEL ((KIRQL)31)
#include <ntlite/ddk/irql.h>
// Return the current processor's software IRQL.
__declspec(dllexport) KIRQL KeGetCurrentIrql(void);
// Raise to newIrql and return the previous level. Raising to a lower level is
// a kernel bug and will panic in checked/debug-style builds.
// Raise to newIrql and return the previous level.
__declspec(dllexport) KIRQL KeRaiseIrql(KIRQL newIrql);
// Restore a previously returned level. Lowering to a higher level is a kernel
// bug and will panic.
// Restore a previously returned level.
__declspec(dllexport) void KeLowerIrql(KIRQL oldIrql);
// Assert that the current IRQL exactly matches expected.
__declspec(dllexport) void KeAssertIrql(KIRQL expected);
__declspec(dllexport) void KeAssertIrqlAtOrBelow(KIRQL maxIrql);
__declspec(dllexport) int KeCanWait(void);
// Internal/debug helper used by diagnostics and panic messages.
// Assert that the current IRQL is at or below maxIrql.
__declspec(dllexport) void KeAssertIrqlAtOrBelow(KIRQL maxIrql);
// Return nonzero when the current context may block.
__declspec(dllexport) int KeCanWait(void);
// Return a diagnostic name for an IRQL.
__declspec(dllexport) const char* KeIrqlName(KIRQL irql);
+4 -44
View File
@@ -1,49 +1,9 @@
// Kernel ke list declarations shared by implementation files and kernel clients.
#pragma once
// ke_list.h - intrusive doubly-linked list
// Used throughout the kernel for run queues, wait lists, thread lists, etc.
#include <stddef.h>
typedef struct LIST_ENTRY {
struct LIST_ENTRY* Fwd;
struct LIST_ENTRY* Bwd;
} LIST_ENTRY;
// ke_list.h - kernel-private include path for the shared intrusive list type.
// The type currently remains DDK-visible because legacy driver objects still
// expose embedded lists and IRPs. Opaque request/device work removes that need.
#define LIST_INIT(head) ((head)->Fwd = (head)->Bwd = (head))
#define LIST_IS_EMPTY(head) ((head)->Fwd == (head))
// Recover the containing struct pointer from an embedded LIST_ENTRY.
#define CONTAINING_RECORD(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type, member)))
// Implements the list Insert Tail operation.
static inline void ListInsertTail(LIST_ENTRY* head, LIST_ENTRY* node) {
node->Bwd = head->Bwd;
node->Fwd = head;
head->Bwd->Fwd = node;
head->Bwd = node;
}
// Implements the list Insert Head operation.
static inline void ListInsertHead(LIST_ENTRY* head, LIST_ENTRY* node) {
node->Fwd = head->Fwd;
node->Bwd = head;
head->Fwd->Bwd = node;
head->Fwd = node;
}
// Implements the list Remove operation.
static inline void ListRemove(LIST_ENTRY* node) {
node->Bwd->Fwd = node->Fwd;
node->Fwd->Bwd = node->Bwd;
node->Fwd = node->Bwd = node; // self-loop: poison against double-remove
}
// Pop the first entry off the list, or NULL if empty.
static inline LIST_ENTRY* ListPopHead(LIST_ENTRY* head) {
if (LIST_IS_EMPTY(head)) return (LIST_ENTRY *)0;
LIST_ENTRY* node = head->Fwd;
ListRemove(node);
return node;
}
#include <ntlite/ddk/list.h>
+4 -91
View File
@@ -1,95 +1,8 @@
// Kernel ke spinlock declarations shared by implementation files and kernel clients.
#pragma once
// ke_spinlock.h - spinlock for short, non-sleeping critical sections
// Step 3 IRQL bring-up:
// * Acquiring a spinlock disables maskable interrupts and raises the software
// IRQL to at least DISPATCH_LEVEL.
// * Releasing restores both the previous IRQL and the previous RFLAGS.IF
// state through the returned cookie.
// The public type remains uintptr_t so existing callers do not need to change.
// Never hold a spinlock across a wait/blocking operation.
#include <stdint.h>
#include <intrin.h>
#include <kernel/ke_irql.h>
#include <ntlite/ddi/hal_api.h>
typedef struct SPINLOCK {
volatile long Locked;
} SPINLOCK;
#define SPINLOCK_INIT { 0 }
#define KI_SPINLOCK_IRQL_SHIFT ((unsigned)(sizeof(uintptr_t) * 8u - 8u))
#define KI_SPINLOCK_FLAGS_MASK (~(((uintptr_t)0xFFu) << KI_SPINLOCK_IRQL_SHIFT))
// Implements the pack Spinlock Cookie operation.
static __forceinline uintptr_t KiPackSpinlockCookie(uintptr_t flags, KIRQL oldIrql) {
return (flags & KI_SPINLOCK_FLAGS_MASK) |
(((uintptr_t)oldIrql) << KI_SPINLOCK_IRQL_SHIFT);
}
// Implements the spinlock Cookie Flags operation.
static __forceinline uintptr_t KiSpinlockCookieFlags(uintptr_t cookie) {
return cookie & KI_SPINLOCK_FLAGS_MASK;
}
// Implements the spinlock Cookie Irql operation.
static __forceinline KIRQL KiSpinlockCookieIrql(uintptr_t cookie) {
return (KIRQL)(cookie >> KI_SPINLOCK_IRQL_SHIFT);
}
// Save RFLAGS, mask interrupts, raise to DISPATCH_LEVEL if needed, acquire.
// If already running at DIRQL, the higher IRQL is preserved.
static __forceinline uintptr_t KeAcquireSpinlock(SPINLOCK* sl) {
uintptr_t flags = HalDisableInterrupts();
KIRQL oldIrql = KeGetCurrentIrql();
if (oldIrql < DISPATCH_LEVEL)
KeRaiseIrql(DISPATCH_LEVEL);
while (_InterlockedCompareExchange(&sl->Locked, 1, 0) != 0)
_mm_pause();
return KiPackSpinlockCookie(flags, oldIrql);
}
// Release and restore the caller's previous software IRQL/RFLAGS state.
static __forceinline void KeReleaseSpinlock(SPINLOCK* sl, uintptr_t cookie) {
uintptr_t flags = KiSpinlockCookieFlags(cookie);
KIRQL oldIrql = KiSpinlockCookieIrql(cookie);
_InterlockedExchange(&sl->Locked, 0);
KeLowerIrql(oldIrql);
HalRestoreInterrupts(flags);
}
// Implements the try Acquire Spinlock operation.
static __forceinline int KeTryAcquireSpinlock(SPINLOCK* sl, uintptr_t* outCookie) {
uintptr_t flags = HalDisableInterrupts();
KIRQL oldIrql = KeGetCurrentIrql();
if (oldIrql < DISPATCH_LEVEL)
KeRaiseIrql(DISPATCH_LEVEL);
if (_InterlockedCompareExchange(&sl->Locked, 1, 0) == 0) {
*outCookie = KiPackSpinlockCookie(flags, oldIrql);
return 1;
}
KeLowerIrql(oldIrql);
HalRestoreInterrupts(flags);
return 0;
}
// Transitional names for the IRQL-aware driver model work that follows.
static __forceinline uintptr_t KeAcquireSpinlockRaiseToDpc(SPINLOCK* sl) {
return KeAcquireSpinlock(sl);
}
// Releases spinlock From Dpc.
static __forceinline void KeReleaseSpinlockFromDpc(SPINLOCK* sl, uintptr_t cookie) {
KeReleaseSpinlock(sl, cookie);
}
// The current spinlock layout and inline operations are DDK-visible while
// driver objects still embed spinlocks. The kernel-private header remains as a
// compatibility include for kernel implementation files only.
#include <ntlite/ddk/sync.h>
+5
View File
@@ -1,6 +1,8 @@
// Kernel ke thread declarations shared by implementation files and kernel clients.
#pragma once
#include <ntlite/ddk/thread.h>
// ke_thread.h - thread model
// A THREAD is the unit of scheduling. Every thread belongs to exactly one process.
#include <stdint.h>
@@ -17,12 +19,15 @@
typedef struct THREAD THREAD;
#ifndef NTL_THREAD_PRIORITY_DEFINED
typedef enum THREAD_PRIORITY {
PriorityLow = 0,
PriorityNormal = 1,
PriorityHigh = 2,
PriorityCount = 3,
} THREAD_PRIORITY;
#define NTL_THREAD_PRIORITY_DEFINED 1
#endif
typedef enum THREAD_STATE {
ThreadReady = 0,
+6
View File
@@ -5,6 +5,8 @@
#pragma once
#include <ntlite/ddk/memory.h>
#include <stdint.h>
#include <stddef.h>
#include <ntlite/status.h>
@@ -12,6 +14,7 @@
#define MM_PFN_INVALID_INDEX ((size_t)-1)
#ifndef NTL_MM_PFN_TYPES_DEFINED
typedef enum MM_PFN_STATE {
MmPfnStateInvalid = 0,
MmPfnStateReserved,
@@ -51,6 +54,9 @@ typedef struct MM_PFN {
uint64_t BackingPage;
} MM_PFN;
#define NTL_MM_PFN_TYPES_DEFINED 1
#endif
typedef struct MM_PFN_STATS {
uint64_t TotalFrames;
uint64_t FreeFrames;
+9
View File
@@ -4,15 +4,24 @@
#pragma once
#include <ntlite/ddk/memory.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <ntlite/memory_map.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096ULL
#endif
#ifndef PAGE_MASK
#define PAGE_MASK (~(PAGE_SIZE - 1))
#endif
#ifndef NTL_PHYSICAL_ADDRESS_DEFINED
typedef uint64_t PHYSICAL_ADDRESS;
#define NTL_PHYSICAL_ADDRESS_DEFINED 1
#endif
typedef struct MM_PHYSICAL_STATS {
uint64_t TotalFrames;
+7
View File
@@ -1,6 +1,8 @@
// Kernel page-table manager declarations shared by the VMM and low-level kernel clients.
#pragma once
#include <ntlite/ddk/memory.h>
#include <stdint.h>
#include <stddef.h>
#include <kernel/mm_phys.h>
@@ -10,7 +12,9 @@
#define PAGE_PRESENT (1ULL << 0)
#define PAGE_WRITE (1ULL << 1)
#define PAGE_USER (1ULL << 2)
#ifndef PAGE_WRITETHROUGH
#define PAGE_WRITETHROUGH (1ULL << 3)
#endif
#define PAGE_NOCACHE (1ULL << 4)
#define PAGE_ACCESSED (1ULL << 5)
#define PAGE_DIRTY (1ULL << 6)
@@ -57,10 +61,13 @@ typedef struct MM_PTE_STATS {
uint64_t CurrentLeafMappings;
} MM_PTE_STATS;
#ifndef NTL_MM_PTE_MAP_MODE_DEFINED
typedef enum MM_PTE_MAP_MODE {
MmPteMapFailIfPresent = 0,
MmPteMapReplaceExisting = 1,
} MM_PTE_MAP_MODE;
#define NTL_MM_PTE_MAP_MODE_DEFINED 1
#endif
// Initializes the page-table manager around the bootloader-created PML4.
void MmPteInitialize(PHYSICAL_ADDRESS bootPml4Phys);
+10 -37
View File
@@ -1,48 +1,21 @@
// Kernel ob object declarations shared by implementation files and kernel clients.
#pragma once
// ob_object.h - executive object model
// Every resource the kernel tracks is a typed, reference-counted OBJECT.
// The OBJECT header must be the first member of any derived struct.
#include <stdint.h>
// ob_object.h - executive object model.
// Every resource the kernel tracks is a typed, reference-counted OBJECT. The
// legacy OBJECT layout lives in the DDK while driver/device objects are still
// public; object-manager routines remain kernel-private.
#include <stddef.h>
#include <ntlite/status.h>
typedef enum OBJECT_TYPE {
ObjectTypeProcess = 1,
ObjectTypeThread = 2,
ObjectTypeMutex = 3,
ObjectTypeSemaphore = 4,
ObjectTypeEvent = 5,
ObjectTypeQueue = 6,
ObjectTypeFile = 7,
ObjectTypeDir = 8,
ObjectTypeAsyncIo = 9,
ObjectTypeSocket = 10,
ObjectTypeDevice = 11,
ObjectTypeDriver = 12,
ObjectTypeUsbDevice = 13,
ObjectTypeUsbPipe = 14,
ObjectTypeFileMapping = 15,
ObjectTypeSurface = 16,
ObjectTypeInputQueue = 17,
ObjectTypeImageSection = 18,
ObjectTypeTimer = 19,
ObjectTypeModule = 20,
} OBJECT_TYPE;
typedef struct OBJECT {
OBJECT_TYPE Type;
volatile long RefCount; // interlocked
void (*Destroy)(struct OBJECT* self);
} OBJECT;
#include <ntlite/ddk/object.h>
// Increment the reference count. Call whenever ownership is shared.
__declspec(dllexport) void ObReferenceObject(OBJECT* object);
__declspec(dllexport) void ObReferenceObject(OBJECT* object);
// Decrement. Calls Destroy() and frees the object when count reaches zero.
__declspec(dllexport) void ObDereferenceObject(OBJECT* object);
// Decrement the reference count and destroy the object when it reaches zero.
__declspec(dllexport) void ObDereferenceObject(OBJECT* object);
// Allocate a zeroed object of the given size from kernel pool.
// Caller must fill Type and Destroy before publishing the pointer.
__declspec(dllexport) OBJECT* ObAllocateObject(OBJECT_TYPE type, size_t size);
+119
View File
@@ -0,0 +1,119 @@
// Kernel DDK-table provider implementation.
#include <stdint.h>
#include <ntlite/ddk/ddk.h>
#include <ntlite/ddi/hal_api.h>
#include <kernel/hal/hal_apic.h>
#include <kernel/io_ddk.h>
#include <kernel/ke_irq.h>
#include <kernel/ke_sched.h>
static const HAL_API* gIoDdkHal;
// Returns the kernel direct-map alias for a physical address.
static void* IoDdkPhysToVirt(uint64_t physicalAddress) {
if (!gIoDdkHal || !gIoDdkHal->PhysToVirt)
return (void*)0;
return gIoDdkHal->PhysToVirt(physicalAddress);
}
// Maps one kernel page through the DDK memory surface.
static KSTATUS IoDdkMapPage(uintptr_t virtualAddress,
uint64_t physicalAddress,
uint64_t pageFlags,
NTL_DDK_MAP_MODE mode) {
MM_PTE_MAP_MODE kernelMode = MmPteMapFailIfPresent;
if (mode == NtlDdkMapReplaceExisting)
kernelMode = MmPteMapReplaceExisting;
return MmPteMapPage(virtualAddress, physicalAddress, pageFlags, kernelMode);
}
// Reads one aligned PCI configuration DWORD through the platform HAL.
static uint32_t IoDdkPciRead32(uint16_t segment,
uint8_t bus,
uint8_t device,
uint8_t function,
uint16_t offset) {
if (!gIoDdkHal || !gIoDdkHal->Pci.Read32)
return 0xFFFFFFFFu;
return gIoDdkHal->Pci.Read32(segment, bus, device, function, offset);
}
// Writes one aligned PCI configuration DWORD through the platform HAL.
static void IoDdkPciWrite32(uint16_t segment,
uint8_t bus,
uint8_t device,
uint8_t function,
uint16_t offset,
uint32_t value) {
if (!gIoDdkHal || !gIoDdkHal->Pci.Write32)
return;
gIoDdkHal->Pci.Write32(segment, bus, device, function, offset, value);
}
// Returns the BSP local APIC identifier.
static uint32_t IoDdkGetBspLapicId(void) {
return HalGetBspLapicId();
}
// Returns whether the platform interrupt controller is using x2APIC mode.
static uint8_t IoDdkIsX2ApicEnabled(void) {
return HalApicUsingX2Apic();
}
// Allocates one kernel IRQ slot for MSI delivery.
static KSTATUS IoDdkAllocateMsiVector(uint8_t* outIrq) {
return KeIrqAllocateMsiVector(outIrq);
}
static const NTL_DDK_DEBUG gIoDdkDebug = {
.Print = DbgPrint,
};
static const NTL_DDK_INTERRUPT gIoDdkInterrupt = {
.AllocateMsiVector = IoDdkAllocateMsiVector,
};
static const NTL_DDK_MEMORY gIoDdkMemory = {
.PhysToVirt = IoDdkPhysToVirt,
.MapPage = IoDdkMapPage,
};
static const NTL_DDK_PLATFORM gIoDdkPlatform = {
.PciRead32 = IoDdkPciRead32,
.PciWrite32 = IoDdkPciWrite32,
.GetBspLapicId = IoDdkGetBspLapicId,
.IsX2ApicEnabled = IoDdkIsX2ApicEnabled,
};
static const NTL_DDK_SCHEDULER gIoDdkScheduler = {
.DelayThread = KeDelayThread,
.Yield = KeYield,
};
static NTL_DDK_TIMER gIoDdkTimer = {
.QueryTicks = 0,
.Stall = 0,
};
static NTL_DDK gIoDdk = {
.Version = NTL_DDK_VERSION,
.Debug = &gIoDdkDebug,
.Interrupt = &gIoDdkInterrupt,
.Memory = &gIoDdkMemory,
.Platform = &gIoDdkPlatform,
.Scheduler = &gIoDdkScheduler,
.Timer = &gIoDdkTimer,
};
// Initializes the kernel-owned DDK table from platform services.
void IoInitializeDdk(const HAL_API* hal) {
gIoDdkHal = hal;
gIoDdkTimer.QueryTicks = hal ? hal->Timer.QueryTicks : 0;
gIoDdkTimer.Stall = hal ? hal->Timer.Stall : 0;
}
// Returns the kernel-owned DDK table passed to driver entrypoints.
const NTL_DDK* IoGetDdk(void) {
return &gIoDdk;
}
+9 -3
View File
@@ -23,6 +23,7 @@
#include <kernel/ldr_image.h>
#include <ntlite/ddi/hal_api.h>
#include <kernel/io_file.h>
#include <kernel/io_ddk.h>
#include <kernel/ke_selftest.h>
#include <kernel/ke_smp.h>
#include <kernel/ke_input.h>
@@ -122,7 +123,7 @@ static void KiInitializeSwapFromSettings(void) {
}
}
typedef KSTATUS (*DRIVER_ENTRY_FN)(const HAL_API *);
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;
@@ -190,6 +191,8 @@ static void KiDriversIniCb(const char* section, const char* key,
// Initializes drivers.
static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
(void)hal;
const NTL_DDK* ddk = IoGetDdk();
DbgPrint("KiInitializeDrivers: Initializing drivers...\n");
// boot drivers (provided by the bootloader).
@@ -230,7 +233,8 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
// Execute Entry Point.
DRIVER_ENTRY_FN entry = (DRIVER_ENTRY_FN)LdrGetEntryPoint(mappedBase);
if (entry) {
KSTATUS ds = entry(hal);
NTL_DRIVER_INIT init = {0};
KSTATUS ds = entry(ddk, &init);
if (!KSUCCESS(ds)) {
DbgPrint("WARNING: Driver %s returned failure status 0x%X\n", mod->Name, ds);
}
@@ -326,7 +330,8 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
DRIVER_ENTRY_FN entry = (DRIVER_ENTRY_FN)(LdrGetEntryPoint(mappedBase));
KSTATUS ds = entry(hal);
NTL_DRIVER_INIT init = {0};
KSTATUS ds = entry(ddk, &init);
if (!KSUCCESS(ds)) {
DbgPrint("KiInitializeDrivers: Driver %s failed to init!\n", runtimeKeys[i]);
}
@@ -523,6 +528,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
HalStopProcessor();
const HAL_API* hal = HalGetApi();
IoInitializeDdk(hal);
gKmainHal = hal;
KeInitDebug(hal, bootInfo->Debug);