summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorFeng Tian <feng.tian@intel.com>2016-05-03 14:07:38 +0800
committerFeng Tian <feng.tian@intel.com>2016-05-09 16:18:01 +0800
commit275d51369a55952c7d75399752c7269a16ff03de (patch)
tree7f67f2be16146e2275fa2ad3a5050e4d88088fd6 /MdeModulePkg
parent140cc8000f74258a7e3985452538415b77b66b94 (diff)
downloadedk2-platforms-275d51369a55952c7d75399752c7269a16ff03de.tar.xz
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>
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c413
-rw-r--r--MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.h39
-rw-r--r--MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c74
-rw-r--r--MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.h5
-rw-r--r--MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf3
-rw-r--r--MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c386
-rw-r--r--MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h39
-rw-r--r--MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c15
-rw-r--r--MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h7
-rw-r--r--MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf3
10 files changed, 978 insertions, 6 deletions
diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
index edb438b09b..5fe710dbb5 100644
--- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
+++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
@@ -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;
+}
+
diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.h b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.h
index f0e1312b25..c8a6c5cab4 100644
--- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.h
+++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.h
@@ -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
diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c
index 2dd29814d9..6e156e9cc3 100644
--- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c
+++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c
@@ -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;
@@ -1096,6 +1136,38 @@ EmmcDxeDriverBindingStop (
}
//
+ // 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.
//
Status = gBS->OpenProtocol (
diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.h b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.h
index 0c50d62eb7..0ae4eccac6 100644
--- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.h
+++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.h
@@ -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;
diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
index a10bcd2343..7b0504937a 100644
--- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
+++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
@@ -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
diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c
index b7a5fe49ae..d8b9459c63 100644
--- a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c
+++ b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c
@@ -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;
+}
diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h
index 36e20dee72..227b45bebf 100644
--- a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h
+++ b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h
@@ -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
diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c
index 7ed80b6bd0..f657fb9c6e 100644
--- a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c
+++ b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c
@@ -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)) {
diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h
index ca1609e900..0ba72b7f9c 100644
--- a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h
+++ b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h
@@ -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;
diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
index b24b721236..6f5e6ca72e 100644
--- a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
+++ b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
@@ -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