mirror of https://github.com/acidanthera/audk.git
Add BlockIO2 Protocol.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11606 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
c89ea31f52
commit
490b5ea10b
|
@ -184,9 +184,50 @@ AhciWaitMemSet (
|
|||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
Check the memory status to the test value.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Offset The memory address to test.
|
||||
@param[in] MaskValue The mask value of memory.
|
||||
@param[in] TestValue The test value of memory.
|
||||
@param[in, out] RetryTimes The retry times value for waitting memory set.
|
||||
|
||||
@retval EFI_NOTREADY The memory is not set.
|
||||
@retval EFI_TIMEOUT The memory setting retry times out.
|
||||
@retval EFI_SUCCESS The memory is correct set.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AhciCheckMemSet (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT32 Offset,
|
||||
IN UINT32 MaskValue,
|
||||
IN UINT32 TestValue,
|
||||
IN UINTN *RetryTimes
|
||||
)
|
||||
{
|
||||
UINT32 Value;
|
||||
|
||||
(*RetryTimes) --;
|
||||
|
||||
Value = AhciReadReg (PciIo, Offset) & MaskValue;
|
||||
|
||||
if (Value == TestValue) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if ((*RetryTimes) == 0) {
|
||||
return EFI_TIMEOUT;
|
||||
} else {
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the device is still on port. It also checks if the AHCI controller
|
||||
supports the address and data count will be transfered.
|
||||
supports the address and data count will be transferred.
|
||||
|
||||
@param PciIo The PCI IO protocol instance.
|
||||
@param Port The number of port.
|
||||
|
@ -543,18 +584,21 @@ AhciBuildCommandFis (
|
|||
/**
|
||||
Start a PIO data transfer on specific port.
|
||||
|
||||
@param PciIo The PCI IO protocol instance.
|
||||
@param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param Port The number of port.
|
||||
@param PortMultiplier The timeout value of stop.
|
||||
@param AtapiCommand The atapi command will be used for the transfer.
|
||||
@param AtapiCommandLength The length of the atapi command.
|
||||
@param Read The transfer direction.
|
||||
@param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param MemoryAddr The pointer to the data buffer.
|
||||
@param DataCount The data count to be transferred.
|
||||
@param Timeout The timeout value of non data transfer.
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param[in] Port The number of port.
|
||||
@param[in] PortMultiplier The timeout value of stop.
|
||||
@param[in] AtapiCommand The atapi command will be used for the
|
||||
transfer.
|
||||
@param[in] AtapiCommandLength The length of the atapi command.
|
||||
@param[in] Read The transfer direction.
|
||||
@param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param[in, out] MemoryAddr The pointer to the data buffer.
|
||||
@param[in] DataCount The data count to be transferred.
|
||||
@param[in] Timeout The timeout value of non data transfer.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
|
||||
@retval EFI_TIMEOUT The operation is time out.
|
||||
|
@ -576,7 +620,8 @@ AhciPioTransfer (
|
|||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN OUT VOID *MemoryAddr,
|
||||
IN UINT32 DataCount,
|
||||
IN UINT64 Timeout
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -649,7 +694,7 @@ AhciPioTransfer (
|
|||
}
|
||||
|
||||
//
|
||||
// Checking the status and wait the driver sending data
|
||||
// Check the status and wait the driver sending data
|
||||
//
|
||||
FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
|
||||
//
|
||||
|
@ -730,18 +775,21 @@ Exit:
|
|||
/**
|
||||
Start a DMA data transfer on specific port
|
||||
|
||||
@param PciIo The PCI IO protocol instance.
|
||||
@param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param Port The number of port.
|
||||
@param PortMultiplier The timeout value of stop.
|
||||
@param AtapiCommand The atapi command will be used for the transfer.
|
||||
@param AtapiCommandLength The length of the atapi command.
|
||||
@param Read The transfer direction.
|
||||
@param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param MemoryAddr The pointer to the data buffer.
|
||||
@param DataCount The data count to be transferred.
|
||||
@param Timeout The timeout value of non data transfer.
|
||||
@param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
|
||||
@param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param[in] Port The number of port.
|
||||
@param[in] PortMultiplier The timeout value of stop.
|
||||
@param[in] AtapiCommand The atapi command will be used for the
|
||||
transfer.
|
||||
@param[in] AtapiCommandLength The length of the atapi command.
|
||||
@param[in] Read The transfer direction.
|
||||
@param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param[in, out] MemoryAddr The pointer to the data buffer.
|
||||
@param[in] DataCount The data count to be transferred.
|
||||
@param[in] Timeout The timeout value of non data transfer.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
|
||||
@retval EFI_TIMEOUT The operation is time out.
|
||||
|
@ -752,7 +800,7 @@ Exit:
|
|||
EFI_STATUS
|
||||
EFIAPI
|
||||
AhciDmaTransfer (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
|
||||
IN EFI_AHCI_REGISTERS *AhciRegisters,
|
||||
IN UINT8 Port,
|
||||
IN UINT8 PortMultiplier,
|
||||
|
@ -763,7 +811,8 @@ AhciDmaTransfer (
|
|||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN OUT VOID *MemoryAddr,
|
||||
IN UINTN DataCount,
|
||||
IN UINT64 Timeout
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -775,6 +824,39 @@ AhciDmaTransfer (
|
|||
EFI_AHCI_COMMAND_FIS CFis;
|
||||
EFI_AHCI_COMMAND_LIST CmdList;
|
||||
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
Map = NULL;
|
||||
PciIo = Instance->PciIo;
|
||||
|
||||
if (PciIo == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Before starting the Blocking BlockIO operation, push to finish all non-blocking
|
||||
// BlockIO tasks.
|
||||
// Delay 100us to simulate the blocking time out checking.
|
||||
//
|
||||
while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {
|
||||
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
||||
AsyncNonBlockingTransferRoutine (NULL, Instance);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
//
|
||||
// Stall for 100us.
|
||||
//
|
||||
MicroSecondDelay (100);
|
||||
}
|
||||
|
||||
if ((Task == NULL) || ((Task != NULL) && (!Task->IsStart))) {
|
||||
//
|
||||
// Mark the Task to indicate that it has been started.
|
||||
//
|
||||
if (Task != NULL) {
|
||||
Task->IsStart = TRUE;
|
||||
Task->RetryTimes = (UINT32) (DivU64x32(Timeout, 1000) + 1);
|
||||
}
|
||||
if (Read) {
|
||||
Flag = EfiPciIoOperationBusMasterWrite;
|
||||
} else {
|
||||
|
@ -782,7 +864,7 @@ AhciDmaTransfer (
|
|||
}
|
||||
|
||||
//
|
||||
// construct command list and command table with pci bus address
|
||||
// Construct command list and command table with pci bus address.
|
||||
//
|
||||
MapLength = DataCount;
|
||||
Status = PciIo->Map (
|
||||
|
@ -798,6 +880,9 @@ AhciDmaTransfer (
|
|||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (Task != NULL) {
|
||||
Task->Map = Map;
|
||||
}
|
||||
//
|
||||
// Package read needed
|
||||
//
|
||||
|
@ -847,11 +932,24 @@ AhciDmaTransfer (
|
|||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Wait for command compelte
|
||||
//
|
||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
|
||||
if (Task != NULL) {
|
||||
//
|
||||
// For Non-blocking
|
||||
//
|
||||
Status = AhciCheckMemSet (
|
||||
PciIo,
|
||||
Offset,
|
||||
0xFFFFFFFF,
|
||||
0,
|
||||
(UINTN *) (&Task->RetryTimes)
|
||||
);
|
||||
} else {
|
||||
Status = AhciWaitMemSet (
|
||||
PciIo,
|
||||
Offset,
|
||||
|
@ -859,11 +957,26 @@ AhciDmaTransfer (
|
|||
0,
|
||||
Timeout
|
||||
);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
|
||||
|
||||
if (Task != NULL) {
|
||||
//
|
||||
// For Non-blocking
|
||||
//
|
||||
Status = AhciCheckMemSet (
|
||||
PciIo,
|
||||
Offset,
|
||||
EFI_AHCI_PORT_IS_DHRS,
|
||||
EFI_AHCI_PORT_IS_DHRS,
|
||||
(UINTN *) (&Task->RetryTimes)
|
||||
);
|
||||
} else {
|
||||
Status = AhciWaitMemSet (
|
||||
PciIo,
|
||||
Offset,
|
||||
|
@ -871,11 +984,23 @@ AhciDmaTransfer (
|
|||
EFI_AHCI_PORT_IS_DHRS,
|
||||
Timeout
|
||||
);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
//
|
||||
// For Blocking mode, the command should be stopped, the Fis should be disabled
|
||||
// and the PciIo should be unmapped.
|
||||
// For non-blocking mode, only when a error is happened (if the return status is
|
||||
// EFI_NOT_READY that means the command doesn't finished, try again.), first do the
|
||||
// context cleanup, then set the packet's Asb status.
|
||||
//
|
||||
if (Task == NULL ||
|
||||
((Task != NULL) && (Status != EFI_NOT_READY))
|
||||
) {
|
||||
AhciStopCommand (
|
||||
PciIo,
|
||||
Port,
|
||||
|
@ -890,26 +1015,33 @@ Exit:
|
|||
|
||||
PciIo->Unmap (
|
||||
PciIo,
|
||||
Map
|
||||
(Task != NULL) ? Task->Map : Map
|
||||
);
|
||||
|
||||
AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);
|
||||
if (Task != NULL) {
|
||||
Task->Packet->Asb->AtaStatus = 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Start a non data transfer on specific port.
|
||||
|
||||
@param PciIo The PCI IO protocol instance.
|
||||
@param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param Port The number of port.
|
||||
@param PortMultiplier The timeout value of stop.
|
||||
@param AtapiCommand The atapi command will be used for the transfer.
|
||||
@param AtapiCommandLength The length of the atapi command.
|
||||
@param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param Timeout The timeout value of non data transfer.
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param[in] Port The number of port.
|
||||
@param[in] PortMultiplier The timeout value of stop.
|
||||
@param[in] AtapiCommand The atapi command will be used for the
|
||||
transfer.
|
||||
@param[in] AtapiCommandLength The length of the atapi command.
|
||||
@param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param[in] Timeout The timeout value of non data transfer.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
|
||||
@retval EFI_TIMEOUT The operation is time out.
|
||||
|
@ -928,7 +1060,8 @@ AhciNonDataTransfer (
|
|||
IN UINT8 AtapiCommandLength,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -1077,7 +1210,7 @@ AhciStopCommand (
|
|||
|
||||
@param PciIo The PCI IO protocol instance.
|
||||
@param Port The number of port.
|
||||
@param CommandSlot The number of CommandSlot.
|
||||
@param CommandSlot The number of Command Slot.
|
||||
@param Timeout The timeout value of start.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The command start unsuccessfully.
|
||||
|
@ -1205,14 +1338,14 @@ AhciPortReset (
|
|||
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_DET_INIT);
|
||||
|
||||
//
|
||||
// wait 5 milliseceond before de-assert DET
|
||||
// wait 5 millisecond before de-assert DET
|
||||
//
|
||||
MicroSecondDelay (5000);
|
||||
|
||||
AhciAndReg (PciIo, Offset, (UINT32)EFI_AHCI_PORT_SCTL_MASK);
|
||||
|
||||
//
|
||||
// wait 5 milliseceond before de-assert DET
|
||||
// wait 5 millisecond before de-assert DET
|
||||
//
|
||||
MicroSecondDelay (5000);
|
||||
|
||||
|
@ -1244,7 +1377,6 @@ AhciPortReset (
|
|||
@param PciIo The PCI IO protocol instance.
|
||||
@param Timeout The timeout value of reset.
|
||||
|
||||
|
||||
@retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
|
||||
@retval EFI_TIMEOUT The reset operation is time out.
|
||||
@retval EFI_SUCCESS AHCI controller is reset successfully.
|
||||
|
@ -1340,7 +1472,8 @@ AhciAtaSmartReturnStatusCheck (
|
|||
0,
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
@ -1430,7 +1563,8 @@ AhciAtaSmartSupport (
|
|||
0,
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
|
||||
|
@ -1455,7 +1589,8 @@ AhciAtaSmartSupport (
|
|||
0,
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
|
@ -1527,7 +1662,8 @@ AhciIdentify (
|
|||
&AtaStatusBlock,
|
||||
Buffer,
|
||||
sizeof (EFI_IDENTIFY_DATA),
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
|
@ -1584,7 +1720,8 @@ AhciIdentifyPacket (
|
|||
&AtaStatusBlock,
|
||||
Buffer,
|
||||
sizeof (EFI_IDENTIFY_DATA),
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
|
@ -1641,7 +1778,8 @@ AhciDeviceSetFeature (
|
|||
0,
|
||||
&AtaCommandBlock,
|
||||
&AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
|
@ -1718,7 +1856,8 @@ AhciPacketCommandExecute (
|
|||
Packet->CdbLength,
|
||||
&AtaCommandBlock,
|
||||
&AtaStatusBlock,
|
||||
Packet->Timeout
|
||||
Packet->Timeout,
|
||||
NULL
|
||||
);
|
||||
} else {
|
||||
//
|
||||
|
@ -1742,7 +1881,8 @@ AhciPacketCommandExecute (
|
|||
&AtaStatusBlock,
|
||||
Buffer,
|
||||
Length,
|
||||
Packet->Timeout
|
||||
Packet->Timeout,
|
||||
NULL
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
break;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Header file for AHCI mode of ATA host controller.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2011, 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
|
||||
|
@ -348,117 +348,5 @@ AhciStopCommand (
|
|||
IN UINT64 Timeout
|
||||
);
|
||||
|
||||
/**
|
||||
Start a non data transfer on specific port.
|
||||
|
||||
@param PciIo The PCI IO protocol instance.
|
||||
@param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param Port The number of port.
|
||||
@param PortMultiplier The timeout value of stop.
|
||||
@param AtapiCommand The atapi command will be used for the transfer.
|
||||
@param AtapiCommandLength The length of the atapi command.
|
||||
@param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param Timeout The timeout value of non data transfer.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
|
||||
@retval EFI_TIMEOUT The operation is time out.
|
||||
@retval EFI_UNSUPPORTED The device is not ready for transfer.
|
||||
@retval EFI_SUCCESS The non data transfer executes successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AhciNonDataTransfer (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_AHCI_REGISTERS *AhciRegisters,
|
||||
IN UINT8 Port,
|
||||
IN UINT8 PortMultiplier,
|
||||
IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
|
||||
IN UINT8 AtapiCommandLength,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout
|
||||
);
|
||||
|
||||
/**
|
||||
Start a DMA data transfer on specific port
|
||||
|
||||
@param PciIo The PCI IO protocol instance.
|
||||
@param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param Port The number of port.
|
||||
@param PortMultiplier The timeout value of stop.
|
||||
@param AtapiCommand The atapi command will be used for the transfer.
|
||||
@param AtapiCommandLength The length of the atapi command.
|
||||
@param Read The transfer direction.
|
||||
@param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param MemoryAddr The pointer to the data buffer.
|
||||
@param DataCount The data count to be transferred.
|
||||
@param Timeout The timeout value of non data transfer.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
|
||||
@retval EFI_TIMEOUT The operation is time out.
|
||||
@retval EFI_UNSUPPORTED The device is not ready for transfer.
|
||||
@retval EFI_SUCCESS The DMA data transfer executes successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AhciDmaTransfer (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_AHCI_REGISTERS *AhciRegisters,
|
||||
IN UINT8 Port,
|
||||
IN UINT8 PortMultiplier,
|
||||
IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
|
||||
IN UINT8 AtapiCommandLength,
|
||||
IN BOOLEAN Read,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN OUT VOID *MemoryAddr,
|
||||
IN UINTN DataCount,
|
||||
IN UINT64 Timeout
|
||||
);
|
||||
|
||||
/**
|
||||
Start a PIO data transfer on specific port.
|
||||
|
||||
@param PciIo The PCI IO protocol instance.
|
||||
@param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param Port The number of port.
|
||||
@param PortMultiplier The timeout value of stop.
|
||||
@param AtapiCommand The atapi command will be used for the transfer.
|
||||
@param AtapiCommandLength The length of the atapi command.
|
||||
@param Read The transfer direction.
|
||||
@param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param MemoryAddr The pointer to the data buffer.
|
||||
@param DataCount The data count to be transferred.
|
||||
@param Timeout The timeout value of non data transfer.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
|
||||
@retval EFI_TIMEOUT The operation is time out.
|
||||
@retval EFI_UNSUPPORTED The device is not ready for transfer.
|
||||
@retval EFI_SUCCESS The PIO data transfer executes successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AhciPioTransfer (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_AHCI_REGISTERS *AhciRegisters,
|
||||
IN UINT8 Port,
|
||||
IN UINT8 PortMultiplier,
|
||||
IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
|
||||
IN UINT8 AtapiCommandLength,
|
||||
IN BOOLEAN Read,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN OUT VOID *MemoryAddr,
|
||||
IN UINT32 DataCount,
|
||||
IN UINT64 Timeout
|
||||
);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ ATA_ATAPI_PASS_THRU_INSTANCE gAtaAtapiPassThruInstanceTemplate = {
|
|||
// bits.
|
||||
// Note that the driver doesn't support AtaPassThru non blocking I/O.
|
||||
//
|
||||
EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL,
|
||||
EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_NONBLOCKIO,
|
||||
//
|
||||
// IoAlign
|
||||
//
|
||||
|
@ -98,7 +98,12 @@ ATA_ATAPI_PASS_THRU_INSTANCE gAtaAtapiPassThruInstanceTemplate = {
|
|||
0, // PreviousPort
|
||||
0, // PreviousPortMultiplier
|
||||
0, // PreviousTargetId
|
||||
0 // PreviousLun
|
||||
0, // PreviousLun
|
||||
NULL, // Timer event
|
||||
{ // NonBlocking TaskList
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
ATAPI_DEVICE_PATH mAtapiDevicePathTemplate = {
|
||||
|
@ -132,6 +137,298 @@ UINT8 mScsiId[TARGET_MAX_BYTES] = {
|
|||
0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
Sends an ATA command to an ATA device that is attached to the ATA controller. This function
|
||||
supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,
|
||||
and the non-blocking I/O functionality is optional.
|
||||
|
||||
@param[in] Port The port number of the ATA device to send the command.
|
||||
@param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
|
||||
If there is no port multiplier, then specify 0.
|
||||
@param[in, out] Packet A pointer to the ATA command to send to the ATA device specified by Port
|
||||
and PortMultiplierPort.
|
||||
@param[in] Instance Pointer to the ATA_ATAPI_PASS_THRU_INSTANCE.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_SUCCESS The ATA command was sent by the host. For
|
||||
bi-directional commands, InTransferLength bytes
|
||||
were transferred from InDataBuffer. For
|
||||
write and bi-directional commands, OutTransferLength
|
||||
bytes were transferred by OutDataBuffer.
|
||||
@retval EFI_BAD_BUFFER_SIZE The ATA command was not executed. The number
|
||||
of bytes that could be transferred is returned
|
||||
in InTransferLength. For write and bi-directional
|
||||
commands, OutTransferLength bytes were transferred
|
||||
by OutDataBuffer.
|
||||
@retval EFI_NOT_READY The ATA command could not be sent because
|
||||
there are too many ATA commands already
|
||||
queued. The caller may retry again later.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting
|
||||
to send the ATA command.
|
||||
@retval EFI_INVALID_PARAMETER Port, PortMultiplierPort, or the contents
|
||||
of Acb are invalid. The ATA command was
|
||||
not sent, so no additional status information
|
||||
is available.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaPassThruPassThruExecute (
|
||||
IN UINT16 Port,
|
||||
IN UINT16 PortMultiplierPort,
|
||||
IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,
|
||||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
|
||||
IN ATA_NONBLOCK_TASK *Task OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_ATA_PASS_THRU_CMD_PROTOCOL Protocol;
|
||||
EFI_ATA_HC_WORK_MODE Mode;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Protocol = Packet->Protocol;
|
||||
|
||||
Mode = Instance->Mode;
|
||||
switch (Mode) {
|
||||
case EfiAtaIdeMode:
|
||||
//
|
||||
// Reassign IDE mode io port registers' base addresses
|
||||
//
|
||||
Status = GetIdeRegisterIoAddr (Instance->PciIo, Instance->IdeRegisters);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
switch (Protocol) {
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
|
||||
Status = AtaNonDataCommandIn (
|
||||
Instance->PciIo,
|
||||
&Instance->IdeRegisters[Port],
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
|
||||
Status = AtaPioDataInOut (
|
||||
Instance->PciIo,
|
||||
&Instance->IdeRegisters[Port],
|
||||
Packet->InDataBuffer,
|
||||
Packet->InTransferLength,
|
||||
TRUE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
|
||||
Status = AtaPioDataInOut (
|
||||
Instance->PciIo,
|
||||
&Instance->IdeRegisters[Port],
|
||||
Packet->OutDataBuffer,
|
||||
Packet->OutTransferLength,
|
||||
FALSE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
|
||||
Status = AtaUdmaInOut (
|
||||
Instance,
|
||||
&Instance->IdeRegisters[Port],
|
||||
TRUE,
|
||||
Packet->InDataBuffer,
|
||||
Packet->InTransferLength,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
|
||||
Status = AtaUdmaInOut (
|
||||
Instance,
|
||||
&Instance->IdeRegisters[Port],
|
||||
FALSE,
|
||||
Packet->OutDataBuffer,
|
||||
Packet->OutTransferLength,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
default :
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
break;
|
||||
case EfiAtaAhciMode :
|
||||
switch (Protocol) {
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
|
||||
Status = AhciNonDataTransfer (
|
||||
Instance->PciIo,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
|
||||
Status = AhciPioTransfer (
|
||||
Instance->PciIo,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
TRUE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->InDataBuffer,
|
||||
Packet->InTransferLength,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
|
||||
Status = AhciPioTransfer (
|
||||
Instance->PciIo,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
FALSE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->OutDataBuffer,
|
||||
Packet->OutTransferLength,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
|
||||
Status = AhciDmaTransfer (
|
||||
Instance,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
TRUE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->InDataBuffer,
|
||||
Packet->InTransferLength,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
|
||||
Status = AhciDmaTransfer (
|
||||
Instance,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
FALSE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->OutDataBuffer,
|
||||
Packet->OutTransferLength,
|
||||
Packet->Timeout,
|
||||
Task
|
||||
);
|
||||
break;
|
||||
default :
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Call back function when the timer event is signaled.
|
||||
|
||||
@param[in] Event The Event this notify function registered to.
|
||||
@param[in] Context Pointer to the context data registered to the
|
||||
Event.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
AsyncNonBlockingTransferRoutine (
|
||||
EFI_EVENT Event,
|
||||
VOID* Context
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *EntryHeader;
|
||||
ATA_NONBLOCK_TASK *Task;
|
||||
EFI_STATUS Status;
|
||||
ATA_ATAPI_PASS_THRU_INSTANCE *Instance;
|
||||
|
||||
Instance = (ATA_ATAPI_PASS_THRU_INSTANCE *) Context;
|
||||
EntryHeader = &Instance->NonBlockingTaskList;
|
||||
//
|
||||
// Get the Taks from the Taks List and execute it, until there is
|
||||
// no task in the list or the device is busy with task (EFI_NOT_READY).
|
||||
//
|
||||
while (TRUE) {
|
||||
if (!IsListEmpty (EntryHeader)) {
|
||||
Entry = GetFirstNode (EntryHeader);
|
||||
Task = ATA_NON_BLOCK_TASK_FROM_ENTRY (Entry);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
Status = AtaPassThruPassThruExecute (
|
||||
Task->Port,
|
||||
Task->PortMultiplier,
|
||||
Task->Packet,
|
||||
Instance,
|
||||
Task
|
||||
);
|
||||
|
||||
//
|
||||
// If the data transfer meet a error which is not dumped into the status block
|
||||
// set the Status block related bit.
|
||||
//
|
||||
if ((Status != EFI_NOT_READY) && (Status != EFI_SUCCESS)) {
|
||||
Task->Packet->Asb->AtaStatus = 0x01;
|
||||
}
|
||||
//
|
||||
// For Non blocking mode, the Status of EFI_NOT_READY means the operation
|
||||
// is not finished yet. Other Status indicate the operation is either
|
||||
// successful or failed.
|
||||
//
|
||||
if (Status != EFI_NOT_READY) {
|
||||
RemoveEntryList (&Task->Link);
|
||||
gBS->SignalEvent (Task->Event);
|
||||
FreePool (Task);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The Entry Point of module.
|
||||
|
||||
|
@ -446,6 +743,28 @@ AtaAtapiPassThruStart (
|
|||
Instance->AtaPassThru.Mode = &Instance->AtaPassThruMode;
|
||||
Instance->ExtScsiPassThru.Mode = &Instance->ExtScsiPassThruMode;
|
||||
InitializeListHead(&Instance->DeviceList);
|
||||
InitializeListHead(&Instance->NonBlockingTaskList);
|
||||
|
||||
Instance->TimerEvent = NULL;
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_TIMER | EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
AsyncNonBlockingTransferRoutine,
|
||||
Instance,
|
||||
&Instance->TimerEvent
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
//
|
||||
// Set 1ms timer.
|
||||
//
|
||||
Status = gBS->SetTimer (Instance->TimerEvent, TimerPeriodic, 10000);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
//
|
||||
// Enumerate all inserted ATA devices.
|
||||
|
@ -475,6 +794,10 @@ ErrorExit:
|
|||
);
|
||||
}
|
||||
|
||||
if (Instance->TimerEvent != NULL) {
|
||||
gBS->CloseEvent (Instance->TimerEvent);
|
||||
}
|
||||
|
||||
//
|
||||
// Remove all inserted ATA devices.
|
||||
//
|
||||
|
@ -543,12 +866,21 @@ AtaAtapiPassThruStop (
|
|||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS(AtaPassThru);
|
||||
PciIo = Instance->PciIo;
|
||||
Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (AtaPassThru);
|
||||
|
||||
//
|
||||
// Close Non-Blocking timer and free Task list.
|
||||
//
|
||||
if (Instance->TimerEvent != NULL) {
|
||||
gBS->CloseEvent (Instance->TimerEvent);
|
||||
Instance->TimerEvent = NULL;
|
||||
}
|
||||
DestroyAsynTaskList (Instance);
|
||||
|
||||
//
|
||||
// Disable this ATA host controller.
|
||||
//
|
||||
PciIo = Instance->PciIo;
|
||||
Status = PciIo->Attributes (
|
||||
PciIo,
|
||||
EfiPciIoAttributeOperationSupported,
|
||||
|
@ -757,6 +1089,42 @@ DestroyDeviceInfoList (
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Destroy all pending non blocking tasks.
|
||||
|
||||
@param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DestroyAsynTaskList (
|
||||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *DelEntry;
|
||||
ATA_NONBLOCK_TASK *Task;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
||||
if (!IsListEmpty (&Instance->NonBlockingTaskList)) {
|
||||
//
|
||||
// Free the Subtask list.
|
||||
//
|
||||
for (Entry = (&Instance->NonBlockingTaskList)->ForwardLink;
|
||||
Entry != (&Instance->NonBlockingTaskList);
|
||||
) {
|
||||
DelEntry = Entry;
|
||||
Entry = Entry->ForwardLink;
|
||||
Task = ATA_NON_BLOCK_TASK_FROM_ENTRY (DelEntry);
|
||||
|
||||
RemoveEntryList (DelEntry);
|
||||
FreePool (Task);
|
||||
}
|
||||
}
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
}
|
||||
|
||||
/**
|
||||
Enumerate all attached ATA devices at IDE mode or AHCI mode separately.
|
||||
|
||||
|
@ -865,15 +1233,14 @@ AtaPassThruPassThru (
|
|||
IN EFI_EVENT Event OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ATA_ATAPI_PASS_THRU_INSTANCE *Instance;
|
||||
EFI_ATA_PASS_THRU_CMD_PROTOCOL Protocol;
|
||||
EFI_ATA_HC_WORK_MODE Mode;
|
||||
LIST_ENTRY *Node;
|
||||
EFI_ATA_DEVICE_INFO *DeviceInfo;
|
||||
EFI_IDENTIFY_DATA *IdentifyData;
|
||||
UINT64 Capacity;
|
||||
UINT32 MaxSectorCount;
|
||||
ATA_NONBLOCK_TASK *Task;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
|
||||
|
||||
|
@ -940,173 +1307,37 @@ AtaPassThruPassThru (
|
|||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
Status = EFI_UNSUPPORTED;
|
||||
Protocol = Packet->Protocol;
|
||||
|
||||
Mode = Instance->Mode;
|
||||
switch (Mode) {
|
||||
case EfiAtaIdeMode:
|
||||
//
|
||||
// Reassign IDE mode io port registers' base addresses
|
||||
// For non-blocking mode, queue the Task into the list.
|
||||
//
|
||||
Status = GetIdeRegisterIoAddr (Instance->PciIo, Instance->IdeRegisters);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
if (Event != NULL) {
|
||||
Task = AllocateZeroPool (sizeof (ATA_NONBLOCK_TASK));
|
||||
if (Task == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
switch (Protocol) {
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
|
||||
Status = AtaNonDataCommandIn(
|
||||
Instance->PciIo,
|
||||
&Instance->IdeRegisters[Port],
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
|
||||
Status = AtaPioDataInOut(
|
||||
Instance->PciIo,
|
||||
&Instance->IdeRegisters[Port],
|
||||
Packet->InDataBuffer,
|
||||
Packet->InTransferLength,
|
||||
TRUE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
|
||||
Status = AtaPioDataInOut(
|
||||
Instance->PciIo,
|
||||
&Instance->IdeRegisters[Port],
|
||||
Packet->OutDataBuffer,
|
||||
Packet->OutTransferLength,
|
||||
FALSE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
|
||||
Status = AtaUdmaInOut(
|
||||
Instance->PciIo,
|
||||
&Instance->IdeRegisters[Port],
|
||||
TRUE,
|
||||
Packet->InDataBuffer,
|
||||
Packet->InTransferLength,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
|
||||
Status = AtaUdmaInOut(
|
||||
Instance->PciIo,
|
||||
&Instance->IdeRegisters[Port],
|
||||
FALSE,
|
||||
Packet->OutDataBuffer,
|
||||
Packet->OutTransferLength,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
default :
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
break;
|
||||
case EfiAtaAhciMode :
|
||||
switch (Protocol) {
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
|
||||
Status = AhciNonDataTransfer(
|
||||
Instance->PciIo,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
|
||||
Status = AhciPioTransfer(
|
||||
Instance->PciIo,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
TRUE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->InDataBuffer,
|
||||
Packet->InTransferLength,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
|
||||
Status = AhciPioTransfer(
|
||||
Instance->PciIo,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
FALSE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->OutDataBuffer,
|
||||
Packet->OutTransferLength,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
|
||||
Status = AhciDmaTransfer(
|
||||
Instance->PciIo,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
TRUE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->InDataBuffer,
|
||||
Packet->InTransferLength,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
|
||||
Status = AhciDmaTransfer(
|
||||
Instance->PciIo,
|
||||
&Instance->AhciRegisters,
|
||||
(UINT8)Port,
|
||||
(UINT8)PortMultiplierPort,
|
||||
NULL,
|
||||
0,
|
||||
FALSE,
|
||||
Packet->Acb,
|
||||
Packet->Asb,
|
||||
Packet->OutDataBuffer,
|
||||
Packet->OutTransferLength,
|
||||
Packet->Timeout
|
||||
);
|
||||
break;
|
||||
default :
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
break;
|
||||
Task->Signature = ATA_NONBLOCKING_TASK_SIGNATURE;
|
||||
Task->Port = Port;
|
||||
Task->PortMultiplier = PortMultiplierPort;
|
||||
Task->Packet = Packet;
|
||||
Task->Event = Event;
|
||||
Task->IsStart = FALSE;
|
||||
Task->RetryTimes = 0;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
||||
InsertTailList (&Instance->NonBlockingTaskList, &Task->Link);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
return EFI_SUCCESS;
|
||||
} else {
|
||||
return AtaPassThruPassThruExecute (
|
||||
Port,
|
||||
PortMultiplierPort,
|
||||
Packet,
|
||||
Instance,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Header file for ATA/ATAPI PASS THRU driver.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2011, 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
|
||||
|
@ -47,6 +47,9 @@ extern EFI_COMPONENT_NAME2_PROTOCOL gAtaAtapiPassThruComponentName2;
|
|||
|
||||
#define ATA_ATAPI_PASS_THRU_SIGNATURE SIGNATURE_32 ('a', 'a', 'p', 't')
|
||||
#define ATA_ATAPI_DEVICE_SIGNATURE SIGNATURE_32 ('a', 'd', 'e', 'v')
|
||||
#define ATA_NONBLOCKING_TASK_SIGNATURE SIGNATURE_32 ('a', 't', 's', 'k')
|
||||
|
||||
typedef struct _ATA_NONBLOCK_TASK ATA_NONBLOCK_TASK;
|
||||
|
||||
typedef enum {
|
||||
EfiAtaIdeMode,
|
||||
|
@ -112,8 +115,32 @@ typedef struct {
|
|||
UINT16 PreviousTargetId;
|
||||
UINT64 PreviousLun;
|
||||
|
||||
//
|
||||
// For Non-blocking.
|
||||
//
|
||||
EFI_EVENT TimerEvent;
|
||||
LIST_ENTRY NonBlockingTaskList;
|
||||
} ATA_ATAPI_PASS_THRU_INSTANCE;
|
||||
|
||||
//
|
||||
// Task for Non-blocking mode.
|
||||
//
|
||||
struct _ATA_NONBLOCK_TASK {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
UINT16 Port;
|
||||
UINT16 PortMultiplier;
|
||||
EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
|
||||
BOOLEAN IsStart;
|
||||
EFI_EVENT Event;
|
||||
UINT64 RetryTimes;
|
||||
VOID *Map; // Pointer to map.
|
||||
VOID *TableMap;// Pointer to PRD table map.
|
||||
EFI_ATA_DMA_PRD *MapBaseAddress; // Pointer to range Base address for Map.
|
||||
UINTN PageCount; // The page numbers used by PCIO freebuffer.
|
||||
};
|
||||
|
||||
//
|
||||
// Timeout value which uses 100ns as a unit.
|
||||
// It means 3 second span.
|
||||
|
@ -142,6 +169,14 @@ typedef struct {
|
|||
Link, \
|
||||
ATA_ATAPI_DEVICE_SIGNATURE \
|
||||
);
|
||||
|
||||
#define ATA_NON_BLOCK_TASK_FROM_ENTRY(a) \
|
||||
CR (a, \
|
||||
ATA_NONBLOCK_TASK, \
|
||||
Link, \
|
||||
ATA_NONBLOCKING_TASK_SIGNATURE \
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the driver.
|
||||
|
||||
|
@ -453,6 +488,18 @@ DestroyDeviceInfoList (
|
|||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Destroy all pending non blocking tasks.
|
||||
|
||||
@param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DestroyAsynTaskList (
|
||||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Enumerate all attached ATA devices at IDE mode or AHCI mode separately.
|
||||
|
||||
|
@ -470,6 +517,21 @@ EnumerateAttachedDevice (
|
|||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Call back funtion when the timer event is signaled.
|
||||
|
||||
@param[in] Event The Event this notify function registered to.
|
||||
@param[in] Context Pointer to the context data registered to the
|
||||
Event.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
AsyncNonBlockingTransferRoutine (
|
||||
EFI_EVENT Event,
|
||||
VOID* Context
|
||||
);
|
||||
|
||||
/**
|
||||
Sends an ATA command to an ATA device that is attached to the ATA controller. This function
|
||||
supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,
|
||||
|
@ -673,6 +735,7 @@ AtaPassThruBuildDevicePath (
|
|||
@retval EFI_UNSUPPORTED This driver does not support the device path node type in DevicePath.
|
||||
@retval EFI_NOT_FOUND A valid translation from DevicePath to a port number and port multiplier
|
||||
port number does not exist.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
|
@ -1003,5 +1066,231 @@ AhciModeInitialization (
|
|||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
|
||||
);
|
||||
|
||||
/**
|
||||
Start a non data transfer on specific port.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param[in] Port The number of port.
|
||||
@param[in] PortMultiplier The timeout value of stop.
|
||||
@param[in] AtapiCommand The atapi command will be used for the
|
||||
transfer.
|
||||
@param[in] AtapiCommandLength The length of the atapi command.
|
||||
@param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param[in] Timeout The timeout value of non data transfer.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
|
||||
@retval EFI_TIMEOUT The operation is time out.
|
||||
@retval EFI_UNSUPPORTED The device is not ready for transfer.
|
||||
@retval EFI_SUCCESS The non data transfer executes successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AhciNonDataTransfer (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_AHCI_REGISTERS *AhciRegisters,
|
||||
IN UINT8 Port,
|
||||
IN UINT8 PortMultiplier,
|
||||
IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
|
||||
IN UINT8 AtapiCommandLength,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
);
|
||||
|
||||
/**
|
||||
Start a DMA data transfer on specific port
|
||||
|
||||
@param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
|
||||
@param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param[in] Port The number of port.
|
||||
@param[in] PortMultiplier The timeout value of stop.
|
||||
@param[in] AtapiCommand The atapi command will be used for the
|
||||
transfer.
|
||||
@param[in] AtapiCommandLength The length of the atapi command.
|
||||
@param[in] Read The transfer direction.
|
||||
@param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param[in, out] MemoryAddr The pointer to the data buffer.
|
||||
@param[in] DataCount The data count to be transferred.
|
||||
@param[in] Timeout The timeout value of non data transfer.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
|
||||
@retval EFI_TIMEOUT The operation is time out.
|
||||
@retval EFI_UNSUPPORTED The device is not ready for transfer.
|
||||
@retval EFI_SUCCESS The DMA data transfer executes successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AhciDmaTransfer (
|
||||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
|
||||
IN EFI_AHCI_REGISTERS *AhciRegisters,
|
||||
IN UINT8 Port,
|
||||
IN UINT8 PortMultiplier,
|
||||
IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
|
||||
IN UINT8 AtapiCommandLength,
|
||||
IN BOOLEAN Read,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN OUT VOID *MemoryAddr,
|
||||
IN UINTN DataCount,
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
);
|
||||
|
||||
/**
|
||||
Start a PIO data transfer on specific port.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||
@param[in] Port The number of port.
|
||||
@param[in] PortMultiplier The timeout value of stop.
|
||||
@param[in] AtapiCommand The atapi command will be used for the
|
||||
transfer.
|
||||
@param[in] AtapiCommandLength The length of the atapi command.
|
||||
@param[in] Read The transfer direction.
|
||||
@param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
|
||||
@param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
|
||||
@param[in, out] MemoryAddr The pointer to the data buffer.
|
||||
@param[in] DataCount The data count to be transferred.
|
||||
@param[in] Timeout The timeout value of non data transfer.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
|
||||
@retval EFI_TIMEOUT The operation is time out.
|
||||
@retval EFI_UNSUPPORTED The device is not ready for transfer.
|
||||
@retval EFI_SUCCESS The PIO data transfer executes successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AhciPioTransfer (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_AHCI_REGISTERS *AhciRegisters,
|
||||
IN UINT8 Port,
|
||||
IN UINT8 PortMultiplier,
|
||||
IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
|
||||
IN UINT8 AtapiCommandLength,
|
||||
IN BOOLEAN Read,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN OUT VOID *MemoryAddr,
|
||||
IN UINT32 DataCount,
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
);
|
||||
|
||||
/**
|
||||
Send ATA command into device with NON_DATA protocol
|
||||
|
||||
@param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE
|
||||
data structure.
|
||||
@param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data
|
||||
structure.
|
||||
@param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param[in] Timeout The time to complete the command.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_SUCCESS Reading succeed
|
||||
@retval EFI_ABORTED Command failed
|
||||
@retval EFI_DEVICE_ERROR Device status error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaNonDataCommandIn (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_IDE_REGISTERS *IdeRegisters,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
);
|
||||
|
||||
/**
|
||||
Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
|
||||
|
||||
@param[in] Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
|
||||
structure.
|
||||
@param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param[in] Read Flag used to determine the data transfer
|
||||
direction. Read equals 1, means data transferred
|
||||
from device to host;Read equals 0, means data
|
||||
transferred from host to device.
|
||||
@param[in] DataBuffer A pointer to the source buffer for the data.
|
||||
@param[in] DataLength The length of the data.
|
||||
@param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param[in] Timeout The time to complete the command.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_SUCCESS the operation is successful.
|
||||
@retval EFI_OUT_OF_RESOURCES Build PRD table failed
|
||||
@retval EFI_UNSUPPORTED Unknown channel or operations command
|
||||
@retval EFI_DEVICE_ERROR Ata command execute failed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaUdmaInOut (
|
||||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
|
||||
IN EFI_IDE_REGISTERS *IdeRegisters,
|
||||
IN BOOLEAN Read,
|
||||
IN VOID *DataBuffer,
|
||||
IN UINT64 DataLength,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
);
|
||||
|
||||
/**
|
||||
This function is used to send out ATA commands conforms to the PIO Data In Protocol.
|
||||
|
||||
@param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
|
||||
structure.
|
||||
@param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param[in, out] Buffer A pointer to the source buffer for the data.
|
||||
@param[in] ByteCount The length of the data.
|
||||
@param[in] Read Flag used to determine the data transfer direction.
|
||||
Read equals 1, means data transferred from device
|
||||
to host;Read equals 0, means data transferred
|
||||
from host to device.
|
||||
@param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param[in] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param[in] Timeout The time to complete the command.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_SUCCESS send out the ATA command and device send required data successfully.
|
||||
@retval EFI_DEVICE_ERROR command sent failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaPioDataInOut (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_IDE_REGISTERS *IdeRegisters,
|
||||
IN OUT VOID *Buffer,
|
||||
IN UINT64 ByteCount,
|
||||
IN BOOLEAN Read,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Header file for AHCI mode of ATA host controller.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2011, 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
|
||||
|
@ -1123,16 +1123,20 @@ AtaIssueCommand (
|
|||
/**
|
||||
This function is used to send out ATA commands conforms to the PIO Data In Protocol.
|
||||
|
||||
@param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
|
||||
@param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param Buffer A pointer to the source buffer for the data.
|
||||
@param ByteCount The length of the data.
|
||||
@param Read Flag used to determine the data transfer direction.
|
||||
Read equals 1, means data transferred from device to host;
|
||||
Read equals 0, means data transferred from host to device.
|
||||
@param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param Timeout The time to complete the command.
|
||||
@param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
|
||||
structure.
|
||||
@param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param[in, out] Buffer A pointer to the source buffer for the data.
|
||||
@param[in] ByteCount The length of the data.
|
||||
@param[in] Read Flag used to determine the data transfer direction.
|
||||
Read equals 1, means data transferred from device
|
||||
to host;Read equals 0, means data transferred
|
||||
from host to device.
|
||||
@param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param[in] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param[in] Timeout The time to complete the command.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_SUCCESS send out the ATA command and device send required data successfully.
|
||||
@retval EFI_DEVICE_ERROR command sent failed.
|
||||
|
@ -1148,7 +1152,8 @@ AtaPioDataInOut (
|
|||
IN BOOLEAN Read,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
)
|
||||
{
|
||||
UINTN WordCount;
|
||||
|
@ -1248,17 +1253,24 @@ Exit:
|
|||
//
|
||||
DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);
|
||||
|
||||
//
|
||||
// Not support the Non-blocking now,just do the blocking process.
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Send ATA command into device with NON_DATA protocol
|
||||
|
||||
@param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
|
||||
@param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param Timeout The time to complete the command.
|
||||
@param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE
|
||||
data structure.
|
||||
@param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data
|
||||
structure.
|
||||
@param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param[in] Timeout The time to complete the command.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_SUCCESS Reading succeed
|
||||
@retval EFI_ABORTED Command failed
|
||||
|
@ -1272,7 +1284,8 @@ AtaNonDataCommandIn (
|
|||
IN EFI_IDE_REGISTERS *IdeRegisters,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -1311,23 +1324,122 @@ Exit:
|
|||
//
|
||||
DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);
|
||||
|
||||
//
|
||||
// Not support the Non-blocking now,just do the blocking process.
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Wait for memory to be set.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] PortNum The IDE Port number.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The memory is not set.
|
||||
@retval EFI_TIMEOUT The memory setting is time out.
|
||||
@retval EFI_SUCCESS The memory is correct set.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
AtaUdmStatusWait (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT16 PortNum
|
||||
)
|
||||
{
|
||||
UINT8 RegisterValue;
|
||||
EFI_STATUS Status;
|
||||
UINT64 Timeout;
|
||||
|
||||
Timeout = 2000;
|
||||
|
||||
while (TRUE) {
|
||||
RegisterValue = IdeReadPortB (PciIo, PortNum);
|
||||
|
||||
if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {
|
||||
DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((RegisterValue & BMIS_INTERRUPT) != 0) {
|
||||
Status = EFI_SUCCESS;
|
||||
DEBUG ((DEBUG_INFO, "Task->RetryTimes = %x\n", Timeout));
|
||||
break;
|
||||
}
|
||||
//
|
||||
// Stall for 1 milliseconds.
|
||||
//
|
||||
MicroSecondDelay (1000);
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the memory to be set.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
@param[in] PortForBit The bit to be checked.
|
||||
|
||||
@retval EFI_DEVICE_ERROR The memory setting met a issue.
|
||||
@retval EFI_NOT_READY The memory is not set.
|
||||
@retval EFI_TIMEOUT The memory setting is time out.
|
||||
@retval EFI_SUCCESS The memory is correct set.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
AtaUdmStatusCheck (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN ATA_NONBLOCK_TASK *Task,
|
||||
IN UINT16 PortForBit
|
||||
)
|
||||
{
|
||||
UINT8 RegisterValue;
|
||||
|
||||
Task->RetryTimes--;
|
||||
RegisterValue = IdeReadPortB(PciIo, PortForBit);
|
||||
|
||||
if ((RegisterValue & BMIS_ERROR) != 0) {
|
||||
DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if ((RegisterValue & BMIS_INTERRUPT) != 0) {
|
||||
DEBUG ((DEBUG_INFO, "Task->RetryTimes = %x\n", Task->RetryTimes));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (Task->RetryTimes == 0) {
|
||||
return EFI_TIMEOUT;
|
||||
} else {
|
||||
//
|
||||
// The memory is not set.
|
||||
//
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
|
||||
|
||||
@param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
|
||||
@param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param Read Flag used to determine the data transfer direction.
|
||||
Read equals 1, means data transferred from device to host;
|
||||
Read equals 0, means data transferred from host to device.
|
||||
@param DataBuffer A pointer to the source buffer for the data.
|
||||
@param DataLength The length of the data.
|
||||
@param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param Timeout The time to complete the command.
|
||||
@param[in] Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
|
||||
structure.
|
||||
@param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param[in] Read Flag used to determine the data transfer
|
||||
direction. Read equals 1, means data transferred
|
||||
from device to host;Read equals 0, means data
|
||||
transferred from host to device.
|
||||
@param[in] DataBuffer A pointer to the source buffer for the data.
|
||||
@param[in] DataLength The length of the data.
|
||||
@param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param[in] Timeout The time to complete the command.
|
||||
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
|
||||
used by non-blocking mode.
|
||||
|
||||
@retval EFI_SUCCESS the operation is successful.
|
||||
@retval EFI_OUT_OF_RESOURCES Build PRD table failed
|
||||
|
@ -1338,14 +1450,15 @@ Exit:
|
|||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaUdmaInOut (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
|
||||
IN EFI_IDE_REGISTERS *IdeRegisters,
|
||||
IN BOOLEAN Read,
|
||||
IN VOID *DataBuffer,
|
||||
IN UINT64 DataLength,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout
|
||||
IN UINT64 Timeout,
|
||||
IN ATA_NONBLOCK_TASK *Task
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -1353,18 +1466,16 @@ AtaUdmaInOut (
|
|||
UINT16 IoPortForBmis;
|
||||
UINT16 IoPortForBmid;
|
||||
|
||||
UINT8 RegisterValue;
|
||||
|
||||
EFI_ATA_DMA_PRD *PrdBaseAddr;
|
||||
UINTN PrdTableNum;
|
||||
UINTN PrdTableSize;
|
||||
EFI_PHYSICAL_ADDRESS PrdTableMapAddr;
|
||||
VOID *PrdTableMap;
|
||||
EFI_ATA_DMA_PRD *PrdBaseAddr;
|
||||
UINTN PrdTableNum;
|
||||
|
||||
UINT8 RegisterValue;
|
||||
UINTN PageCount;
|
||||
UINTN ByteCount;
|
||||
UINTN ByteRemaining;
|
||||
|
||||
UINT8 DeviceControl;
|
||||
|
||||
VOID *BufferMap;
|
||||
|
@ -1373,14 +1484,36 @@ AtaUdmaInOut (
|
|||
|
||||
UINT8 DeviceHead;
|
||||
UINT8 AtaCommand;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
PrdBaseAddr = NULL;
|
||||
PrdTableMap = NULL;
|
||||
BufferMap = NULL;
|
||||
PageCount = 0;
|
||||
PciIo = Instance->PciIo;
|
||||
|
||||
if ((PciIo == NULL) || (IdeRegisters == NULL) || (DataBuffer == NULL) || (AtaCommandBlock == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Before starting the Blocking BlockIO operation, push to finish all non-blocking
|
||||
// BlockIO tasks.
|
||||
// Delay 1ms to simulate the blocking time out checking.
|
||||
//
|
||||
while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {
|
||||
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
||||
AsyncNonBlockingTransferRoutine (NULL, Instance);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
//
|
||||
// Stall for 1 milliseconds.
|
||||
//
|
||||
MicroSecondDelay (1000);
|
||||
}
|
||||
|
||||
//
|
||||
// The data buffer should be even alignment
|
||||
//
|
||||
|
@ -1388,6 +1521,19 @@ AtaUdmaInOut (
|
|||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Set relevant IO Port address.
|
||||
//
|
||||
IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);
|
||||
IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);
|
||||
IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);
|
||||
|
||||
//
|
||||
// For Blocking mode, start the command.
|
||||
// For non-blocking mode, when the command is not started, start it, otherwise
|
||||
// go to check the status.
|
||||
//
|
||||
if (((Task != NULL) && (!Task->IsStart)) || (Task == NULL)) {
|
||||
//
|
||||
// Calculate the number of PRD entry.
|
||||
// Every entry in PRD table can specify a 64K memory region.
|
||||
|
@ -1503,10 +1649,6 @@ AtaUdmaInOut (
|
|||
DeviceControl = 0;
|
||||
IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);
|
||||
|
||||
IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);
|
||||
IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);
|
||||
IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);
|
||||
|
||||
//
|
||||
// Read BMIS register and clear ERROR and INTR bit
|
||||
//
|
||||
|
@ -1517,7 +1659,7 @@ AtaUdmaInOut (
|
|||
//
|
||||
// Set the base address to BMID register
|
||||
//
|
||||
IdeWritePortDW(PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);
|
||||
IdeWritePortDW (PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);
|
||||
|
||||
//
|
||||
// Set BMIC register to identify the operation direction
|
||||
|
@ -1528,7 +1670,7 @@ AtaUdmaInOut (
|
|||
} else {
|
||||
RegisterValue &= ~((UINT8) BMIC_NREAD);
|
||||
}
|
||||
IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);
|
||||
IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);
|
||||
|
||||
//
|
||||
// Issue ATA command
|
||||
|
@ -1547,39 +1689,46 @@ AtaUdmaInOut (
|
|||
RegisterValue |= BMIC_START;
|
||||
IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);
|
||||
|
||||
if (Task != NULL) {
|
||||
//
|
||||
// Max transfer number of sectors for one command is 65536(32Mbyte),
|
||||
// it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
|
||||
// So set the variable Count to 2000, for about 2 second Timeout time.
|
||||
//
|
||||
Task->RetryTimes = 2000;
|
||||
Task->Map = BufferMap;
|
||||
Task->TableMap = PrdTableMap;
|
||||
Task->MapBaseAddress = PrdBaseAddr;
|
||||
Task->PageCount = PageCount;
|
||||
Task->IsStart = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check the INTERRUPT and ERROR bit of BMIS
|
||||
// Max transfer number of sectors for one command is 65536(32Mbyte),
|
||||
// it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
|
||||
// So set the variable Count to 2000, for about 2 second Timeout time.
|
||||
//
|
||||
Timeout = 2000;
|
||||
while (TRUE) {
|
||||
RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);
|
||||
|
||||
if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {
|
||||
DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
break;
|
||||
if (Task != NULL) {
|
||||
Status = AtaUdmStatusCheck (PciIo, Task, IoPortForBmis);
|
||||
} else {
|
||||
Status = AtaUdmStatusWait (PciIo, IoPortForBmis);
|
||||
}
|
||||
|
||||
if ((RegisterValue & BMIS_INTERRUPT) != 0) {
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
}
|
||||
//
|
||||
// Stall for 1 milliseconds.
|
||||
// For blocking mode, clear registers and free buffers.
|
||||
// For non blocking mode, when the related registers have been set or time
|
||||
// out, or a error has been happened, it needs to clear the register and free
|
||||
// buffer.
|
||||
//
|
||||
MicroSecondDelay (1000);
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if ((Task == NULL) || Status != EFI_NOT_READY) {
|
||||
//
|
||||
// Read BMIS register and clear ERROR and INTR bit
|
||||
//
|
||||
RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);
|
||||
RegisterValue = IdeReadPortB (PciIo, IoPortForBmis);
|
||||
RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
|
||||
IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);
|
||||
IdeWritePortB (PciIo, IoPortForBmis, RegisterValue);
|
||||
|
||||
//
|
||||
// Read Status Register of IDE device to clear interrupt
|
||||
|
@ -1591,7 +1740,7 @@ AtaUdmaInOut (
|
|||
//
|
||||
RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);
|
||||
RegisterValue &= ~((UINT8) BMIC_START);
|
||||
IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);
|
||||
IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);
|
||||
|
||||
//
|
||||
// Disable interrupt of Select device
|
||||
|
@ -1604,18 +1753,28 @@ AtaUdmaInOut (
|
|||
//
|
||||
MicroSecondDelay (10000);
|
||||
|
||||
}
|
||||
|
||||
Exit:
|
||||
//
|
||||
// Free all allocated resource
|
||||
//
|
||||
if ((Task == NULL) || Status != EFI_NOT_READY) {
|
||||
if (Task != NULL) {
|
||||
PciIo->Unmap (PciIo, Task->TableMap);
|
||||
PciIo->FreeBuffer (PciIo, Task->PageCount, Task->MapBaseAddress);
|
||||
PciIo->Unmap (PciIo, Task->Map);
|
||||
} else {
|
||||
PciIo->Unmap (PciIo, PrdTableMap);
|
||||
PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);
|
||||
PciIo->Unmap (PciIo, BufferMap);
|
||||
}
|
||||
|
||||
//
|
||||
// Dump All Ide registers to ATA_STATUS_BLOCK
|
||||
//
|
||||
DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -2021,7 +2180,8 @@ SetDeviceTransferMode (
|
|||
&Instance->IdeRegisters[Channel],
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
|
@ -2069,7 +2229,8 @@ SetDriveParameters (
|
|||
&Instance->IdeRegisters[Channel],
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
//
|
||||
|
@ -2084,7 +2245,8 @@ SetDriveParameters (
|
|||
&Instance->IdeRegisters[Channel],
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
|
@ -2132,7 +2294,8 @@ IdeAtaSmartReturnStatusCheck (
|
|||
&Instance->IdeRegisters[Channel],
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
@ -2212,7 +2375,8 @@ IdeAtaSmartSupport (
|
|||
&Instance->IdeRegisters[Channel],
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
|
@ -2233,7 +2397,8 @@ IdeAtaSmartSupport (
|
|||
&Instance->IdeRegisters[Channel],
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = IdeAtaSmartReturnStatusCheck (
|
||||
|
@ -2254,6 +2419,7 @@ IdeAtaSmartSupport (
|
|||
return ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sends out an ATA Identify Command to the specified device.
|
||||
|
||||
|
@ -2274,6 +2440,7 @@ IdeAtaSmartSupport (
|
|||
@retval EFI_SUCCESS Identify ATA device successfully.
|
||||
@retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device.
|
||||
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
|
@ -2301,7 +2468,8 @@ AtaIdentify (
|
|||
TRUE,
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
|
@ -2368,7 +2536,8 @@ AtaIdentifyPacket (
|
|||
TRUE,
|
||||
&AtaCommandBlock,
|
||||
AtaStatusBlock,
|
||||
ATA_ATAPI_TIMEOUT
|
||||
ATA_ATAPI_TIMEOUT,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
|
@ -2496,7 +2665,6 @@ DetectAndConfigIdeDevice (
|
|||
DEBUG ((EFI_D_INFO, "[%a] channel [%a] [%a] device\n",
|
||||
(IdeChannel == 1) ? "secondary" : "primary ", (IdeDevice == 1) ? "slave " : "master",
|
||||
DeviceType == EfiIdeCdrom ? "cdrom " : "harddisk"));
|
||||
|
||||
//
|
||||
// If the device is a hard disk, then try to enable S.M.A.R.T feature
|
||||
//
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Header file for IDE mode of ATA host controller.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2011, 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
|
||||
|
@ -200,94 +200,5 @@ AtaPacketCommandExecute (
|
|||
IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Send ATA command into device with NON_DATA protocol
|
||||
|
||||
@param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
|
||||
@param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param Timeout The time to complete the command.
|
||||
|
||||
@retval EFI_SUCCESS Reading succeed
|
||||
@retval EFI_ABORTED Command failed
|
||||
@retval EFI_DEVICE_ERROR Device status error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaNonDataCommandIn (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_IDE_REGISTERS *IdeRegisters,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout
|
||||
);
|
||||
|
||||
/**
|
||||
Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
|
||||
|
||||
@param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
|
||||
@param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param Read Flag used to determine the data transfer direction.
|
||||
Read equals 1, means data transferred from device to host;
|
||||
Read equals 0, means data transferred from host to device.
|
||||
@param DataBuffer A pointer to the source buffer for the data.
|
||||
@param DataLength The length of the data.
|
||||
@param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param Timeout The time to complete the command.
|
||||
|
||||
@retval EFI_SUCCESS the operation is successful.
|
||||
@retval EFI_OUT_OF_RESOURCES Build PRD table failed
|
||||
@retval EFI_UNSUPPORTED Unknown channel or operations command
|
||||
@retval EFI_DEVICE_ERROR Ata command execute failed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaUdmaInOut (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_IDE_REGISTERS *IdeRegisters,
|
||||
IN BOOLEAN Read,
|
||||
IN VOID *DataBuffer,
|
||||
IN UINT64 DataLength,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout
|
||||
);
|
||||
|
||||
/**
|
||||
This function is used to send out ATA commands conforms to the PIO Data In Protocol.
|
||||
|
||||
@param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
|
||||
@param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
|
||||
@param Buffer A pointer to the source buffer for the data.
|
||||
@param ByteCount The length of the data.
|
||||
@param Read Flag used to determine the data transfer direction.
|
||||
Read equals 1, means data transferred from device to host;
|
||||
Read equals 0, means data transferred from host to device.
|
||||
@param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
|
||||
@param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||
@param Timeout The time to complete the command.
|
||||
|
||||
@retval EFI_SUCCESS send out the ATA command and device send required data successfully.
|
||||
@retval EFI_DEVICE_ERROR command sent failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaPioDataInOut (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN EFI_IDE_REGISTERS *IdeRegisters,
|
||||
IN OUT VOID *Buffer,
|
||||
IN UINT64 ByteCount,
|
||||
IN BOOLEAN Read,
|
||||
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
|
||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
|
||||
IN UINT64 Timeout
|
||||
);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -44,6 +44,13 @@ ATA_DEVICE gAtaDeviceTemplate = {
|
|||
AtaBlockIoWriteBlocks,
|
||||
AtaBlockIoFlushBlocks
|
||||
},
|
||||
{ // BlockIo2
|
||||
NULL,
|
||||
AtaBlockIoResetEx,
|
||||
AtaBlockIoReadBlocksEx,
|
||||
AtaBlockIoWriteBlocksEx,
|
||||
AtaBlockIoFlushBlocksEx
|
||||
},
|
||||
{ // BlockMedia
|
||||
0, // MediaId
|
||||
FALSE, // RemovableMedia
|
||||
|
@ -75,7 +82,8 @@ ATA_DEVICE gAtaDeviceTemplate = {
|
|||
FALSE, // Lba48Bit
|
||||
NULL, // IdentifyData
|
||||
NULL, // ControllerNameTable
|
||||
{L'\0', } // ModelName
|
||||
{L'\0', }, // ModelName
|
||||
{NULL, NULL} // AtaTaskList
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -135,12 +143,34 @@ ReleaseAtaResources (
|
|||
IN ATA_DEVICE *AtaDevice
|
||||
)
|
||||
{
|
||||
ATA_BUS_ASYN_TASK *Task;
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *DelEntry;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
FreeUnicodeStringTable (AtaDevice->ControllerNameTable);
|
||||
FreeAlignedBuffer (AtaDevice->Asb, sizeof (*AtaDevice->Asb));
|
||||
FreeAlignedBuffer (AtaDevice->IdentifyData, sizeof (*AtaDevice->IdentifyData));
|
||||
if (AtaDevice->DevicePath != NULL) {
|
||||
FreePool (AtaDevice->DevicePath);
|
||||
}
|
||||
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
||||
if (!IsListEmpty (&AtaDevice->AtaTaskList)) {
|
||||
//
|
||||
// Free the Subtask list.
|
||||
//
|
||||
for(Entry = (&AtaDevice->AtaTaskList)->ForwardLink;
|
||||
Entry != (&AtaDevice->AtaTaskList);
|
||||
) {
|
||||
DelEntry = Entry;
|
||||
Entry = Entry->ForwardLink;
|
||||
Task = ATA_AYNS_TASK_FROM_ENTRY (DelEntry);
|
||||
|
||||
RemoveEntryList (DelEntry);
|
||||
FreeAtaSubTask (Task);
|
||||
}
|
||||
}
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
FreePool (AtaDevice);
|
||||
}
|
||||
|
||||
|
@ -219,6 +249,7 @@ RegisterAtaDevice (
|
|||
// Initializes ATA device structures and allocates the required buffer.
|
||||
//
|
||||
AtaDevice->BlockIo.Media = &AtaDevice->BlockMedia;
|
||||
AtaDevice->BlockIo2.Media = &AtaDevice->BlockMedia;
|
||||
AtaDevice->AtaBusDriverData = AtaBusDriverData;
|
||||
AtaDevice->DevicePath = DevicePath;
|
||||
AtaDevice->Port = Port;
|
||||
|
@ -234,6 +265,11 @@ RegisterAtaDevice (
|
|||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Initial Ata Task List
|
||||
//
|
||||
InitializeListHead (&AtaDevice->AtaTaskList);
|
||||
|
||||
//
|
||||
// Try to identify the ATA device via the ATA pass through command.
|
||||
//
|
||||
|
@ -281,6 +317,8 @@ RegisterAtaDevice (
|
|||
AtaDevice->DevicePath,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&AtaDevice->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&AtaDevice->BlockIo2,
|
||||
&gEfiDiskInfoProtocolGuid,
|
||||
&AtaDevice->DiskInfo,
|
||||
NULL
|
||||
|
@ -334,8 +372,11 @@ UnregisterAtaDevice (
|
|||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
|
||||
ATA_DEVICE *AtaDevice;
|
||||
EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
|
||||
BlockIo2 = NULL;
|
||||
BlockIo = NULL;
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Handle,
|
||||
|
@ -345,11 +386,31 @@ UnregisterAtaDevice (
|
|||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Locate BlockIo2 protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Handle,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
(VOID **) &BlockIo2,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get AtaDevice data.
|
||||
//
|
||||
if (BlockIo != NULL) {
|
||||
AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (BlockIo);
|
||||
} else {
|
||||
AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (BlockIo2);
|
||||
}
|
||||
|
||||
//
|
||||
// Close the child handle
|
||||
|
@ -361,12 +422,18 @@ UnregisterAtaDevice (
|
|||
Handle
|
||||
);
|
||||
|
||||
//
|
||||
// The Ata Bus driver installs the BlockIo and BlockIo2 in the DriverBindingStart().
|
||||
// Here should uninstall both of them.
|
||||
//
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
AtaDevice->DevicePath,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&AtaDevice->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&AtaDevice->BlockIo2,
|
||||
&gEfiDiskInfoProtocolGuid,
|
||||
&AtaDevice->DiskInfo,
|
||||
NULL
|
||||
|
@ -385,7 +452,6 @@ UnregisterAtaDevice (
|
|||
}
|
||||
|
||||
ReleaseAtaResources (AtaDevice);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -803,13 +869,18 @@ AtaBlockIoReset (
|
|||
/**
|
||||
Read/Write BufferSize bytes from Lba from/into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId The media ID that the read/write request is for.
|
||||
@param Lba The starting logical block address to be read/written. The caller is
|
||||
responsible for reading/writing to only legitimate locations.
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the destination/source buffer for the data.
|
||||
@param IsWrite Indicates whether it is a write operation.
|
||||
@param[in] This Indicates a pointer to the calling context. Either be
|
||||
block I/O or block I/O2.
|
||||
@param[in] MediaId The media ID that the read/write request is for.
|
||||
@param[in] Lba The starting logical block address to be read/written.
|
||||
The caller is responsible for reading/writing to only
|
||||
legitimate locations.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[out] Buffer A pointer to the destination/source buffer for the data.
|
||||
@param[in] IsBlockIo2 Indicate the calling is from BlockIO or BlockIO2. TURE is
|
||||
from BlockIO2, FALSE is for BlockIO.
|
||||
@param[in] IsWrite Indicates whether it is a write operation.
|
||||
|
||||
@retval EFI_SUCCESS The data was read/written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be read/written to.
|
||||
|
@ -823,11 +894,13 @@ AtaBlockIoReset (
|
|||
**/
|
||||
EFI_STATUS
|
||||
BlockIoReadWrite (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN VOID *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer,
|
||||
IN BOOLEAN IsBlockIo2,
|
||||
IN BOOLEAN IsWrite
|
||||
)
|
||||
{
|
||||
|
@ -839,14 +912,21 @@ BlockIoReadWrite (
|
|||
UINTN NumberOfBlocks;
|
||||
UINTN IoAlign;
|
||||
|
||||
//
|
||||
// Check parameters.
|
||||
//
|
||||
Media = This->Media;
|
||||
if (IsBlockIo2) {
|
||||
Media = ((EFI_BLOCK_IO2_PROTOCOL *) This)->Media;
|
||||
AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);
|
||||
} else {
|
||||
Media = ((EFI_BLOCK_IO_PROTOCOL *) This)->Media;
|
||||
AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);
|
||||
}
|
||||
|
||||
if (MediaId != Media->MediaId) {
|
||||
return EFI_MEDIA_CHANGED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check parameters.
|
||||
//
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
@ -872,12 +952,10 @@ BlockIoReadWrite (
|
|||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
AtaDevice = ATA_DEVICE_FROM_BLOCK_IO (This);
|
||||
|
||||
//
|
||||
// Invoke low level AtaDevice Access Routine.
|
||||
//
|
||||
Status = AccessAtaDevice (AtaDevice, Buffer, Lba, NumberOfBlocks, IsWrite);
|
||||
Status = AccessAtaDevice (AtaDevice, Buffer, Lba, NumberOfBlocks, IsWrite, Token);
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
|
@ -914,7 +992,7 @@ AtaBlockIoReadBlocks (
|
|||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
return BlockIoReadWrite (This, MediaId, Lba, BufferSize, Buffer, FALSE);
|
||||
return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -948,7 +1026,7 @@ AtaBlockIoWriteBlocks (
|
|||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
return BlockIoReadWrite (This, MediaId, Lba, BufferSize, Buffer, TRUE);
|
||||
return BlockIoReadWrite ((VOID *) This, MediaId, Lba, NULL, BufferSize, Buffer, FALSE, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -974,7 +1052,147 @@ AtaBlockIoFlushBlocks (
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Reset the Block Device.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaBlockIoResetEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ATA_DEVICE *AtaDevice;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
AtaDevice = ATA_DEVICE_FROM_BLOCK_IO2 (This);
|
||||
|
||||
Status = ResetAtaDevice (AtaDevice);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId Id of the media, changes every time the media is replaced.
|
||||
@param[in] Lba The starting Logical Block Address to read from.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[out] Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit ownership of the buffer.
|
||||
|
||||
@retval EFI_SUCCESS The read request was queued if Event is not NULL.
|
||||
The data was read correctly from the device if
|
||||
the Event is NULL.
|
||||
@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_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
|
||||
intrinsic block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
|
||||
of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaBlockIoReadBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, FALSE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the write request is for.
|
||||
@param[in] Lba The starting logical block address to be written. The
|
||||
caller is responsible for writing to only legitimate
|
||||
locations.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] Buffer A pointer to the source buffer for the 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_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaBlockIoWriteBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
return BlockIoReadWrite ((VOID *) This, MediaId, Lba, Token, BufferSize, Buffer, TRUE, TRUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writing back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaBlockIoFlushBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
)
|
||||
{
|
||||
//
|
||||
// Signla event and return directly.
|
||||
//
|
||||
if (Token != NULL && Token->Event != NULL) {
|
||||
Token->TransactionStatus = EFI_SUCCESS;
|
||||
gBS->SignalEvent (Token->Event);
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
/**
|
||||
Provides inquiry information for the controller type.
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <Protocol/AtaPassThru.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/BlockIo2.h>
|
||||
#include <Protocol/DiskInfo.h>
|
||||
#include <Protocol/DevicePath.h>
|
||||
|
||||
|
@ -59,13 +60,37 @@
|
|||
//
|
||||
// The maximum ATA transaction sector count in 48 bit addressing mode.
|
||||
//
|
||||
#define MAX_48BIT_TRANSFER_BLOCK_NUM 0x10000
|
||||
//#define MAX_48BIT_TRANSFER_BLOCK_NUM 0x10000
|
||||
|
||||
//
|
||||
// BugBug: if the TransferLength is equal with 0x10000 (the 48bit max length),
|
||||
// there is a bug that even the register interrupt bit has been sit, the buffer
|
||||
// seems not ready. Change the Maximum Sector Numbers to 0xFFFF to work round
|
||||
// this issue.
|
||||
//
|
||||
#define MAX_48BIT_TRANSFER_BLOCK_NUM 0xFFFF
|
||||
|
||||
//
|
||||
// The maximum model name in ATA identify data
|
||||
//
|
||||
#define MAX_MODEL_NAME_LEN 40
|
||||
|
||||
#define ATA_TASK_SIGNATURE SIGNATURE_32 ('A', 'T', 'S', 'K')
|
||||
#define ATA_DEVICE_SIGNATURE SIGNATURE_32 ('A', 'B', 'I', 'D')
|
||||
|
||||
#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
|
||||
|
||||
//
|
||||
// Task for the non blocking I/O
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
EFI_BLOCK_IO2_TOKEN *Token;
|
||||
UINTN *UnsignalledEventCount;
|
||||
EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;
|
||||
BOOLEAN *IsError;// Indicate whether meeting error during source allocation for new task.
|
||||
LIST_ENTRY TaskEntry;
|
||||
} ATA_BUS_ASYN_TASK;
|
||||
|
||||
//
|
||||
// ATA bus data structure for ATA controller
|
||||
|
@ -77,8 +102,6 @@ typedef struct {
|
|||
EFI_HANDLE DriverBindingHandle;
|
||||
} ATA_BUS_DRIVER_DATA;
|
||||
|
||||
#define ATA_DEVICE_SIGNATURE SIGNATURE_32 ('A', 'B', 'I', 'D')
|
||||
|
||||
//
|
||||
// ATA device data structure for each child device
|
||||
//
|
||||
|
@ -87,6 +110,7 @@ typedef struct {
|
|||
|
||||
EFI_HANDLE Handle;
|
||||
EFI_BLOCK_IO_PROTOCOL BlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL BlockIo2;
|
||||
EFI_BLOCK_IO_MEDIA BlockMedia;
|
||||
EFI_DISK_INFO_PROTOCOL DiskInfo;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
|
@ -113,10 +137,13 @@ typedef struct {
|
|||
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
|
||||
CHAR16 ModelName[MAX_MODEL_NAME_LEN + 1];
|
||||
|
||||
LIST_ENTRY AtaTaskList;
|
||||
} ATA_DEVICE;
|
||||
|
||||
#define ATA_DEVICE_FROM_BLOCK_IO(a) CR (a, ATA_DEVICE, BlockIo, ATA_DEVICE_SIGNATURE)
|
||||
#define ATA_DEVICE_FROM_BLOCK_IO2(a) CR (a, ATA_DEVICE, BlockIo2, ATA_DEVICE_SIGNATURE)
|
||||
#define ATA_DEVICE_FROM_DISK_INFO(a) CR (a, ATA_DEVICE, DiskInfo, ATA_DEVICE_SIGNATURE)
|
||||
#define ATA_AYNS_TASK_FROM_ENTRY(a) CR (a, ATA_BUS_ASYN_TASK, TaskEntry, ATA_TASK_SIGNATURE)
|
||||
|
||||
//
|
||||
// Global Variables
|
||||
|
@ -125,6 +152,52 @@ extern EFI_DRIVER_BINDING_PROTOCOL gAtaBusDriverBinding;
|
|||
extern EFI_COMPONENT_NAME_PROTOCOL gAtaBusComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gAtaBusComponentName2;
|
||||
|
||||
/**
|
||||
Allocates an aligned buffer for ATA device.
|
||||
|
||||
This function allocates an aligned buffer for the ATA device to perform
|
||||
ATA pass through operations. The alignment requirement is from ATA pass
|
||||
through interface.
|
||||
|
||||
@param AtaDevice The ATA child device involved for the operation.
|
||||
@param BufferSize The request buffer size.
|
||||
|
||||
@return A pointer to the aligned buffer or NULL if the allocation fails.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
AllocateAlignedBuffer (
|
||||
IN ATA_DEVICE *AtaDevice,
|
||||
IN UINTN BufferSize
|
||||
);
|
||||
|
||||
/**
|
||||
Frees an aligned buffer for ATA device.
|
||||
|
||||
This function frees an aligned buffer for the ATA device to perform
|
||||
ATA pass through operations.
|
||||
|
||||
@param Buffer The aligned buffer to be freed.
|
||||
@param BufferSize The request buffer size.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FreeAlignedBuffer (
|
||||
IN VOID *Buffer,
|
||||
IN UINTN BufferSize
|
||||
);
|
||||
|
||||
/**
|
||||
Free SubTask.
|
||||
|
||||
@param[in, out] Task Pointer to task to be freed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
FreeAtaSubTask (
|
||||
IN ATA_BUS_ASYN_TASK *Task
|
||||
);
|
||||
|
||||
/**
|
||||
Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.ResetDevice().
|
||||
|
@ -162,7 +235,6 @@ DiscoverAtaDevice (
|
|||
IN OUT ATA_DEVICE *AtaDevice
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Read or write a number of blocks from ATA device.
|
||||
|
||||
|
@ -170,11 +242,12 @@ DiscoverAtaDevice (
|
|||
ATA device. It may separate the read/write request into several ATA pass through
|
||||
transactions.
|
||||
|
||||
@param AtaDevice The ATA child device involved for the operation.
|
||||
@param Buffer The pointer to the current transaction buffer.
|
||||
@param StartLba The starting logical block address to be accessed.
|
||||
@param NumberOfBlocks The block number or sector count of the transfer.
|
||||
@param IsWrite Indicates whether it is a write operation.
|
||||
@param[in, out] AtaDevice The ATA child device involved for the operation.
|
||||
@param[in, out] Buffer The pointer to the current transaction buffer.
|
||||
@param[in] StartLba The starting logical block address to be accessed.
|
||||
@param[in] NumberOfBlocks The block number or sector count of the transfer.
|
||||
@param[in] IsWrite Indicates whether it is a write operation.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS The data transfer is complete successfully.
|
||||
@return others Some error occurs when transferring data.
|
||||
|
@ -186,7 +259,8 @@ AccessAtaDevice(
|
|||
IN OUT UINT8 *Buffer,
|
||||
IN EFI_LBA StartLba,
|
||||
IN UINTN NumberOfBlocks,
|
||||
IN BOOLEAN IsWrite
|
||||
IN BOOLEAN IsWrite,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
);
|
||||
|
||||
//
|
||||
|
@ -544,6 +618,111 @@ AtaBlockIoFlushBlocks (
|
|||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Reset the Block Device throught Block I/O2 protocol.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaBlockIoResetEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId Id of the media, changes every time the media is replaced.
|
||||
@param[in] Lba The starting Logical Block Address to read from.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[out] Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit ownership of the buffer.
|
||||
|
||||
@retval EFI_SUCCESS The read request was queued if Event is not NULL.
|
||||
The data was read correctly from the device if
|
||||
the Event is NULL.
|
||||
@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_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
|
||||
intrinsic block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
|
||||
of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaBlockIoReadBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the write request is for.
|
||||
@param[in] Lba The starting logical block address to be written. The
|
||||
caller is responsible for writing to only legitimate
|
||||
locations.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] Buffer A pointer to the source buffer for the 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_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaBlockIoWriteBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writing back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AtaBlockIoFlushBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Provides inquiry information for the controller type.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# in UEFI spec 2.2. It installs Block IO and Disk Info protocol for each ATA device
|
||||
# it enumerates and identifies successfully.
|
||||
#
|
||||
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2009 - 2011, 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
|
||||
|
@ -63,6 +63,7 @@
|
|||
[Protocols]
|
||||
gEfiDiskInfoProtocolGuid # BY_START
|
||||
gEfiBlockIoProtocolGuid # BY_START
|
||||
gEfiBlockIo2ProtocolGuid # BY_START
|
||||
gEfiAtaPassThruProtocolGuid # TO_START
|
||||
gEfiDevicePathProtocolGuid # TO_START
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
It transforms the high level identity, read/write, reset command to ATA pass
|
||||
through command and protocol.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2009 - 2011, 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
|
||||
|
@ -75,14 +75,25 @@ UINTN mMaxTransferBlockNumber[] = {
|
|||
for an ATA device. It assembles the ATA pass through command packet for ATA
|
||||
transaction.
|
||||
|
||||
@param AtaDevice The ATA child device involved for the operation.
|
||||
@param[in, out] AtaDevice The ATA child device involved for the operation.
|
||||
@param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,
|
||||
if it is NULL, blocking mode, and use the packet
|
||||
in AtaDevice. If it is not NULL, non blocking mode,
|
||||
and pass down this Packet.
|
||||
@param[in] Event If Event is NULL, then blocking I/O is performed.
|
||||
If Event is not NULL and non-blocking I/O is
|
||||
supported,then non-blocking I/O is performed,
|
||||
and Event will be signaled when the write
|
||||
request is completed.
|
||||
|
||||
@return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
AtaDevicePassThru (
|
||||
IN OUT ATA_DEVICE *AtaDevice
|
||||
IN OUT ATA_DEVICE *AtaDevice,
|
||||
IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL
|
||||
IN OUT EFI_EVENT Event OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -90,12 +101,19 @@ AtaDevicePassThru (
|
|||
EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
|
||||
|
||||
//
|
||||
// Assemble packet
|
||||
// Assemble packet. If it is non blocking mode, the Ata driver should keep each
|
||||
// subtask and clean them when the event is signaled.
|
||||
//
|
||||
if (TaskPacket != NULL) {
|
||||
Packet = TaskPacket;
|
||||
Packet->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (*AtaDevice->Asb));
|
||||
CopyMem (Packet->Asb, AtaDevice->Asb, sizeof (*AtaDevice->Asb));
|
||||
Packet->Acb = AllocateCopyPool(sizeof (EFI_ATA_COMMAND_BLOCK), &AtaDevice->Acb);
|
||||
} else {
|
||||
Packet = &AtaDevice->Packet;
|
||||
Packet->Asb = AtaDevice->Asb;
|
||||
Packet->Acb = &AtaDevice->Acb;
|
||||
Packet->Timeout = ATA_TIMEOUT;
|
||||
}
|
||||
|
||||
AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;
|
||||
|
||||
|
@ -104,7 +122,7 @@ AtaDevicePassThru (
|
|||
AtaDevice->Port,
|
||||
AtaDevice->PortMultiplierPort,
|
||||
Packet,
|
||||
NULL
|
||||
Event
|
||||
);
|
||||
//
|
||||
// Ensure ATA pass through caller and callee have the same
|
||||
|
@ -257,6 +275,8 @@ IdentifyAtaDevice (
|
|||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
DEBUG ((EFI_D_INFO, "AtaBus - Identify Device (%x %x)\n", (UINTN)AtaDevice->Port, (UINTN)AtaDevice->PortMultiplierPort));
|
||||
|
||||
//
|
||||
// Check whether the WORD 88 (supported UltraDMA by drive) is valid
|
||||
//
|
||||
|
@ -364,10 +384,11 @@ DiscoverAtaDevice (
|
|||
Packet->InTransferLength = sizeof (*AtaDevice->IdentifyData);
|
||||
Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;
|
||||
Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;
|
||||
Packet->Timeout = ATA_TIMEOUT;
|
||||
|
||||
Retry = MAX_RETRY_TIMES;
|
||||
do {
|
||||
Status = AtaDevicePassThru (AtaDevice);
|
||||
Status = AtaDevicePassThru (AtaDevice, NULL, NULL);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// The command is issued successfully
|
||||
|
@ -389,11 +410,20 @@ DiscoverAtaDevice (
|
|||
ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru
|
||||
interface of ATA pass through.
|
||||
|
||||
@param AtaDevice The ATA child device involved for the operation.
|
||||
@param Buffer The pointer to the current transaction buffer.
|
||||
@param StartLba The starting logical block address to be accessed.
|
||||
@param TransferLength The block number or sector count of the transfer.
|
||||
@param IsWrite Indicates whether it is a write operation.
|
||||
@param[in, out] AtaDevice The ATA child device involved for the operation.
|
||||
@param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,
|
||||
if it is NULL, blocking mode, and use the packet
|
||||
in AtaDevice. If it is not NULL, non blocking mode,
|
||||
and pass down this Packet.
|
||||
@param[in, out] Buffer The pointer to the current transaction buffer.
|
||||
@param[in] StartLba The starting logical block address to be accessed.
|
||||
@param[in] TransferLength The block number or sector count of the transfer.
|
||||
@param[in] IsWrite Indicates whether it is a write operation.
|
||||
@param[in] Event If Event is NULL, then blocking I/O is performed.
|
||||
If Event is not NULL and non-blocking I/O is
|
||||
supported,then non-blocking I/O is performed,
|
||||
and Event will be signaled when the write
|
||||
request is completed.
|
||||
|
||||
@retval EFI_SUCCESS The data transfer is complete successfully.
|
||||
@return others Some error occurs when transferring data.
|
||||
|
@ -402,10 +432,12 @@ DiscoverAtaDevice (
|
|||
EFI_STATUS
|
||||
TransferAtaDevice (
|
||||
IN OUT ATA_DEVICE *AtaDevice,
|
||||
IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL
|
||||
IN OUT VOID *Buffer,
|
||||
IN EFI_LBA StartLba,
|
||||
IN UINT32 TransferLength,
|
||||
IN BOOLEAN IsWrite
|
||||
IN BOOLEAN IsWrite,
|
||||
IN EFI_EVENT Event OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_ATA_COMMAND_BLOCK *Acb;
|
||||
|
@ -439,7 +471,12 @@ TransferAtaDevice (
|
|||
//
|
||||
// Prepare for ATA pass through packet.
|
||||
//
|
||||
if (TaskPacket != NULL) {
|
||||
Packet = ZeroMem (TaskPacket, sizeof (*Packet));
|
||||
} else {
|
||||
Packet = ZeroMem (&AtaDevice->Packet, sizeof (*Packet));
|
||||
}
|
||||
|
||||
if (IsWrite) {
|
||||
Packet->OutDataBuffer = Buffer;
|
||||
Packet->OutTransferLength = TransferLength;
|
||||
|
@ -447,10 +484,109 @@ TransferAtaDevice (
|
|||
Packet->InDataBuffer = Buffer;
|
||||
Packet->InTransferLength = TransferLength;
|
||||
}
|
||||
|
||||
Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsWrite];
|
||||
Packet->Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;
|
||||
Packet->Timeout = ATA_TIMEOUT;
|
||||
|
||||
return AtaDevicePassThru (AtaDevice);
|
||||
return AtaDevicePassThru (AtaDevice, TaskPacket, Event);
|
||||
}
|
||||
|
||||
/**
|
||||
Free SubTask.
|
||||
|
||||
@param[in, out] Task Pointer to task to be freed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
FreeAtaSubTask (
|
||||
IN ATA_BUS_ASYN_TASK *Task
|
||||
)
|
||||
{
|
||||
if (Task->Packet.Asb != NULL) {
|
||||
FreeAlignedBuffer (Task->Packet.Asb, sizeof (Task->Packet.Asb));
|
||||
}
|
||||
if (Task->Packet.Acb != NULL) {
|
||||
FreePool (Task->Packet.Acb);
|
||||
}
|
||||
|
||||
FreePool (Task);
|
||||
}
|
||||
|
||||
/**
|
||||
Call back funtion when the event is signaled.
|
||||
|
||||
@param[in] Event The Event this notify function registered to.
|
||||
@param[in] Context Pointer to the context data registerd to the
|
||||
Event.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
AtaNonBlockingCallBack (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
ATA_BUS_ASYN_TASK *Task;
|
||||
|
||||
Task = (ATA_BUS_ASYN_TASK *) Context;
|
||||
gBS->CloseEvent (Event);
|
||||
|
||||
//
|
||||
// Check the command status.
|
||||
// If there is error during the sub task source allocation, the error status
|
||||
// should be returned to the caller directly, so here the Task->Token may already
|
||||
// be deleted by the caller and no need to update the status.
|
||||
//
|
||||
if ((!(*Task->IsError)) && (Task->Packet.Asb->AtaStatus & 0x01) == 0x01) {
|
||||
Task->Token->TransactionStatus = EFI_DEVICE_ERROR;
|
||||
}
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"NON-BLOCKING EVENT FINISHED!- STATUS = %r\n",
|
||||
Task->Token->TransactionStatus
|
||||
));
|
||||
|
||||
//
|
||||
// Reduce the SubEventCount, till it comes to zero.
|
||||
//
|
||||
(*Task->UnsignalledEventCount) --;
|
||||
DEBUG ((DEBUG_INFO, "UnsignalledEventCount = %x\n", *Task->UnsignalledEventCount));
|
||||
|
||||
//
|
||||
// Remove the SubTask from the Task list.
|
||||
//
|
||||
RemoveEntryList (&Task->TaskEntry);
|
||||
if ((*Task->UnsignalledEventCount) == 0) {
|
||||
//
|
||||
// All Sub tasks are done, then signal the upper layyer event.
|
||||
// Except there is error during the sub task source allocation.
|
||||
//
|
||||
if (!(*Task->IsError)) {
|
||||
gBS->SignalEvent (Task->Token->Event);
|
||||
DEBUG ((DEBUG_INFO, "Signal Up Level Event UnsignalledEventCount = %x!\n", *Task->UnsignalledEventCount));
|
||||
}
|
||||
|
||||
FreePool (Task->UnsignalledEventCount);
|
||||
FreePool (Task->IsError);
|
||||
}
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"PACKET INFO: Write=%s, Lenght=%x, LowCylinder=%x, HighCylinder=%x,SectionNumber=%x",
|
||||
Task->Packet.OutDataBuffer != NULL ? L"YES" : L"NO",
|
||||
Task->Packet.OutDataBuffer != NULL ? Task->Packet.OutTransferLength : Task->Packet.InTransferLength,
|
||||
Task->Packet.Acb->AtaCylinderLow,
|
||||
Task->Packet.Acb->AtaCylinderHigh,
|
||||
Task->Packet.Acb->AtaSectorCount
|
||||
));
|
||||
|
||||
//
|
||||
// Free the buffer of SubTask.
|
||||
//
|
||||
FreeAtaSubTask (Task);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -460,11 +596,12 @@ TransferAtaDevice (
|
|||
ATA device. It may separate the read/write request into several ATA pass through
|
||||
transactions.
|
||||
|
||||
@param AtaDevice The ATA child device involved for the operation.
|
||||
@param Buffer The pointer to the current transaction buffer.
|
||||
@param StartLba The starting logical block address to be accessed.
|
||||
@param NumberOfBlocks The block number or sector count of the transfer.
|
||||
@param IsWrite Indicates whether it is a write operation.
|
||||
@param[in, out] AtaDevice The ATA child device involved for the operation.
|
||||
@param[in, out] Buffer The pointer to the current transaction buffer.
|
||||
@param[in] StartLba The starting logical block address to be accessed.
|
||||
@param[in] NumberOfBlocks The block number or sector count of the transfer.
|
||||
@param[in] IsWrite Indicates whether it is a write operation.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS The data transfer is complete successfully.
|
||||
@return others Some error occurs when transferring data.
|
||||
|
@ -476,20 +613,54 @@ AccessAtaDevice(
|
|||
IN OUT UINT8 *Buffer,
|
||||
IN EFI_LBA StartLba,
|
||||
IN UINTN NumberOfBlocks,
|
||||
IN BOOLEAN IsWrite
|
||||
IN BOOLEAN IsWrite,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN MaxTransferBlockNumber;
|
||||
UINTN TransferBlockNumber;
|
||||
UINTN BlockSize;
|
||||
UINTN *EventCount;
|
||||
UINTN TempCount;
|
||||
ATA_BUS_ASYN_TASK *Task;
|
||||
EFI_EVENT SubEvent;
|
||||
UINTN Index;
|
||||
BOOLEAN *IsError;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
SubEvent = NULL;
|
||||
TempCount = 0;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
EventCount = AllocateZeroPool (sizeof (UINTN));
|
||||
if (EventCount == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
IsError = AllocateZeroPool (sizeof (BOOLEAN));
|
||||
if (IsError == NULL) {
|
||||
goto EXIT;
|
||||
}
|
||||
*IsError = FALSE;
|
||||
|
||||
//
|
||||
// Initial the return status for Non Blocking.
|
||||
//
|
||||
if (Token != NULL && Token->Event != NULL) {
|
||||
Token->TransactionStatus = EFI_SUCCESS;
|
||||
}
|
||||
//
|
||||
// Ensure AtaDevice->Lba48Bit is a valid boolean value
|
||||
//
|
||||
ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);
|
||||
MaxTransferBlockNumber = mMaxTransferBlockNumber[AtaDevice->Lba48Bit];
|
||||
BlockSize = AtaDevice->BlockMedia.BlockSize;
|
||||
|
||||
TempCount = (NumberOfBlocks + MaxTransferBlockNumber - 1) / MaxTransferBlockNumber;
|
||||
*EventCount = TempCount;
|
||||
Index = 0;
|
||||
|
||||
do {
|
||||
if (NumberOfBlocks > MaxTransferBlockNumber) {
|
||||
TransferBlockNumber = MaxTransferBlockNumber;
|
||||
|
@ -499,13 +670,89 @@ AccessAtaDevice(
|
|||
NumberOfBlocks = 0;
|
||||
}
|
||||
|
||||
Status = TransferAtaDevice (AtaDevice, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
//
|
||||
// Create sub event for the sub Ata task. Non-Blocking Mode.
|
||||
//
|
||||
if (Token != NULL && Token->Event != NULL) {
|
||||
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
||||
Task = AllocateZeroPool (sizeof (ATA_BUS_ASYN_TASK));
|
||||
if (Task == NULL) {
|
||||
//
|
||||
// If resource allocation fail, reduce the total sub event counts.
|
||||
//
|
||||
*EventCount = (*EventCount) - (TempCount - Index);
|
||||
*IsError = TRUE;
|
||||
Token->TransactionStatus = EFI_OUT_OF_RESOURCES;
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
Task->UnsignalledEventCount = EventCount;
|
||||
Task->Token = Token;
|
||||
Task->IsError = IsError;
|
||||
|
||||
InsertTailList (&AtaDevice->AtaTaskList, &Task->TaskEntry);
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
AtaNonBlockingCallBack,
|
||||
Task,
|
||||
&SubEvent
|
||||
);
|
||||
//
|
||||
// If resource allocation fail, the un-signalled event count should equal to
|
||||
// the original one minus the unassigned subtasks number.
|
||||
//
|
||||
if (EFI_ERROR (Status)) {
|
||||
*EventCount = (*EventCount) - (TempCount - Index);
|
||||
*IsError = TRUE;
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
goto EXIT;
|
||||
}
|
||||
Index++;
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
DEBUG ((EFI_D_INFO, "NON-BLOCKING SET EVENT START: WRITE = %d\n", IsWrite));
|
||||
Status = TransferAtaDevice (AtaDevice, &Task->Packet, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, SubEvent);
|
||||
DEBUG ((
|
||||
EFI_D_INFO,
|
||||
"NON-BLOCKING SET EVENT END:StartLba=%x, TransferBlockNumbers=%x, Status=%r\n",
|
||||
StartLba,
|
||||
TransferBlockNumber,
|
||||
Status
|
||||
));
|
||||
}else {
|
||||
//
|
||||
// Blocking Mode.
|
||||
//
|
||||
DEBUG ((EFI_D_INFO, "BLOCKING BLOCK I/O START: WRITE = %d\n", IsWrite));
|
||||
Status = TransferAtaDevice (AtaDevice, NULL, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, NULL);
|
||||
DEBUG ((
|
||||
EFI_D_INFO,
|
||||
"BLOCKING BLOCK I/O FINISHE - StartLba = %x; TransferBlockNumbers = %x, status = %r\n",
|
||||
StartLba,
|
||||
TransferBlockNumber,
|
||||
Status
|
||||
));
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
StartLba += TransferBlockNumber;
|
||||
Buffer += TransferBlockNumber * BlockSize;
|
||||
} while (NumberOfBlocks > 0);
|
||||
|
||||
EXIT:
|
||||
|
||||
if (*EventCount == 0) {
|
||||
FreePool (EventCount);
|
||||
FreePool (IsError);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Decode an El Torito formatted CD-ROM
|
||||
|
||||
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2006 - 2011, 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
|
||||
|
@ -20,15 +20,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
Install child handles if the Handle supports El Torito format.
|
||||
|
||||
@param[in] This Calling context.
|
||||
@param[in] Handle Parent Handle
|
||||
@param[in] DiskIo Parent DiskIo interface
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] Handle Parent Handle.
|
||||
@param[in] DiskIo Parent DiskIo interface.
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] BlockIo2 Parent BlockIo2 interface.
|
||||
@param[in] DevicePath Parent Device Path
|
||||
|
||||
|
||||
@retval EFI_SUCCESS Child handle(s) was added
|
||||
@retval EFI_MEDIA_CHANGED Media changed Detected
|
||||
@retval other no child handle was added
|
||||
@retval EFI_SUCCESS Child handle(s) was added.
|
||||
@retval EFI_MEDIA_CHANGED Media changed Detected.
|
||||
@retval other no child handle was added.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
|
@ -37,6 +38,7 @@ PartitionInstallElToritoChildHandles (
|
|||
IN EFI_HANDLE Handle,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||
)
|
||||
{
|
||||
|
@ -59,6 +61,7 @@ PartitionInstallElToritoChildHandles (
|
|||
|
||||
Found = EFI_NOT_FOUND;
|
||||
Media = BlockIo->Media;
|
||||
|
||||
VolSpaceSize = 0;
|
||||
|
||||
//
|
||||
|
@ -256,6 +259,7 @@ PartitionInstallElToritoChildHandles (
|
|||
Handle,
|
||||
DiskIo,
|
||||
BlockIo,
|
||||
BlockIo2,
|
||||
DevicePath,
|
||||
(EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
|
||||
Catalog->Boot.Lba,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Decode a hard disk partitioned with the GPT scheme in the UEFI 2.0
|
||||
specification.
|
||||
|
||||
Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2006 - 2011, 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
|
||||
|
@ -16,11 +16,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
|
||||
#include "Partition.h"
|
||||
|
||||
|
||||
/**
|
||||
Install child handles if the Handle supports GPT partition structure.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io protocol.
|
||||
@param[in] Lba The starting Lba of the Partition Table
|
||||
@param[out] PartHeader Stores the partition table that is read
|
||||
|
@ -37,7 +36,6 @@ PartitionValidGptTable (
|
|||
OUT EFI_PARTITION_TABLE_HEADER *PartHeader
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Check if the CRC field in the Partition table header is valid
|
||||
for Partition entry array.
|
||||
|
@ -60,11 +58,11 @@ PartitionCheckGptEntryArrayCRC (
|
|||
|
||||
/**
|
||||
Restore Partition Table to its alternate place
|
||||
(Primary -> Backup or Backup -> Primary)
|
||||
(Primary -> Backup or Backup -> Primary).
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure
|
||||
@param[in] PartHeader Partition table header structure.
|
||||
|
||||
@retval TRUE Restoring succeeds
|
||||
@retval FALSE Restoring failed
|
||||
|
@ -160,15 +158,16 @@ PartitionSetCrc (
|
|||
/**
|
||||
Install child handles if the Handle supports GPT partition structure.
|
||||
|
||||
@param[in] This - Calling context.
|
||||
@param[in] Handle - Parent Handle
|
||||
@param[in] DiskIo - Parent DiskIo interface
|
||||
@param[in] BlockIo - Parent BlockIo interface
|
||||
@param[in] DevicePath - Parent Device Path
|
||||
@param[in] This Calling context.
|
||||
@param[in] Handle Parent Handle.
|
||||
@param[in] DiskIo Parent DiskIo interface.
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] BlockIo2 Parent BlockIo2 interface.
|
||||
@param[in] DevicePath Parent Device Path.
|
||||
|
||||
@retval EFI_SUCCESS Valid GPT disk
|
||||
@retval EFI_MEDIA_CHANGED Media changed Detected
|
||||
@retval other Not a valid GPT disk
|
||||
@retval EFI_SUCCESS Valid GPT disk.
|
||||
@retval EFI_MEDIA_CHANGED Media changed Detected.
|
||||
@retval other Not a valid GPT disk.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
|
@ -177,6 +176,7 @@ PartitionInstallGptChildHandles (
|
|||
IN EFI_HANDLE Handle,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||
)
|
||||
{
|
||||
|
@ -191,6 +191,7 @@ PartitionInstallGptChildHandles (
|
|||
UINTN Index;
|
||||
EFI_STATUS GptValidStatus;
|
||||
HARDDRIVE_DEVICE_PATH HdDev;
|
||||
UINT32 MediaId;
|
||||
|
||||
ProtectiveMbr = NULL;
|
||||
PrimaryHeader = NULL;
|
||||
|
@ -200,6 +201,7 @@ PartitionInstallGptChildHandles (
|
|||
|
||||
BlockSize = BlockIo->Media->BlockSize;
|
||||
LastBlock = BlockIo->Media->LastBlock;
|
||||
MediaId = BlockIo->Media->MediaId;
|
||||
|
||||
DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize));
|
||||
DEBUG ((EFI_D_INFO, " LastBlock : %lx \n", LastBlock));
|
||||
|
@ -219,15 +221,16 @@ PartitionInstallGptChildHandles (
|
|||
//
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MediaId,
|
||||
0,
|
||||
BlockIo->Media->BlockSize,
|
||||
BlockSize,
|
||||
ProtectiveMbr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
GptValidStatus = Status;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Verify that the Protective MBR is valid
|
||||
//
|
||||
|
@ -302,7 +305,7 @@ PartitionInstallGptChildHandles (
|
|||
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MediaId,
|
||||
MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize),
|
||||
PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry),
|
||||
PartEntry
|
||||
|
@ -373,6 +376,7 @@ PartitionInstallGptChildHandles (
|
|||
Handle,
|
||||
DiskIo,
|
||||
BlockIo,
|
||||
BlockIo2,
|
||||
DevicePath,
|
||||
(EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
|
||||
PartEntry[Index].StartingLBA,
|
||||
|
@ -404,11 +408,10 @@ Done:
|
|||
return GptValidStatus;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Install child handles if the Handle supports GPT partition structure.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io protocol.
|
||||
@param[in] Lba The starting Lba of the Partition Table
|
||||
@param[out] PartHeader Stores the partition table that is read
|
||||
|
@ -428,9 +431,10 @@ PartitionValidGptTable (
|
|||
EFI_STATUS Status;
|
||||
UINT32 BlockSize;
|
||||
EFI_PARTITION_TABLE_HEADER *PartHdr;
|
||||
UINT32 MediaId;
|
||||
|
||||
BlockSize = BlockIo->Media->BlockSize;
|
||||
|
||||
MediaId = BlockIo->Media->MediaId;
|
||||
PartHdr = AllocateZeroPool (BlockSize);
|
||||
|
||||
if (PartHdr == NULL) {
|
||||
|
@ -442,7 +446,7 @@ PartitionValidGptTable (
|
|||
//
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MediaId,
|
||||
MultU64x32 (Lba, BlockSize),
|
||||
BlockSize,
|
||||
PartHdr
|
||||
|
@ -472,12 +476,12 @@ PartitionValidGptTable (
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check if the CRC field in the Partition table header is valid
|
||||
for Partition entry array.
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] BlockIo2 Parent BlockIo2 interface.
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure
|
||||
|
||||
|
@ -535,11 +539,11 @@ PartitionCheckGptEntryArrayCRC (
|
|||
|
||||
/**
|
||||
Restore Partition Table to its alternate place
|
||||
(Primary -> Backup or Backup -> Primary)
|
||||
(Primary -> Backup or Backup -> Primary).
|
||||
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] DiskIo Disk Io Protocol.
|
||||
@param[in] PartHeader Partition table header structure
|
||||
@param[in] PartHeader Partition table header structure.
|
||||
|
||||
@retval TRUE Restoring succeeds
|
||||
@retval FALSE Restoring failed
|
||||
|
@ -557,11 +561,13 @@ PartitionRestoreGptTable (
|
|||
EFI_PARTITION_TABLE_HEADER *PartHdr;
|
||||
EFI_LBA PEntryLBA;
|
||||
UINT8 *Ptr;
|
||||
UINT32 MediaId;
|
||||
|
||||
PartHdr = NULL;
|
||||
Ptr = NULL;
|
||||
|
||||
BlockSize = BlockIo->Media->BlockSize;
|
||||
MediaId = BlockIo->Media->MediaId;
|
||||
|
||||
PartHdr = AllocateZeroPool (BlockSize);
|
||||
|
||||
|
@ -583,8 +589,8 @@ PartitionRestoreGptTable (
|
|||
|
||||
Status = DiskIo->WriteDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MultU64x32 (PartHdr->MyLBA, BlockIo->Media->BlockSize),
|
||||
MediaId,
|
||||
MultU64x32 (PartHdr->MyLBA, (UINT32) BlockSize),
|
||||
BlockSize,
|
||||
PartHdr
|
||||
);
|
||||
|
@ -601,8 +607,8 @@ PartitionRestoreGptTable (
|
|||
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
|
||||
MediaId,
|
||||
MultU64x32(PartHeader->PartitionEntryLBA, (UINT32) BlockSize),
|
||||
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
||||
Ptr
|
||||
);
|
||||
|
@ -612,8 +618,8 @@ PartitionRestoreGptTable (
|
|||
|
||||
Status = DiskIo->WriteDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MultU64x32(PEntryLBA, BlockIo->Media->BlockSize),
|
||||
MediaId,
|
||||
MultU64x32(PEntryLBA, (UINT32) BlockSize),
|
||||
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
||||
Ptr
|
||||
);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
always on the first sector of a media. The first sector also contains
|
||||
the legacy boot strap code.
|
||||
|
||||
Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2006 - 2011, 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
|
||||
|
@ -101,11 +101,12 @@ PartitionValidMbr (
|
|||
/**
|
||||
Install child handles if the Handle supports MBR format.
|
||||
|
||||
@param This Calling context.
|
||||
@param Handle Parent Handle.
|
||||
@param DiskIo Parent DiskIo interface.
|
||||
@param BlockIo Parent BlockIo interface.
|
||||
@param DevicePath Parent Device Path.
|
||||
@param[in] This Calling context.
|
||||
@param[in] Handle Parent Handle.
|
||||
@param[in] DiskIo Parent DiskIo interface.
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] BlockIo2 Parent BlockIo2 interface.
|
||||
@param[in] DevicePath Parent Device Path.
|
||||
|
||||
@retval EFI_SUCCESS A child handle was added.
|
||||
@retval EFI_MEDIA_CHANGED Media change was detected.
|
||||
|
@ -118,6 +119,7 @@ PartitionInstallMbrChildHandles (
|
|||
IN EFI_HANDLE Handle,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||
)
|
||||
{
|
||||
|
@ -131,26 +133,33 @@ PartitionInstallMbrChildHandles (
|
|||
UINT32 PartitionNumber;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
|
||||
EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode;
|
||||
UINT32 BlockSize;
|
||||
UINT32 MediaId;
|
||||
EFI_LBA LastBlock;
|
||||
|
||||
Found = EFI_NOT_FOUND;
|
||||
|
||||
Mbr = AllocatePool (BlockIo->Media->BlockSize);
|
||||
BlockSize = BlockIo->Media->BlockSize;
|
||||
MediaId = BlockIo->Media->MediaId;
|
||||
LastBlock = BlockIo->Media->LastBlock;
|
||||
|
||||
Mbr = AllocatePool (BlockSize);
|
||||
if (Mbr == NULL) {
|
||||
return Found;
|
||||
}
|
||||
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MediaId,
|
||||
0,
|
||||
BlockIo->Media->BlockSize,
|
||||
BlockSize,
|
||||
Mbr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Found = Status;
|
||||
goto Done;
|
||||
}
|
||||
if (!PartitionValidMbr (Mbr, BlockIo->Media->LastBlock)) {
|
||||
if (!PartitionValidMbr (Mbr, LastBlock)) {
|
||||
goto Done;
|
||||
}
|
||||
//
|
||||
|
@ -218,6 +227,7 @@ PartitionInstallMbrChildHandles (
|
|||
Handle,
|
||||
DiskIo,
|
||||
BlockIo,
|
||||
BlockIo2,
|
||||
DevicePath,
|
||||
(EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
|
||||
HdDev.PartitionStart,
|
||||
|
@ -241,9 +251,9 @@ PartitionInstallMbrChildHandles (
|
|||
|
||||
Status = DiskIo->ReadDisk (
|
||||
DiskIo,
|
||||
BlockIo->Media->MediaId,
|
||||
MultU64x32 (ExtMbrStartingLba, BlockIo->Media->BlockSize),
|
||||
BlockIo->Media->BlockSize,
|
||||
MediaId,
|
||||
MultU64x32 (ExtMbrStartingLba, BlockSize),
|
||||
BlockSize,
|
||||
Mbr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
@ -278,6 +288,7 @@ PartitionInstallMbrChildHandles (
|
|||
Handle,
|
||||
DiskIo,
|
||||
BlockIo,
|
||||
BlockIo2,
|
||||
DevicePath,
|
||||
(EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
|
||||
HdDev.PartitionStart - ParentHdDev.PartitionStart,
|
||||
|
|
|
@ -40,15 +40,14 @@ PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle. Any ControllerHandle
|
||||
than contains a BlockIo and DiskIo protocol can be supported.
|
||||
than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be
|
||||
supported.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to test
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to test.
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver supports this device
|
||||
|
@ -105,7 +104,6 @@ PartitionDriverBindingSupported (
|
|||
if (Status == EFI_ALREADY_STARTED) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
@ -159,19 +157,38 @@ PartitionDriverBindingSupported (
|
|||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// According to UEFI Spec 2.3.1, if a driver is written for a disk device,
|
||||
// then the EFI_BLOCK_IO_PROTOCOL and EFI_BLOCK_IO2_PROTOCOAL must be implemented.
|
||||
// Currently, SCSI disk driver only produce the EFI_BLOCK_IO_PROTOCOL, it will
|
||||
// not be updated until the non blocking SCSI Pass Thru Protocol is provided.
|
||||
// If there is no EFI_BLOCK_IO2_PROTOCOL, skip here.
|
||||
//
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle by opening a Block IO and Disk IO
|
||||
protocol, reading Device Path, and creating a child handle with a
|
||||
Disk IO and device path protocol.
|
||||
Start this driver on ControllerHandle by opening a Block IO or a Block IO2
|
||||
or both, and Disk IO protocol, reading Device Path, and creating a child
|
||||
handle with a Disk IO and device path protocol.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to bind driver to
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to bind driver to
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver is added to ControllerHandle
|
||||
|
@ -190,6 +207,7 @@ PartitionDriverBindingStart (
|
|||
EFI_STATUS Status;
|
||||
EFI_STATUS OpenStatus;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
|
||||
EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
||||
PARTITION_DETECT_ROUTINE *Routine;
|
||||
|
@ -211,6 +229,10 @@ PartitionDriverBindingStart (
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Try to open BlockIO and BlockIO2. If BlockIO would be opened, continue,
|
||||
// otherwise, return error.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
|
@ -222,8 +244,27 @@ PartitionDriverBindingStart (
|
|||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
(VOID **) &BlockIo2,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Get the Device Path Protocol on ControllerHandle's handle
|
||||
// According to UEFI Spec 2.3.1, if a driver is written for a disk device,
|
||||
// then the EFI_BLOCK_IO_PROTOCOL and EFI_BLOCK_IO2_PROTOCOAL must be implemented.
|
||||
// Currently, SCSI disk driver only produce the EFI_BLOCK_IO_PROTOCOL, it will
|
||||
// not be updated until the non blocking SCSI Pass Thru Protocol is provided.
|
||||
// If there is no EFI_BLOCK_IO2_PROTOCOL, skip here.
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// Get the Device Path Protocol on ControllerHandle's handle.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
|
@ -276,6 +317,7 @@ PartitionDriverBindingStart (
|
|||
ControllerHandle,
|
||||
DiskIo,
|
||||
BlockIo,
|
||||
BlockIo2,
|
||||
ParentDevicePath
|
||||
);
|
||||
if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED || Status == EFI_NO_MEDIA) {
|
||||
|
@ -306,6 +348,15 @@ PartitionDriverBindingStart (
|
|||
This->DriverBindingHandle,
|
||||
ControllerHandle
|
||||
);
|
||||
//
|
||||
// Close Parent BlockIO2 if has.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle
|
||||
);
|
||||
|
||||
gBS->CloseProtocol (
|
||||
ControllerHandle,
|
||||
|
@ -320,7 +371,6 @@ Exit:
|
|||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle. Support stopping any child handles
|
||||
created by this driver.
|
||||
|
@ -347,10 +397,15 @@ PartitionDriverBindingStop (
|
|||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
|
||||
BOOLEAN AllChildrenStopped;
|
||||
PARTITION_PRIVATE_DATA *Private;
|
||||
EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||
|
||||
BlockIo = NULL;
|
||||
BlockIo2 = NULL;
|
||||
Private = NULL;
|
||||
|
||||
if (NumberOfChildren == 0) {
|
||||
//
|
||||
// Close the bus driver
|
||||
|
@ -361,6 +416,15 @@ PartitionDriverBindingStop (
|
|||
This->DriverBindingHandle,
|
||||
ControllerHandle
|
||||
);
|
||||
//
|
||||
// Close Parent BlockIO2 if has.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle
|
||||
);
|
||||
|
||||
gBS->CloseProtocol (
|
||||
ControllerHandle,
|
||||
|
@ -368,13 +432,12 @@ PartitionDriverBindingStop (
|
|||
This->DriverBindingHandle,
|
||||
ControllerHandle
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
AllChildrenStopped = TRUE;
|
||||
for (Index = 0; Index < NumberOfChildren; Index++) {
|
||||
Status = gBS->OpenProtocol (
|
||||
gBS->OpenProtocol (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
(VOID **) &BlockIo,
|
||||
|
@ -382,14 +445,25 @@ PartitionDriverBindingStop (
|
|||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Try to locate BlockIo2.
|
||||
//
|
||||
gBS->OpenProtocol (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
(VOID **) &BlockIo2,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (BlockIo != NULL) {
|
||||
Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
|
||||
|
||||
//
|
||||
// All Software protocols have be freed from the handle so remove it.
|
||||
//
|
||||
BlockIo->FlushBlocks (BlockIo);
|
||||
} else if (BlockIo2 != NULL) {
|
||||
Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (BlockIo2);
|
||||
} else {
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
Status = gBS->CloseProtocol (
|
||||
ControllerHandle,
|
||||
|
@ -397,7 +471,28 @@ PartitionDriverBindingStop (
|
|||
This->DriverBindingHandle,
|
||||
ChildHandleBuffer[Index]
|
||||
);
|
||||
|
||||
//
|
||||
// All Software protocols have be freed from the handle so remove it.
|
||||
// Remove the BlockIo Protocol if has.
|
||||
// Remove the BlockIo2 Protocol if has.
|
||||
//
|
||||
if (BlockIo2 != NULL) {
|
||||
BlockIo->FlushBlocks (BlockIo);
|
||||
BlockIo2->FlushBlocksEx (BlockIo2, NULL);
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
Private->DevicePath,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&Private->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&Private->BlockIo2,
|
||||
Private->EspGuid,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
} else {
|
||||
BlockIo->FlushBlocks (BlockIo);
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
|
@ -408,6 +503,8 @@ PartitionDriverBindingStop (
|
|||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
|
@ -422,8 +519,6 @@ PartitionDriverBindingStop (
|
|||
FreePool (Private);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
AllChildrenStopped = FALSE;
|
||||
}
|
||||
|
@ -551,11 +646,11 @@ PartitionReadBlocks (
|
|||
Write by using the Disk IO protocol on the parent device. Lba addresses
|
||||
must be converted to byte offsets.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param MediaId Id of the media, changes every time the media is replaced.
|
||||
@param Lba The starting Logical Block Address to read from
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer Buffer containing read data
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] MediaId Id of the media, changes every time the media is replaced.
|
||||
@param[in] Lba The starting Logical Block Address to read from
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] Buffer Buffer containing data to be written to device.
|
||||
|
||||
@retval EFI_SUCCESS The data was written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
|
@ -574,7 +669,7 @@ PartitionWriteBlocks (
|
|||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
PARTITION_PRIVATE_DATA *Private;
|
||||
|
@ -622,25 +717,261 @@ PartitionFlushBlocks (
|
|||
return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
|
||||
}
|
||||
|
||||
/**
|
||||
Reset the Block Device throught Block I/O2 protocol.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PartitionResetEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
)
|
||||
{
|
||||
PARTITION_PRIVATE_DATA *Private;
|
||||
|
||||
Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
|
||||
|
||||
return Private->ParentBlockIo2->Reset (
|
||||
Private->ParentBlockIo2,
|
||||
ExtendedVerification
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
This function reads the requested number of blocks from the device. All the
|
||||
blocks are read, or an error is returned.
|
||||
If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
|
||||
non-blocking I/O is being used, the Event associated with this request will
|
||||
not be signaled.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId Id of the media, changes every time the media is
|
||||
replaced.
|
||||
@param[in] Lba The starting Logical Block Address to read from.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[out] Buffer A pointer to the destination buffer for the data. The
|
||||
caller is responsible for either having implicit or
|
||||
explicit ownership of the buffer.
|
||||
|
||||
@retval EFI_SUCCESS The read request was queued if Token->Event is
|
||||
not NULL.The data was read correctly from the
|
||||
device if the Token->Event is NULL.
|
||||
@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_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
|
||||
intrinsic block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
|
||||
of resources.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PartitionReadBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
PARTITION_PRIVATE_DATA *Private;
|
||||
UINT64 Offset;
|
||||
UINT32 UnderRun;
|
||||
|
||||
if (Token == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
|
||||
if (BufferSize % Private->BlockSize != 0) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
|
||||
if (Offset + BufferSize > Private->End) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Since the BlockIO2 call Parent BlockIO2 directly, so here the offset must
|
||||
// be multiple of BlockSize. If the Spec will be updated the DiskIO to support
|
||||
// BlockIO2, this limitation will be removed and call DiskIO here.
|
||||
//
|
||||
Lba = DivU64x32Remainder (Offset, Private->BlockSize, &UnderRun);
|
||||
if (UnderRun != 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Because some partitions have different block size from their parent
|
||||
// device, in that case the Block I/O2 couldn't be called.
|
||||
//
|
||||
if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return Private->ParentBlockIo2->ReadBlocksEx (Private->ParentBlockIo2, MediaId, Lba, Token, BufferSize, Buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
This function writes the requested number of blocks to the device. All blocks
|
||||
are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
|
||||
EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
|
||||
being used, the Event associated with this request will not be signaled.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the write request is for.
|
||||
@param[in] Lba The starting logical block address to be written. The
|
||||
caller is responsible for writing to only legitimate
|
||||
locations.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] Buffer A pointer to the source buffer for the data.
|
||||
|
||||
@retval EFI_SUCCESS The write request was queued if Event is not NULL.
|
||||
The data was written correctly to the device if
|
||||
the Event is NULL.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
@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_DEVICE_ERROR The device reported an error while performing the write.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
|
||||
of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PartitionWriteBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
PARTITION_PRIVATE_DATA *Private;
|
||||
UINT64 Offset;
|
||||
UINT32 UnderRun;
|
||||
|
||||
if (Token == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
|
||||
if (BufferSize % Private->BlockSize != 0) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
|
||||
if (Offset + BufferSize > Private->End) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Since the BlockIO2 call Parent BlockIO2 directly, so here the offset must
|
||||
// be multiple of BlockSize. If the Spec will be updated the DiskIO to support
|
||||
// BlockIO2, this limitation will be removed and call DiskIO here.
|
||||
//
|
||||
Lba = DivU64x32Remainder (Offset, Private->BlockSize, &UnderRun);
|
||||
if (UnderRun != 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Because some kinds of partition have different block size from their parent,
|
||||
// in that case it couldn't call parent Block I/O2.
|
||||
//
|
||||
if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return Private->ParentBlockIo2->WriteBlocksEx (Private->ParentBlockIo2, MediaId, Lba, Token, BufferSize, Buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
|
||||
is returned and non-blocking I/O is being used, the Event associated with
|
||||
this request will not be signaled.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in,out] Token A pointer to the token associated with the transaction
|
||||
|
||||
@retval EFI_SUCCESS The flush request was queued if Event is not NULL.
|
||||
All outstanding data was written correctly to the
|
||||
device if the Event is NULL.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writting back
|
||||
the data.
|
||||
@retval EFI_WRITE_PROTECTED The device cannot be written to.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
|
||||
of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PartitionFlushBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
)
|
||||
{
|
||||
PARTITION_PRIVATE_DATA *Private;
|
||||
|
||||
Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
|
||||
|
||||
//
|
||||
// Because some kinds of partition have different block size from their parent,
|
||||
// in that case it couldn't call parent Block I/O2.
|
||||
//
|
||||
if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return Private->ParentBlockIo2->FlushBlocksEx (Private->ParentBlockIo2, Token);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create a child handle for a logical block device that represents the
|
||||
bytes Start to End of the Parent Block IO device.
|
||||
|
||||
@param[in] This Protocol instance pointer
|
||||
@param[in] ParentHandle Parent Handle for new child
|
||||
@param[in] ParentDiskIo Parent DiskIo interface
|
||||
@param[in] ParentBlockIo Parent BlockIo interface
|
||||
@param[in] ParentDevicePath Parent Device Path
|
||||
@param[in] DevicePathNode Child Device Path node
|
||||
@param[in] Start Start Block
|
||||
@param[in] End End Block
|
||||
@param[in] BlockSize Child block size
|
||||
@param[in] InstallEspGuid Flag to install EFI System Partition GUID on handle
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ParentHandle Parent Handle for new child.
|
||||
@param[in] ParentDiskIo Parent DiskIo interface.
|
||||
@param[in] ParentBlockIo Parent BlockIo interface.
|
||||
@param[in] ParentBlockIo2 Parent BlockIo2 interface.
|
||||
@param[in] ParentDevicePath Parent Device Path.
|
||||
@param[in] DevicePathNode Child Device Path node.
|
||||
@param[in] Start Start Block.
|
||||
@param[in] End End Block.
|
||||
@param[in] BlockSize Child block size.
|
||||
@param[in] InstallEspGuid Flag to install EFI System Partition GUID on handle.
|
||||
|
||||
@retval EFI_SUCCESS A child handle was added
|
||||
@retval other A child handle was not added
|
||||
@retval EFI_SUCCESS A child handle was added.
|
||||
@retval other A child handle was not added.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
|
@ -649,6 +980,7 @@ PartitionInstallChildHandle (
|
|||
IN EFI_HANDLE ParentHandle,
|
||||
IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
|
||||
IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
|
||||
IN EFI_LBA Start,
|
||||
|
@ -660,6 +992,7 @@ PartitionInstallChildHandle (
|
|||
EFI_STATUS Status;
|
||||
PARTITION_PRIVATE_DATA *Private;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
|
||||
if (Private == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
@ -672,28 +1005,51 @@ PartitionInstallChildHandle (
|
|||
|
||||
Private->BlockSize = BlockSize;
|
||||
Private->ParentBlockIo = ParentBlockIo;
|
||||
Private->ParentBlockIo2 = ParentBlockIo2;
|
||||
Private->DiskIo = ParentDiskIo;
|
||||
|
||||
if (Private->ParentBlockIo != NULL) {
|
||||
Private->BlockIo.Revision = ParentBlockIo->Revision;
|
||||
|
||||
Private->BlockIo.Media = &Private->Media;
|
||||
CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
|
||||
Private->Media.LogicalPartition = TRUE;
|
||||
|
||||
//
|
||||
// Logical BlockIo instance doesn't have IoAlign restriction because it implements block io operation based on DiskIo
|
||||
//
|
||||
|
||||
Private->BlockIo.Reset = PartitionReset;
|
||||
Private->BlockIo.ReadBlocks = PartitionReadBlocks;
|
||||
Private->BlockIo.WriteBlocks = PartitionWriteBlocks;
|
||||
Private->BlockIo.FlushBlocks = PartitionFlushBlocks;
|
||||
}
|
||||
|
||||
if (Private->ParentBlockIo2 != NULL) {
|
||||
Private->BlockIo2.Media = &Private->Media2;
|
||||
CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));
|
||||
|
||||
Private->BlockIo2.Reset = PartitionResetEx;
|
||||
Private->BlockIo2.ReadBlocksEx = PartitionReadBlocksEx;
|
||||
Private->BlockIo2.WriteBlocksEx = PartitionWriteBlocksEx;
|
||||
Private->BlockIo2.FlushBlocksEx = PartitionFlushBlocksEx;
|
||||
}
|
||||
|
||||
Private->Media.IoAlign = 0;
|
||||
Private->Media.LogicalPartition = TRUE;
|
||||
Private->Media.LastBlock = DivU64x32 (
|
||||
MultU64x32 (
|
||||
End - Start + 1,
|
||||
ParentBlockIo->Media->BlockSize
|
||||
(ParentBlockIo != NULL) ? ParentBlockIo->Media->BlockSize : ParentBlockIo2->Media->BlockSize
|
||||
),
|
||||
BlockSize
|
||||
) - 1;
|
||||
|
||||
Private->Media.BlockSize = (UINT32) BlockSize;
|
||||
|
||||
//
|
||||
// For BlockIO2, it should keep the same alignment with the parent BlockIO2's.
|
||||
//
|
||||
Private->Media2.LogicalPartition = TRUE;
|
||||
Private->Media2.LastBlock = Private->Media.LastBlock;
|
||||
Private->Media2.BlockSize = (UINT32) BlockSize;
|
||||
|
||||
//
|
||||
// Per UEFI Spec, LowestAlignedLba and LogicalBlocksPerPhysicalBlock must be 0
|
||||
// for logical partitions.
|
||||
|
@ -703,11 +1059,6 @@ PartitionInstallChildHandle (
|
|||
Private->BlockIo.Media->LogicalBlocksPerPhysicalBlock = 0;
|
||||
}
|
||||
|
||||
Private->BlockIo.Reset = PartitionReset;
|
||||
Private->BlockIo.ReadBlocks = PartitionReadBlocks;
|
||||
Private->BlockIo.WriteBlocks = PartitionWriteBlocks;
|
||||
Private->BlockIo.FlushBlocks = PartitionFlushBlocks;
|
||||
|
||||
Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
|
||||
|
||||
if (Private->DevicePath == NULL) {
|
||||
|
@ -723,10 +1074,35 @@ PartitionInstallChildHandle (
|
|||
//
|
||||
Private->EspGuid = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the new handle
|
||||
// Create the new handle.
|
||||
// BlockIO2 will be installed on the condition that the blocksize of parent BlockIO
|
||||
// is same with the child BlockIO's. Instead of calling the DiskIO, the child BlockIO2
|
||||
// directly call the parent BlockIO and doesn't handle the different block size issue.
|
||||
// If SPEC will update the DiskIO to support the Non-Blocking model, the BlockIO2 will call
|
||||
// DiskIO to handle the blocksize unequal issue and the limitation will be remove from
|
||||
// here.
|
||||
//
|
||||
Private->Handle = NULL;
|
||||
if ((Private->ParentBlockIo != NULL) &&
|
||||
(Private->ParentBlockIo2 != NULL) &&
|
||||
(Private->ParentBlockIo2->Media->BlockSize == BlockSize)
|
||||
) {
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Private->Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
Private->DevicePath,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&Private->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&Private->BlockIo2,
|
||||
Private->EspGuid,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
} else {
|
||||
if (Private->ParentBlockIo != NULL) {
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Private->Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
|
@ -737,6 +1113,22 @@ PartitionInstallChildHandle (
|
|||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
if (Private->ParentBlockIo2 != NULL &&
|
||||
Private->ParentBlockIo2->Media->BlockSize == BlockSize
|
||||
) {
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Private->Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
Private->DevicePath,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&Private->BlockIo2,
|
||||
Private->EspGuid,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
of the raw block devices media. Currently "El Torito CD-ROM", Legacy
|
||||
MBR, and GPT partition schemes are supported.
|
||||
|
||||
Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2006 - 2011, 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
|
||||
|
@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
|
||||
#include <Uefi.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/BlockIo2.h>
|
||||
#include <Guid/Gpt.h>
|
||||
#include <Protocol/ComponentName.h>
|
||||
#include <Protocol/DevicePath.h>
|
||||
|
@ -48,10 +49,13 @@ typedef struct {
|
|||
EFI_HANDLE Handle;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
EFI_BLOCK_IO_PROTOCOL BlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL BlockIo2;
|
||||
EFI_BLOCK_IO_MEDIA Media;
|
||||
EFI_BLOCK_IO_MEDIA Media2;//For BlockIO2
|
||||
|
||||
EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||
EFI_BLOCK_IO_PROTOCOL *ParentBlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2;
|
||||
UINT64 Start;
|
||||
UINT64 End;
|
||||
UINT32 BlockSize;
|
||||
|
@ -61,6 +65,7 @@ typedef struct {
|
|||
} PARTITION_PRIVATE_DATA;
|
||||
|
||||
#define PARTITION_DEVICE_FROM_BLOCK_IO_THIS(a) CR (a, PARTITION_PRIVATE_DATA, BlockIo, PARTITION_PRIVATE_DATA_SIGNATURE)
|
||||
#define PARTITION_DEVICE_FROM_BLOCK_IO2_THIS(a) CR (a, PARTITION_PRIVATE_DATA, BlockIo2, PARTITION_PRIVATE_DATA_SIGNATURE)
|
||||
|
||||
//
|
||||
// Global Variables
|
||||
|
@ -300,19 +305,20 @@ PartitionComponentNameGetControllerName (
|
|||
Create a child handle for a logical block device that represents the
|
||||
bytes Start to End of the Parent Block IO device.
|
||||
|
||||
@param[in] This Protocol instance pointer
|
||||
@param[in] ParentHandle Parent Handle for new child
|
||||
@param[in] ParentDiskIo Parent DiskIo interface
|
||||
@param[in] ParentBlockIo Parent BlockIo interface
|
||||
@param[in] ParentDevicePath Parent Device Path
|
||||
@param[in] DevicePathNode Child Device Path node
|
||||
@param[in] Start Start Block
|
||||
@param[in] End End Block
|
||||
@param[in] BlockSize Child block size
|
||||
@param[in] InstallEspGuid Flag to install EFI System Partition GUID on handle
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ParentHandle Parent Handle for new child.
|
||||
@param[in] ParentDiskIo Parent DiskIo interface.
|
||||
@param[in] ParentBlockIo Parent BlockIo interface.
|
||||
@param[in] ParentBlockIo2 Parent BlockIo2 interface.
|
||||
@param[in] ParentDevicePath Parent Device Path.
|
||||
@param[in] DevicePathNode Child Device Path node.
|
||||
@param[in] Start Start Block.
|
||||
@param[in] End End Block.
|
||||
@param[in] BlockSize Child block size.
|
||||
@param[in] InstallEspGuid Flag to install EFI System Partition GUID on handle.
|
||||
|
||||
@retval EFI_SUCCESS A child handle was added
|
||||
@retval other A child handle was not added
|
||||
@retval EFI_SUCCESS A child handle was added.
|
||||
@retval other A child handle was not added.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
|
@ -321,6 +327,7 @@ PartitionInstallChildHandle (
|
|||
IN EFI_HANDLE ParentHandle,
|
||||
IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
|
||||
IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
|
||||
IN EFI_LBA Start,
|
||||
|
@ -332,15 +339,17 @@ PartitionInstallChildHandle (
|
|||
/**
|
||||
Install child handles if the Handle supports GPT partition structure.
|
||||
|
||||
@param[in] This - Calling context.
|
||||
@param[in] Handle - Parent Handle
|
||||
@param[in] DiskIo - Parent DiskIo interface
|
||||
@param[in] BlockIo - Parent BlockIo interface
|
||||
@param[in] DevicePath - Parent Device Path
|
||||
@param[in] This Calling context.
|
||||
@param[in] Handle Parent Handle.
|
||||
@param[in] DiskIo Parent DiskIo interface.
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] BlockIo2 Parent BlockIo2 interface.
|
||||
@param[in] DevicePath Parent Device Path.
|
||||
|
||||
@retval EFI_SUCCESS Valid GPT disk
|
||||
@retval EFI_MEDIA_CHANGED Media changed Detected
|
||||
@retval other Not a valid GPT disk
|
||||
@retval EFI_SUCCESS Valid GPT disk.
|
||||
@retval EFI_MEDIA_CHANGED Media changed Detected.
|
||||
@retval EFI_INVALID_PARAMETER If both BlockIo and BlockIo2 are NULL;
|
||||
@retval other Not a valid GPT disk.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
|
@ -349,6 +358,7 @@ PartitionInstallGptChildHandles (
|
|||
IN EFI_HANDLE Handle,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||
);
|
||||
|
||||
|
@ -356,15 +366,16 @@ PartitionInstallGptChildHandles (
|
|||
Install child handles if the Handle supports El Torito format.
|
||||
|
||||
@param[in] This Calling context.
|
||||
@param[in] Handle Parent Handle
|
||||
@param[in] DiskIo Parent DiskIo interface
|
||||
@param[in] BlockIo Parent BlockIo interface
|
||||
@param[in] Handle Parent Handle.
|
||||
@param[in] DiskIo Parent DiskIo interface.
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] BlockIo2 Parent BlockIo2 interface.
|
||||
@param[in] DevicePath Parent Device Path
|
||||
|
||||
|
||||
@retval EFI_SUCCESS Child handle(s) was added
|
||||
@retval EFI_MEDIA_CHANGED Media changed Detected
|
||||
@retval other no child handle was added
|
||||
@retval EFI_SUCCESS Child handle(s) was added.
|
||||
@retval EFI_MEDIA_CHANGED Media changed Detected.
|
||||
@retval other no child handle was added.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
|
@ -373,17 +384,19 @@ PartitionInstallElToritoChildHandles (
|
|||
IN EFI_HANDLE Handle,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
Install child handles if the Handle supports MBR format.
|
||||
|
||||
@param This Calling context.
|
||||
@param Handle Parent Handle.
|
||||
@param DiskIo Parent DiskIo interface.
|
||||
@param BlockIo Parent BlockIo interface.
|
||||
@param DevicePath Parent Device Path.
|
||||
@param[in] This Calling context.
|
||||
@param[in] Handle Parent Handle.
|
||||
@param[in] DiskIo Parent DiskIo interface.
|
||||
@param[in] BlockIo Parent BlockIo interface.
|
||||
@param[in] BlockIo2 Parent BlockIo2 interface.
|
||||
@param[in] DevicePath Parent Device Path.
|
||||
|
||||
@retval EFI_SUCCESS A child handle was added.
|
||||
@retval EFI_MEDIA_CHANGED Media change was detected.
|
||||
|
@ -396,6 +409,7 @@ PartitionInstallMbrChildHandles (
|
|||
IN EFI_HANDLE Handle,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||
);
|
||||
|
||||
|
@ -406,6 +420,7 @@ EFI_STATUS
|
|||
IN EFI_HANDLE Handle,
|
||||
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||
);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# The partition of physical BlockIo device supported is one of legacy MBR, GPT,
|
||||
# and "El Torito" partitions.
|
||||
#
|
||||
# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2006 - 2011, 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
|
||||
|
@ -70,5 +70,6 @@
|
|||
gEfiDevicePathProtocolGuid ## BY_START
|
||||
gEfiDiskIoProtocolGuid ## BY_START
|
||||
gEfiBlockIoProtocolGuid ## TO_START
|
||||
gEfiBlockIo2ProtocolGuid ## TO_START
|
||||
gEfiDevicePathProtocolGuid ## TO_START
|
||||
gEfiDiskIoProtocolGuid ## TO_START
|
||||
|
|
|
@ -894,6 +894,9 @@
|
|||
## Include/Protocol/BlockIo.h
|
||||
gEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}
|
||||
|
||||
## Include/Protocol/BlockIo2.h
|
||||
gEfiBlockIo2ProtocolGuid = { 0xa77b2472, 0xe282, 0x4e9f, {0xa2, 0x45, 0xc2, 0xc0, 0xe2, 0x7b, 0xbc, 0xc1 }}
|
||||
|
||||
## Include/Protocol/UnicodeCollation.h
|
||||
gEfiUnicodeCollationProtocolGuid = { 0x1D85CD7F, 0xF43D, 0x11D2, { 0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}
|
||||
|
||||
|
|
Loading…
Reference in New Issue