# DiskIoDxe

## Function Table

| Address | Name | Description |
|---------|------|-------------|
|  | **InternalAssert** |  |
|  | **_ModuleEntryPoint** |  |
|  | **DiskIoDxeInstallProtocols** |  |
|  | **DiskIoDriverBindingSupported** |  |
|  | **DiskIoDriverBindingStart** |  |
|  | **DiskIoDriverBindingStop** |  |
|  | **DiskIoReadDisk** |  |
|  | **DiskIoWriteDisk** |  |
|  | **DiskIo2ReadDiskEx** |  |
|  | **DiskIo2WriteDiskEx** |  |
|  | **DiskIo2FlushDiskEx** |  |
|  | **DiskIo2Cancel** |  |
|  | **DiskIoRequest** |  |
|  | **DiskIoCreateSubtasks** |  |
|  | **DiskIoSubtaskCallback** |  |
|  | **DiskIoCheckAllSubtasksCompleted** |  |
|  | **DiskIoComponentNameGetDriverName** |  |
|  | **DiskIoComponentNameGetControllerName** |  |
|  | **ProcessLibraryConstructorList** |  |
| Module | **globals (set by _ModuleEntryPoint at 0x390)** |  |
| EFI_HANDLE | **gImageHandle          = NULL;** |  |
| Debug | **print error level protocol (lazily resolved)** |  |
| qword_38E0 | **in the binary** |  |
| DEBUG_PRINT_ERROR_LEVEL_PROTOCOL | ***gDebugPrintErrorLevelProtocol = NULL;** |  |
| Driver | **Binding Protocol instance** |  |
| Installed | **in DiskIoDxeInstallProtocols (sub_448)** |  |
| EFI_DRIVER_BINDING_PROTOCOL | **gDiskIoDriverBinding = {** |  |
| Version | **NULL,     // ImageHandle - set during binding** |  |
| DriverBindingHandle | **- set by InstallMultipleProtocolInterfaces** |  |
| Component | **Name tables (at .rdata +0x3868 and +0x3880)** |  |
| Stored | **as: { GetDriverName, GetControllerName, DriverNameString }** |  |
| where | **GetDriverName = DiskIoComponentNameGetDriverName (0x1CEC)** |  |
| GetControllerName | **= DiskIoComponentNameGetControllerName (0x1E48)** |  |
| DriverNameString | **= "Generic Disk I/O Driver" (0x2EA0) for COMPONENT_NAME** |  |
| DriverNameString | **= "Disk I/O Driver" (0x2E94 "eng;en" table) for COMPONENT_NAME2** |  |
| EFI_COMPONENT_NAME_PROTOCOL | **gDiskIoComponentName = {** |  |
| Supported | **Languages** |  |
| Forward | **declarations for library-internal helpers** |  |
| Module | **Entry Point** |  |
| Process | **library constructors (sub_26D0)** |  |
| This | **calls ProcessLibraryConstructorList to initialize HOB list, etc.** |  |
| ProcessLibraryConstructorList | **();** |  |
| Install | **the driver binding and component name protocols (sub_448)** |  |
| return | **DiskIoDxeInstallProtocols (ImageHandle);** |  |
| Protocol | **Installation** |  |
| Driver | **Binding Protocol: Supported, Start, Stop** |  |
| Allocate | **a pool tag (8 bytes) for tracking** |  |
| HandlePtr | **= gBootServices->AllocatePool (EfiBootServicesData, sizeof (EFI_HANDLE));** |  |
| Open | **Block I/O protocol BY_DRIVER** |  |
| Status | **= gBootServices->OpenProtocol (** |  |
| Optionally | **open Block I/O 2 protocol BY_DRIVER** |  |
| Allocate | **and initialize the private data structure** |  |
| Instance | **= InternalAllocateCopyPool (BlockIo2, sizeof (DISK_IO_PRIVATE_DATA));** |  |
| Validate | **BlockIo vs BlockIo2 alignment consistency** |  |
| if | **(BlockIo2 != NULL) {** |  |
| Initialize | **DiskIo protocol interface (at Instance + 0x08)** |  |
| Initialize | **DiskIo2 protocol interface (at Instance + 0x28)** |  |
| Initialize | **the task list** |  |
| InitializeListHead | **(&Instance->TaskList);** |  |
| Initialize | **the EFI lock (LockType=16, Tpl=4, EfiLockReleased=1)** |  |
| EfiInitializeLock | **(&Instance->TaskListLock, TPL_NOTIFY);** |  |
| Allocate | **an aligned media buffer for bouncing unaligned transfers** |  |
| BlockSize | **= BlockIo->Media->BlockSize;** |  |
| Install | **the Disk I/O protocols on the controller handle** |  |
| On | **failure, free the aligned buffer and instance** |  |
| InternalFreeAlignedBuffer | **(** |  |
| Open | **the installed DiskIo protocol to get our private instance** |  |
| CR | **macro: DiskIo is at Instance + 0x08 (offset 8)** |  |
| Instance | **= CR (DiskIo, DISK_IO_PRIVATE_DATA, DiskIo, DISK_IO_PRIVATE_DATA_SIGNATURE);** |  |
| Drain | **all outstanding non-blocking I/O** |  |
| do | **{** |  |
| Uninstall | **protocols** |  |
| if | **(Instance->BlockIo2 != NULL) {** |  |
| Free | **the aligned media buffer** |  |
| if | **(Instance->MediaBuffer != NULL) {** |  |
| Close | **the underlying Block I/O protocols** |  |
| Free | **the instance** |  |
| InternalFreePool | **(Instance);** |  |
| EFI_DISK_IO_PROTOCOL | **Implementation** |  |
| Synchronous | **flush** |  |
| return | **Instance->BlockIo2->FlushBlocksEx (Instance->BlockIo2, NULL);** |  |
| FlushTask | **= InternalAllocatePool (EfiBootServicesData, sizeof (DISK_IO_FLUSH_TASK));** |  |
| Create | **a notification event** |  |
| Status | **= gBootServices->CreateEvent (** |  |
| Submit | **to BlockIo2 with our event** |  |
| Status | **= Instance->BlockIo2->FlushBlocksEx (Instance->BlockIo2, FlushTask->Event);** |  |
| EfiAcquireLock | **(&Instance->TaskListLock);** |  |
| Entry | **= GetFirstNode (&Instance->TaskList);** |  |
| Cancel | **this task: abort the user's token** |  |
| if | **(Task->Token != NULL) {** |  |
| Free | **the task (implicitly removes from list)** |  |
| RemoveEntryList | **(Entry);** |  |
| Core | **I/O Dispatcher: DiskIoRequest** |  |
| IsBlocking | **= FALSE;** |  |
| Wait | **for previous non-blocking requests to drain** |  |
| while | **(!DiskIoCheckAllSubtasksCompleted (Instance)) {** |  |
| Spin | **until all subtasks complete** |  |
| Allocate | **a DISK_IO_TASK (0x50 bytes)** |  |
| Task | **= InternalAllocatePool (EfiBootServicesData, sizeof (DISK_IO_TASK));** |  |
| Insert | **the task into the instance's task list** |  |
| InsertTailList | **(&Instance->TaskList, &Task->Link);** |  |
| Initialize | **the subtask list for this task** |  |
| InitializeListHead | **(&Task->SubtaskList);** |  |
| Create | **the subtasks** |  |
| Blocking | **path (Token == NULL or Token->Event == NULL)** |  |
| IsBlocking | **= TRUE;** |  |
| Use | **local stack variable for the subtask list head** |  |
| InitializeListHead | **(&SubtaskList);** |  |
| Blocking | **Instance->MediaBuffer** |  |
| If | **no subtasks were created, clean up and return error** |  |
| if | **(IsListEmpty (SubtaskListPtr)) {** |  |
| Execute | **all subtasks** |  |
| Status | **= EFI_SUCCESS;** |  |
| Validate | **block alignment** |  |
| if | **((Subtask->Length % BlockSize != 0) && (Subtask->Length >= BlockSize)) {** |  |
| Choose | **between BlockIo2 (non-blocking) and BlockIo (blocking)** |  |
| if | **(Subtask->IsWrite) {** |  |
| Write | **operation** |  |
| if | **(Subtask->WorkingBuffer != NULL) {** |  |
| Copy | **from user buffer to bounce buffer first** |  |
| if | **(Subtask->UseBlockIo2) {** |  |
| Status | **= BlockIo2->ReadBlocksEx (** |  |
| Blocking | **read via BlockIo** |  |
| Status | **= BlockIo->ReadBlocks (** |  |
| For | **blocking reads with bounce buffer: copy to user buffer** |  |
| if | **(!EFI_ERROR (Status) && (Subtask->WorkingBuffer != NULL)) {** |  |
| Clean | **up completed subtask** |  |
| DiskIoFreeSubtask | **(Instance, (DISK_IO_TASK *)Subtask);** |  |
| If | **blocking and error: stop processing further subtasks** |  |
| if | **(EFI_ERROR (Status) && !Subtask->UseBlockIo2) {** |  |
| If | **any blocking subtask failed, drain remaining subtask list** |  |
| if | **(EFI_ERROR (Status)) {** |  |
| For | **non-blocking tasks: cleanup and possibly signal completion** |  |
| if | **(!IsBlocking && Task != NULL) {** |  |
| If | **the non-blocking request was effectively blocking (all subtasks** |  |
| completed | **synchronously), signal the user's event directly** |  |
| if | **(!EFI_ERROR (Status) && (Task->Token != NULL)) {** |  |
| Remove | **the task from the instance's task list and free it** |  |
| RemoveEntryList | **(&Task->Link);** |  |
| Subtask | **Management** |  |
| Calculate | **starting LBA and offset within first block** |  |
| DivU64x32Remainder | **(Offset, (UINT32)BlockSize, &OffsetInBlock);** |  |
| Subtask | **= DiskIoCreateSubtask (** |  |
| UseBlockIo2 | **for non-blocking** |  |
| Head | **fragment: start is not block-aligned** |  |
| FragmentSize | **= BlockSize - OffsetInBlock;** |  |
| For | **blocking: use MediaBuffer as the bounce buffer** |  |
| For | **non-blocking: reuse the subtask's own buffer** |  |
| if | **(!IsBlocking) {** |  |
| Process | **aligned remaining data** |  |
| if | **(Remaining > 0) {** |  |
| If | **the remaining data is perfectly block-aligned** |  |
| do | **it as one large aligned transfer (no bounce buffer needed)** |  |
| if | **(Remaining % BlockSize == 0) {** |  |
| No | **bounce buffer for aligned transfer** |  |
| Process | **aligned full blocks one at a time** |  |
| while | **(Remaining >= BlockSize) {** |  |
| No | **bounce buffer needed** |  |
| Tail | **unaligned fragment** |  |
| Bounce | **buffer for tail fragment** |  |
| Allocate | **the subtask (0x68 = 104 bytes)** |  |
| Subtask | **= InternalAllocatePool (EfiBootServicesData, sizeof (DISK_IO_SUBTASK));** |  |
| Zero | **the structure** |  |
| ZeroMem | **(Subtask, sizeof (DISK_IO_SUBTASK));** |  |
| For | **reads with bounce buffer: copy data to user buffer** |  |
| if | **(!Subtask->IsWrite && (Subtask->WorkingBuffer != NULL)) {** |  |
| Close | **the event** |  |
| or | **by the cleanup code in DiskIoRequest** |  |
| Remove | **from linked list** |  |
| RemoveEntryList | **(&Subtask->Link);** |  |
| Close | **event if non-blocking subtask** |  |
| if | **(Subtask->Token != NULL) {** |  |
| This | **is actually the subtask's Event field at offset 0x58** |  |
| Free | **the allocation** |  |
| InternalFreePool | **(Subtask);** |  |
| Task | **completed, signal its token** |  |
| Remove | **and free the completed task** |  |
| RemoveEntryList | **(TaskEntry);** |  |
| Component | **Name Protocol** |  |
| The | **component name table at .rdata +0x3868 / +0x3880 contains:** |  |
| For | **COMPONENT_NAME: DriverNameString = "Generic Disk I/O Driver" (0x2EA0)** |  |
| For | **COMPONENT_NAME2: DriverNameString = "eng;en" string table -> "Disk I/O Driver"** |  |
| The | **actual implementation iterates over the language table checking** |  |
| each | **entry against the requested Language parameter.** |  |
| if | **((Language == NULL) || (DriverName == NULL)) {** |  |
| each | **entry with string comparison. For English, returns the known string.** |  |
| Library | **Constructors** |  |
| to | **find the DebugPrintErrorLevelLib protocol and cache it.** |  |
| At | **qword_38E0 and qword_38E8, the debug print protocol pointer** |  |
| is | **lazily resolved on first use via DebugPrintErrorLevelLibGetDebug** |  |

---
*Generated by HR650X BIOS Decompilation Project*