From nobody Fri Dec 27 02:28:32 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1502426288436115.28277488694471; Thu, 10 Aug 2017 21:38:08 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 4AC5521D490F5; Thu, 10 Aug 2017 21:35:44 -0700 (PDT) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (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 BCEA921D490EE for ; Thu, 10 Aug 2017 21:35:42 -0700 (PDT) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 Aug 2017 21:38:02 -0700 Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.13]) by orsmga001.jf.intel.com with ESMTP; 10 Aug 2017 21:38:01 -0700 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,356,1498546800"; d="scan'208";a="1161545971" From: Hao Wu To: edk2-devel@lists.01.org Date: Fri, 11 Aug 2017 12:37:59 +0800 Message-Id: <20170811043759.10368-1-hao.a.wu@intel.com> X-Mailer: git-send-email 2.12.0.windows.1 Subject: [edk2] [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: , Cc: Hao Wu , Ruiyu Ni , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" V3 changes: Add debug messages for new return path when successfully erase the specified 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 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 Cc: Ruiyu Ni Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu Reviewed-by: Star Zeng --- 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, FA= LSE, 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 + EraseG= roupSize - Remainder); + + DivU64x32Remainder (LastLba + 1, EraseGroupSize, &Remainder); + EndGroupLba =3D 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 =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, (EFI_BLOCK_IO2_TOKE= N*)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; } --=20 2.12.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel