// hal_disk.c - drive registry; drivers register themselves via IoRegisterDisk. // // This file lives in the HAL layer and must NOT reference any kernel sync // objects (KeEventCreate, KeSignalEvent, KeWaitForEvent, ObDereferenceObject). // All IRP event signalling is done in kernel/ke_irp.c, which sits above us // in the dependency graph. // // HalDiskDispatch is the one bridge: it calls the driver's SubmitIrp (async) // or runs the sync callbacks inline and writes irp->Status. It does not // touch irp->CompletionEvent — that is ke_irp.c's responsibility. #include #include #include #include #include #define MAX_DRIVES 8 static DISK_DRIVER gDrives[MAX_DRIVES]; static bool gPresent[MAX_DRIVES]; __declspec(dllexport) KSTATUS IoRegisterDisk(uint8_t index, const DISK_DRIVER *driver) { if (index >= MAX_DRIVES || !driver) return STATUS_INVALID_PARAMETER; if (gPresent[index]) return STATUS_ALREADY_EXISTS; gDrives[index] = *driver; gPresent[index] = true; return STATUS_SUCCESS; } // ------------------------------------------------------------------------- // HalDiskDispatch — called exclusively by ke_irp.c::IoSubmitIrp() // ------------------------------------------------------------------------- // Separating dispatch here keeps hal_disk.c free of event primitives while // still allowing ke_irp.c (kernel layer) to fire completion hooks after we // return. // // Returns STATUS_PENDING — driver accepted the IRP asynchronously. // ke_irp.c must NOT touch irp->CompletionEvent // yet; the driver will fire it. // Returns STATUS_SUCCESS — sync fallback ran; irp->Status is already // written. ke_irp.c should fire completion hooks. // Returns STATUS_NOT_FOUND — drive not registered. __declspec(dllexport) KSTATUS HalDiskDispatch(uint8_t drive, IRP *irp) { if (drive >= MAX_DRIVES || !gPresent[drive]) return STATUS_NOT_FOUND; DISK_DRIVER *drv = &gDrives[drive]; if (drv->SubmitIrp) return drv->SubmitIrp(drv->Ctx, irp); // STATUS_PENDING // Sync fallback: execute inline, write result, let caller fire hooks. bool write = !!(irp->Flags & IRP_FLAG_WRITE); if (write) irp->Status = drv->WriteSectors(drv->Ctx, irp->Lba, irp->SectorCount, irp->Buffer); else irp->Status = drv->ReadSectors (drv->Ctx, irp->Lba, irp->SectorCount, irp->Buffer); return STATUS_SUCCESS; // ran synchronously } // ------------------------------------------------------------------------- // Legacy HAL_DISK vtable — direct sync calls, no IRP involvement. // Existing callers (FAT32, shell) use this path unchanged. // ------------------------------------------------------------------------- static KSTATUS DiskRead(uint8_t drive, uint64_t lba, uint32_t count, void *buf) { if (drive >= MAX_DRIVES || !gPresent[drive]) return STATUS_NOT_FOUND; return gDrives[drive].ReadSectors(gDrives[drive].Ctx, lba, count, buf); } static KSTATUS DiskWrite(uint8_t drive, uint64_t lba, uint32_t count, const void *buf) { if (drive >= MAX_DRIVES || !gPresent[drive]) return STATUS_NOT_FOUND; return gDrives[drive].WriteSectors(gDrives[drive].Ctx, lba, count, buf); } static bool DiskPresent(uint8_t drive) { return drive < MAX_DRIVES && gPresent[drive]; } static uint64_t DiskSectorCount(uint8_t drive) { if (drive >= MAX_DRIVES || !gPresent[drive]) return 0; return gDrives[drive].SectorCount; } void HalDiskInitialize(HAL_DISK *out) { out->ReadSectors = DiskRead; out->WriteSectors = DiskWrite; out->DrivePresent = DiskPresent; out->DriveSectorCount = DiskSectorCount; }