mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
feat(kernel,gui): NT I/O Manager (IRP-based drivers) + Registry Editor
Kernel (NT I/O subsystem): - kernel/nt/io.c + include/kernel/nt/io.h (new): DRIVER_OBJECTs with a MajorFunction dispatch table, DEVICE_OBJECTs that can be stacked (attached), and IRPs pushed down the stack via io_call_driver / completed with io_complete_request. Ships three demo drivers: \Driver\Null (write sink, EOF reads), \Driver\Zero (zero-filled reads), and \Driver\Monitor -- a filter attached above \Device\Null that counts and forwards each IRP down the stack. Wired into the [12/14] boot step. - LazyBox `iodev` lists drivers/devices with the stack and IRP counters, then runs a live demo: a WRITE IRP through the filtered Null stack and a READ from the Zero device. GUI: - gui/gui_apps.c: "Registry Editor" -- navigate the NT \Registry hive tree, click subkeys to descend and ".." to go up, with a values pane showing each value's name/type/data. Registered in the app table (start menu). Verified live in the GUI terminal (screenshotted): 3 drivers / 3 devices, the NullMonitor->Null device stack, a 16-byte WRITE sunk through the filter (status 0x0), and an 8-byte zeroed READ from \Device\Zero. Clean build on x86_64/aarch64/armv8i; 0 panics / 0 OOM. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
This commit is contained in:
1 parent
526ad8c741
commit
ea937a699c
8 files changed
+513
-3
No files matched your search
@@ -9,6 +9,7 @@
|
||||
#include <kernel/module.h>
|
||||
#include <kernel/nt/ob.h>
|
||||
#include <kernel/nt/reg.h>
|
||||
#include <kernel/nt/io.h>
|
||||
#include <kernel/trace.h>
|
||||
#include <kernel/namespace.h>
|
||||
#include <kernel/syslog.h>
|
||||
@@ -243,6 +244,7 @@ static void subos_modular_core_boot(void) {
|
||||
cron_init();
|
||||
ob_init();
|
||||
reg_init();
|
||||
io_init();
|
||||
service_manager_init();
|
||||
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
|
||||
|
||||
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// SUB-OS NT-Inspired I/O Manager (Io)
|
||||
//
|
||||
// Drivers register a MajorFunction dispatch table and create named device
|
||||
// objects. Devices can be stacked (a filter attached on top of a lower device);
|
||||
// io_call_driver invokes the top device's dispatch, which may forward the IRP
|
||||
// down to dev->attached_to. Ships three demo drivers: Null, Zero, and a Monitor
|
||||
// filter stacked above Null that counts and forwards every IRP.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <kernel/nt/io.h>
|
||||
#include <mm/kmalloc.h>
|
||||
#include <lib/string.h>
|
||||
#include <kernel/printk.h>
|
||||
#include <kernel/sync.h>
|
||||
|
||||
static DRIVER_OBJECT* g_drivers[IO_MAX_DRIVERS];
|
||||
static int g_driver_count = 0;
|
||||
static DEVICE_OBJECT* g_devices[IO_MAX_DEVICES];
|
||||
static int g_device_count = 0;
|
||||
static uint64_t g_total_irps = 0;
|
||||
static spinlock_t g_io_lock = SPINLOCK_INIT;
|
||||
|
||||
const char* io_major_name(irp_major_t mj) {
|
||||
switch (mj) {
|
||||
case IRP_MJ_CREATE: return "CREATE";
|
||||
case IRP_MJ_CLOSE: return "CLOSE";
|
||||
case IRP_MJ_READ: return "READ";
|
||||
case IRP_MJ_WRITE: return "WRITE";
|
||||
case IRP_MJ_DEVICE_CONTROL: return "DEVICE_CONTROL";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
DRIVER_OBJECT* io_create_driver(const char* name, driver_entry_t entry) {
|
||||
spin_lock(&g_io_lock);
|
||||
if (g_driver_count >= IO_MAX_DRIVERS) {
|
||||
spin_unlock(&g_io_lock);
|
||||
return NULL;
|
||||
}
|
||||
DRIVER_OBJECT* drv = (DRIVER_OBJECT*)kzalloc(sizeof(DRIVER_OBJECT));
|
||||
if (!drv) {
|
||||
spin_unlock(&g_io_lock);
|
||||
return NULL;
|
||||
}
|
||||
strncpy(drv->name, name ? name : "", IO_NAME_MAX - 1);
|
||||
g_drivers[g_driver_count++] = drv;
|
||||
spin_unlock(&g_io_lock);
|
||||
|
||||
if (entry) {
|
||||
entry(drv); // DriverEntry fills the MajorFunction table and creates devices
|
||||
}
|
||||
return drv;
|
||||
}
|
||||
|
||||
NTSTATUS io_create_device(DRIVER_OBJECT* drv, const char* name,
|
||||
size_t ext_size, DEVICE_OBJECT** out) {
|
||||
if (!drv) return STATUS_UNSUCCESSFUL;
|
||||
spin_lock(&g_io_lock);
|
||||
if (g_device_count >= IO_MAX_DEVICES) {
|
||||
spin_unlock(&g_io_lock);
|
||||
return STATUS_INSUFFICIENT_RES;
|
||||
}
|
||||
DEVICE_OBJECT* dev = (DEVICE_OBJECT*)kzalloc(sizeof(DEVICE_OBJECT));
|
||||
if (!dev) {
|
||||
spin_unlock(&g_io_lock);
|
||||
return STATUS_INSUFFICIENT_RES;
|
||||
}
|
||||
strncpy(dev->name, name ? name : "", IO_NAME_MAX - 1);
|
||||
dev->driver = drv;
|
||||
if (ext_size > 0) {
|
||||
dev->device_extension = kzalloc(ext_size);
|
||||
}
|
||||
// Link into the driver's device list and the global table.
|
||||
dev->next_on_driver = drv->device_list;
|
||||
drv->device_list = dev;
|
||||
g_devices[g_device_count++] = dev;
|
||||
spin_unlock(&g_io_lock);
|
||||
|
||||
if (out) *out = dev;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DEVICE_OBJECT* io_attach_device(DEVICE_OBJECT* source, DEVICE_OBJECT* target) {
|
||||
if (!source || !target) return NULL;
|
||||
spin_lock(&g_io_lock);
|
||||
source->attached_to = target; // source now sits above target in the stack
|
||||
spin_unlock(&g_io_lock);
|
||||
return target;
|
||||
}
|
||||
|
||||
DEVICE_OBJECT* io_lookup_device(const char* name) {
|
||||
if (!name) return NULL;
|
||||
spin_lock(&g_io_lock);
|
||||
DEVICE_OBJECT* found = NULL;
|
||||
for (int i = 0; i < g_device_count; i++) {
|
||||
if (strcmp(g_devices[i]->name, name) == 0) { found = g_devices[i]; break; }
|
||||
}
|
||||
spin_unlock(&g_io_lock);
|
||||
return found;
|
||||
}
|
||||
|
||||
IRP* io_build_irp(irp_major_t mj, void* buffer, uint32_t length) {
|
||||
IRP* irp = (IRP*)kzalloc(sizeof(IRP));
|
||||
if (!irp) return NULL;
|
||||
irp->major_function = mj;
|
||||
irp->buffer = buffer;
|
||||
irp->length = length;
|
||||
irp->status = STATUS_UNSUCCESSFUL;
|
||||
irp->information = 0;
|
||||
return irp;
|
||||
}
|
||||
|
||||
NTSTATUS io_call_driver(DEVICE_OBJECT* dev, IRP* irp) {
|
||||
if (!dev || !irp) return STATUS_UNSUCCESSFUL;
|
||||
irp->current_device = dev;
|
||||
|
||||
spin_lock(&g_io_lock);
|
||||
g_total_irps++;
|
||||
if (dev->driver) dev->driver->irp_count++;
|
||||
switch (irp->major_function) {
|
||||
case IRP_MJ_READ: dev->read_count++; break;
|
||||
case IRP_MJ_WRITE: dev->write_count++; break;
|
||||
case IRP_MJ_DEVICE_CONTROL: dev->ioctl_count++; break;
|
||||
default: break;
|
||||
}
|
||||
driver_dispatch_t fn = NULL;
|
||||
if (dev->driver && irp->major_function < IRP_MJ_MAXIMUM) {
|
||||
fn = dev->driver->major_function[irp->major_function];
|
||||
}
|
||||
spin_unlock(&g_io_lock);
|
||||
|
||||
if (!fn) {
|
||||
irp->status = STATUS_UNSUCCESSFUL;
|
||||
return irp->status;
|
||||
}
|
||||
return fn(dev, irp);
|
||||
}
|
||||
|
||||
void io_complete_request(IRP* irp, NTSTATUS status) {
|
||||
if (!irp) return;
|
||||
irp->status = status;
|
||||
}
|
||||
|
||||
void io_free_irp(IRP* irp) {
|
||||
if (irp) kfree(irp);
|
||||
}
|
||||
|
||||
int io_driver_count(void) { return g_driver_count; }
|
||||
DRIVER_OBJECT* io_driver_at(int index) {
|
||||
return (index >= 0 && index < g_driver_count) ? g_drivers[index] : NULL;
|
||||
}
|
||||
int io_device_count(void) { return g_device_count; }
|
||||
DEVICE_OBJECT* io_device_at(int index) {
|
||||
return (index >= 0 && index < g_device_count) ? g_devices[index] : NULL;
|
||||
}
|
||||
void io_get_stats(uint32_t* out_drivers, uint32_t* out_devices, uint64_t* out_irps) {
|
||||
if (out_drivers) *out_drivers = (uint32_t)g_driver_count;
|
||||
if (out_devices) *out_devices = (uint32_t)g_device_count;
|
||||
if (out_irps) *out_irps = g_total_irps;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Demo drivers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// \Driver\Null : sink writes, return EOF on reads (like NT's \Device\Null).
|
||||
static NTSTATUS null_read(DEVICE_OBJECT* dev, IRP* irp) {
|
||||
(void)dev;
|
||||
irp->information = 0; // 0 bytes == end of file
|
||||
io_complete_request(irp, STATUS_SUCCESS);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
static NTSTATUS null_write(DEVICE_OBJECT* dev, IRP* irp) {
|
||||
(void)dev;
|
||||
irp->information = irp->length; // swallow everything
|
||||
io_complete_request(irp, STATUS_SUCCESS);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
static NTSTATUS null_entry(DRIVER_OBJECT* drv) {
|
||||
drv->major_function[IRP_MJ_READ] = null_read;
|
||||
drv->major_function[IRP_MJ_WRITE] = null_write;
|
||||
io_create_device(drv, "\\Device\\Null", 0, NULL);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// \Driver\Zero : reads yield a buffer full of zero bytes.
|
||||
static NTSTATUS zero_read(DEVICE_OBJECT* dev, IRP* irp) {
|
||||
(void)dev;
|
||||
if (irp->buffer && irp->length) {
|
||||
memset(irp->buffer, 0, irp->length);
|
||||
}
|
||||
irp->information = irp->length;
|
||||
io_complete_request(irp, STATUS_SUCCESS);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
static NTSTATUS zero_entry(DRIVER_OBJECT* drv) {
|
||||
drv->major_function[IRP_MJ_READ] = zero_read;
|
||||
io_create_device(drv, "\\Device\\Zero", 0, NULL);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// \Driver\Monitor : a filter stacked above \Device\Null. It counts each IRP in
|
||||
// its device extension and forwards to the lower device, demonstrating a stack.
|
||||
typedef struct { uint64_t forwarded; } monitor_ext_t;
|
||||
|
||||
static NTSTATUS monitor_passthrough(DEVICE_OBJECT* dev, IRP* irp) {
|
||||
monitor_ext_t* ext = (monitor_ext_t*)dev->device_extension;
|
||||
if (ext) ext->forwarded++;
|
||||
if (dev->attached_to) {
|
||||
return io_call_driver(dev->attached_to, irp); // pass down the stack
|
||||
}
|
||||
io_complete_request(irp, STATUS_SUCCESS);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
static NTSTATUS monitor_entry(DRIVER_OBJECT* drv) {
|
||||
drv->major_function[IRP_MJ_READ] = monitor_passthrough;
|
||||
drv->major_function[IRP_MJ_WRITE] = monitor_passthrough;
|
||||
drv->major_function[IRP_MJ_DEVICE_CONTROL] = monitor_passthrough;
|
||||
|
||||
DEVICE_OBJECT* filter = NULL;
|
||||
io_create_device(drv, "\\Device\\NullMonitor", sizeof(monitor_ext_t), &filter);
|
||||
DEVICE_OBJECT* lower = io_lookup_device("\\Device\\Null");
|
||||
if (filter && lower) {
|
||||
io_attach_device(filter, lower);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void io_init(void) {
|
||||
g_driver_count = 0;
|
||||
g_device_count = 0;
|
||||
g_total_irps = 0;
|
||||
|
||||
io_create_driver("\\Driver\\Null", null_entry);
|
||||
io_create_driver("\\Driver\\Zero", zero_entry);
|
||||
io_create_driver("\\Driver\\Monitor", monitor_entry);
|
||||
|
||||
printk(ANSI_BRIGHT_GREEN "IO: " ANSI_RESET
|
||||
"NT I/O Manager online (%d drivers, %d devices, IRP-based dispatch)\n",
|
||||
g_driver_count, g_device_count);
|
||||
}
|
||||
Reference in new issue
Block a user