I agree your comment. I will update it during check-in Thanks Feng
-----Original Message----- From: Wu, Hao A Sent: Monday, May 9, 2016 10:54 AM To: Tian, Feng <feng.t...@intel.com> Cc: edk2-devel@lists.01.org Subject: RE: [patch] MdeModulePkg/Sd: add Erase Block support on sd/emmc device One comment below. And with that solved, Reviewed-by: Hao Wu <hao.a...@intel.com> Best Regards, Hao Wu > -----Original Message----- > From: Tian, Feng > Sent: Wednesday, May 04, 2016 1:30 PM > To: Wu, Hao A > Cc: edk2-devel@lists.01.org; Wu > Subject: [patch] MdeModulePkg/Sd: add Erase Block support on sd/emmc > device > > It's done by producing EFI_ERASE_BLOCK_PROTOCOL protocol instance. > > Cc: Wu, Hao A <hao.a...@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Feng Tian <feng.t...@intel.com> > --- > MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c | 411 > ++++++++++++++++++++++++++++++ > MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.h | 39 ++- > MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c | 74 +++++- > MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.h | 5 + > MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf | 3 +- > MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c | 384 > ++++++++++++++++++++++++++++ > MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h | 39 ++- > MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c | 15 ++ > MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h | 7 +- > MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf | 3 +- > 10 files changed, 974 insertions(+), 6 deletions(-) > > diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c > b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c > index edb438b..a12cd63 100644 > --- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c > +++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c > @@ -47,6 +47,8 @@ AsyncIoCallback ( > > if (EFI_ERROR (Request->Packet.TransactionStatus)) { > Request->Token->TransactionStatus = > Request->Packet.TransactionStatus; > + } else { > + Request->Token->TransactionStatus = EFI_SUCCESS; I think the 'TransactionStatus' cannot be set to EFI_SUCCESS upon every successful async I/O completion. If a previous subtask of an async I/O request fails, the 'TransactionStatus' should be an error status regardless of the execution status of subsequent subtasks. Similar issue also exists in SdBlockIo.c. > } > > RemoveEntryList (&Request->Link); > @@ -1589,3 +1591,412 @@ 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; > + } > + > + 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 f0e1312..c8a6c5c 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 2dd2981..6e156e9 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 0c50d62..0ae4ecc 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 a10bcd2..7b05049 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 b7a5fe4..a9106a9 100644 > --- a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c > +++ b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c > @@ -43,6 +43,8 @@ AsyncIoCallback ( > > if (EFI_ERROR (Request->Packet.TransactionStatus)) { > Request->Token->TransactionStatus = > Request->Packet.TransactionStatus; > + } else { > + Request->Token->TransactionStatus = EFI_SUCCESS; > } > > RemoveEntryList (&Request->Link); > @@ -970,4 +972,386 @@ 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; > + } > + > + 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 36e20de..227b45b 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 7ed80b6..f657fb9 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 ca1609e..0ba72b7 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 b24b721..6f5e6ca 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 > -- > 2.7.1.windows.2 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel