From: "Wu, Hao A" <hao.a.wu@intel.com>
To: "Wu, Hao A" <hao.a.wu@intel.com>,
'Paulo Alcantara' <pcacjr@zytor.com>,
"Ni, Ruiyu" <ruiyu.ni@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Dong, Eric" <eric.dong@intel.com>, "Zeng, Star" <star.zeng@intel.com>
Subject: Re: [PATCH] MdeModulePkg/PartitionDxe: Fix UDF fs access on certain CD/DVD medias
Date: Wed, 15 Nov 2017 12:45:04 +0000 [thread overview]
Message-ID: <B80AF82E9BFB8E4FBD8C89DA810C6A0931D1CC48@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <B80AF82E9BFB8E4FBD8C89DA810C6A0931D1C389@SHSMSX104.ccr.corp.intel.com>
Pushed at: 1fbe8276c4
Best Regards,
Hao Wu
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wu,
> Hao A
> Sent: Tuesday, November 14, 2017 3:49 PM
> To: 'Paulo Alcantara'; Ni, Ruiyu; edk2-devel@lists.01.org
> Cc: Dong, Eric; Zeng, Star
> Subject: Re: [edk2] [PATCH] MdeModulePkg/PartitionDxe: Fix UDF fs access on
> certain CD/DVD medias
>
> Hi Paulo,
>
> Sorry for the delayed response. The patch is good to me:
> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
>
> Hi Ray,
>
> Do you have any other comment on this?
>
>
> Best Regards,
> Hao Wu
>
>
> > -----Original Message-----
> > From: Paulo Alcantara [mailto:pcacjr@zytor.com]
> > Sent: Friday, October 13, 2017 9:25 PM
> > To: edk2-devel@lists.01.org
> > Cc: Paulo Alcantara; Wu, Hao A; Ni, Ruiyu; Zeng, Star; Dong, Eric
> > Subject: [PATCH] MdeModulePkg/PartitionDxe: Fix UDF fs access on certain
> > CD/DVD medias
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=725
> >
> > Historically many drives or medias do not correctly return their value
> > for block N - which is also referred as last addressable/recorded block.
> > When they do so, there is still a problem when relying on last recorded
> > block number returned by SCSI commands READ CAPACITY and READ TRACK
> > INFORMATION - that is, between block 0 and block N there may be
> > unwritten blocks which are located outside any track.
> >
> > That said, the Partition driver was unable to find AVDP at block N on
> > certain medias that do not either return or report their last recorded
> > block number correctly.
> >
> > Apparently there is no official or correct way to find the correct block
> > number, however tools like the Philips UDF Conformance Tool (udf_test)
> > apply a correction by searching for an AVDP or VAT in blocks N through
> > N-456 -- this can be observed by looking at the log reported by udf_test
> > on those CD/DVD medias. So, if the AVDP or VAT is found, then it sets
> > the last recorded block number to where AVDP or VAT was located.
> >
> > With the below setence in UDF 2.60, 6.13.2.2 Background Physical
> > Formatting:
> >
> > "... the second AVDP must be recorded after the Background physical
> > Formatting has been finished..."
> >
> > Implies that the last recorded block is the one where second AVDP was
> > recorded.
> >
> > This patch implements a similar way to correct the last recorded block
> > number by searching for last AVDP in blocks N-1 through N-512 on those
> > certain medias, as well as ensure a minimum number of 2 AVDPs found as
> > specified by ECMA 167 and UDF 2.60 specifications.
> >
> > Cc: Hao Wu <hao.a.wu@intel.com>
> > Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Reported-by: Hao Wu <hao.a.wu@intel.com>
> > Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
> > ---
> > MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 254
> ++++++++++++++++--
> > --
> > 1 file changed, 201 insertions(+), 53 deletions(-)
> >
> > diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
> > b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
> > index 8aee30c759..7eee748958 100644
> > --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
> > +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
> > @@ -14,6 +14,8 @@
> >
> > #include "Partition.h"
> >
> > +#define MAX_CORRECTION_BLOCKS_NUM 512u
> > +
> > //
> > // C5BD4D42-1A76-4996-8956-73CDA326CD0A
> > //
> > @@ -48,61 +50,199 @@ UDF_DEVICE_PATH gUdfDevicePath = {
> > /**
> > Find the anchor volume descriptor pointer.
> >
> > - @param[in] BlockIo BlockIo interface.
> > - @param[in] DiskIo DiskIo interface.
> > - @param[out] AnchorPoint Anchor volume descriptor pointer.
> > + @param[in] BlockIo BlockIo interface.
> > + @param[in] DiskIo DiskIo interface.
> > + @param[out] AnchorPoint Anchor volume descriptor pointer.
> > + @param[out] LastRecordedBlock Last recorded block.
> >
> > - @retval EFI_SUCCESS Anchor volume descriptor pointer found.
> > - @retval EFI_VOLUME_CORRUPTED The file system structures are
> > corrupted.
> > - @retval other Anchor volume descriptor pointer not found.
> > + @retval EFI_SUCCESS Anchor volume descriptor pointer found.
> > + @retval EFI_VOLUME_CORRUPTED The file system structures are
> > corrupted.
> > + @retval other Anchor volume descriptor pointer not found.
> >
> > **/
> > EFI_STATUS
> > FindAnchorVolumeDescriptorPointer (
> > IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
> > IN EFI_DISK_IO_PROTOCOL *DiskIo,
> > - OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint
> > + OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint,
> > + OUT EFI_LBA *LastRecordedBlock
> > )
> > {
> > - EFI_STATUS Status;
> > - UINT32 BlockSize;
> > - EFI_LBA EndLBA;
> > - EFI_LBA DescriptorLBAs[4];
> > - UINTN Index;
> > - UDF_DESCRIPTOR_TAG *DescriptorTag;
> > + EFI_STATUS Status;
> > + UINT32 BlockSize;
> > + EFI_LBA EndLBA;
> > + UDF_DESCRIPTOR_TAG *DescriptorTag;
> > + UINTN AvdpsCount;
> > + UINTN Size;
> > + UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoints;
> > + INTN Index;
> > + UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPointPtr;
> > + EFI_LBA LastAvdpBlockNum;
> >
> > + //
> > + // UDF 2.60, 2.2.3 Anchor Volume Descriptor Pointer
> > + //
> > + // An Anchor Volume Descriptor Pointer structure shall be recorded in at
> > + // least 2 of the following 3 locations on the media: Logical Sector 256,
> > + // N - 256 or N, where N is the last *addressable* sector of a volume.
> > + //
> > + // To figure out what logical sector N is, the SCSI commands READ
> CAPACITY
> > and
> > + // READ TRACK INFORMATION are used, however many drives or medias
> > report their
> > + // "last recorded block" wrongly. Although, READ CAPACITY returns the last
> > + // readable data block but there might be unwritten blocks, which are
> > located
> > + // outside any track and therefore AVDP will not be found at block N.
> > + //
> > + // That said, we define a magic number of 512 blocks to be used as
> > correction
> > + // when attempting to find AVDP and define last block number.
> > + //
> > BlockSize = BlockIo->Media->BlockSize;
> > EndLBA = BlockIo->Media->LastBlock;
> > - DescriptorLBAs[0] = 256;
> > - DescriptorLBAs[1] = EndLBA - 256;
> > - DescriptorLBAs[2] = EndLBA;
> > - DescriptorLBAs[3] = 512;
> > + *LastRecordedBlock = EndLBA;
> > + AvdpsCount = 0;
> >
> > - for (Index = 0; Index < ARRAY_SIZE (DescriptorLBAs); Index++) {
> > - Status = DiskIo->ReadDisk (
> > - DiskIo,
> > - BlockIo->Media->MediaId,
> > - MultU64x32 (DescriptorLBAs[Index], BlockSize),
> > - sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),
> > - (VOID *)AnchorPoint
> > - );
> > - if (EFI_ERROR (Status)) {
> > - return Status;
> > - }
> > + //
> > + // Find AVDP at block 256
> > + //
> > + Status = DiskIo->ReadDisk (
> > + DiskIo,
> > + BlockIo->Media->MediaId,
> > + MultU64x32 (256, BlockSize),
> > + sizeof (*AnchorPoint),
> > + AnchorPoint
> > + );
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + DescriptorTag = &AnchorPoint->DescriptorTag;
> > +
> > + //
> > + // Check if read block is a valid AVDP descriptor
> > + //
> > + if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
> > + DEBUG ((DEBUG_INFO, "%a: found AVDP at block %d\n", __FUNCTION__,
> > 256));
> > + AvdpsCount++;
> > + }
> > +
> > + //
> > + // Find AVDP at block N - 256
> > + //
> > + Status = DiskIo->ReadDisk (
> > + DiskIo,
> > + BlockIo->Media->MediaId,
> > + MultU64x32 ((UINT64)EndLBA - 256, BlockSize),
> > + sizeof (*AnchorPoint),
> > + AnchorPoint
> > + );
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + //
> > + // Check if read block is a valid AVDP descriptor
> > + //
> > + if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer &&
> > + ++AvdpsCount == 2) {
> > + DEBUG ((DEBUG_INFO, "%a: found AVDP at block %Ld\n", __FUNCTION__,
> > + EndLBA - 256));
> > + return EFI_SUCCESS;
> > + }
> > +
> > + //
> > + // Check if at least one AVDP was found in previous locations
> > + //
> > + if (AvdpsCount == 0) {
> > + return EFI_VOLUME_CORRUPTED;
> > + }
> > +
> > + //
> > + // Find AVDP at block N
> > + //
> > + Status = DiskIo->ReadDisk (
> > + DiskIo,
> > + BlockIo->Media->MediaId,
> > + MultU64x32 ((UINT64)EndLBA, BlockSize),
> > + sizeof (*AnchorPoint),
> > + AnchorPoint
> > + );
> > + if (EFI_ERROR (Status)) {
> > + return Status;
> > + }
> > +
> > + //
> > + // Check if read block is a valid AVDP descriptor
> > + //
> > + if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
> > + return EFI_SUCCESS;
> > + }
> > +
> > + //
> > + // No AVDP found at block N. Possibly drive/media returned bad last
> > recorded
> > + // block, or it is part of unwritten data blocks and outside any track.
> > + //
> > + // Search backwards for an AVDP from block N-1 through
> > + // N-MAX_CORRECTION_BLOCKS_NUM. If any AVDP is found, then correct
> > last block
> > + // number for the new UDF partition child handle.
> > + //
> > + Size = MAX_CORRECTION_BLOCKS_NUM * BlockSize;
> > +
> > + AnchorPoints = AllocateZeroPool (Size);
> > + if (AnchorPoints == NULL) {
> > + return EFI_OUT_OF_RESOURCES;
> > + }
> > +
> > + //
> > + // Read consecutive MAX_CORRECTION_BLOCKS_NUM disk blocks
> > + //
> > + Status = DiskIo->ReadDisk (
> > + DiskIo,
> > + BlockIo->Media->MediaId,
> > + MultU64x32 ((UINT64)EndLBA - MAX_CORRECTION_BLOCKS_NUM,
> > BlockSize),
> > + Size,
> > + AnchorPoints
> > + );
> > + if (EFI_ERROR (Status)) {
> > + goto Out_Free;
> > + }
> >
> > - DescriptorTag = &AnchorPoint->DescriptorTag;
> > + Status = EFI_VOLUME_CORRUPTED;
> > +
> > + //
> > + // Search for AVDP from blocks N-1 through N-
> > MAX_CORRECTION_BLOCKS_NUM
> > + //
> > + for (Index = MAX_CORRECTION_BLOCKS_NUM - 2; Index >= 0; Index--) {
> > + AnchorPointPtr = (VOID *)((UINTN)AnchorPoints + Index * BlockSize);
> > +
> > + DescriptorTag = &AnchorPointPtr->DescriptorTag;
> >
> > //
> > - // Check if read LBA has a valid AVDP descriptor.
> > + // Check if read block is a valid AVDP descriptor
> > //
> > if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
> > - return EFI_SUCCESS;
> > + //
> > + // Calculate last recorded block number
> > + //
> > + LastAvdpBlockNum = EndLBA - (MAX_CORRECTION_BLOCKS_NUM -
> > Index);
> > + DEBUG ((DEBUG_WARN, "%a: found AVDP at block %Ld\n",
> > __FUNCTION__,
> > + LastAvdpBlockNum));
> > + DEBUG ((DEBUG_WARN, "%a: correcting last block from %Ld to %Ld\n",
> > + __FUNCTION__, EndLBA, LastAvdpBlockNum));
> > + //
> > + // Save read AVDP from last block
> > + //
> > + CopyMem (AnchorPoint, AnchorPointPtr, sizeof (*AnchorPointPtr));
> > + //
> > + // Set last recorded block number
> > + //
> > + *LastRecordedBlock = LastAvdpBlockNum;
> > + Status = EFI_SUCCESS;
> > + break;
> > }
> > }
> > - //
> > - // No AVDP found.
> > - //
> > - return EFI_VOLUME_CORRUPTED;
> > +
> > +Out_Free:
> > + FreePool (AnchorPoints);
> > + return Status;
> > }
> >
> > /**
> > @@ -280,16 +420,17 @@ IsLogicalVolumeDescriptorSupported (
> > Find UDF logical volume location and whether it is supported by current
> EDK2
> > UDF file system implementation.
> >
> > - @param[in] BlockIo BlockIo interface.
> > - @param[in] DiskIo DiskIo interface.
> > - @param[in] AnchorPoint Anchor volume descriptor pointer.
> > - @param[out] MainVdsStartBlock Main VDS starting block number.
> > - @param[out] MainVdsEndBlock Main VDS ending block number.
> > + @param[in] BlockIo BlockIo interface.
> > + @param[in] DiskIo DiskIo interface.
> > + @param[in] AnchorPoint Anchor volume descriptor pointer.
> > + @param[in] LastRecordedBlock Last recorded block in media.
> > + @param[out] MainVdsStartBlock Main VDS starting block number.
> > + @param[out] MainVdsEndBlock Main VDS ending block number.
> >
> > - @retval EFI_SUCCESS UDF logical volume was found.
> > - @retval EFI_VOLUME_CORRUPTED UDF file system structures are
> > corrupted.
> > - @retval EFI_UNSUPPORTED UDF logical volume is not supported.
> > - @retval other Failed to perform disk I/O.
> > + @retval EFI_SUCCESS UDF logical volume was found.
> > + @retval EFI_VOLUME_CORRUPTED UDF file system structures are
> > corrupted.
> > + @retval EFI_UNSUPPORTED UDF logical volume is not supported.
> > + @retval other Failed to perform disk I/O.
> >
> > **/
> > EFI_STATUS
> > @@ -297,13 +438,13 @@ FindLogicalVolumeLocation (
> > IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
> > IN EFI_DISK_IO_PROTOCOL *DiskIo,
> > IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint,
> > + IN EFI_LBA LastRecordedBlock,
> > OUT UINT64 *MainVdsStartBlock,
> > OUT UINT64 *MainVdsEndBlock
> > )
> > {
> > EFI_STATUS Status;
> > UINT32 BlockSize;
> > - EFI_LBA LastBlock;
> > UDF_EXTENT_AD *ExtentAd;
> > UINT64 SeqBlocksNum;
> > UINT64 SeqStartBlock;
> > @@ -316,7 +457,6 @@ FindLogicalVolumeLocation (
> > UDF_DESCRIPTOR_TAG *DescriptorTag;
> >
> > BlockSize = BlockIo->Media->BlockSize;
> > - LastBlock = BlockIo->Media->LastBlock;
> > ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;
> >
> > //
> > @@ -328,7 +468,7 @@ FindLogicalVolumeLocation (
> > // Also make sure it does not exceed maximum number of blocks in the disk.
> > //
> > SeqBlocksNum = DivU64x32 ((UINT64)ExtentAd->ExtentLength, BlockSize);
> > - if (SeqBlocksNum < 16 || (EFI_LBA)SeqBlocksNum > LastBlock + 1) {
> > + if (SeqBlocksNum < 16 || (EFI_LBA)SeqBlocksNum > LastRecordedBlock + 1)
> {
> > return EFI_VOLUME_CORRUPTED;
> > }
> >
> > @@ -336,8 +476,8 @@ FindLogicalVolumeLocation (
> > // Check for valid Volume Descriptor Sequence starting block number
> > //
> > SeqStartBlock = (UINT64)ExtentAd->ExtentLocation;
> > - if (SeqStartBlock > LastBlock ||
> > - SeqStartBlock + SeqBlocksNum - 1 > LastBlock) {
> > + if (SeqStartBlock > LastRecordedBlock ||
> > + SeqStartBlock + SeqBlocksNum - 1 > LastRecordedBlock) {
> > return EFI_VOLUME_CORRUPTED;
> > }
> >
> > @@ -437,9 +577,10 @@ FindLogicalVolumeLocation (
> > *MainVdsStartBlock = GuardMainVdsStartBlock;
> > //
> > // We do not need to read either LVD or PD descriptors to know the last
> > - // valid block in the found UDF file system. It's already LastBlock.
> > + // valid block in the found UDF file system. It's already
> > + // LastRecordedBlock.
> > //
> > - *MainVdsEndBlock = LastBlock;
> > + *MainVdsEndBlock = LastRecordedBlock;
> >
> > Status = EFI_SUCCESS;
> > }
> > @@ -473,8 +614,9 @@ FindUdfFileSystem (
> > OUT EFI_LBA *EndingLBA
> > )
> > {
> > - EFI_STATUS Status;
> > + EFI_STATUS Status;
> > UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;
> > + EFI_LBA LastRecordedBlock;
> >
> > //
> > // Find UDF volume identifiers
> > @@ -487,7 +629,12 @@ FindUdfFileSystem (
> > //
> > // Find Anchor Volume Descriptor Pointer
> > //
> > - Status = FindAnchorVolumeDescriptorPointer (BlockIo, DiskIo,
> &AnchorPoint);
> > + Status = FindAnchorVolumeDescriptorPointer (
> > + BlockIo,
> > + DiskIo,
> > + &AnchorPoint,
> > + &LastRecordedBlock
> > + );
> > if (EFI_ERROR (Status)) {
> > return Status;
> > }
> > @@ -499,6 +646,7 @@ FindUdfFileSystem (
> > BlockIo,
> > DiskIo,
> > &AnchorPoint,
> > + LastRecordedBlock,
> > (UINT64 *)StartingLBA,
> > (UINT64 *)EndingLBA
> > );
> > --
> > 2.11.0
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
prev parent reply other threads:[~2017-11-15 12:41 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-13 13:24 [PATCH] MdeModulePkg/PartitionDxe: Fix UDF fs access on certain CD/DVD medias Paulo Alcantara
2017-10-13 13:37 ` Laszlo Ersek
2017-10-13 13:49 ` Paulo Alcantara
2017-11-14 7:48 ` Wu, Hao A
2017-11-15 12:45 ` Wu, Hao A [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=B80AF82E9BFB8E4FBD8C89DA810C6A0931D1CC48@SHSMSX104.ccr.corp.intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox