> -----Original Message-----
> From: Zeng, Star
> Sent: Friday, August 11, 2017 10:37 AM
> To: Wu, Hao A; edk2-devel@lists.01.org
> Cc: Wu, Hao A; Ni, Ruiyu; Zeng, Star
> Subject: RE: [edk2] [PATCH v2] MdeModulePkg/EmmcDxe: Make sure no extra
> data is erased by EraseBlocks
> 
> Two minor comments, others are good to me.
> 
> 1. Could the code use (LastLba + 1 - EndGroupLba) instead of (LastLba -
> EndGroupLba + 1)?
> 
> 2. Could the code have the debug message "DEBUG ((EFI_D_ERROR,
> "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", Lba,
> BlockNum, Token->Event, Status))" for the new return paths the patch added?
> And the debug level should be DEBUG_INFO instead of EFI_D_ERROR?
> 

Thanks for the feedbacks. I will submit a new version of the patch.

Best Regards,
Hao Wu

> 
> Thanks,
> Star
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Hao
> Wu
> Sent: Thursday, August 10, 2017 9:21 AM
> To: edk2-devel@lists.01.org
> Cc: Wu, Hao A <hao.a...@intel.com>; Ni, Ruiyu <ruiyu...@intel.com>; Zeng,
> Star <star.z...@intel.com>
> Subject: [edk2] [PATCH v2] MdeModulePkg/EmmcDxe: Make sure no extra
> data is erased by EraseBlocks
> 
> V2 changes:
> 
> The Trim command is not supported on all eMMC devices. For those devices
> that do not support such command, add codes to handle the scenario.
> 
> Commit message:
> 
> The current implementation of the Erase Block Protocol service
> EraseBlocks() uses the erase command. According to spec eMMC Electrical
> Standard 5.1, Section 6.6.9:
> 
> The erasable unit of the eMMC is the "Erase Group"; Erase group is measured
> in write blocks that are the basic writable units of the Device.
> ...
> When the Erase is executed it will apply to all write blocks within an erase
> group.
> 
> However, code logic in function EmmcEraseBlocks() does not check whether
> the blocks to be erased form complete erase groups. Missing such checks will
> lead to erasing extra data on the device.
> 
> This commit will:
> a. If the device support the Trim command, use the Trim command to perform
> the erase operations for eMMC devices.
> 
> According to the spec:
> Unlike the Erase command, the Trim function applies the erase operation to
> write blocks instead of erase groups.
> 
> b. If the device does not support the Trim command, use the Erase command to
> erase the data in the erase groups. And write zeros to those blocks that 
> cannot
> form a complete erase group.
> 
> Cc: Star Zeng <star.z...@intel.com>
> Cc: Ruiyu Ni <ruiyu...@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Hao Wu <hao.a...@intel.com>
> ---
>  MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c | 127
> +++++++++++++++++++++++++++++-
>  1 file changed, 125 insertions(+), 2 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
> b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
> index c432d26801..916f15d429 100644
> --- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
> +++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
> @@ -1851,6 +1851,14 @@ EmmcEraseBlock (
>    EraseBlock->SdMmcCmdBlk.CommandIndex = EMMC_ERASE;
>    EraseBlock->SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
>    EraseBlock->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
> +  if ((Device->ExtCsd.SecFeatureSupport & BIT4) != 0) {
> +    //
> +    // Perform a Trim operation which applies the erase operation to write
> blocks
> +    // instead of erase groups. (Spec JESD84-B51, eMMC Electrical Standard 
> 5.1,
> +    // Section 6.6.10 and 6.10.4)
> +    //
> +    EraseBlock->SdMmcCmdBlk.CommandArgument = 1;  }
> 
>    EraseBlock->IsEnd = IsEnd;
>    EraseBlock->Token = Token;
> @@ -1903,6 +1911,43 @@ Error:
>  }
> 
>  /**
> +  Write zeros to specified blocks.
> +
> +  @param[in]  Partition         A pointer to the EMMC_PARTITION instance.
> +  @param[in]  StartLba          The starting logical block address to write 
> zeros.
> +  @param[in]  Size              The size in bytes to fill with zeros. This 
> must be a
> multiple of
> +                                the physical block size of the device.
> +
> +  @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
> +EmmcWriteZeros (
> +  IN  EMMC_PARTITION            *Partition,
> +  IN  EFI_LBA                   StartLba,
> +  IN  UINTN                     Size
> +  )
> +{
> +  EFI_STATUS                           Status;
> +  UINT8                                *Buffer;
> +  UINT32                               MediaId;
> +
> +  Buffer = AllocateZeroPool (Size);
> +  if (Buffer == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  MediaId = Partition->BlockMedia.MediaId;
> +
> +  Status = EmmcReadWrite (Partition, MediaId, StartLba, Buffer, Size,
> + FALSE, NULL);  FreePool (Buffer);
> +
> +  return Status;
> +}
> +
> +/**
>    Erase a specified number of device blocks.
> 
>    @param[in]       This           Indicates a pointer to the calling context.
> @@ -1943,7 +1988,13 @@ EmmcEraseBlocks (
>    EFI_BLOCK_IO_MEDIA                    *Media;
>    UINTN                                 BlockSize;
>    UINTN                                 BlockNum;
> +  EFI_LBA                               FirstLba;
>    EFI_LBA                               LastLba;
> +  EFI_LBA                               StartGroupLba;
> +  EFI_LBA                               EndGroupLba;
> +  UINT32                                EraseGroupSize;
> +  UINT32                                Remainder;
> +  UINTN                                 WriteZeroSize;
>    UINT8                                 PartitionConfig;
>    EMMC_PARTITION                        *Partition;
>    EMMC_DEVICE                           *Device;
> @@ -1978,7 +2029,8 @@ EmmcEraseBlocks (
>      Token->TransactionStatus = EFI_SUCCESS;
>    }
> 
> -  LastLba = Lba + BlockNum - 1;
> +  FirstLba = Lba;
> +  LastLba  = Lba + BlockNum - 1;
> 
>    //
>    // Check if needs to switch partition access.
> @@ -1994,7 +2046,78 @@ EmmcEraseBlocks (
>      Device->ExtCsd.PartitionConfig = PartitionConfig;
>    }
> 
> -  Status = EmmcEraseBlockStart (Partition, Lba,
> (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);
> +  if ((Device->ExtCsd.SecFeatureSupport & BIT4) == 0) {
> +    //
> +    // If the Trim operation is not supported by the device, handle the erase
> +    // of blocks that do not form a complete erase group separately.
> +    //
> +    EraseGroupSize = This->EraseLengthGranularity;
> +
> +    DivU64x32Remainder (FirstLba, EraseGroupSize, &Remainder);
> +    StartGroupLba = (Remainder == 0) ? FirstLba : (FirstLba +
> + EraseGroupSize - Remainder);
> +
> +    DivU64x32Remainder (LastLba + 1, EraseGroupSize, &Remainder);
> +    EndGroupLba = LastLba + 1 - Remainder;
> +
> +    //
> +    // If the size to erase is smaller than the erase group size, the whole
> +    // erase operation is performed by writting zeros.
> +    //
> +    if (BlockNum < EraseGroupSize) {
> +      Status = EmmcWriteZeros (Partition, FirstLba, Size);
> +      if (EFI_ERROR (Status)) {
> +        return Status;
> +      }
> +
> +      if ((Token != NULL) && (Token->Event != NULL)) {
> +        Token->TransactionStatus = EFI_SUCCESS;
> +        gBS->SignalEvent (Token->Event);
> +      }
> +      return EFI_SUCCESS;
> +    }
> +
> +    //
> +    // If the starting LBA to erase is not aligned with the start of an erase
> +    // group, write zeros to erase the data from starting LBA to the end of 
> the
> +    // current erase group.
> +    //
> +    if (StartGroupLba > FirstLba) {
> +      WriteZeroSize = (UINTN)(StartGroupLba - FirstLba) * BlockSize;
> +      Status = EmmcWriteZeros (Partition, FirstLba, WriteZeroSize);
> +      if (EFI_ERROR (Status)) {
> +        return Status;
> +      }
> +    }
> +
> +    //
> +    // If the ending LBA to erase is not aligned with the end of an erase
> +    // group, write zeros to erase the data from the start of the erase group
> +    // to the ending LBA.
> +    //
> +    if (EndGroupLba <= LastLba) {
> +      WriteZeroSize = (UINTN)(LastLba - EndGroupLba + 1) * BlockSize;
> +      Status = EmmcWriteZeros (Partition, EndGroupLba, WriteZeroSize);
> +      if (EFI_ERROR (Status)) {
> +        return Status;
> +      }
> +    }
> +
> +    //
> +    // Check whether there is erase group to erase.
> +    //
> +    if (EndGroupLba <= StartGroupLba) {
> +      if ((Token != NULL) && (Token->Event != NULL)) {
> +        Token->TransactionStatus = EFI_SUCCESS;
> +        gBS->SignalEvent (Token->Event);
> +      }
> +      return EFI_SUCCESS;
> +    }
> +
> +    FirstLba = StartGroupLba;
> +    LastLba  = EndGroupLba - 1;
> +  }
> +
> +  Status = EmmcEraseBlockStart (Partition, FirstLba,
> + (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);
>    if (EFI_ERROR (Status)) {
>      return Status;
>    }
> --
> 2.12.0.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to