From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 46B9021D490EF for ; Thu, 10 Aug 2017 21:58:05 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 Aug 2017 22:00:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,356,1498546800"; d="scan'208";a="1204494710" Received: from fmsmsx104.amr.corp.intel.com ([10.18.124.202]) by fmsmga002.fm.intel.com with ESMTP; 10 Aug 2017 22:00:24 -0700 Received: from fmsmsx116.amr.corp.intel.com (10.18.116.20) by fmsmsx104.amr.corp.intel.com (10.18.124.202) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 10 Aug 2017 22:00:25 -0700 Received: from shsmsx152.ccr.corp.intel.com (10.239.6.52) by fmsmsx116.amr.corp.intel.com (10.18.116.20) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 10 Aug 2017 22:00:24 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.183]) by SHSMSX152.ccr.corp.intel.com ([169.254.6.135]) with mapi id 14.03.0319.002; Fri, 11 Aug 2017 13:00:22 +0800 From: "Zeng, Star" To: "Wu, Hao A" , "edk2-devel@lists.01.org" CC: "Ni, Ruiyu" , "Zeng, Star" Thread-Topic: [PATCH v3] MdeModulePkg/EmmcDxe: Make sure no extra data is erased by EraseBlocks Thread-Index: AQHTElufubwcps68DEGftGYXMnaji6J+mKlg Date: Fri, 11 Aug 2017 05:00:21 +0000 Message-ID: <0C09AFA07DD0434D9E2A0C6AEB0483103B9182B9@shsmsx102.ccr.corp.intel.com> References: <20170811043759.10368-1-hao.a.wu@intel.com> In-Reply-To: <20170811043759.10368-1-hao.a.wu@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH v3] MdeModulePkg/EmmcDxe: Make sure no extra data is erased by EraseBlocks X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Aug 2017 04:58:05 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Star Zeng -----Original Message----- From: Wu, Hao A=20 Sent: Friday, August 11, 2017 12:38 PM To: edk2-devel@lists.01.org Cc: Wu, Hao A ; Zeng, Star ; Ni, R= uiyu Subject: [PATCH v3] MdeModulePkg/EmmcDxe: Make sure no extra data is erased= by EraseBlocks V3 changes: Add debug messages for new return path when successfully erase the specifie= d blocks. Refine logic for calculating the size for writing zeros to device= . V2 changes: The Trim command is not supported on all eMMC devices. For those devices th= at 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 Sta= ndard 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 eras= e group. However, code logic in function EmmcEraseBlocks() does not check whether th= e 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 t= o erase the data in the erase groups. And write zeros to those blocks that = cannot form a complete erase group. Cc: Star Zeng Cc: Ruiyu Ni Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu --- MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c | 154 ++++++++++++++++++++++++++= +++- 1 file changed, 151 insertions(+), 3 deletions(-) diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c b/MdeModulePkg/Bus/S= d/EmmcDxe/EmmcBlockIo.c index c432d26801..2e3bf5f156 100644 --- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c +++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c @@ -1851,6 +1851,14 @@ EmmcEraseBlock ( EraseBlock->SdMmcCmdBlk.CommandIndex =3D EMMC_ERASE; EraseBlock->SdMmcCmdBlk.CommandType =3D SdMmcCommandTypeAc; EraseBlock->SdMmcCmdBlk.ResponseType =3D SdMmcResponseTypeR1b; + if ((Device->ExtCsd.SecFeatureSupport & BIT4) !=3D 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 =3D 1; } =20 EraseBlock->IsEnd =3D IsEnd; EraseBlock->Token =3D Token; @@ -1903,6 +1911,43 @@ Error: } =20 /** + Write zeros to specified blocks. + + @param[in] Partition A pointer to the EMMC_PARTITION instance. + @param[in] StartLba The starting logical block address to writ= e 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 successf= ully. + +**/ +EFI_STATUS +EmmcWriteZeros ( + IN EMMC_PARTITION *Partition, + IN EFI_LBA StartLba, + IN UINTN Size + ) +{ + EFI_STATUS Status; + UINT8 *Buffer; + UINT32 MediaId; + + Buffer =3D AllocateZeroPool (Size); + if (Buffer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + MediaId =3D Partition->BlockMedia.MediaId; + + Status =3D EmmcReadWrite (Partition, MediaId, StartLba, Buffer, Size,=20 + FALSE, NULL); FreePool (Buffer); + + return Status; +} + +/** Erase a specified number of device blocks. =20 @param[in] This Indicates a pointer to the calling conte= xt. @@ -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 =3D EFI_SUCCESS; } =20 - LastLba =3D Lba + BlockNum - 1; + FirstLba =3D Lba; + LastLba =3D Lba + BlockNum - 1; =20 // // Check if needs to switch partition access. @@ -1994,7 +2046,96 @@ EmmcEraseBlocks ( Device->ExtCsd.PartitionConfig =3D PartitionConfig; } =20 - Status =3D EmmcEraseBlockStart (Partition, Lba, (EFI_BLOCK_IO2_TOKEN*)To= ken, FALSE); + if ((Device->ExtCsd.SecFeatureSupport & BIT4) =3D=3D 0) { + // + // If the Trim operation is not supported by the device, handle the er= ase + // of blocks that do not form a complete erase group separately. + // + EraseGroupSize =3D This->EraseLengthGranularity; + + DivU64x32Remainder (FirstLba, EraseGroupSize, &Remainder); + StartGroupLba =3D (Remainder =3D=3D 0) ? FirstLba : (FirstLba +=20 + EraseGroupSize - Remainder); + + DivU64x32Remainder (LastLba + 1, EraseGroupSize, &Remainder); + EndGroupLba =3D LastLba + 1 - Remainder; + + // + // If the size to erase is smaller than the erase group size, the whol= e + // erase operation is performed by writting zeros. + // + if (BlockNum < EraseGroupSize) { + Status =3D EmmcWriteZeros (Partition, FirstLba, Size); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG (( + DEBUG_INFO, + "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", + Lba, + BlockNum, + (Token !=3D NULL) ? Token->Event : NULL, + Status + )); + + if ((Token !=3D NULL) && (Token->Event !=3D NULL)) { + Token->TransactionStatus =3D EFI_SUCCESS; + gBS->SignalEvent (Token->Event); + } + return EFI_SUCCESS; + } + + // + // If the starting LBA to erase is not aligned with the start of an er= ase + // group, write zeros to erase the data from starting LBA to the end o= f the + // current erase group. + // + if (StartGroupLba > FirstLba) { + WriteZeroSize =3D (UINTN)(StartGroupLba - FirstLba) * BlockSize; + Status =3D 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 gr= oup + // to the ending LBA. + // + if (EndGroupLba <=3D LastLba) { + WriteZeroSize =3D (UINTN)(LastLba + 1 - EndGroupLba) * BlockSize; + Status =3D EmmcWriteZeros (Partition, EndGroupLba, WriteZeroSize); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Check whether there is erase group to erase. + // + if (EndGroupLba <=3D StartGroupLba) { + DEBUG (( + DEBUG_INFO, + "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", + Lba, + BlockNum, + (Token !=3D NULL) ? Token->Event : NULL, + Status + )); + + if ((Token !=3D NULL) && (Token->Event !=3D NULL)) { + Token->TransactionStatus =3D EFI_SUCCESS; + gBS->SignalEvent (Token->Event); + } + return EFI_SUCCESS; + } + + FirstLba =3D StartGroupLba; + LastLba =3D EndGroupLba - 1; + } + + Status =3D EmmcEraseBlockStart (Partition, FirstLba,=20 + (EFI_BLOCK_IO2_TOKEN*)Token, FALSE); if (EFI_ERROR (Status)) { return Status; } @@ -2009,7 +2150,14 @@ EmmcEraseBlocks ( return Status; } =20 - DEBUG ((EFI_D_ERROR, "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p wi= th %r\n", Lba, BlockNum, Token->Event, Status)); + DEBUG (( + DEBUG_INFO, + "EmmcEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", + Lba, + BlockNum, + (Token !=3D NULL) ? Token->Event : NULL, + Status + )); =20 return Status; } -- 2.12.0.windows.1