From nobody Thu Dec 26 13:18:29 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 1505654170914975.1117967097464; Sun, 17 Sep 2017 06:16:10 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id D3AC621E97813; Sun, 17 Sep 2017 06:13:05 -0700 (PDT) Received: from mail.zytor.com (terminus.zytor.com [65.50.211.136]) (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 BF37821E977FF for ; Sun, 17 Sep 2017 06:13:04 -0700 (PDT) Received: from localhost.localdomain ([IPv6:2804:7f4:c480:8f0c:0:0:0:2]) (authenticated bits=0) by mail.zytor.com (8.15.2/8.15.2) with ESMTPSA id v8HDDhe7002117 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Sun, 17 Sep 2017 06:13:53 -0700 X-Original-To: edk2-devel@lists.01.org From: Paulo Alcantara To: edk2-devel@lists.01.org Date: Sun, 17 Sep 2017 10:13:27 -0300 Message-Id: <1321928015f9ed919425051e0d75c132de77348c.1505653040.git.pcacjr@zytor.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: Subject: [edk2] [PATCH v2 2/3] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition 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: Ruiyu Ni , Laszlo Ersek , Eric Dong , 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" Do not use entire block device size for the UDF logical partition, instead reserve the appropriate space (LVD space) for it. Cc: Eric Dong Cc: Ruiyu Ni Cc: Star Zeng Cc: Laszlo Ersek Reported-by: Ruiyu Ni Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara --- MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 323 ++++++++++++++++++-- 1 file changed, 299 insertions(+), 24 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c b/MdeModulePkg/= Universal/Disk/PartitionDxe/Udf.c index 7856b5dfc1..3e84882922 100644 --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c @@ -84,24 +84,8 @@ FindAnchorVolumeDescriptorPointer ( return EFI_VOLUME_CORRUPTED; } =20 -/** - Check if block device supports a valid UDF file system as specified by O= STA - Universal Disk Format Specification 2.60. - - @param[in] BlockIo BlockIo interface. - @param[in] DiskIo DiskIo interface. - - @retval EFI_SUCCESS UDF file system found. - @retval EFI_UNSUPPORTED UDF file system not found. - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_OUT_OF_RESOURCES The scan was not successful due to lack of - resources. - -**/ EFI_STATUS -SupportUdfFileSystem ( +FindUdfVolumeIdentifiers ( IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo ) @@ -111,7 +95,6 @@ SupportUdfFileSystem ( UINT64 EndDiskOffset; CDROM_VOLUME_DESCRIPTOR VolDescriptor; CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor; - UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint; =20 ZeroMem ((VOID *)&TerminatingVolDescriptor, sizeof (CDROM_VOLUME_DESCRIP= TOR)); =20 @@ -207,12 +190,302 @@ SupportUdfFileSystem ( return EFI_UNSUPPORTED; } =20 + return EFI_SUCCESS; +} + +EFI_STATUS +GetPartitionNumber ( + IN UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc, + OUT UINT16 *PartitionNum + ) +{ + EFI_STATUS Status; + UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd; + + Status =3D EFI_SUCCESS; + + switch (LV_UDF_REVISION (LogicalVolDesc)) { + case 0x0102: + // + // UDF 1.20 only supports Type 1 Partition + // + *PartitionNum =3D *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]= ); + break; + case 0x0150: + // + // Ensure Type 1 Partition map + // + ASSERT (LogicalVolDesc->PartitionMaps[0] =3D=3D 1 && + LogicalVolDesc->PartitionMaps[1] =3D=3D 6); + *PartitionNum =3D *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]= ); + break; + case 0x0260: + LongAd =3D &LogicalVolDesc->LogicalVolumeContentsUse; + *PartitionNum =3D LongAd->ExtentLocation.PartitionReferenceNumber; + break; + default: + // + // Unhandled UDF revision + // + Status =3D EFI_VOLUME_CORRUPTED; + break; + } + + return Status; +} + +EFI_STATUS +FindLogicalVolumeLocation ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint, + OUT UINT64 *MainVdsStartLsn, + OUT UINT64 *LogicalVolEndLsn + ) +{ + EFI_STATUS Status; + UINT32 BlockSize; + EFI_LBA LastBlock; + UDF_EXTENT_AD *ExtentAd; + UINT64 StartingLsn; + UINT64 EndingLsn; + VOID *Buffer; + UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc; + UDF_PARTITION_DESCRIPTOR *PartitionDesc; + UINT64 GuardMainVdsStartLsn; + UINT16 PartitionNum; + + BlockSize =3D BlockIo->Media->BlockSize; + LastBlock =3D BlockIo->Media->LastBlock; + ExtentAd =3D &AnchorPoint->MainVolumeDescriptorSequenceExte= nt; + StartingLsn =3D (UINT64)ExtentAd->ExtentLocation; + EndingLsn =3D + StartingLsn + DivU64x32 ((UINT64)ExtentAd->ExtentLength, BlockSize); + + LogicalVolDesc =3D NULL; + PartitionDesc =3D NULL; + GuardMainVdsStartLsn =3D StartingLsn; + + // + // Allocate buffer for reading disk blocks + // + Buffer =3D AllocateZeroPool (BlockSize); + if (Buffer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status =3D EFI_VOLUME_CORRUPTED; + + // + // As per UDF 2.60 specification: + // + // There shall be exactly one prevailing Logical Volume Descriptor + // recorded per Volume Set. + // + // Start Main Volume Descriptor Sequence and find Logical Volume Descrip= tor + // + while (StartingLsn <=3D EndingLsn) { + // + // Read disk block + // + Status =3D DiskIo->ReadDisk ( + DiskIo, + BlockIo->Media->MediaId, + MultU64x32 (StartingLsn, BlockSize), + BlockSize, + Buffer + ); + if (EFI_ERROR (Status)) { + goto Out_Free; + } + + // + // Check if read block is a Terminating Descriptor + // + if (IS_TD (Buffer)) { + // + // Stop Main Volume Descriptor Sequence + // + break; + } + + // + // Check if read block is a Logical Volume Descriptor + // + if (IS_LVD (Buffer)) { + // + // Ensure only one LVD (Logical Volume Descriptor) is handled + // + if (LogicalVolDesc !=3D NULL) { + Status =3D EFI_UNSUPPORTED; + goto Out_Free; + } + + // + // As per UDF 2.60 specification: + // + // For the purpose of interchange, Partition Maps shall be limited to + // Partition Map type 1, except type 2 maps. + // + // NOTE: Type 1 Partitions are the only supported in this implementa= tion. + // + LogicalVolDesc =3D AllocateZeroPool (sizeof (*LogicalVolDesc)); + if (LogicalVolDesc =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Out_Free; + } + + // + // Save Logical Volume Descriptor + // + CopyMem (LogicalVolDesc, Buffer, sizeof (*LogicalVolDesc)); + } else if (IS_PD (Buffer)) { + // + // Ensure only one PD (Partition Descriptor) is handled + // + if (PartitionDesc !=3D NULL) { + Status =3D EFI_UNSUPPORTED; + goto Out_Free; + } + + // + // Found a Partition Descriptor. + // + // As per UDF 2.60 specification: + // + // A Partition Descriptor Access Type of read-only, rewritable, + // overwritable, write-once and pseudo-overwritable shall be + // supported. There shall be exactly one prevailing Partition + // Descriptor recorded per volume, with one exception. For Volume + // Sets that consist of single volume, the volume may contain 2 non- + // overlapping Partitions with 2 prevailing Partition Descriptors on= ly + // if one has an Access Type of read-only and the other has an + // Access Type of rewritable, overwritable, or write-once. The + // Logical Volume for this volume would consist of the contents of + // both partitions. + // + PartitionDesc =3D AllocateZeroPool (sizeof (*PartitionDesc)); + if (PartitionDesc =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Out_Free; + } + + // + // Save Partition Descriptor + // + CopyMem (PartitionDesc, Buffer, sizeof (*PartitionDesc)); + } + // + // Go to next disk block + // + StartingLsn++; + } + + Status =3D EFI_VOLUME_CORRUPTED; + + // + // Check if LVD and PD were found + // + if (LogicalVolDesc !=3D NULL && PartitionDesc !=3D NULL) { + // + // Get partition number from Partition map in LVD descriptor + // + Status =3D GetPartitionNumber (LogicalVolDesc, &PartitionNum); + if (EFI_ERROR (Status)) { + goto Out_Free; + } + + // + // Make sure we're handling expected Partition Descriptor + // + if (PartitionDesc->PartitionNumber !=3D PartitionNum) { + Status =3D EFI_VOLUME_CORRUPTED; + goto Out_Free; + } + + // + // Cover the main VDS area so UdfDxe driver will also be able to get L= VD and + // PD descriptors out from the file system. + // + *MainVdsStartLsn =3D GuardMainVdsStartLsn; + *LogicalVolEndLsn =3D *MainVdsStartLsn + (UINT64)ExtentAd->ExtentLengt= h; + + // + // Cover UDF partition area + // + *LogicalVolEndLsn +=3D + ((UINT64)PartitionDesc->PartitionStartingLocation - + *LogicalVolEndLsn) + PartitionDesc->PartitionLength - 1; + // + // Ensure to not attempt reading past end of device + // + if (*LogicalVolEndLsn > LastBlock) { + Status =3D EFI_VOLUME_CORRUPTED; + } else { + Status =3D EFI_SUCCESS; + } + } + +Out_Free: + // + // Free block read buffer + // + FreePool (Buffer); + // + // Free Logical Volume Descriptor + // + if (LogicalVolDesc !=3D NULL) { + FreePool (LogicalVolDesc); + } + // + // Free Partition Descriptor + // + if (PartitionDesc !=3D NULL) { + FreePool (PartitionDesc); + } + + return Status; +} + +EFI_STATUS +FindUdfLogicalVolume ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + OUT EFI_LBA *StartingLBA, + OUT EFI_LBA *EndingLBA + ) +{ + EFI_STATUS Status; + UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint; + + // + // Find UDF volume identifiers + // + Status =3D FindUdfVolumeIdentifiers (BlockIo, DiskIo); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find Anchor Volume Descriptor Pointer + // Status =3D FindAnchorVolumeDescriptorPointer (BlockIo, DiskIo, &AnchorPo= int); if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; + return Status; } =20 - return EFI_SUCCESS; + // + // Find Logical Volume location + // + Status =3D FindLogicalVolumeLocation ( + BlockIo, + DiskIo, + &AnchorPoint, + (UINT64 *)StartingLBA, + (UINT64 *)EndingLBA + ); + + return Status; } =20 /** @@ -250,6 +523,8 @@ PartitionInstallUdfChildHandles ( EFI_GUID *VendorDefinedGuid; EFI_GUID UdfDevPathGuid =3D EFI_UDF_DEVICE_PATH_GUID; EFI_PARTITION_INFO_PROTOCOL PartitionInfo; + EFI_LBA StartingLBA; + EFI_LBA EndingLBA; =20 Media =3D BlockIo->Media; =20 @@ -291,9 +566,9 @@ PartitionInstallUdfChildHandles ( } =20 // - // Check if block device supports an UDF file system + // Find UDF logical volume on block device // - Status =3D SupportUdfFileSystem (BlockIo, DiskIo); + Status =3D FindUdfLogicalVolume (BlockIo, DiskIo, &StartingLBA, &EndingL= BA); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } @@ -318,8 +593,8 @@ PartitionInstallUdfChildHandles ( DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUdfDevicePath, &PartitionInfo, - 0, - Media->LastBlock, + StartingLBA, + EndingLBA, Media->BlockSize ); if (!EFI_ERROR (Status)) { --=20 2.11.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel