mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/Sd: add Erase Block support on sd/emmc device
It's done by producing EFI_ERASE_BLOCK_PROTOCOL protocol instance. Cc: Hao Wu <hao.a.wu@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
This commit is contained in:
parent
140cc8000f
commit
275d51369a
|
@ -1589,3 +1589,416 @@ EmmcSecurityProtocolOut (
|
|||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the erase start address through sync or async I/O request.
|
||||
|
||||
@param[in] Partition A pointer to the EMMC_PARTITION instance.
|
||||
@param[in] StartLba The starting logical block address to be erased.
|
||||
@param[in] Token A pointer to the token associated with the transaction.
|
||||
@param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
|
||||
This parameter is only meaningful in async I/O request.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcEraseBlockStart (
|
||||
IN EMMC_PARTITION *Partition,
|
||||
IN EFI_LBA StartLba,
|
||||
IN EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN BOOLEAN IsEnd
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EMMC_DEVICE *Device;
|
||||
EMMC_REQUEST *EraseBlockStart;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
EraseBlockStart = NULL;
|
||||
|
||||
Device = Partition->Device;
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
EraseBlockStart = AllocateZeroPool (sizeof (EMMC_REQUEST));
|
||||
if (EraseBlockStart == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
EraseBlockStart->Signature = EMMC_REQUEST_SIGNATURE;
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
InsertTailList (&Partition->Queue, &EraseBlockStart->Link);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
EraseBlockStart->Packet.SdMmcCmdBlk = &EraseBlockStart->SdMmcCmdBlk;
|
||||
EraseBlockStart->Packet.SdMmcStatusBlk = &EraseBlockStart->SdMmcStatusBlk;
|
||||
EraseBlockStart->Packet.Timeout = EMMC_GENERIC_TIMEOUT;
|
||||
|
||||
EraseBlockStart->SdMmcCmdBlk.CommandIndex = EMMC_ERASE_GROUP_START;
|
||||
EraseBlockStart->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
EraseBlockStart->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
|
||||
|
||||
if (Device->SectorAddressing) {
|
||||
EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)StartLba;
|
||||
} else {
|
||||
EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (StartLba, Partition->BlockMedia.BlockSize);
|
||||
}
|
||||
|
||||
EraseBlockStart->IsEnd = IsEnd;
|
||||
EraseBlockStart->Token = Token;
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
AsyncIoCallback,
|
||||
EraseBlockStart,
|
||||
&EraseBlockStart->Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
EraseBlockStart->Event = NULL;
|
||||
}
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockStart->Packet, EraseBlockStart->Event);
|
||||
|
||||
Error:
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
//
|
||||
// For asynchronous operation, only free request and event in error case.
|
||||
// The request and event will be freed in asynchronous callback for success case.
|
||||
//
|
||||
if (EFI_ERROR (Status) && (EraseBlockStart != NULL)) {
|
||||
RemoveEntryList (&EraseBlockStart->Link);
|
||||
if (EraseBlockStart->Event != NULL) {
|
||||
gBS->CloseEvent (EraseBlockStart->Event);
|
||||
}
|
||||
FreePool (EraseBlockStart);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// For synchronous operation, free request whatever the execution result is.
|
||||
//
|
||||
if (EraseBlockStart != NULL) {
|
||||
RemoveEntryList (&EraseBlockStart->Link);
|
||||
FreePool (EraseBlockStart);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the erase end address through sync or async I/O request.
|
||||
|
||||
@param[in] Partition A pointer to the EMMC_PARTITION instance.
|
||||
@param[in] EndLba The ending logical block address to be erased.
|
||||
@param[in] Token A pointer to the token associated with the transaction.
|
||||
@param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
|
||||
This parameter is only meaningful in async I/O request.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcEraseBlockEnd (
|
||||
IN EMMC_PARTITION *Partition,
|
||||
IN EFI_LBA EndLba,
|
||||
IN EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN BOOLEAN IsEnd
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EMMC_DEVICE *Device;
|
||||
EMMC_REQUEST *EraseBlockEnd;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
EraseBlockEnd = NULL;
|
||||
|
||||
Device = Partition->Device;
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
EraseBlockEnd = AllocateZeroPool (sizeof (EMMC_REQUEST));
|
||||
if (EraseBlockEnd == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
EraseBlockEnd->Signature = EMMC_REQUEST_SIGNATURE;
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
InsertTailList (&Partition->Queue, &EraseBlockEnd->Link);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
EraseBlockEnd->Packet.SdMmcCmdBlk = &EraseBlockEnd->SdMmcCmdBlk;
|
||||
EraseBlockEnd->Packet.SdMmcStatusBlk = &EraseBlockEnd->SdMmcStatusBlk;
|
||||
EraseBlockEnd->Packet.Timeout = EMMC_GENERIC_TIMEOUT;
|
||||
|
||||
EraseBlockEnd->SdMmcCmdBlk.CommandIndex = EMMC_ERASE_GROUP_END;
|
||||
EraseBlockEnd->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
EraseBlockEnd->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
|
||||
|
||||
if (Device->SectorAddressing) {
|
||||
EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)EndLba;
|
||||
} else {
|
||||
EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (EndLba, Partition->BlockMedia.BlockSize);
|
||||
}
|
||||
|
||||
EraseBlockEnd->IsEnd = IsEnd;
|
||||
EraseBlockEnd->Token = Token;
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
AsyncIoCallback,
|
||||
EraseBlockEnd,
|
||||
&EraseBlockEnd->Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
EraseBlockEnd->Event = NULL;
|
||||
}
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockEnd->Packet, EraseBlockEnd->Event);
|
||||
|
||||
Error:
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
//
|
||||
// For asynchronous operation, only free request and event in error case.
|
||||
// The request and event will be freed in asynchronous callback for success case.
|
||||
//
|
||||
if (EFI_ERROR (Status) && (EraseBlockEnd != NULL)) {
|
||||
RemoveEntryList (&EraseBlockEnd->Link);
|
||||
if (EraseBlockEnd->Event != NULL) {
|
||||
gBS->CloseEvent (EraseBlockEnd->Event);
|
||||
}
|
||||
FreePool (EraseBlockEnd);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// For synchronous operation, free request whatever the execution result is.
|
||||
//
|
||||
if (EraseBlockEnd != NULL) {
|
||||
RemoveEntryList (&EraseBlockEnd->Link);
|
||||
FreePool (EraseBlockEnd);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Erase specified blocks through sync or async I/O request.
|
||||
|
||||
@param[in] Partition A pointer to the EMMC_PARTITION instance.
|
||||
@param[in] Token A pointer to the token associated with the transaction.
|
||||
@param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
|
||||
This parameter is only meaningful in async I/O request.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcEraseBlock (
|
||||
IN EMMC_PARTITION *Partition,
|
||||
IN EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN BOOLEAN IsEnd
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EMMC_DEVICE *Device;
|
||||
EMMC_REQUEST *EraseBlock;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
EraseBlock = NULL;
|
||||
|
||||
Device = Partition->Device;
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
EraseBlock = AllocateZeroPool (sizeof (EMMC_REQUEST));
|
||||
if (EraseBlock == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
EraseBlock->Signature = EMMC_REQUEST_SIGNATURE;
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
InsertTailList (&Partition->Queue, &EraseBlock->Link);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
EraseBlock->Packet.SdMmcCmdBlk = &EraseBlock->SdMmcCmdBlk;
|
||||
EraseBlock->Packet.SdMmcStatusBlk = &EraseBlock->SdMmcStatusBlk;
|
||||
EraseBlock->Packet.Timeout = EMMC_GENERIC_TIMEOUT;
|
||||
|
||||
EraseBlock->SdMmcCmdBlk.CommandIndex = EMMC_ERASE;
|
||||
EraseBlock->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
EraseBlock->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
|
||||
|
||||
EraseBlock->IsEnd = IsEnd;
|
||||
EraseBlock->Token = Token;
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
AsyncIoCallback,
|
||||
EraseBlock,
|
||||
&EraseBlock->Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
EraseBlock->Event = NULL;
|
||||
}
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlock->Packet, EraseBlock->Event);
|
||||
|
||||
Error:
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
//
|
||||
// For asynchronous operation, only free request and event in error case.
|
||||
// The request and event will be freed in asynchronous callback for success case.
|
||||
//
|
||||
if (EFI_ERROR (Status) && (EraseBlock != NULL)) {
|
||||
RemoveEntryList (&EraseBlock->Link);
|
||||
if (EraseBlock->Event != NULL) {
|
||||
gBS->CloseEvent (EraseBlock->Event);
|
||||
}
|
||||
FreePool (EraseBlock);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// For synchronous operation, free request whatever the execution result is.
|
||||
//
|
||||
if (EraseBlock != NULL) {
|
||||
RemoveEntryList (&EraseBlock->Link);
|
||||
FreePool (EraseBlock);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Erase a specified number of device blocks.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the erase request is for.
|
||||
@param[in] Lba The starting logical block address to be
|
||||
erased. The caller is responsible for erasing
|
||||
only legitimate locations.
|
||||
@param[in, out] Token A pointer to the token associated with the
|
||||
transaction.
|
||||
@param[in] Size The size in bytes to be erased. This must be
|
||||
a multiple of the physical block size of the
|
||||
device.
|
||||
|
||||
@retval EFI_SUCCESS The erase request was queued if Event is not
|
||||
NULL. The data was erased correctly to the
|
||||
device if the Event is NULL.to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device cannot be erased due to write
|
||||
protection.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while attempting
|
||||
to perform the erase operation.
|
||||
@retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not
|
||||
valid.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcEraseBlocks (
|
||||
IN EFI_ERASE_BLOCK_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_ERASE_BLOCK_TOKEN *Token,
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_BLOCK_IO_MEDIA *Media;
|
||||
UINTN BlockSize;
|
||||
UINTN BlockNum;
|
||||
EFI_LBA LastLba;
|
||||
UINT8 PartitionConfig;
|
||||
EMMC_PARTITION *Partition;
|
||||
EMMC_DEVICE *Device;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Partition = EMMC_PARTITION_DATA_FROM_ERASEBLK (This);
|
||||
Device = Partition->Device;
|
||||
Media = &Partition->BlockMedia;
|
||||
|
||||
if (MediaId != Media->MediaId) {
|
||||
return EFI_MEDIA_CHANGED;
|
||||
}
|
||||
|
||||
if (Media->ReadOnly) {
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check parameters.
|
||||
//
|
||||
BlockSize = Media->BlockSize;
|
||||
if ((Size % BlockSize) != 0) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
BlockNum = Size / BlockSize;
|
||||
if ((Lba + BlockNum - 1) > Media->LastBlock) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Token->TransactionStatus = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
LastLba = Lba + BlockNum - 1;
|
||||
|
||||
//
|
||||
// Check if needs to switch partition access.
|
||||
//
|
||||
PartitionConfig = Device->ExtCsd.PartitionConfig;
|
||||
if ((PartitionConfig & 0x7) != Partition->PartitionType) {
|
||||
PartitionConfig &= (UINT8)~0x7;
|
||||
PartitionConfig |= Partition->PartitionType;
|
||||
Status = EmmcSetExtCsd (Partition, OFFSET_OF (EMMC_EXT_CSD, PartitionConfig), PartitionConfig, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
Device->ExtCsd.PartitionConfig = PartitionConfig;
|
||||
}
|
||||
|
||||
Status = EmmcEraseBlockStart (Partition, Lba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = EmmcEraseBlockEnd (Partition, LastLba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = EmmcEraseBlock (Partition, (EFI_BLOCK_IO2_TOKEN*)Token, TRUE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
DEBUG ((EFI_D_ERROR, "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", Lba, BlockNum, Token->Event, Status));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
This file defines common data structures, macro definitions and some module
|
||||
internal function header files.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2015 - 2016, 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
|
||||
|
@ -462,5 +462,42 @@ EmmcSecurityProtocolOut (
|
|||
IN VOID *PayloadBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
Erase a specified number of device blocks.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the erase request is for.
|
||||
@param[in] Lba The starting logical block address to be
|
||||
erased. The caller is responsible for erasing
|
||||
only legitimate locations.
|
||||
@param[in, out] Token A pointer to the token associated with the
|
||||
transaction.
|
||||
@param[in] Size The size in bytes to be erased. This must be
|
||||
a multiple of the physical block size of the
|
||||
device.
|
||||
|
||||
@retval EFI_SUCCESS The erase request was queued if Event is not
|
||||
NULL. The data was erased correctly to the
|
||||
device if the Event is NULL.to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device cannot be erased due to write
|
||||
protection.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while attempting
|
||||
to perform the erase operation.
|
||||
@retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not
|
||||
valid.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcEraseBlocks (
|
||||
IN EFI_ERASE_BLOCK_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_ERASE_BLOCK_TOKEN *Token,
|
||||
IN UINTN Size
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -68,6 +68,11 @@ EMMC_PARTITION mEmmcPartitionTemplate = {
|
|||
EmmcSecurityProtocolIn,
|
||||
EmmcSecurityProtocolOut
|
||||
},
|
||||
{ // EraseBlock
|
||||
EFI_ERASE_BLOCK_PROTOCOL_REVISION,
|
||||
1,
|
||||
EmmcEraseBlocks
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
|
@ -369,6 +374,16 @@ DiscoverAllPartitions (
|
|||
Partition->Enable = TRUE;
|
||||
Partition->BlockMedia.LastBlock = DivU64x32 (Capacity, Partition->BlockMedia.BlockSize) - 1;
|
||||
}
|
||||
|
||||
if ((ExtCsd->EraseGroupDef & BIT0) == 0) {
|
||||
if (Csd->WriteBlLen < 9) {
|
||||
Partition->EraseBlock.EraseLengthGranularity = 1;
|
||||
} else {
|
||||
Partition->EraseBlock.EraseLengthGranularity = (Csd->EraseGrpMult + 1) * (Csd->EraseGrpSize + 1) * (1 << (Csd->WriteBlLen - 9));
|
||||
}
|
||||
} else {
|
||||
Partition->EraseBlock.EraseLengthGranularity = 1024 * ExtCsd->HcEraseGrpSize;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
@ -438,10 +453,32 @@ InstallProtocolOnPartition (
|
|||
&Partition->BlockIo2,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
if (Partition->PartitionType != EmmcPartitionRPMB) {
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&Partition->Handle,
|
||||
&gEfiEraseBlockProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&Partition->EraseBlock
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
&Partition->Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
Partition->DevicePath,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&Partition->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&Partition->BlockIo2,
|
||||
NULL
|
||||
);
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (((Partition->PartitionType == EmmcPartitionUserData) ||
|
||||
(Partition->PartitionType == EmmcPartitionBoot1) ||
|
||||
(Partition->PartitionType == EmmcPartitionBoot2)) &&
|
||||
|
@ -461,6 +498,8 @@ InstallProtocolOnPartition (
|
|||
&Partition->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&Partition->BlockIo2,
|
||||
&gEfiEraseBlockProtocolGuid,
|
||||
&Partition->EraseBlock,
|
||||
NULL
|
||||
);
|
||||
goto Error;
|
||||
|
@ -954,6 +993,7 @@ EmmcDxeDriverBindingStop (
|
|||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
|
||||
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;
|
||||
EFI_ERASE_BLOCK_PROTOCOL *EraseBlock;
|
||||
LIST_ENTRY *Link;
|
||||
LIST_ENTRY *NextLink;
|
||||
EMMC_REQUEST *Request;
|
||||
|
@ -1095,6 +1135,38 @@ EmmcDxeDriverBindingStop (
|
|||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// If Erase Block Protocol is installed, then uninstall this protocol.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiEraseBlockProtocolGuid,
|
||||
(VOID **) &EraseBlock,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiEraseBlockProtocolGuid,
|
||||
&Partition->EraseBlock
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
(VOID **) &Partition->Device->Private->PassThru,
|
||||
This->DriverBindingHandle,
|
||||
ChildHandleBuffer[Index],
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
AllChildrenStopped = FALSE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If Storage Security Command Protocol is installed, then uninstall this protocol.
|
||||
//
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/BlockIo2.h>
|
||||
#include <Protocol/StorageSecurityCommand.h>
|
||||
#include <Protocol/EraseBlock.h>
|
||||
|
||||
#include <Protocol/DevicePath.h>
|
||||
|
||||
|
@ -57,6 +58,9 @@ extern EFI_COMPONENT_NAME2_PROTOCOL gEmmcDxeComponentName2;
|
|||
#define EMMC_PARTITION_DATA_FROM_SSP(a) \
|
||||
CR(a, EMMC_PARTITION, StorageSecurity, EMMC_PARTITION_SIGNATURE)
|
||||
|
||||
#define EMMC_PARTITION_DATA_FROM_ERASEBLK(a) \
|
||||
CR(a, EMMC_PARTITION, EraseBlock, EMMC_PARTITION_SIGNATURE)
|
||||
|
||||
//
|
||||
// Take 2.5 seconds as generic time out value, 1 microsecond as unit.
|
||||
//
|
||||
|
@ -97,6 +101,7 @@ typedef struct {
|
|||
EFI_BLOCK_IO2_PROTOCOL BlockIo2;
|
||||
EFI_BLOCK_IO_MEDIA BlockMedia;
|
||||
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL StorageSecurity;
|
||||
EFI_ERASE_BLOCK_PROTOCOL EraseBlock;
|
||||
|
||||
LIST_ENTRY Queue;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# It produces BlockIo, BlockIo2 and StorageSecurity protocols to allow upper layer
|
||||
# access the EMMC device.
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2015 - 2016, 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
|
||||
|
@ -60,6 +60,7 @@
|
|||
gEfiBlockIoProtocolGuid ## BY_START
|
||||
gEfiBlockIo2ProtocolGuid ## BY_START
|
||||
gEfiStorageSecurityCommandProtocolGuid ## SOMETIMES_PRODUCES
|
||||
gEfiEraseBlockProtocolGuid ## BY_START
|
||||
## TO_START
|
||||
## BY_START
|
||||
gEfiDevicePathProtocolGuid
|
||||
|
|
|
@ -970,4 +970,390 @@ SdFlushBlocksEx (
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the erase start address through sync or async I/O request.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] StartLba The starting logical block address to be erased.
|
||||
@param[in] Token A pointer to the token associated with the transaction.
|
||||
@param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
|
||||
This parameter is only meaningful in async I/O request.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdEraseBlockStart (
|
||||
IN SD_DEVICE *Device,
|
||||
IN EFI_LBA StartLba,
|
||||
IN EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN BOOLEAN IsEnd
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
SD_REQUEST *EraseBlockStart;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
EraseBlockStart = NULL;
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
EraseBlockStart = AllocateZeroPool (sizeof (SD_REQUEST));
|
||||
if (EraseBlockStart == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
EraseBlockStart->Signature = SD_REQUEST_SIGNATURE;
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
InsertTailList (&Device->Queue, &EraseBlockStart->Link);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
EraseBlockStart->Packet.SdMmcCmdBlk = &EraseBlockStart->SdMmcCmdBlk;
|
||||
EraseBlockStart->Packet.SdMmcStatusBlk = &EraseBlockStart->SdMmcStatusBlk;
|
||||
EraseBlockStart->Packet.Timeout = SD_GENERIC_TIMEOUT;
|
||||
|
||||
EraseBlockStart->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_START;
|
||||
EraseBlockStart->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
EraseBlockStart->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
|
||||
|
||||
if (Device->SectorAddressing) {
|
||||
EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)StartLba;
|
||||
} else {
|
||||
EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (StartLba, Device->BlockMedia.BlockSize);
|
||||
}
|
||||
|
||||
EraseBlockStart->IsEnd = IsEnd;
|
||||
EraseBlockStart->Token = Token;
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
AsyncIoCallback,
|
||||
EraseBlockStart,
|
||||
&EraseBlockStart->Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
EraseBlockStart->Event = NULL;
|
||||
}
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockStart->Packet, EraseBlockStart->Event);
|
||||
|
||||
Error:
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
//
|
||||
// For asynchronous operation, only free request and event in error case.
|
||||
// The request and event will be freed in asynchronous callback for success case.
|
||||
//
|
||||
if (EFI_ERROR (Status) && (EraseBlockStart != NULL)) {
|
||||
RemoveEntryList (&EraseBlockStart->Link);
|
||||
if (EraseBlockStart->Event != NULL) {
|
||||
gBS->CloseEvent (EraseBlockStart->Event);
|
||||
}
|
||||
FreePool (EraseBlockStart);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// For synchronous operation, free request whatever the execution result is.
|
||||
//
|
||||
if (EraseBlockStart != NULL) {
|
||||
RemoveEntryList (&EraseBlockStart->Link);
|
||||
FreePool (EraseBlockStart);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the erase end address through sync or async I/O request.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] EndLba The ending logical block address to be erased.
|
||||
@param[in] Token A pointer to the token associated with the transaction.
|
||||
@param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
|
||||
This parameter is only meaningful in async I/O request.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdEraseBlockEnd (
|
||||
IN SD_DEVICE *Device,
|
||||
IN EFI_LBA EndLba,
|
||||
IN EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN BOOLEAN IsEnd
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
SD_REQUEST *EraseBlockEnd;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
EraseBlockEnd = NULL;
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
EraseBlockEnd = AllocateZeroPool (sizeof (SD_REQUEST));
|
||||
if (EraseBlockEnd == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
EraseBlockEnd->Signature = SD_REQUEST_SIGNATURE;
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
InsertTailList (&Device->Queue, &EraseBlockEnd->Link);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
EraseBlockEnd->Packet.SdMmcCmdBlk = &EraseBlockEnd->SdMmcCmdBlk;
|
||||
EraseBlockEnd->Packet.SdMmcStatusBlk = &EraseBlockEnd->SdMmcStatusBlk;
|
||||
EraseBlockEnd->Packet.Timeout = SD_GENERIC_TIMEOUT;
|
||||
|
||||
EraseBlockEnd->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_END;
|
||||
EraseBlockEnd->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
EraseBlockEnd->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
|
||||
|
||||
if (Device->SectorAddressing) {
|
||||
EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)EndLba;
|
||||
} else {
|
||||
EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (EndLba, Device->BlockMedia.BlockSize);
|
||||
}
|
||||
|
||||
EraseBlockEnd->IsEnd = IsEnd;
|
||||
EraseBlockEnd->Token = Token;
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
AsyncIoCallback,
|
||||
EraseBlockEnd,
|
||||
&EraseBlockEnd->Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
EraseBlockEnd->Event = NULL;
|
||||
}
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockEnd->Packet, EraseBlockEnd->Event);
|
||||
|
||||
Error:
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
//
|
||||
// For asynchronous operation, only free request and event in error case.
|
||||
// The request and event will be freed in asynchronous callback for success case.
|
||||
//
|
||||
if (EFI_ERROR (Status) && (EraseBlockEnd != NULL)) {
|
||||
RemoveEntryList (&EraseBlockEnd->Link);
|
||||
if (EraseBlockEnd->Event != NULL) {
|
||||
gBS->CloseEvent (EraseBlockEnd->Event);
|
||||
}
|
||||
FreePool (EraseBlockEnd);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// For synchronous operation, free request whatever the execution result is.
|
||||
//
|
||||
if (EraseBlockEnd != NULL) {
|
||||
RemoveEntryList (&EraseBlockEnd->Link);
|
||||
FreePool (EraseBlockEnd);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Erase specified blocks through sync or async I/O request.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Token A pointer to the token associated with the transaction.
|
||||
@param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
|
||||
This parameter is only meaningful in async I/O request.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdEraseBlock (
|
||||
IN SD_DEVICE *Device,
|
||||
IN EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN BOOLEAN IsEnd
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
SD_REQUEST *EraseBlock;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
EraseBlock = NULL;
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
EraseBlock = AllocateZeroPool (sizeof (SD_REQUEST));
|
||||
if (EraseBlock == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
EraseBlock->Signature = SD_REQUEST_SIGNATURE;
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
InsertTailList (&Device->Queue, &EraseBlock->Link);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
EraseBlock->Packet.SdMmcCmdBlk = &EraseBlock->SdMmcCmdBlk;
|
||||
EraseBlock->Packet.SdMmcStatusBlk = &EraseBlock->SdMmcStatusBlk;
|
||||
EraseBlock->Packet.Timeout = SD_GENERIC_TIMEOUT;
|
||||
|
||||
EraseBlock->SdMmcCmdBlk.CommandIndex = SD_ERASE;
|
||||
EraseBlock->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
EraseBlock->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
|
||||
|
||||
EraseBlock->IsEnd = IsEnd;
|
||||
EraseBlock->Token = Token;
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
AsyncIoCallback,
|
||||
EraseBlock,
|
||||
&EraseBlock->Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
EraseBlock->Event = NULL;
|
||||
}
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlock->Packet, EraseBlock->Event);
|
||||
|
||||
Error:
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
//
|
||||
// For asynchronous operation, only free request and event in error case.
|
||||
// The request and event will be freed in asynchronous callback for success case.
|
||||
//
|
||||
if (EFI_ERROR (Status) && (EraseBlock != NULL)) {
|
||||
RemoveEntryList (&EraseBlock->Link);
|
||||
if (EraseBlock->Event != NULL) {
|
||||
gBS->CloseEvent (EraseBlock->Event);
|
||||
}
|
||||
FreePool (EraseBlock);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// For synchronous operation, free request whatever the execution result is.
|
||||
//
|
||||
if (EraseBlock != NULL) {
|
||||
RemoveEntryList (&EraseBlock->Link);
|
||||
FreePool (EraseBlock);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Erase a specified number of device blocks.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the erase request is for.
|
||||
@param[in] Lba The starting logical block address to be
|
||||
erased. The caller is responsible for erasing
|
||||
only legitimate locations.
|
||||
@param[in, out] Token A pointer to the token associated with the
|
||||
transaction.
|
||||
@param[in] Size The size in bytes to be erased. This must be
|
||||
a multiple of the physical block size of the
|
||||
device.
|
||||
|
||||
@retval EFI_SUCCESS The erase request was queued if Event is not
|
||||
NULL. The data was erased correctly to the
|
||||
device if the Event is NULL.to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device cannot be erased due to write
|
||||
protection.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while attempting
|
||||
to perform the erase operation.
|
||||
@retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not
|
||||
valid.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdEraseBlocks (
|
||||
IN EFI_ERASE_BLOCK_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_ERASE_BLOCK_TOKEN *Token,
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_BLOCK_IO_MEDIA *Media;
|
||||
UINTN BlockSize;
|
||||
UINTN BlockNum;
|
||||
EFI_LBA LastLba;
|
||||
SD_DEVICE *Device;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Device = SD_DEVICE_DATA_FROM_ERASEBLK (This);
|
||||
Media = &Device->BlockMedia;
|
||||
|
||||
if (MediaId != Media->MediaId) {
|
||||
return EFI_MEDIA_CHANGED;
|
||||
}
|
||||
|
||||
if (Media->ReadOnly) {
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check parameters.
|
||||
//
|
||||
BlockSize = Media->BlockSize;
|
||||
if ((Size % BlockSize) != 0) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
BlockNum = Size / BlockSize;
|
||||
if ((Lba + BlockNum - 1) > Media->LastBlock) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Token->TransactionStatus = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
LastLba = Lba + BlockNum - 1;
|
||||
|
||||
Status = SdEraseBlockStart (Device, Lba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = SdEraseBlockEnd (Device, LastLba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = SdEraseBlock (Device, (EFI_BLOCK_IO2_TOKEN*)Token, TRUE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
DEBUG ((EFI_D_ERROR, "SdEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", Lba, BlockNum, Token->Event, Status));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
This file defines common data structures, macro definitions and some module
|
||||
internal function header files.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2015 - 2016, 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
|
||||
|
@ -217,5 +217,42 @@ SdFlushBlocksEx (
|
|||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Erase a specified number of device blocks.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the erase request is for.
|
||||
@param[in] Lba The starting logical block address to be
|
||||
erased. The caller is responsible for erasing
|
||||
only legitimate locations.
|
||||
@param[in, out] Token A pointer to the token associated with the
|
||||
transaction.
|
||||
@param[in] Size The size in bytes to be erased. This must be
|
||||
a multiple of the physical block size of the
|
||||
device.
|
||||
|
||||
@retval EFI_SUCCESS The erase request was queued if Event is not
|
||||
NULL. The data was erased correctly to the
|
||||
device if the Event is NULL.to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device cannot be erased due to write
|
||||
protection.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while attempting
|
||||
to perform the erase operation.
|
||||
@retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not
|
||||
valid.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdEraseBlocks (
|
||||
IN EFI_ERASE_BLOCK_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_ERASE_BLOCK_TOKEN *Token,
|
||||
IN UINTN Size
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -64,6 +64,11 @@ SD_DEVICE mSdDeviceTemplate = {
|
|||
0, // IoAlign
|
||||
0 // LastBlock
|
||||
},
|
||||
{ // EraseBlock
|
||||
EFI_ERASE_BLOCK_PROTOCOL_REVISION,
|
||||
1,
|
||||
SdEraseBlocks
|
||||
},
|
||||
{ // Queue
|
||||
NULL,
|
||||
NULL
|
||||
|
@ -247,6 +252,12 @@ DiscoverUserArea (
|
|||
Device->BlockMedia.LogicalPartition = FALSE;
|
||||
Device->BlockMedia.LastBlock = DivU64x32 (Capacity, Device->BlockMedia.BlockSize) - 1;
|
||||
|
||||
if (Csd->EraseBlkEn) {
|
||||
Device->EraseBlock.EraseLengthGranularity = 1;
|
||||
} else {
|
||||
Device->EraseBlock.EraseLengthGranularity = (Csd->SectorSize + 1) * (1 << (Csd->WriteBlLen - 9));
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -369,6 +380,8 @@ DiscoverSdDevice (
|
|||
&Device->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&Device->BlockIo2,
|
||||
&gEfiEraseBlockProtocolGuid,
|
||||
&Device->EraseBlock,
|
||||
NULL
|
||||
);
|
||||
|
||||
|
@ -825,6 +838,8 @@ SdDxeDriverBindingStop (
|
|||
&Device->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&Device->BlockIo2,
|
||||
&gEfiEraseBlockProtocolGuid,
|
||||
&Device->EraseBlock,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
This file defines common data structures, macro definitions and some module
|
||||
internal function header files.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2015 - 2016, 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
|
||||
|
@ -24,6 +24,7 @@
|
|||
#include <Protocol/SdMmcPassThru.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/BlockIo2.h>
|
||||
#include <Protocol/EraseBlock.h>
|
||||
|
||||
#include <Protocol/DevicePath.h>
|
||||
|
||||
|
@ -53,6 +54,9 @@ extern EFI_COMPONENT_NAME2_PROTOCOL gSdDxeComponentName2;
|
|||
#define SD_DEVICE_DATA_FROM_BLKIO2(a) \
|
||||
CR(a, SD_DEVICE, BlockIo2, SD_DEVICE_SIGNATURE)
|
||||
|
||||
#define SD_DEVICE_DATA_FROM_ERASEBLK(a) \
|
||||
CR(a, SD_DEVICE, EraseBlock, SD_DEVICE_SIGNATURE)
|
||||
|
||||
//
|
||||
// Take 2.5 seconds as generic time out value, 1 microsecond as unit.
|
||||
//
|
||||
|
@ -95,6 +99,7 @@ struct _SD_DEVICE {
|
|||
EFI_BLOCK_IO_PROTOCOL BlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL BlockIo2;
|
||||
EFI_BLOCK_IO_MEDIA BlockMedia;
|
||||
EFI_ERASE_BLOCK_PROTOCOL EraseBlock;
|
||||
|
||||
LIST_ENTRY Queue;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# It produces BlockIo and BlockIo2 protocols to allow upper layer
|
||||
# access the SD memory card device.
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2015 - 2016, 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
|
||||
|
@ -59,6 +59,7 @@
|
|||
gEfiSdMmcPassThruProtocolGuid ## TO_START
|
||||
gEfiBlockIoProtocolGuid ## BY_START
|
||||
gEfiBlockIo2ProtocolGuid ## BY_START
|
||||
gEfiEraseBlockProtocolGuid ## BY_START
|
||||
## TO_START
|
||||
## BY_START
|
||||
gEfiDevicePathProtocolGuid
|
||||
|
|
Loading…
Reference in New Issue