36 DISK_IO_PRIVATE_DATA_SIGNATURE,
38 EFI_DISK_IO_PROTOCOL_REVISION,
43 EFI_DISK_IO2_PROTOCOL_REVISION,
78 Status =
gBS->OpenProtocol (
80 &gEfiBlockIoProtocolGuid,
82 This->DriverBindingHandle,
84 EFI_OPEN_PROTOCOL_BY_DRIVER
86 if (EFI_ERROR (Status)) {
95 &gEfiBlockIoProtocolGuid,
96 This->DriverBindingHandle,
130 OldTpl =
gBS->RaiseTPL (TPL_CALLBACK);
135 Status =
gBS->OpenProtocol (
137 &gEfiBlockIoProtocolGuid,
138 (VOID **)&gDiskIoPrivateDataTemplate.BlockIo,
139 This->DriverBindingHandle,
141 EFI_OPEN_PROTOCOL_BY_DRIVER
143 if (EFI_ERROR (Status)) {
147 Status =
gBS->OpenProtocol (
149 &gEfiBlockIo2ProtocolGuid,
150 (VOID **)&gDiskIoPrivateDataTemplate.BlockIo2,
151 This->DriverBindingHandle,
153 EFI_OPEN_PROTOCOL_BY_DRIVER
155 if (EFI_ERROR (Status)) {
156 gDiskIoPrivateDataTemplate.BlockIo2 =
NULL;
163 if (Instance ==
NULL) {
164 Status = EFI_OUT_OF_RESOURCES;
172 (Instance->BlockIo2 ==
NULL) ||
184 if (Instance->SharedWorkingBuffer ==
NULL) {
185 Status = EFI_OUT_OF_RESOURCES;
192 if (Instance->BlockIo2 !=
NULL) {
193 Status =
gBS->InstallMultipleProtocolInterfaces (
195 &gEfiDiskIoProtocolGuid,
197 &gEfiDiskIo2ProtocolGuid,
202 Status =
gBS->InstallMultipleProtocolInterfaces (
204 &gEfiDiskIoProtocolGuid,
211 if (EFI_ERROR (Status)) {
212 if ((Instance !=
NULL) && (Instance->SharedWorkingBuffer !=
NULL)) {
214 Instance->SharedWorkingBuffer,
219 if (Instance !=
NULL) {
225 &gEfiBlockIoProtocolGuid,
226 This->DriverBindingHandle,
232 gBS->RestoreTPL (OldTpl);
268 Status =
gBS->OpenProtocol (
270 &gEfiDiskIoProtocolGuid,
272 This->DriverBindingHandle,
274 EFI_OPEN_PROTOCOL_GET_PROTOCOL
276 if (EFI_ERROR (Status)) {
280 Status =
gBS->OpenProtocol (
282 &gEfiDiskIo2ProtocolGuid,
284 This->DriverBindingHandle,
286 EFI_OPEN_PROTOCOL_GET_PROTOCOL
288 if (EFI_ERROR (Status)) {
292 Instance = DISK_IO_PRIVATE_DATA_FROM_DISK_IO (DiskIo);
294 if (DiskIo2 !=
NULL) {
298 ASSERT (Instance->BlockIo2 !=
NULL);
299 Status = Instance->BlockIo2->Reset (Instance->BlockIo2,
FALSE);
300 if (EFI_ERROR (Status)) {
304 Status =
gBS->UninstallMultipleProtocolInterfaces (
306 &gEfiDiskIoProtocolGuid,
308 &gEfiDiskIo2ProtocolGuid,
313 Status =
gBS->UninstallMultipleProtocolInterfaces (
315 &gEfiDiskIoProtocolGuid,
321 if (!EFI_ERROR (Status)) {
326 }
while (!AllTaskDone);
329 Instance->SharedWorkingBuffer,
333 Status =
gBS->CloseProtocol (
335 &gEfiBlockIoProtocolGuid,
336 This->DriverBindingHandle,
340 if (DiskIo2 !=
NULL) {
341 Status =
gBS->CloseProtocol (
343 &gEfiBlockIo2ProtocolGuid,
344 This->DriverBindingHandle,
372 if (Subtask->Task !=
NULL) {
377 if (Subtask->Task !=
NULL) {
381 if (!Subtask->Blocking) {
382 if (Subtask->WorkingBuffer !=
NULL) {
384 Subtask->WorkingBuffer,
385 Subtask->Length < Instance->BlockIo->Media->BlockSize
391 if (Subtask->BlockIo2Token.Event !=
NULL) {
392 gBS->CloseEvent (Subtask->BlockIo2Token.Event);
421 Task = Subtask->Task;
422 Instance = Task->Instance;
424 ASSERT (Subtask->Signature == DISK_IO_SUBTASK_SIGNATURE);
425 ASSERT (Instance->Signature == DISK_IO_PRIVATE_DATA_SIGNATURE);
426 ASSERT (Task->Signature == DISK_IO2_TASK_SIGNATURE);
428 if ((Subtask->WorkingBuffer !=
NULL) && !EFI_ERROR (TransactionStatus) &&
432 CopyMem (Subtask->
Buffer, Subtask->WorkingBuffer + Subtask->Offset, Subtask->Length);
437 if (EFI_ERROR (TransactionStatus) ||
IsListEmpty (&Task->Subtasks)) {
443 Task->
Token->TransactionStatus = TransactionStatus;
444 gBS->SignalEvent (Task->
Token->Event);
473 IN VOID *WorkingBuffer OPTIONAL,
482 if (Subtask ==
NULL) {
486 Subtask->Signature = DISK_IO_SUBTASK_SIGNATURE;
487 Subtask->Write = Write;
489 Subtask->Offset = Offset;
490 Subtask->Length = Length;
491 Subtask->WorkingBuffer = WorkingBuffer;
493 Subtask->Blocking = Blocking;
495 Status =
gBS->CreateEvent (
500 &Subtask->BlockIo2Token.
Event
502 if (EFI_ERROR (Status)) {
510 " %c:Lba/Offset/Length/WorkingBuffer/Buffer = %016lx/%08x/%08x/%08x/%08x\n",
545 IN VOID *SharedWorkingBuffer,
557 UINTN DataBufferSize;
562 DEBUG ((DEBUG_BLKIO,
"DiskIo: Create subtasks for task: Offset/BufferSize/Buffer = %016lx/%08x/%08x\n", Offset, BufferSize, Buffer));
564 BlockSize = Instance->BlockIo->Media->BlockSize;
565 IoAlign = Instance->BlockIo->Media->IoAlign;
571 BufferPtr = (UINT8 *)Buffer;
576 if (BufferSize == 0) {
578 if (Subtask ==
NULL) {
587 Length =
MIN (BlockSize - UnderRun, BufferSize);
589 WorkingBuffer = SharedWorkingBuffer;
592 if (WorkingBuffer ==
NULL) {
603 if (Subtask ==
NULL) {
610 Subtask =
DiskIoCreateSubtask (Write, Lba, UnderRun, Length, WorkingBuffer, BufferPtr, Blocking);
611 if (Subtask ==
NULL) {
619 BufferSize -= Length;
624 BufferSize -= OverRun;
628 WorkingBuffer = SharedWorkingBuffer;
631 if (WorkingBuffer ==
NULL) {
642 if (Subtask ==
NULL) {
649 Subtask =
DiskIoCreateSubtask (Write, OverRunLba, 0, OverRun, WorkingBuffer, BufferPtr + BufferSize, Blocking);
650 if (Subtask ==
NULL) {
657 if (OverRunLba > Lba) {
663 if (Subtask ==
NULL) {
669 BufferPtr += BufferSize;
670 Offset += BufferSize;
671 BufferSize -= BufferSize;
678 for ( ; Lba < OverRunLba; Lba +=
PcdGet32 (PcdDiskIoDataBufferBlockNum)) {
679 DataBufferSize =
MIN (BufferSize,
PcdGet32 (PcdDiskIoDataBufferBlockNum) * BlockSize);
681 Subtask =
DiskIoCreateSubtask (Write, Lba, 0, DataBufferSize, SharedWorkingBuffer, BufferPtr, Blocking);
682 if (Subtask ==
NULL) {
688 BufferPtr += DataBufferSize;
689 Offset += DataBufferSize;
690 BufferSize -= DataBufferSize;
694 if (WorkingBuffer ==
NULL) {
698 DEBUG ((DEBUG_VERBOSE,
"DiskIo: No enough memory so downgrade to blocking access\n"));
703 Subtask =
DiskIoCreateSubtask (Write, Lba, 0, BufferSize, WorkingBuffer, BufferPtr, Blocking);
704 if (Subtask ==
NULL) {
711 BufferPtr += BufferSize;
712 Offset += BufferSize;
713 BufferSize -= BufferSize;
718 ASSERT (BufferSize == 0);
753 Instance = DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This);
758 ; !
IsNull (&Instance->TaskQueue, Link)
765 Task->
Token->TransactionStatus = EFI_ABORTED;
766 gBS->SignalEvent (Task->
Token->Event);
799 for (Link =
GetFirstNode (&Instance->TaskQueue); !
IsNull (&Instance->TaskQueue, Link); ) {
852 BOOLEAN SubtaskBlocking;
856 BlockIo = Instance->BlockIo;
857 BlockIo2 = Instance->BlockIo2;
858 Media = BlockIo->
Media;
860 Blocking = (BOOLEAN)((Token ==
NULL) || (Token->Event ==
NULL));
869 SubtasksPtr = &Subtasks;
874 return EFI_OUT_OF_RESOURCES;
881 Task->Signature = DISK_IO2_TASK_SIGNATURE;
882 Task->Instance = Instance;
886 SubtasksPtr = &Task->Subtasks;
890 if (!
DiskIoCreateSubtaskList (Instance, Write, Offset, BufferSize, Buffer, Blocking, Instance->SharedWorkingBuffer, SubtasksPtr)) {
895 return EFI_OUT_OF_RESOURCES;
900 SubtaskPerformTpl =
gBS->RaiseTPL (TPL_CALLBACK);
902 ; !
IsNull (SubtasksPtr, Link)
903 ; Link = NextLink, NextLink =
GetNextNode (SubtasksPtr, NextLink)
907 Subtask->Task = Task;
908 SubtaskBlocking = Subtask->Blocking;
910 ASSERT ((Subtask->Length % Media->
BlockSize == 0) || (Subtask->Length < Media->
BlockSize));
912 if (Subtask->Write) {
916 if (Subtask->WorkingBuffer !=
NULL) {
920 CopyMem (Subtask->WorkingBuffer + Subtask->Offset, Subtask->
Buffer, Subtask->Length);
923 if (SubtaskBlocking) {
924 Status = BlockIo->WriteBlocks (
929 (Subtask->WorkingBuffer !=
NULL) ? Subtask->WorkingBuffer : Subtask->
Buffer
932 Status = BlockIo2->WriteBlocksEx (
936 &Subtask->BlockIo2Token,
938 (Subtask->WorkingBuffer !=
NULL) ? Subtask->WorkingBuffer : Subtask->
Buffer
945 if (SubtaskBlocking) {
946 Status = BlockIo->ReadBlocks (
951 (Subtask->WorkingBuffer !=
NULL) ? Subtask->WorkingBuffer : Subtask->
Buffer
953 if (!EFI_ERROR (Status) && (Subtask->WorkingBuffer !=
NULL)) {
954 CopyMem (Subtask->
Buffer, Subtask->WorkingBuffer + Subtask->Offset, Subtask->Length);
957 Status = BlockIo2->ReadBlocksEx (
961 &Subtask->BlockIo2Token,
963 (Subtask->WorkingBuffer !=
NULL) ? Subtask->WorkingBuffer : Subtask->
Buffer
968 if (SubtaskBlocking || EFI_ERROR (Status)) {
976 if (EFI_ERROR (Status)) {
981 SubtaskLockTpl =
gBS->RaiseTPL (TPL_NOTIFY);
987 if (EFI_ERROR (Status)) {
988 while (!
IsNull (SubtasksPtr, NextLink)) {
1003 if (!EFI_ERROR (Status) && (Task->
Token !=
NULL)) {
1008 DEBUG ((DEBUG_VERBOSE,
"DiskIo: Non-blocking request was downgraded to blocking request, signal event directly.\n"));
1009 Task->
Token->TransactionStatus = Status;
1010 gBS->SignalEvent (Task->
Token->Event);
1016 gBS->RestoreTPL (SubtaskLockTpl);
1017 gBS->RestoreTPL (SubtaskPerformTpl);
1056 DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This),
1100 DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This),
1125 gBS->CloseEvent (Event);
1128 ASSERT (Task->Signature == DISK_IO2_FLUSH_TASK_SIGNATURE);
1130 gBS->SignalEvent (Task->Token->Event);
1161 Private = DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This);
1163 if ((Token !=
NULL) && (Token->Event !=
NULL)) {
1166 return EFI_OUT_OF_RESOURCES;
1169 Status =
gBS->CreateEvent (
1174 &Task->BlockIo2Token.
Event
1176 if (EFI_ERROR (Status)) {
1181 Task->Signature = DISK_IO2_FLUSH_TASK_SIGNATURE;
1182 Task->Token = Token;
1183 Status = Private->BlockIo2->FlushBlocksEx (Private->BlockIo2, &Task->BlockIo2Token);
1184 if (EFI_ERROR (Status)) {
1185 gBS->CloseEvent (Task->BlockIo2Token.
Event);
1189 Status = Private->BlockIo2->FlushBlocksEx (Private->BlockIo2,
NULL);
1229 DISK_IO_PRIVATE_DATA_FROM_DISK_IO (This),
1275 DISK_IO_PRIVATE_DATA_FROM_DISK_IO (This),
1310 &gDiskIoDriverBinding,
1312 &gDiskIoComponentName,
1313 &gDiskIoComponentName2
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
UINT64 EFIAPI DivU64x32Remainder(IN UINT64 Dividend, IN UINT32 Divisor, OUT UINT32 *Remainder OPTIONAL)
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_STATUS EFIAPI DiskIo2WriteDiskEx(IN EFI_DISK_IO2_PROTOCOL *This, IN UINT32 MediaId, IN UINT64 Offset, IN OUT EFI_DISK_IO2_TOKEN *Token, IN UINTN BufferSize, IN VOID *Buffer)
EFI_STATUS EFIAPI InitializeDiskIo(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
BOOLEAN DiskIo2RemoveCompletedTask(IN DISK_IO_PRIVATE_DATA *Instance)
EFI_STATUS EFIAPI DiskIo2ReadDiskEx(IN EFI_DISK_IO2_PROTOCOL *This, IN UINT32 MediaId, IN UINT64 Offset, IN OUT EFI_DISK_IO2_TOKEN *Token, IN UINTN BufferSize, OUT VOID *Buffer)
VOID EFIAPI DiskIo2OnFlushComplete(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EFIAPI DiskIoWriteDisk(IN EFI_DISK_IO_PROTOCOL *This, IN UINT32 MediaId, IN UINT64 Offset, IN UINTN BufferSize, IN VOID *Buffer)
VOID EFIAPI DiskIo2OnReadWriteComplete(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EFIAPI DiskIo2Cancel(IN EFI_DISK_IO2_PROTOCOL *This)
EFI_STATUS EFIAPI DiskIoReadDisk(IN EFI_DISK_IO_PROTOCOL *This, IN UINT32 MediaId, IN UINT64 Offset, IN UINTN BufferSize, OUT VOID *Buffer)
EFI_STATUS EFIAPI DiskIoDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)
DISK_IO_SUBTASK * DiskIoCreateSubtask(IN BOOLEAN Write, IN UINT64 Lba, IN UINT32 Offset, IN UINTN Length, IN VOID *WorkingBuffer OPTIONAL, IN VOID *Buffer, IN BOOLEAN Blocking)
EFI_STATUS EFIAPI DiskIo2FlushDiskEx(IN EFI_DISK_IO2_PROTOCOL *This, IN OUT EFI_DISK_IO2_TOKEN *Token)
BOOLEAN DiskIoCreateSubtaskList(IN DISK_IO_PRIVATE_DATA *Instance, IN BOOLEAN Write, IN UINT64 Offset, IN UINTN BufferSize, IN VOID *Buffer, IN BOOLEAN Blocking, IN VOID *SharedWorkingBuffer, IN OUT LIST_ENTRY *Subtasks)
LIST_ENTRY * DiskIoDestroySubtask(IN DISK_IO_PRIVATE_DATA *Instance, IN DISK_IO_SUBTASK *Subtask)
EFI_STATUS DiskIo2ReadWriteDisk(IN DISK_IO_PRIVATE_DATA *Instance, IN BOOLEAN Write, IN UINT32 MediaId, IN UINT64 Offset, IN EFI_DISK_IO2_TOKEN *Token, IN UINTN BufferSize, IN UINT8 *Buffer)
EFI_STATUS EFIAPI DiskIoDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL)
EFI_STATUS EFIAPI DiskIoDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID EFIAPI FreeAlignedPages(IN VOID *Buffer, IN UINTN Pages)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define ALIGN_POINTER(Pointer, Alignment)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
#define CR(Record, TYPE, Field, TestSignature)
#define PcdGet32(TokenName)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID *EFIAPI AllocateAlignedPages(IN UINTN Pages, IN UINTN Alignment)
#define EFI_SIZE_TO_PAGES(Size)
VOID EFIAPI EfiReleaseLock(IN EFI_LOCK *Lock)
VOID EFIAPI EfiAcquireLock(IN EFI_LOCK *Lock)
EFI_LOCK *EFIAPI EfiInitializeLock(IN OUT EFI_LOCK *Lock, IN EFI_TPL Priority)
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
EFI_BLOCK_IO_MEDIA * Media
EFI_BLOCK_IO_MEDIA * Media
EFI_LOCK SubtasksLock
< link to other task
EFI_DISK_IO2_TOKEN * Token
< header of subtasks
UINT8 * Buffer
< NULL indicates using "Buffer" directly
EFI_STATUS TransactionStatus