summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2017-08-02 09:54:47 +0800
committerGuo Mang <mang.guo@intel.com>2017-09-05 19:45:08 +0800
commit6c128c65b5ec0e5b8b5a0ccb165f3afd29e485f8 (patch)
tree444372d92a0ae8991fe4d15eb3937df43690dfda /MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
parentb207c6434d7a5a4502975d322312e07017e8a8cb (diff)
downloadedk2-platforms-6c128c65b5ec0e5b8b5a0ccb165f3afd29e485f8.tar.xz
Remove core packages since we can get them from edk2 repository
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c')
-rw-r--r--MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c1276
1 files changed, 0 insertions, 1276 deletions
diff --git a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c b/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
deleted file mode 100644
index 0f0dbfee82..0000000000
--- a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
+++ /dev/null
@@ -1,1276 +0,0 @@
-/** @file
- DiskIo driver that lays on every BlockIo protocol in the system.
- DiskIo converts a block oriented device to a byte oriented device.
-
- Disk access may have to handle unaligned request about sector boundaries.
- There are three cases:
- UnderRun - The first byte is not on a sector boundary or the read request is
- less than a sector in length.
- Aligned - A read of N contiguous sectors.
- OverRun - The last byte is not on a sector boundary.
-
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "DiskIo.h"
-
-//
-// Driver binding protocol implementation for DiskIo driver.
-//
-EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding = {
- DiskIoDriverBindingSupported,
- DiskIoDriverBindingStart,
- DiskIoDriverBindingStop,
- 0xa,
- NULL,
- NULL
-};
-
-//
-// Template for DiskIo private data structure.
-// The pointer to BlockIo protocol interface is assigned dynamically.
-//
-DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate = {
- DISK_IO_PRIVATE_DATA_SIGNATURE,
- {
- EFI_DISK_IO_PROTOCOL_REVISION,
- DiskIoReadDisk,
- DiskIoWriteDisk
- },
- {
- EFI_DISK_IO2_PROTOCOL_REVISION,
- DiskIo2Cancel,
- DiskIo2ReadDiskEx,
- DiskIo2WriteDiskEx,
- DiskIo2FlushDiskEx
- }
-};
-
-/**
- Test to see if this driver supports ControllerHandle.
-
- @param This Protocol instance pointer.
- @param ControllerHandle Handle of device to test
- @param RemainingDevicePath Optional parameter use to pick a specific child
- device to start.
-
- @retval EFI_SUCCESS This driver supports this device
- @retval EFI_ALREADY_STARTED This driver is already running on this device
- @retval other This driver does not support this device
-
-**/
-EFI_STATUS
-EFIAPI
-DiskIoDriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
- )
-{
- EFI_STATUS Status;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
-
- //
- // Open the IO Abstraction(s) needed to perform the supported test.
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- (VOID **) &BlockIo,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Close the I/O Abstraction(s) used to perform the supported test.
- //
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- return EFI_SUCCESS;
-}
-
-
-/**
- Start this driver on ControllerHandle by opening a Block IO protocol and
- installing a Disk IO protocol on ControllerHandle.
-
- @param This Protocol instance pointer.
- @param ControllerHandle Handle of device to bind driver to
- @param RemainingDevicePath Optional parameter use to pick a specific child
- device to start.
-
- @retval EFI_SUCCESS This driver is added to ControllerHandle
- @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
- @retval other This driver does not support this device
-
-**/
-EFI_STATUS
-EFIAPI
-DiskIoDriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
- )
-{
- EFI_STATUS Status;
- DISK_IO_PRIVATE_DATA *Instance;
- EFI_TPL OldTpl;
-
- Instance = NULL;
-
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
-
- //
- // Connect to the Block IO and Block IO2 interface on ControllerHandle.
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- (VOID **) &gDiskIoPrivateDataTemplate.BlockIo,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status)) {
- goto ErrorExit1;
- }
-
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiBlockIo2ProtocolGuid,
- (VOID **) &gDiskIoPrivateDataTemplate.BlockIo2,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status)) {
- gDiskIoPrivateDataTemplate.BlockIo2 = NULL;
- }
-
- //
- // Initialize the Disk IO device instance.
- //
- Instance = AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA), &gDiskIoPrivateDataTemplate);
- if (Instance == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ErrorExit;
- }
-
- //
- // The BlockSize and IoAlign of BlockIo and BlockIo2 should equal.
- //
- ASSERT ((Instance->BlockIo2 == NULL) ||
- ((Instance->BlockIo->Media->IoAlign == Instance->BlockIo2->Media->IoAlign) &&
- (Instance->BlockIo->Media->BlockSize == Instance->BlockIo2->Media->BlockSize)
- ));
-
- InitializeListHead (&Instance->TaskQueue);
- EfiInitializeLock (&Instance->TaskQueueLock, TPL_NOTIFY);
- Instance->SharedWorkingBuffer = AllocateAlignedPages (
- EFI_SIZE_TO_PAGES (PcdGet32 (PcdDiskIoDataBufferBlockNum) * Instance->BlockIo->Media->BlockSize),
- Instance->BlockIo->Media->IoAlign
- );
- if (Instance->SharedWorkingBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ErrorExit;
- }
-
- //
- // Install protocol interfaces for the Disk IO device.
- //
- if (Instance->BlockIo2 != NULL) {
- Status = gBS->InstallMultipleProtocolInterfaces (
- &ControllerHandle,
- &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
- &gEfiDiskIo2ProtocolGuid, &Instance->DiskIo2,
- NULL
- );
- } else {
- Status = gBS->InstallMultipleProtocolInterfaces (
- &ControllerHandle,
- &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
- NULL
- );
- }
-
-ErrorExit:
- if (EFI_ERROR (Status)) {
- if (Instance != NULL && Instance->SharedWorkingBuffer != NULL) {
- FreeAlignedPages (
- Instance->SharedWorkingBuffer,
- EFI_SIZE_TO_PAGES (PcdGet32 (PcdDiskIoDataBufferBlockNum) * Instance->BlockIo->Media->BlockSize)
- );
- }
-
- if (Instance != NULL) {
- FreePool (Instance);
- }
-
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- }
-
-ErrorExit1:
- gBS->RestoreTPL (OldTpl);
- return Status;
-}
-
-/**
- Stop this driver on ControllerHandle by removing Disk IO protocol and closing
- the Block IO protocol on ControllerHandle.
-
- @param This Protocol instance pointer.
- @param ControllerHandle Handle of device to stop driver on
- @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
- children is zero stop the entire bus driver.
- @param ChildHandleBuffer List of Child Handles to Stop.
-
- @retval EFI_SUCCESS This driver is removed ControllerHandle
- @retval other This driver was not removed from this device
-
-**/
-EFI_STATUS
-EFIAPI
-DiskIoDriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- )
-{
- EFI_STATUS Status;
- EFI_DISK_IO_PROTOCOL *DiskIo;
- EFI_DISK_IO2_PROTOCOL *DiskIo2;
- DISK_IO_PRIVATE_DATA *Instance;
- BOOLEAN AllTaskDone;
-
- //
- // Get our context back.
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiDiskIoProtocolGuid,
- (VOID **) &DiskIo,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiDiskIo2ProtocolGuid,
- (VOID **) &DiskIo2,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- DiskIo2 = NULL;
- }
-
- Instance = DISK_IO_PRIVATE_DATA_FROM_DISK_IO (DiskIo);
-
- if (DiskIo2 != NULL) {
- //
- // Call BlockIo2::Reset() to terminate any in-flight non-blocking I/O requests
- //
- ASSERT (Instance->BlockIo2 != NULL);
- Status = Instance->BlockIo2->Reset (Instance->BlockIo2, FALSE);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = gBS->UninstallMultipleProtocolInterfaces (
- ControllerHandle,
- &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
- &gEfiDiskIo2ProtocolGuid, &Instance->DiskIo2,
- NULL
- );
- } else {
- Status = gBS->UninstallMultipleProtocolInterfaces (
- ControllerHandle,
- &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
- NULL
- );
- }
- if (!EFI_ERROR (Status)) {
-
- do {
- EfiAcquireLock (&Instance->TaskQueueLock);
- AllTaskDone = IsListEmpty (&Instance->TaskQueue);
- EfiReleaseLock (&Instance->TaskQueueLock);
- } while (!AllTaskDone);
-
- FreeAlignedPages (
- Instance->SharedWorkingBuffer,
- EFI_SIZE_TO_PAGES (PcdGet32 (PcdDiskIoDataBufferBlockNum) * Instance->BlockIo->Media->BlockSize)
- );
-
- Status = gBS->CloseProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- ASSERT_EFI_ERROR (Status);
- if (DiskIo2 != NULL) {
- Status = gBS->CloseProtocol (
- ControllerHandle,
- &gEfiBlockIo2ProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- ASSERT_EFI_ERROR (Status);
- }
-
- FreePool (Instance);
- }
-
- return Status;
-}
-
-
-/**
- Destroy the sub task.
-
- @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
- @param Subtask Subtask.
-
- @return LIST_ENTRY * Pointer to the next link of subtask.
-**/
-LIST_ENTRY *
-DiskIoDestroySubtask (
- IN DISK_IO_PRIVATE_DATA *Instance,
- IN DISK_IO_SUBTASK *Subtask
- )
-{
- LIST_ENTRY *Link;
-
- if (Subtask->Task != NULL) {
- EfiAcquireLock (&Subtask->Task->SubtasksLock);
- }
- Link = RemoveEntryList (&Subtask->Link);
- if (Subtask->Task != NULL) {
- EfiReleaseLock (&Subtask->Task->SubtasksLock);
- }
-
- if (!Subtask->Blocking) {
- if (Subtask->WorkingBuffer != NULL) {
- FreeAlignedPages (
- Subtask->WorkingBuffer,
- Subtask->Length < Instance->BlockIo->Media->BlockSize
- ? EFI_SIZE_TO_PAGES (Instance->BlockIo->Media->BlockSize)
- : EFI_SIZE_TO_PAGES (Subtask->Length)
- );
- }
- if (Subtask->BlockIo2Token.Event != NULL) {
- gBS->CloseEvent (Subtask->BlockIo2Token.Event);
- }
- }
- FreePool (Subtask);
-
- return Link;
-}
-
-/**
- The callback for the BlockIo2 ReadBlocksEx/WriteBlocksEx.
- @param Event Event whose notification function is being invoked.
- @param Context The pointer to the notification function's context,
- which points to the DISK_IO_SUBTASK instance.
-**/
-VOID
-EFIAPI
-DiskIo2OnReadWriteComplete (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- DISK_IO_SUBTASK *Subtask;
- DISK_IO2_TASK *Task;
- EFI_STATUS TransactionStatus;
- DISK_IO_PRIVATE_DATA *Instance;
-
- Subtask = (DISK_IO_SUBTASK *) Context;
- TransactionStatus = Subtask->BlockIo2Token.TransactionStatus;
- Task = Subtask->Task;
- Instance = Task->Instance;
-
- ASSERT (Subtask->Signature == DISK_IO_SUBTASK_SIGNATURE);
- ASSERT (Instance->Signature == DISK_IO_PRIVATE_DATA_SIGNATURE);
- ASSERT (Task->Signature == DISK_IO2_TASK_SIGNATURE);
-
- if ((Subtask->WorkingBuffer != NULL) && !EFI_ERROR (TransactionStatus) &&
- (Task->Token != NULL) && !Subtask->Write
- ) {
- CopyMem (Subtask->Buffer, Subtask->WorkingBuffer + Subtask->Offset, Subtask->Length);
- }
-
- DiskIoDestroySubtask (Instance, Subtask);
-
- if (EFI_ERROR (TransactionStatus) || IsListEmpty (&Task->Subtasks)) {
- if (Task->Token != NULL) {
- //
- // Signal error status once the subtask is failed.
- // Or signal the last status once the last subtask is finished.
- //
- Task->Token->TransactionStatus = TransactionStatus;
- gBS->SignalEvent (Task->Token->Event);
-
- //
- // Mark token to NULL indicating the Task is a dead task.
- //
- Task->Token = NULL;
- }
- }
-}
-
-/**
- Create the subtask.
-
- @param Write TRUE: Write request; FALSE: Read request.
- @param Lba The starting logical block address to read from on the device.
- @param Offset The starting byte offset to read from the LBA.
- @param Length The number of bytes to read from the device.
- @param WorkingBuffer The aligned buffer to hold the data for reading or writing.
- @param Buffer The buffer to hold the data for reading or writing.
- @param Blocking TRUE: Blocking request; FALSE: Non-blocking request.
-
- @return A pointer to the created subtask.
-**/
-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
- )
-{
- DISK_IO_SUBTASK *Subtask;
- EFI_STATUS Status;
-
- Subtask = AllocateZeroPool (sizeof (DISK_IO_SUBTASK));
- if (Subtask == NULL) {
- return NULL;
- }
- Subtask->Signature = DISK_IO_SUBTASK_SIGNATURE;
- Subtask->Write = Write;
- Subtask->Lba = Lba;
- Subtask->Offset = Offset;
- Subtask->Length = Length;
- Subtask->WorkingBuffer = WorkingBuffer;
- Subtask->Buffer = Buffer;
- Subtask->Blocking = Blocking;
- if (!Blocking) {
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- DiskIo2OnReadWriteComplete,
- Subtask,
- &Subtask->BlockIo2Token.Event
- );
- if (EFI_ERROR (Status)) {
- FreePool (Subtask);
- return NULL;
- }
- }
- DEBUG ((
- EFI_D_BLKIO,
- " %c:Lba/Offset/Length/WorkingBuffer/Buffer = %016lx/%08x/%08x/%08x/%08x\n",
- Write ? 'W': 'R', Lba, Offset, Length, WorkingBuffer, Buffer
- ));
-
- return Subtask;
-}
-
-/**
- Create the subtask list.
-
- @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
- @param Write TRUE: Write request; FALSE: Read request.
- @param Offset The starting byte offset to read from the device.
- @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
- @param Buffer A pointer to the buffer for the data.
- @param Blocking TRUE: Blocking request; FALSE: Non-blocking request.
- @param SharedWorkingBuffer The aligned buffer to hold the data for reading or writing.
- @param Subtasks The subtask list header.
-
- @retval TRUE The subtask list is created successfully.
- @retval FALSE The subtask list is not created.
-**/
-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
- )
-{
- UINT32 BlockSize;
- UINT32 IoAlign;
- UINT64 Lba;
- UINT64 OverRunLba;
- UINT32 UnderRun;
- UINT32 OverRun;
- UINT8 *BufferPtr;
- UINTN Length;
- UINTN DataBufferSize;
- DISK_IO_SUBTASK *Subtask;
- VOID *WorkingBuffer;
- LIST_ENTRY *Link;
-
- DEBUG ((EFI_D_BLKIO, "DiskIo: Create subtasks for task: Offset/BufferSize/Buffer = %016lx/%08x/%08x\n", Offset, BufferSize, Buffer));
-
- BlockSize = Instance->BlockIo->Media->BlockSize;
- IoAlign = Instance->BlockIo->Media->IoAlign;
- if (IoAlign == 0) {
- IoAlign = 1;
- }
-
- Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun);
- BufferPtr = (UINT8 *) Buffer;
-
- //
- // Special handling for zero BufferSize
- //
- if (BufferSize == 0) {
- Subtask = DiskIoCreateSubtask (Write, Lba, UnderRun, 0, NULL, BufferPtr, Blocking);
- if (Subtask == NULL) {
- goto Done;
- }
- InsertTailList (Subtasks, &Subtask->Link);
- return TRUE;
- }
-
- if (UnderRun != 0) {
- Length = MIN (BlockSize - UnderRun, BufferSize);
- if (Blocking) {
- WorkingBuffer = SharedWorkingBuffer;
- } else {
- WorkingBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BlockSize), IoAlign);
- if (WorkingBuffer == NULL) {
- goto Done;
- }
- }
- if (Write) {
- //
- // A half write operation can be splitted to a blocking block-read and half write operation
- // This can simplify the sub task processing logic
- //
- Subtask = DiskIoCreateSubtask (FALSE, Lba, 0, BlockSize, NULL, WorkingBuffer, TRUE);
- if (Subtask == NULL) {
- goto Done;
- }
- InsertTailList (Subtasks, &Subtask->Link);
- }
-
- Subtask = DiskIoCreateSubtask (Write, Lba, UnderRun, Length, WorkingBuffer, BufferPtr, Blocking);
- if (Subtask == NULL) {
- goto Done;
- }
- InsertTailList (Subtasks, &Subtask->Link);
-
- BufferPtr += Length;
- Offset += Length;
- BufferSize -= Length;
- Lba ++;
- }
-
- OverRunLba = Lba + DivU64x32Remainder (BufferSize, BlockSize, &OverRun);
- BufferSize -= OverRun;
-
- if (OverRun != 0) {
- if (Blocking) {
- WorkingBuffer = SharedWorkingBuffer;
- } else {
- WorkingBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BlockSize), IoAlign);
- if (WorkingBuffer == NULL) {
- goto Done;
- }
- }
- if (Write) {
- //
- // A half write operation can be splitted to a blocking block-read and half write operation
- // This can simplify the sub task processing logic
- //
- Subtask = DiskIoCreateSubtask (FALSE, OverRunLba, 0, BlockSize, NULL, WorkingBuffer, TRUE);
- if (Subtask == NULL) {
- goto Done;
- }
- InsertTailList (Subtasks, &Subtask->Link);
- }
-
- Subtask = DiskIoCreateSubtask (Write, OverRunLba, 0, OverRun, WorkingBuffer, BufferPtr + BufferSize, Blocking);
- if (Subtask == NULL) {
- goto Done;
- }
- InsertTailList (Subtasks, &Subtask->Link);
- }
-
- if (OverRunLba > Lba) {
- //
- // If the DiskIo maps directly to a BlockIo device do the read.
- //
- if (ALIGN_POINTER (BufferPtr, IoAlign) == BufferPtr) {
- Subtask = DiskIoCreateSubtask (Write, Lba, 0, BufferSize, NULL, BufferPtr, Blocking);
- if (Subtask == NULL) {
- goto Done;
- }
- InsertTailList (Subtasks, &Subtask->Link);
-
- BufferPtr += BufferSize;
- Offset += BufferSize;
- BufferSize -= BufferSize;
-
- } else {
- if (Blocking) {
- //
- // Use the allocated buffer instead of the original buffer
- // to avoid alignment issue.
- //
- for (; Lba < OverRunLba; Lba += PcdGet32 (PcdDiskIoDataBufferBlockNum)) {
- DataBufferSize = MIN (BufferSize, PcdGet32 (PcdDiskIoDataBufferBlockNum) * BlockSize);
-
- Subtask = DiskIoCreateSubtask (Write, Lba, 0, DataBufferSize, SharedWorkingBuffer, BufferPtr, Blocking);
- if (Subtask == NULL) {
- goto Done;
- }
- InsertTailList (Subtasks, &Subtask->Link);
-
- BufferPtr += DataBufferSize;
- Offset += DataBufferSize;
- BufferSize -= DataBufferSize;
- }
- } else {
- WorkingBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), IoAlign);
- if (WorkingBuffer == NULL) {
- //
- // If there is not enough memory, downgrade to blocking access
- //
- DEBUG ((EFI_D_VERBOSE, "DiskIo: No enough memory so downgrade to blocking access\n"));
- if (!DiskIoCreateSubtaskList (Instance, Write, Offset, BufferSize, BufferPtr, TRUE, SharedWorkingBuffer, Subtasks)) {
- goto Done;
- }
- } else {
- Subtask = DiskIoCreateSubtask (Write, Lba, 0, BufferSize, WorkingBuffer, BufferPtr, Blocking);
- if (Subtask == NULL) {
- goto Done;
- }
- InsertTailList (Subtasks, &Subtask->Link);
- }
-
- BufferPtr += BufferSize;
- Offset += BufferSize;
- BufferSize -= BufferSize;
- }
- }
- }
-
- ASSERT (BufferSize == 0);
-
- return TRUE;
-
-Done:
- //
- // Remove all the subtasks.
- //
- for (Link = GetFirstNode (Subtasks); !IsNull (Subtasks, Link); ) {
- Subtask = CR (Link, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
- Link = DiskIoDestroySubtask (Instance, Subtask);
- }
- return FALSE;
-}
-
-/**
- Terminate outstanding asynchronous requests to a device.
-
- @param This Indicates a pointer to the calling context.
-
- @retval EFI_SUCCESS All outstanding requests were successfully terminated.
- @retval EFI_DEVICE_ERROR The device reported an error while performing the cancel
- operation.
-**/
-EFI_STATUS
-EFIAPI
-DiskIo2Cancel (
- IN EFI_DISK_IO2_PROTOCOL *This
- )
-{
- DISK_IO_PRIVATE_DATA *Instance;
- DISK_IO2_TASK *Task;
- LIST_ENTRY *Link;
-
- Instance = DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This);
-
- EfiAcquireLock (&Instance->TaskQueueLock);
-
- for (Link = GetFirstNode (&Instance->TaskQueue)
- ; !IsNull (&Instance->TaskQueue, Link)
- ; Link = GetNextNode (&Instance->TaskQueue, Link)
- ) {
- Task = CR (Link, DISK_IO2_TASK, Link, DISK_IO2_TASK_SIGNATURE);
-
- if (Task->Token != NULL) {
- Task->Token->TransactionStatus = EFI_ABORTED;
- gBS->SignalEvent (Task->Token->Event);
- //
- // Set Token to NULL so that the further BlockIo2 responses will be ignored
- //
- Task->Token = NULL;
- }
- }
-
- EfiReleaseLock (&Instance->TaskQueueLock);
-
- return EFI_SUCCESS;
-}
-
-/**
- Remove the completed tasks from Instance->TaskQueue. Completed tasks are those who don't have any subtasks.
-
- @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
-
- @retval TRUE The Instance->TaskQueue is empty after the completed tasks are removed.
- @retval FALSE The Instance->TaskQueue is not empty after the completed tasks are removed.
-**/
-BOOLEAN
-DiskIo2RemoveCompletedTask (
- IN DISK_IO_PRIVATE_DATA *Instance
- )
-{
- BOOLEAN QueueEmpty;
- LIST_ENTRY *Link;
- DISK_IO2_TASK *Task;
-
- QueueEmpty = TRUE;
-
- EfiAcquireLock (&Instance->TaskQueueLock);
- for (Link = GetFirstNode (&Instance->TaskQueue); !IsNull (&Instance->TaskQueue, Link); ) {
- Task = CR (Link, DISK_IO2_TASK, Link, DISK_IO2_TASK_SIGNATURE);
- if (IsListEmpty (&Task->Subtasks)) {
- Link = RemoveEntryList (&Task->Link);
- ASSERT (Task->Token == NULL);
- FreePool (Task);
- } else {
- Link = GetNextNode (&Instance->TaskQueue, Link);
- QueueEmpty = FALSE;
- }
- }
- EfiReleaseLock (&Instance->TaskQueueLock);
-
- return QueueEmpty;
-}
-
-/**
- Common routine to access the disk.
-
- @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
- @param Write TRUE: Write operation; FALSE: Read operation.
- @param MediaId ID of the medium to access.
- @param Offset The starting byte offset on the logical block I/O device to access.
- @param Token A pointer to the token associated with the transaction.
- If this field is NULL, synchronous/blocking IO is performed.
- @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
- @param Buffer A pointer to the destination buffer for the data.
- The caller is responsible either having implicit or explicit ownership of the buffer.
-**/
-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 Status;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
- EFI_BLOCK_IO_MEDIA *Media;
- LIST_ENTRY *Link;
- LIST_ENTRY *NextLink;
- LIST_ENTRY Subtasks;
- DISK_IO_SUBTASK *Subtask;
- DISK_IO2_TASK *Task;
- EFI_TPL OldTpl;
- BOOLEAN Blocking;
- BOOLEAN SubtaskBlocking;
- LIST_ENTRY *SubtasksPtr;
-
- Task = NULL;
- BlockIo = Instance->BlockIo;
- BlockIo2 = Instance->BlockIo2;
- Media = BlockIo->Media;
- Status = EFI_SUCCESS;
- Blocking = (BOOLEAN) ((Token == NULL) || (Token->Event == NULL));
-
- if (Media->MediaId != MediaId) {
- return EFI_MEDIA_CHANGED;
- }
-
- if (Write && Media->ReadOnly) {
- return EFI_WRITE_PROTECTED;
- }
-
- if (Blocking) {
- //
- // Wait till pending async task is completed.
- //
- while (!DiskIo2RemoveCompletedTask (Instance));
-
- SubtasksPtr = &Subtasks;
- } else {
- DiskIo2RemoveCompletedTask (Instance);
- Task = AllocatePool (sizeof (DISK_IO2_TASK));
- if (Task == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- EfiAcquireLock (&Instance->TaskQueueLock);
- InsertTailList (&Instance->TaskQueue, &Task->Link);
- EfiReleaseLock (&Instance->TaskQueueLock);
-
- Task->Signature = DISK_IO2_TASK_SIGNATURE;
- Task->Instance = Instance;
- Task->Token = Token;
- EfiInitializeLock (&Task->SubtasksLock, TPL_NOTIFY);
-
- SubtasksPtr = &Task->Subtasks;
- }
-
- InitializeListHead (SubtasksPtr);
- if (!DiskIoCreateSubtaskList (Instance, Write, Offset, BufferSize, Buffer, Blocking, Instance->SharedWorkingBuffer, SubtasksPtr)) {
- if (Task != NULL) {
- FreePool (Task);
- }
- return EFI_OUT_OF_RESOURCES;
- }
- ASSERT (!IsListEmpty (SubtasksPtr));
-
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- for ( Link = GetFirstNode (SubtasksPtr), NextLink = GetNextNode (SubtasksPtr, Link)
- ; !IsNull (SubtasksPtr, Link)
- ; Link = NextLink, NextLink = GetNextNode (SubtasksPtr, NextLink)
- ) {
- Subtask = CR (Link, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
- Subtask->Task = Task;
- SubtaskBlocking = Subtask->Blocking;
-
- ASSERT ((Subtask->Length % Media->BlockSize == 0) || (Subtask->Length < Media->BlockSize));
-
- if (Subtask->Write) {
- //
- // Write
- //
- if (Subtask->WorkingBuffer != NULL) {
- //
- // A sub task before this one should be a block read operation, causing the WorkingBuffer filled with the entire one block data.
- //
- CopyMem (Subtask->WorkingBuffer + Subtask->Offset, Subtask->Buffer, Subtask->Length);
- }
-
- if (SubtaskBlocking) {
- Status = BlockIo->WriteBlocks (
- BlockIo,
- MediaId,
- Subtask->Lba,
- (Subtask->Length % Media->BlockSize == 0) ? Subtask->Length : Media->BlockSize,
- (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
- );
- } else {
- Status = BlockIo2->WriteBlocksEx (
- BlockIo2,
- MediaId,
- Subtask->Lba,
- &Subtask->BlockIo2Token,
- (Subtask->Length % Media->BlockSize == 0) ? Subtask->Length : Media->BlockSize,
- (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
- );
- }
-
- } else {
- //
- // Read
- //
- if (SubtaskBlocking) {
- Status = BlockIo->ReadBlocks (
- BlockIo,
- MediaId,
- Subtask->Lba,
- (Subtask->Length % Media->BlockSize == 0) ? Subtask->Length : Media->BlockSize,
- (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
- );
- if (!EFI_ERROR (Status) && (Subtask->WorkingBuffer != NULL)) {
- CopyMem (Subtask->Buffer, Subtask->WorkingBuffer + Subtask->Offset, Subtask->Length);
- }
- } else {
- Status = BlockIo2->ReadBlocksEx (
- BlockIo2,
- MediaId,
- Subtask->Lba,
- &Subtask->BlockIo2Token,
- (Subtask->Length % Media->BlockSize == 0) ? Subtask->Length : Media->BlockSize,
- (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
- );
- }
- }
-
- if (SubtaskBlocking || EFI_ERROR (Status)) {
- //
- // Make sure the subtask list only contains non-blocking subtasks.
- // Remove failed non-blocking subtasks as well because the callback won't be called.
- //
- DiskIoDestroySubtask (Instance, Subtask);
- }
-
- if (EFI_ERROR (Status)) {
- break;
- }
- }
-
- gBS->RaiseTPL (TPL_NOTIFY);
-
- //
- // Remove all the remaining subtasks when failure.
- // We shouldn't remove all the tasks because the non-blocking requests have been submitted and cannot be canceled.
- //
- if (EFI_ERROR (Status)) {
- while (!IsNull (SubtasksPtr, NextLink)) {
- Subtask = CR (NextLink, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
- NextLink = DiskIoDestroySubtask (Instance, Subtask);
- }
- }
-
- //
- // It's possible that the non-blocking subtasks finish before raising TPL to NOTIFY,
- // so the subtasks list might be empty at this point.
- //
- if (!Blocking && IsListEmpty (SubtasksPtr)) {
- EfiAcquireLock (&Instance->TaskQueueLock);
- RemoveEntryList (&Task->Link);
- EfiReleaseLock (&Instance->TaskQueueLock);
-
- if (!EFI_ERROR (Status) && (Task->Token != NULL)) {
- //
- // Task->Token should be set to NULL by the DiskIo2OnReadWriteComplete
- // It it's not, that means the non-blocking request was downgraded to blocking request.
- //
- DEBUG ((EFI_D_VERBOSE, "DiskIo: Non-blocking request was downgraded to blocking request, signal event directly.\n"));
- Task->Token->TransactionStatus = Status;
- gBS->SignalEvent (Task->Token->Event);
- }
-
- FreePool (Task);
- }
-
- gBS->RestoreTPL (OldTpl);
-
- return Status;
-}
-
-/**
- Reads a specified number of bytes from a device.
-
- @param This Indicates a pointer to the calling context.
- @param MediaId ID of the medium to be read.
- @param Offset The starting byte offset on the logical block I/O device to read from.
- @param Token A pointer to the token associated with the transaction.
- If this field is NULL, synchronous/blocking IO is performed.
- @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
- @param Buffer A pointer to the destination buffer for the data.
- The caller is responsible either having implicit or explicit ownership of the buffer.
-
- @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read correctly from the device.
- If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
- Event will be signaled upon completion.
- @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
- @retval EFI_NO_MEDIA There is no medium in the device.
- @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium.
- @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not valid for the device.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
-
-**/
-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
- )
-{
- return DiskIo2ReadWriteDisk (
- DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This),
- FALSE, MediaId, Offset, Token, BufferSize, (UINT8 *) Buffer
- );
-}
-
-/**
- Writes a specified number of bytes to a device.
-
- @param This Indicates a pointer to the calling context.
- @param MediaId ID of the medium to be written.
- @param Offset The starting byte offset on the logical block I/O device to write to.
- @param Token A pointer to the token associated with the transaction.
- If this field is NULL, synchronous/blocking IO is performed.
- @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
- @param Buffer A pointer to the buffer containing the data to be written.
-
- @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was written correctly to the device.
- If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
- Event will be signaled upon completion.
- @retval EFI_WRITE_PROTECTED The device cannot be written to.
- @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation.
- @retval EFI_NO_MEDIA There is no medium in the device.
- @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium.
- @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not valid for the device.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
-
-**/
-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
- )
-{
- return DiskIo2ReadWriteDisk (
- DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This),
- TRUE, MediaId, Offset, Token, BufferSize, (UINT8 *) Buffer
- );
-}
-
-/**
- The callback for the BlockIo2 FlushBlocksEx.
- @param Event Event whose notification function is being invoked.
- @param Context The pointer to the notification function's context,
- which points to the DISK_IO2_FLUSH_TASK instance.
-**/
-VOID
-EFIAPI
-DiskIo2OnFlushComplete (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- DISK_IO2_FLUSH_TASK *Task;
-
- gBS->CloseEvent (Event);
-
- Task = (DISK_IO2_FLUSH_TASK *) Context;
- ASSERT (Task->Signature == DISK_IO2_FLUSH_TASK_SIGNATURE);
- Task->Token->TransactionStatus = Task->BlockIo2Token.TransactionStatus;
- gBS->SignalEvent (Task->Token->Event);
-
- FreePool (Task);
-}
-
-/**
- Flushes all modified data to the physical device.
-
- @param This Indicates a pointer to the calling context.
- @param Token A pointer to the token associated with the transaction.
- If this field is NULL, synchronous/blocking IO is performed.
-
- @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was flushed successfully to the device.
- If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
- Event will be signaled upon completion.
- @retval EFI_WRITE_PROTECTED The device cannot be written to.
- @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation.
- @retval EFI_NO_MEDIA There is no medium in the device.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
-**/
-EFI_STATUS
-EFIAPI
-DiskIo2FlushDiskEx (
- IN EFI_DISK_IO2_PROTOCOL *This,
- IN OUT EFI_DISK_IO2_TOKEN *Token
- )
-{
- EFI_STATUS Status;
- DISK_IO2_FLUSH_TASK *Task;
- DISK_IO_PRIVATE_DATA *Private;
-
- Private = DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This);
-
- if ((Token != NULL) && (Token->Event != NULL)) {
- Task = AllocatePool (sizeof (DISK_IO2_FLUSH_TASK));
- if (Task == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- DiskIo2OnFlushComplete,
- Task,
- &Task->BlockIo2Token.Event
- );
- if (EFI_ERROR (Status)) {
- FreePool (Task);
- return Status;
- }
- Task->Signature = DISK_IO2_FLUSH_TASK_SIGNATURE;
- Task->Token = Token;
- Status = Private->BlockIo2->FlushBlocksEx (Private->BlockIo2, &Task->BlockIo2Token);
- if (EFI_ERROR (Status)) {
- gBS->CloseEvent (Task->BlockIo2Token.Event);
- FreePool (Task);
- }
- } else {
- Status = Private->BlockIo2->FlushBlocksEx (Private->BlockIo2, NULL);
- }
-
- return Status;
-}
-
-/**
- Read BufferSize bytes from Offset into Buffer.
- Reads may support reads that are not aligned on
- sector boundaries. There are three cases:
- UnderRun - The first byte is not on a sector boundary or the read request is
- less than a sector in length.
- Aligned - A read of N contiguous sectors.
- OverRun - The last byte is not on a sector boundary.
-
- @param This Protocol instance pointer.
- @param MediaId Id of the media, changes every time the media is replaced.
- @param Offset The starting byte offset to read from
- @param BufferSize Size of Buffer
- @param Buffer Buffer containing read data
-
- @retval EFI_SUCCESS The data was read correctly from the device.
- @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
- @retval EFI_NO_MEDIA There is no media in the device.
- @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
- @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
- valid for the device.
-
-**/
-EFI_STATUS
-EFIAPI
-DiskIoReadDisk (
- IN EFI_DISK_IO_PROTOCOL *This,
- IN UINT32 MediaId,
- IN UINT64 Offset,
- IN UINTN BufferSize,
- OUT VOID *Buffer
- )
-{
- return DiskIo2ReadWriteDisk (
- DISK_IO_PRIVATE_DATA_FROM_DISK_IO (This),
- FALSE, MediaId, Offset, NULL, BufferSize, (UINT8 *) Buffer
- );
-}
-
-
-/**
- Writes BufferSize bytes from Buffer into Offset.
- Writes may require a read modify write to support writes that are not
- aligned on sector boundaries. There are three cases:
- UnderRun - The first byte is not on a sector boundary or the write request
- is less than a sector in length. Read modify write is required.
- Aligned - A write of N contiguous sectors.
- OverRun - The last byte is not on a sector boundary. Read modified write
- required.
-
- @param This Protocol instance pointer.
- @param MediaId Id of the media, changes every time the media is replaced.
- @param Offset The starting byte offset to read from
- @param BufferSize Size of Buffer
- @param Buffer Buffer containing read data
-
- @retval EFI_SUCCESS The data was written correctly to the device.
- @retval EFI_WRITE_PROTECTED The device can not be written to.
- @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
- @retval EFI_NO_MEDIA There is no media in the device.
- @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
- @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
- valid for the device.
-
-**/
-EFI_STATUS
-EFIAPI
-DiskIoWriteDisk (
- IN EFI_DISK_IO_PROTOCOL *This,
- IN UINT32 MediaId,
- IN UINT64 Offset,
- IN UINTN BufferSize,
- IN VOID *Buffer
- )
-{
- return DiskIo2ReadWriteDisk (
- DISK_IO_PRIVATE_DATA_FROM_DISK_IO (This),
- TRUE, MediaId, Offset, NULL, BufferSize, (UINT8 *) Buffer
- );
-}
-
-/**
- The user Entry Point for module DiskIo. The user code starts with this function.
-
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval other Some error occurs when executing this entry point.
-
-**/
-EFI_STATUS
-EFIAPI
-InitializeDiskIo (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
-
- //
- // Install driver model protocol(s).
- //
- Status = EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gDiskIoDriverBinding,
- ImageHandle,
- &gDiskIoComponentName,
- &gDiskIoComponentName2
- );
- ASSERT_EFI_ERROR (Status);
-
- return Status;
-}