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

Reply via email to