Newer
Older
AMI-Aptio-BIOS-Reversed / DiskIoDxe / DiskIoDxe.md
@Ajax Dong Ajax Dong 2 days ago 10 KB Init

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