public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v4 0/2] UDF partition driver fix
@ 2017-09-22 18:11 Paulo Alcantara
  2017-09-22 18:11 ` [PATCH v4 1/2] MdePkg: Add UDF volume structure definitions Paulo Alcantara
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Paulo Alcantara @ 2017-09-22 18:11 UTC (permalink / raw)
  To: edk2-devel
  Cc: Paulo Alcantara, Michael D Kinney, Liming Gao, Laszlo Ersek,
	Ruiyu Ni, Star Zeng, Jiewen Yao

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=707

Hi,

This patchset fixes a bug in Partition driver that created UDF logical
partitions by using entire block device space and thus polluting
protocol database with broken handles.

v1->v2:
 - Followed Laszlo's suggestions to submit a proper patchset. Thanks!
 - As I'm still waiting for Ruiyu and Star to test this fix, I took
   advantage of it and did some code cleanups :-)

v2->v3:
 - Followed Ruiyu's suggestions to improve code and add additional
   checks for ensuring a valid UDF file system and supported by current
   EDK2 UDF file system implementation. Also run Ecc.py to make sure the
   files I touched did not break EDK2 C Coding Style, as well as
   PatchCheck.py for mal-formed patches.

v3->v4:
 - Change 2/2's title as suggested by Star.
 - Remove UDF_TAG_ID() and refactor out UDF_ENTITY_ID structure as
   suggested by Ruiyu.
 - Tested build with VS2015 toolchain.

I've had a chance to test these changes with my 32GiB USB stick
and formatted it on Windows 10 with `format` command. The UDF revisions
I tested (by specifying it with "/R:revision") were 1.02, 1.50, 2.00,
2.01 (default) and 2.50. They all worked except the 2.50 revision which
adds a Type 2 (Metadata) Partition and it's not supported by current
EDK2 UDF implementation -- which handles only Type 1 (Physical)
Partitions. The UDF 2.60 revision I tested with the usual
`sudo mkudffs -b 512 --media-type=hd /dev/sdX` command in Linux.

Remember, the *officially* supported revision is 2.60, however all
revisions use the same volume structures as defined by ECMA 167
specification, and they usually differ from each other by means of
new optional features, so that's why all those revisions worked with
this implementation.

Well, at least this what I understood when looking at the
specifications. Please correct me if I'm wrong.

Please, test building these changes in toolchains other than GCC and
make sure they don't break the world :-)

Thanks!
Paulo

Repo:   https://github.com/pcacjr/edk2.git
Branch: udf-partition-fix-v4

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Reported-by: Ruiyu Ni <ruiyu.ni@intel.com>
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
---

Paulo Alcantara (2):
  MdePkg: Add UDF volume structure definitions
  MdeModulePkg/UDF: Fix creation of UDF logical partition

 MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c            | 366 ++++++++++--
 MdeModulePkg/Universal/Disk/UdfDxe/File.c                 |  16 +-
 MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 ++++++++------------
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c                  |   7 -
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.h                  | 158 ++---
 MdePkg/Include/IndustryStandard/Udf.h                     |  97 ++-
 6 files changed, 698 insertions(+), 573 deletions(-)

-- 
2.13.3.windows.1



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v4 1/2] MdePkg: Add UDF volume structure definitions
  2017-09-22 18:11 [PATCH v4 0/2] UDF partition driver fix Paulo Alcantara
@ 2017-09-22 18:11 ` Paulo Alcantara
  2017-09-22 18:11 ` [PATCH v4 2/2] MdeModulePkg/UDF: Fix creation of UDF logical partition Paulo Alcantara
  2017-09-25  0:31 ` [PATCH v4 0/2] UDF partition driver fix Ni, Ruiyu
  2 siblings, 0 replies; 5+ messages in thread
From: Paulo Alcantara @ 2017-09-22 18:11 UTC (permalink / raw)
  To: edk2-devel
  Cc: Paulo Alcantara, Michael D Kinney, Liming Gao, Laszlo Ersek,
	Ruiyu Ni

This patch adds a few more UDF volume structures in order to detect an
UDF file system which is supported by current EDK2 UDF file system
implementation in Partition driver.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
Build-tested-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
Tested-by: Hao Wu <hao.a.wu@intel.com>
Build-tested-by: Star Zeng <star.zeng@intel.com>
Build-tested-by: Paulo Alcantara <paulo@hp.com>
---
 MdePkg/Include/IndustryStandard/Udf.h | 97 +++++++++++++++++++-
 1 file changed, 92 insertions(+), 5 deletions(-)

diff --git a/MdePkg/Include/IndustryStandard/Udf.h b/MdePkg/Include/IndustryStandard/Udf.h
index 0febb4bcda..5806560aee 100644
--- a/MdePkg/Include/IndustryStandard/Udf.h
+++ b/MdePkg/Include/IndustryStandard/Udf.h
@@ -24,11 +24,22 @@
 #define UDF_LOGICAL_SECTOR_SIZE   ((UINT64)(1ULL << UDF_LOGICAL_SECTOR_SHIFT))
 #define UDF_VRS_START_OFFSET      ((UINT64)(16ULL << UDF_LOGICAL_SECTOR_SHIFT))
 
-#define _GET_TAG_ID(_Pointer) \
-  (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier)
-
-#define IS_AVDP(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2))
+typedef enum {
+  UdfPrimaryVolumeDescriptor = 1,
+  UdfAnchorVolumeDescriptorPointer = 2,
+  UdfVolumeDescriptorPointer = 3,
+  UdfImplemenationUseVolumeDescriptor = 4,
+  UdfPartitionDescriptor = 5,
+  UdfLogicalVolumeDescriptor = 6,
+  UdfUnallocatedSpaceDescriptor = 7,
+  UdfTerminatingDescriptor = 8,
+  UdfLogicalVolumeIntegrityDescriptor = 9,
+  UdfFileSetDescriptor = 256,
+  UdfFileIdentifierDescriptor = 257,
+  UdfAllocationExtentDescriptor = 258,
+  UdfFileEntry = 261,
+  UdfExtendedFileEntry = 266,
+} UDF_VOLUME_DESCRIPTOR_ID;
 
 #pragma pack(1)
 
@@ -49,12 +60,88 @@ typedef struct {
 } UDF_EXTENT_AD;
 
 typedef struct {
+  UINT8           CharacterSetType;
+  UINT8           CharacterSetInfo[63];
+} UDF_CHAR_SPEC;
+
+typedef struct {
+  UINT8           Flags;
+  UINT8           Identifier[23];
+  union {
+    //
+    // Domain Entity Identifier
+    //
+    struct {
+      UINT16      UdfRevision;
+      UINT8       DomainFlags;
+      UINT8       Reserved[5];
+    } Domain;
+    //
+    // UDF Entity Identifier
+    //
+    struct {
+      UINT16      UdfRevision;
+      UINT8       OSClass;
+      UINT8       OSIdentifier;
+      UINT8       Reserved[4];
+    } Entity;
+    //
+    // Implementation Entity Identifier
+    //
+    struct {
+      UINT8       OSClass;
+      UINT8       OSIdentifier;
+      UINT8       ImplementationUseArea[6];
+    } ImplementationEntity;
+    //
+    // Application Entity Identifier
+    //
+    struct {
+      UINT8       ApplicationUseArea[8];
+    } ApplicationEntity;
+    //
+    // Raw Identifier Suffix
+    //
+    struct {
+      UINT8       Data[8];
+    } Raw;
+  } Suffix;
+} UDF_ENTITY_ID;
+
+typedef struct {
+  UINT32        LogicalBlockNumber;
+  UINT16        PartitionReferenceNumber;
+} UDF_LB_ADDR;
+
+typedef struct {
+  UINT32                           ExtentLength;
+  UDF_LB_ADDR                      ExtentLocation;
+  UINT8                            ImplementationUse[6];
+} UDF_LONG_ALLOCATION_DESCRIPTOR;
+
+typedef struct {
   UDF_DESCRIPTOR_TAG  DescriptorTag;
   UDF_EXTENT_AD       MainVolumeDescriptorSequenceExtent;
   UDF_EXTENT_AD       ReserveVolumeDescriptorSequenceExtent;
   UINT8               Reserved[480];
 } UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER;
 
+typedef struct {
+  UDF_DESCRIPTOR_TAG              DescriptorTag;
+  UINT32                          VolumeDescriptorSequenceNumber;
+  UDF_CHAR_SPEC                   DescriptorCharacterSet;
+  UINT8                           LogicalVolumeIdentifier[128];
+  UINT32                          LogicalBlockSize;
+  UDF_ENTITY_ID                   DomainIdentifier;
+  UDF_LONG_ALLOCATION_DESCRIPTOR  LogicalVolumeContentsUse;
+  UINT32                          MapTableLength;
+  UINT32                          NumberOfPartitionMaps;
+  UDF_ENTITY_ID                   ImplementationIdentifier;
+  UINT8                           ImplementationUse[128];
+  UDF_EXTENT_AD                   IntegritySequenceExtent;
+  UINT8                           PartitionMaps[6];
+} UDF_LOGICAL_VOLUME_DESCRIPTOR;
+
 #pragma pack()
 
 #endif
-- 
2.13.3.windows.1



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 2/2] MdeModulePkg/UDF: Fix creation of UDF logical partition
  2017-09-22 18:11 [PATCH v4 0/2] UDF partition driver fix Paulo Alcantara
  2017-09-22 18:11 ` [PATCH v4 1/2] MdePkg: Add UDF volume structure definitions Paulo Alcantara
@ 2017-09-22 18:11 ` Paulo Alcantara
  2017-09-25  0:31 ` [PATCH v4 0/2] UDF partition driver fix Ni, Ruiyu
  2 siblings, 0 replies; 5+ messages in thread
From: Paulo Alcantara @ 2017-09-22 18:11 UTC (permalink / raw)
  To: edk2-devel; +Cc: Paulo Alcantara, Eric Dong, Ruiyu Ni, Star Zeng, Laszlo Ersek

Do not reserve entire block device size for an UDF file system -
instead, reserve the appropriate space (UDF logical volume space) for
it.

Additionally, only create a logical partition for UDF logical volumes
that are currently supported by EDK2 UDF file system implementation. For
instance, an UDF volume with a single LVD and a single Physical (Type 1)
Partition will be supported.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Reported-by: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
Tested-by: Hao Wu <hao.a.wu@intel.com>
Build-tested-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
Build-tested-by: Star Zeng <star.zeng@intel.com>
Build-tested-by: Paulo Alcantara <paulo@hp.com>
---
 MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c            | 366 ++++++++++--
 MdeModulePkg/Universal/Disk/UdfDxe/File.c                 |  16 +-
 MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 ++++++++------------
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c                  |   7 -
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.h                  | 158 ++---
 5 files changed, 606 insertions(+), 568 deletions(-)

diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
index 609f56cef6..8aee30c759 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
@@ -64,11 +64,12 @@ FindAnchorVolumeDescriptorPointer (
   OUT  UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER  *AnchorPoint
   )
 {
-  EFI_STATUS  Status;
-  UINT32      BlockSize;
-  EFI_LBA     EndLBA;
-  EFI_LBA     DescriptorLBAs[4];
-  UINTN       Index;
+  EFI_STATUS          Status;
+  UINT32              BlockSize;
+  EFI_LBA             EndLBA;
+  EFI_LBA             DescriptorLBAs[4];
+  UINTN               Index;
+  UDF_DESCRIPTOR_TAG  *DescriptorTag;
 
   BlockSize = BlockIo->Media->BlockSize;
   EndLBA = BlockIo->Media->LastBlock;
@@ -88,10 +89,13 @@ FindAnchorVolumeDescriptorPointer (
     if (EFI_ERROR (Status)) {
       return Status;
     }
+
+    DescriptorTag = &AnchorPoint->DescriptorTag;
+
     //
     // Check if read LBA has a valid AVDP descriptor.
     //
-    if (IS_AVDP (AnchorPoint)) {
+    if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
       return EFI_SUCCESS;
     }
   }
@@ -102,23 +106,18 @@ FindAnchorVolumeDescriptorPointer (
 }
 
 /**
-  Check if block device supports a valid UDF file system as specified by OSTA
-  Universal Disk Format Specification 2.60.
+  Find UDF volume identifiers in a Volume Recognition Sequence.
 
-  @param[in]   BlockIo  BlockIo interface.
-  @param[in]   DiskIo   DiskIo interface.
+  @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.
+  @retval EFI_SUCCESS             UDF volume identifiers were found.
+  @retval EFI_NOT_FOUND           UDF volume identifiers were not found.
+  @retval other                   Failed to perform disk I/O.
 
 **/
 EFI_STATUS
-SupportUdfFileSystem (
+FindUdfVolumeIdentifiers (
   IN EFI_BLOCK_IO_PROTOCOL  *BlockIo,
   IN EFI_DISK_IO_PROTOCOL   *DiskIo
   )
@@ -128,7 +127,6 @@ SupportUdfFileSystem (
   UINT64                                EndDiskOffset;
   CDROM_VOLUME_DESCRIPTOR               VolDescriptor;
   CDROM_VOLUME_DESCRIPTOR               TerminatingVolDescriptor;
-  UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER  AnchorPoint;
 
   ZeroMem ((VOID *)&TerminatingVolDescriptor, sizeof (CDROM_VOLUME_DESCRIPTOR));
 
@@ -167,7 +165,7 @@ SupportUdfFileSystem (
         (CompareMem ((VOID *)&VolDescriptor,
                      (VOID *)&TerminatingVolDescriptor,
                      sizeof (CDROM_VOLUME_DESCRIPTOR)) == 0)) {
-      return EFI_UNSUPPORTED;
+      return EFI_NOT_FOUND;
     }
   }
 
@@ -176,7 +174,7 @@ SupportUdfFileSystem (
   //
   Offset += UDF_LOGICAL_SECTOR_SIZE;
   if (Offset >= EndDiskOffset) {
-    return EFI_UNSUPPORTED;
+    return EFI_NOT_FOUND;
   }
 
   Status = DiskIo->ReadDisk (
@@ -196,7 +194,7 @@ SupportUdfFileSystem (
       (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
                    (VOID *)UDF_NSR3_IDENTIFIER,
                    sizeof (VolDescriptor.Unknown.Id)) != 0)) {
-    return EFI_UNSUPPORTED;
+    return EFI_NOT_FOUND;
   }
 
   //
@@ -204,7 +202,7 @@ SupportUdfFileSystem (
   //
   Offset += UDF_LOGICAL_SECTOR_SIZE;
   if (Offset >= EndDiskOffset) {
-    return EFI_UNSUPPORTED;
+    return EFI_NOT_FOUND;
   }
 
   Status = DiskIo->ReadDisk (
@@ -221,15 +219,291 @@ SupportUdfFileSystem (
   if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
                   (VOID *)UDF_TEA_IDENTIFIER,
                   sizeof (VolDescriptor.Unknown.Id)) != 0) {
-    return EFI_UNSUPPORTED;
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Check if Logical Volume Descriptor is supported by current EDK2 UDF file
+  system implementation.
+
+  @param[in]  LogicalVolDesc  Logical Volume Descriptor pointer.
+
+  @retval TRUE                Logical Volume Descriptor is supported.
+  @retval FALSE               Logical Volume Descriptor is not supported.
+
+**/
+BOOLEAN
+IsLogicalVolumeDescriptorSupported (
+  UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc
+  )
+{
+  //
+  // Check for a valid UDF revision range
+  //
+  switch (LogicalVolDesc->DomainIdentifier.Suffix.Domain.UdfRevision) {
+  case 0x0102:
+  case 0x0150:
+  case 0x0200:
+  case 0x0201:
+  case 0x0250:
+  case 0x0260:
+    break;
+  default:
+    return FALSE;
+  }
+
+  //
+  // Check for a single Partition Map
+  //
+  if (LogicalVolDesc->NumberOfPartitionMaps > 1) {
+    return FALSE;
+  }
+  //
+  // UDF 1.02 revision supports only Type 1 (Physical) partitions, but
+  // let's check it any way.
+  //
+  // PartitionMap[0] -> type
+  // PartitionMap[1] -> length (in bytes)
+  //
+  if (LogicalVolDesc->PartitionMaps[0] != 1 ||
+      LogicalVolDesc->PartitionMaps[1] != 6) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  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.
+
+  @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
+FindLogicalVolumeLocation (
+  IN   EFI_BLOCK_IO_PROTOCOL                 *BlockIo,
+  IN   EFI_DISK_IO_PROTOCOL                  *DiskIo,
+  IN   UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER  *AnchorPoint,
+  OUT  UINT64                                *MainVdsStartBlock,
+  OUT  UINT64                                *MainVdsEndBlock
+  )
+{
+  EFI_STATUS                     Status;
+  UINT32                         BlockSize;
+  EFI_LBA                        LastBlock;
+  UDF_EXTENT_AD                  *ExtentAd;
+  UINT64                         SeqBlocksNum;
+  UINT64                         SeqStartBlock;
+  UINT64                         GuardMainVdsStartBlock;
+  VOID                           *Buffer;
+  UINT64                         SeqEndBlock;
+  BOOLEAN                        StopSequence;
+  UINTN                          LvdsCount;
+  UDF_LOGICAL_VOLUME_DESCRIPTOR  *LogicalVolDesc;
+  UDF_DESCRIPTOR_TAG             *DescriptorTag;
+
+  BlockSize = BlockIo->Media->BlockSize;
+  LastBlock = BlockIo->Media->LastBlock;
+  ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;
+
+  //
+  // UDF 2.60, 2.2.3.1 struct MainVolumeDescriptorSequenceExtent
+  //
+  // The Main Volume Descriptor Sequence Extent shall have a minimum length of
+  // 16 logical sectors.
+  //
+  // 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) {
+    return EFI_VOLUME_CORRUPTED;
+  }
+
+  //
+  // Check for valid Volume Descriptor Sequence starting block number
+  //
+  SeqStartBlock = (UINT64)ExtentAd->ExtentLocation;
+  if (SeqStartBlock > LastBlock ||
+      SeqStartBlock + SeqBlocksNum - 1 > LastBlock) {
+    return EFI_VOLUME_CORRUPTED;
+  }
+
+  GuardMainVdsStartBlock = SeqStartBlock;
+
+  //
+  // Allocate buffer for reading disk blocks
+  //
+  Buffer = AllocateZeroPool ((UINTN)BlockSize);
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  SeqEndBlock = SeqStartBlock + SeqBlocksNum;
+  StopSequence = FALSE;
+  LvdsCount = 0;
+  Status = EFI_VOLUME_CORRUPTED;
+  //
+  // Start Main Volume Descriptor Sequence
+  //
+  for (; SeqStartBlock < SeqEndBlock && !StopSequence; SeqStartBlock++) {
+    //
+    // Read disk block
+    //
+    Status = BlockIo->ReadBlocks (
+      BlockIo,
+      BlockIo->Media->MediaId,
+      SeqStartBlock,
+      BlockSize,
+      Buffer
+      );
+    if (EFI_ERROR (Status)) {
+      goto Out_Free;
+    }
+
+    DescriptorTag = Buffer;
+
+    //
+    // ECMA 167, 8.4.1 Contents of a Volume Descriptor Sequence
+    //
+    // - A Volume Descriptor Sequence shall contain one or more Primary Volume
+    //   Descriptors.
+    // - A Volume Descriptor Sequence shall contain zero or more Implementation
+    //   Use Volume Descriptors.
+    // - A Volume Descriptor Sequence shall contain zero or more Partition
+    //   Descriptors.
+    // - A Volume Descriptor Sequence shall contain zero or more Logical Volume
+    //   Descriptors.
+    // - A Volume Descriptor Sequence shall contain zero or more Unallocated
+    //   Space Descriptors.
+    //
+    switch (DescriptorTag->TagIdentifier) {
+    case UdfPrimaryVolumeDescriptor:
+    case UdfImplemenationUseVolumeDescriptor:
+    case UdfPartitionDescriptor:
+    case UdfUnallocatedSpaceDescriptor:
+      break;
+
+    case UdfLogicalVolumeDescriptor:
+      LogicalVolDesc = Buffer;
+
+      //
+      // Check for existence of a single LVD and whether it is supported by
+      // current EDK2 UDF file system implementation.
+      //
+      if (++LvdsCount > 1 ||
+          !IsLogicalVolumeDescriptorSupported (LogicalVolDesc)) {
+        Status = EFI_UNSUPPORTED;
+        StopSequence = TRUE;
+      }
+
+      break;
+
+    case UdfTerminatingDescriptor:
+      //
+      // Stop the sequence when we find a Terminating Descriptor
+      // (aka Unallocated Sector), se we don't have to walk all the unallocated
+      // area unnecessarily.
+      //
+      StopSequence = TRUE;
+      break;
+
+    default:
+      //
+      // An invalid Volume Descriptor has been found in the sequece. Volume is
+      // corrupted.
+      //
+      Status = EFI_VOLUME_CORRUPTED;
+      goto Out_Free;
+    }
+  }
+
+  //
+  // Check if LVD was found
+  //
+  if (!EFI_ERROR (Status) && LvdsCount == 1) {
+    *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.
+    //
+    *MainVdsEndBlock = LastBlock;
+
+    Status = EFI_SUCCESS;
+  }
+
+Out_Free:
+  //
+  // Free block read buffer
+  //
+  FreePool (Buffer);
+
+  return Status;
+}
+
+/**
+  Find a supported UDF file system in block device.
+
+  @param[in]  BlockIo             BlockIo interface.
+  @param[in]  DiskIo              DiskIo interface.
+  @param[out] StartingLBA         UDF file system starting LBA.
+  @param[out] EndingLBA           UDF file system starting LBA.
+
+  @retval EFI_SUCCESS             UDF file system was found.
+  @retval other                   UDF file system was not found.
+
+**/
+EFI_STATUS
+FindUdfFileSystem (
+  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 = FindUdfVolumeIdentifiers (BlockIo, DiskIo);
+  if (EFI_ERROR (Status)) {
+    return Status;
   }
 
+  //
+  // Find Anchor Volume Descriptor Pointer
+  //
   Status = FindAnchorVolumeDescriptorPointer (BlockIo, DiskIo, &AnchorPoint);
   if (EFI_ERROR (Status)) {
-    return EFI_UNSUPPORTED;
+    return Status;
   }
 
-  return EFI_SUCCESS;
+  //
+  // Find Logical Volume location
+  //
+  Status = FindLogicalVolumeLocation (
+    BlockIo,
+    DiskIo,
+    &AnchorPoint,
+    (UINT64 *)StartingLBA,
+    (UINT64 *)EndingLBA
+    );
+
+  return Status;
 }
 
 /**
@@ -263,9 +537,9 @@ PartitionInstallUdfChildHandles (
   UINT32                       RemainderByMediaBlockSize;
   EFI_STATUS                   Status;
   EFI_BLOCK_IO_MEDIA           *Media;
-  EFI_DEVICE_PATH_PROTOCOL     *DevicePathNode;
-  EFI_GUID                     *VendorDefinedGuid;
   EFI_PARTITION_INFO_PROTOCOL  PartitionInfo;
+  EFI_LBA                      StartingLBA;
+  EFI_LBA                      EndingLBA;
 
   Media = BlockIo->Media;
 
@@ -281,35 +555,10 @@ PartitionInstallUdfChildHandles (
     return EFI_NOT_FOUND;
   }
 
-  DevicePathNode = DevicePath;
-  while (!IsDevicePathEnd (DevicePathNode)) {
-    //
-    // Do not allow checking for UDF file systems in CDROM "El Torito"
-    // partitions, and skip duplicate installation of UDF file system child
-    // nodes.
-    //
-    if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) {
-      if (DevicePathSubType (DevicePathNode) == MEDIA_CDROM_DP) {
-        return EFI_NOT_FOUND;
-      }
-      if (DevicePathSubType (DevicePathNode) == MEDIA_VENDOR_DP) {
-        VendorDefinedGuid = (EFI_GUID *)((UINTN)DevicePathNode +
-                                         OFFSET_OF (VENDOR_DEVICE_PATH, Guid));
-        if (CompareGuid (VendorDefinedGuid, &gUdfDevPathGuid)) {
-          return EFI_NOT_FOUND;
-        }
-      }
-    }
-    //
-    // Try next device path node
-    //
-    DevicePathNode = NextDevicePathNode (DevicePathNode);
-  }
-
   //
-  // Check if block device supports an UDF file system
+  // Search for an UDF file system on block device
   //
-  Status = SupportUdfFileSystem (BlockIo, DiskIo);
+  Status = FindUdfFileSystem (BlockIo, DiskIo, &StartingLBA, &EndingLBA);
   if (EFI_ERROR (Status)) {
     return EFI_NOT_FOUND;
   }
@@ -334,13 +583,10 @@ PartitionInstallUdfChildHandles (
     DevicePath,
     (EFI_DEVICE_PATH_PROTOCOL *)&gUdfDevicePath,
     &PartitionInfo,
-    0,
-    Media->LastBlock,
+    StartingLBA,
+    EndingLBA,
     Media->BlockSize
     );
-  if (!EFI_ERROR (Status)) {
-    Status = EFI_NOT_FOUND;
-  }
 
   return Status;
 }
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/File.c b/MdeModulePkg/Universal/Disk/UdfDxe/File.c
index 625f2c5637..6f07bf2066 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/File.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/File.c
@@ -131,7 +131,6 @@ Error_Alloc_Priv_File_Data:
   CleanupFileInformation (&PrivFsData->Root);
 
 Error_Find_Root_Dir:
-  CleanupVolumeInformation (&PrivFsData->Volume);
 
 Error_Read_Udf_Volume:
 Error_Invalid_Params:
@@ -429,7 +428,7 @@ UdfRead (
     }
     ASSERT (NewFileEntryData != NULL);
 
-    if (IS_FE_SYMLINK (NewFileEntryData)) {
+    if (FE_ICB_FILE_TYPE (NewFileEntryData) == UdfFileEntrySymlink) {
       Status = ResolveSymlink (
         BlockIo,
         DiskIo,
@@ -529,7 +528,6 @@ UdfClose (
   EFI_TPL                     OldTpl;
   EFI_STATUS                  Status;
   PRIVATE_UDF_FILE_DATA       *PrivFileData;
-  PRIVATE_UDF_SIMPLE_FS_DATA  *PrivFsData;
 
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 
@@ -542,8 +540,6 @@ UdfClose (
 
   PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
 
-  PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);
-
   if (!PrivFileData->IsRootDirectory) {
     CleanupFileInformation (&PrivFileData->File);
 
@@ -552,10 +548,6 @@ UdfClose (
     }
   }
 
-  if (--PrivFsData->OpenFiles == 0) {
-    CleanupVolumeInformation (&PrivFsData->Volume);
-  }
-
   FreePool ((VOID *)PrivFileData);
 
 Exit:
@@ -652,7 +644,7 @@ UdfGetPosition (
   // As per UEFI spec, if the file handle is a directory, then the current file
   // position has no meaning and the operation is not supported.
   //
-  if (IS_FID_DIRECTORY_FILE (&PrivFileData->File.FileIdentifierDesc)) {
+  if (IS_FID_DIRECTORY_FILE (PrivFileData->File.FileIdentifierDesc)) {
     return  EFI_UNSUPPORTED;
   }
 
@@ -788,7 +780,7 @@ UdfGetInfo (
   } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
     String = VolumeLabel;
 
-    FileSetDesc = PrivFsData->Volume.FileSetDescs[0];
+    FileSetDesc = &PrivFsData->Volume.FileSetDesc;
 
     OstaCompressed = &FileSetDesc->LogicalVolumeIdentifier[0];
 
@@ -847,7 +839,7 @@ UdfGetInfo (
     FileSystemInfo->Size        = FileSystemInfoLength;
     FileSystemInfo->ReadOnly    = TRUE;
     FileSystemInfo->BlockSize   =
-      LV_BLOCK_SIZE (&PrivFsData->Volume, UDF_DEFAULT_LV_NUM);
+      PrivFsData->Volume.LogicalVolDesc.LogicalBlockSize;
     FileSystemInfo->VolumeSize  = VolumeSize;
     FileSystemInfo->FreeSpace   = FreeSpaceSize;
 
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
index 5df267761f..b336ffc553 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c
@@ -38,11 +38,12 @@ FindAnchorVolumeDescriptorPointer (
   OUT  UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER  *AnchorPoint
   )
 {
-  EFI_STATUS  Status;
-  UINT32      BlockSize;
-  EFI_LBA     EndLBA;
-  EFI_LBA     DescriptorLBAs[4];
-  UINTN       Index;
+  EFI_STATUS          Status;
+  UINT32              BlockSize;
+  EFI_LBA             EndLBA;
+  EFI_LBA             DescriptorLBAs[4];
+  UINTN               Index;
+  UDF_DESCRIPTOR_TAG  *DescriptorTag;
 
   BlockSize = BlockIo->Media->BlockSize;
   EndLBA = BlockIo->Media->LastBlock;
@@ -62,10 +63,13 @@ FindAnchorVolumeDescriptorPointer (
     if (EFI_ERROR (Status)) {
       return Status;
     }
+
+    DescriptorTag = &AnchorPoint->DescriptorTag;
+
     //
     // Check if read LBA has a valid AVDP descriptor.
     //
-    if (IS_AVDP (AnchorPoint)) {
+    if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
       return EFI_SUCCESS;
     }
   }
@@ -99,148 +103,98 @@ StartMainVolumeDescriptorSequence (
   OUT  UDF_VOLUME_INFO                       *Volume
   )
 {
-  EFI_STATUS                     Status;
-  UINT32                         BlockSize;
-  UDF_EXTENT_AD                  *ExtentAd;
-  UINT64                         StartingLsn;
-  UINT64                         EndingLsn;
-  VOID                           *Buffer;
-  UDF_LOGICAL_VOLUME_DESCRIPTOR  *LogicalVolDesc;
-  UDF_PARTITION_DESCRIPTOR       *PartitionDesc;
-  UINTN                          Index;
-  UINT32                         LogicalBlockSize;
+  EFI_STATUS            Status;
+  UINT32                BlockSize;
+  UDF_EXTENT_AD         *ExtentAd;
+  EFI_LBA               SeqStartBlock;
+  EFI_LBA               SeqEndBlock;
+  BOOLEAN               StopSequence;
+  VOID                  *Buffer;
+  UDF_DESCRIPTOR_TAG    *DescriptorTag;
+  UINT32                LogicalBlockSize;
+
+  BlockSize = BlockIo->Media->BlockSize;
+  ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;
 
   //
-  // We've already found an ADVP on the volume. It contains the extent
-  // (MainVolumeDescriptorSequenceExtent) where the Main Volume Descriptor
-  // Sequence starts. Therefore, we'll look for Logical Volume Descriptors and
-  // Partitions Descriptors and save them in memory, accordingly.
-  //
-  // Note also that each descriptor will be aligned on a block size (BlockSize)
-  // boundary, so we need to read one block at a time.
+  // Allocate buffer for reading disk blocks
   //
-  BlockSize    = BlockIo->Media->BlockSize;
-  ExtentAd     = &AnchorPoint->MainVolumeDescriptorSequenceExtent;
-  StartingLsn  = (UINT64)ExtentAd->ExtentLocation;
-  EndingLsn    = StartingLsn + DivU64x32 (
-                                     (UINT64)ExtentAd->ExtentLength,
-                                     BlockSize
-                                     );
-
-  Volume->LogicalVolDescs =
-    (UDF_LOGICAL_VOLUME_DESCRIPTOR **)AllocateZeroPool (ExtentAd->ExtentLength);
-  if (Volume->LogicalVolDescs == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  Volume->PartitionDescs =
-    (UDF_PARTITION_DESCRIPTOR **)AllocateZeroPool (ExtentAd->ExtentLength);
-  if (Volume->PartitionDescs == NULL) {
-    Status = EFI_OUT_OF_RESOURCES;
-    goto Error_Alloc_Pds;
-  }
-
-  Buffer = AllocateZeroPool (BlockSize);
+  Buffer = AllocateZeroPool ((UINTN)BlockSize);
   if (Buffer == NULL) {
-    Status = EFI_OUT_OF_RESOURCES;
-    goto Error_Alloc_Buf;
+    return EFI_OUT_OF_RESOURCES;
   }
 
-  Volume->LogicalVolDescsNo  = 0;
-  Volume->PartitionDescsNo   = 0;
-
-  while (StartingLsn <= EndingLsn) {
-    Status = DiskIo->ReadDisk (
-      DiskIo,
+  //
+  // The logical partition created by Partition driver is relative to the main
+  // VDS extent location, so we start the Main Volume Descriptor Sequence at
+  // LBA 0.
+  //
+  // We don't need to check again if we have valid Volume Descriptors here since
+  // Partition driver already did.
+  //
+  SeqStartBlock = 0;
+  SeqEndBlock = SeqStartBlock + DivU64x32 ((UINT64)ExtentAd->ExtentLength,
+                                           BlockSize);
+  StopSequence = FALSE;
+  for (; SeqStartBlock < SeqEndBlock && !StopSequence; SeqStartBlock++) {
+    //
+    // Read disk block
+    //
+    Status = BlockIo->ReadBlocks (
+      BlockIo,
       BlockIo->Media->MediaId,
-      MultU64x32 (StartingLsn, BlockSize),
+      SeqStartBlock,
       BlockSize,
       Buffer
       );
     if (EFI_ERROR (Status)) {
-      goto Error_Read_Disk_Blk;
+      goto Out_Free;
     }
 
-    if (IS_TD (Buffer)) {
+    DescriptorTag = Buffer;
+
+    switch (DescriptorTag->TagIdentifier) {
+    case UdfPartitionDescriptor:
       //
-      // Found a Terminating Descriptor. Stop the sequence then.
+      // Save Partition Descriptor
       //
+      CopyMem (&Volume->PartitionDesc, Buffer, sizeof (Volume->PartitionDesc));
       break;
-    }
 
-    if (IS_LVD (Buffer)) {
+    case UdfLogicalVolumeDescriptor:
       //
-      // Found a Logical Volume Descriptor.
+      // Save Logical Volume Descriptor
       //
-      LogicalVolDesc =
-        (UDF_LOGICAL_VOLUME_DESCRIPTOR *)
-        AllocateZeroPool (sizeof (UDF_LOGICAL_VOLUME_DESCRIPTOR));
-      if (LogicalVolDesc == NULL) {
-        Status = EFI_OUT_OF_RESOURCES;
-        goto Error_Alloc_Lvd;
-      }
+      CopyMem (&Volume->LogicalVolDesc, Buffer, sizeof (Volume->LogicalVolDesc));
+      break;
 
-      CopyMem ((VOID *)LogicalVolDesc, Buffer,
-               sizeof (UDF_LOGICAL_VOLUME_DESCRIPTOR));
-      Volume->LogicalVolDescs[Volume->LogicalVolDescsNo++] = LogicalVolDesc;
-    } else if (IS_PD (Buffer)) {
-      //
-      // Found a Partition Descriptor.
-      //
-      PartitionDesc =
-        (UDF_PARTITION_DESCRIPTOR *)
-        AllocateZeroPool (sizeof (UDF_PARTITION_DESCRIPTOR));
-      if (PartitionDesc == NULL) {
-        Status = EFI_OUT_OF_RESOURCES;
-        goto Error_Alloc_Pd;
-      }
+    case UdfTerminatingDescriptor:
+      StopSequence = TRUE;
+      break;
 
-      CopyMem ((VOID *)PartitionDesc, Buffer,
-               sizeof (UDF_PARTITION_DESCRIPTOR));
-      Volume->PartitionDescs[Volume->PartitionDescsNo++] = PartitionDesc;
+    default:
+      ;
     }
-
-    StartingLsn++;
   }
 
   //
-  // When an UDF volume (revision 2.00 or higher) contains a File Entry rather
-  // than an Extended File Entry (which is not recommended as per spec), we need
-  // to make sure the size of a FE will be _at least_ 2048
-  // (UDF_LOGICAL_SECTOR_SIZE) bytes long to keep backward compatibility.
+  // Determine FE (File Entry) size
   //
-  LogicalBlockSize = LV_BLOCK_SIZE (Volume, UDF_DEFAULT_LV_NUM);
+  LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
   if (LogicalBlockSize >= UDF_LOGICAL_SECTOR_SIZE) {
-    Volume->FileEntrySize = LogicalBlockSize;
+    Volume->FileEntrySize = (UINTN)LogicalBlockSize;
   } else {
     Volume->FileEntrySize = UDF_LOGICAL_SECTOR_SIZE;
   }
 
-  FreePool (Buffer);
+  Status = EFI_SUCCESS;
 
-  return EFI_SUCCESS;
-
-Error_Alloc_Pd:
-Error_Alloc_Lvd:
-  for (Index = 0; Index < Volume->PartitionDescsNo; Index++) {
-    FreePool ((VOID *)Volume->PartitionDescs[Index]);
-  }
-
-  for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) {
-    FreePool ((VOID *)Volume->LogicalVolDescs[Index]);
-  }
-
-Error_Read_Disk_Blk:
+Out_Free:
+  //
+  // Free block read buffer
+  //
   FreePool (Buffer);
 
-Error_Alloc_Buf:
-  FreePool ((VOID *)Volume->PartitionDescs);
-  Volume->PartitionDescs = NULL;
-
-Error_Alloc_Pds:
-  FreePool ((VOID *)Volume->LogicalVolDescs);
-  Volume->LogicalVolDescs = NULL;
-
   return Status;
 }
 
@@ -262,48 +216,53 @@ GetPdFromLongAd (
   )
 {
   UDF_LOGICAL_VOLUME_DESCRIPTOR  *LogicalVolDesc;
-  UINTN                          Index;
-  UDF_PARTITION_DESCRIPTOR       *PartitionDesc;
   UINT16                         PartitionNum;
 
-  LogicalVolDesc = Volume->LogicalVolDescs[UDF_DEFAULT_LV_NUM];
+  LogicalVolDesc = &Volume->LogicalVolDesc;
 
-  switch (LV_UDF_REVISION (LogicalVolDesc)) {
+  switch (LogicalVolDesc->DomainIdentifier.Suffix.Domain.UdfRevision) {
   case 0x0102:
+  case 0x0150:
+  case 0x0200:
+  case 0x0201:
+  case 0x0250:
+  case 0x0260:
     //
-    // As per UDF 1.02 specification:
+    // UDF 1.02 specification:
     //
     // There shall be exactly one prevailing Logical Volume Descriptor recorded
     // per Volume Set. The Partition Maps field shall contain only Type 1
     // Partition Maps.
     //
-    PartitionNum = *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]);
-    break;
-  case 0x0150:
+    // UDF 1.50 through 2.60 specs say:
     //
-    // Ensure Type 1 Partition map. Other types aren't supported in this
-    // implementation.
+    // For the purpose of interchange partition maps shall be limited to
+    // Partition Map type 1, except type 2 maps as described in the document.
+    //
+    // NOTE: Only one Type 1 (Physical) Partition is supported. It has been
+    // checked already in Partition driver for existence of a single Type 1
+    // Partition map, so we don't have to double check here.
+    //
+    // Partition reference number can also be retrieved from
+    // LongAd->ExtentLocation.PartitionReferenceNumber, however the spec says
+    // it may be 0, so let's not rely on it.
     //
-    if (LogicalVolDesc->PartitionMaps[0] != 1 ||
-        LogicalVolDesc->PartitionMaps[1] != 6) {
-      return NULL;
-    }
     PartitionNum = *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]);
     break;
-  case 0x0260:
+
+  default:
     //
-    // Fall through.
+    // Unsupported UDF revision
     //
-  default:
-    PartitionNum = LongAd->ExtentLocation.PartitionReferenceNumber;
-    break;
+    return NULL;
   }
 
-  for (Index = 0; Index < Volume->PartitionDescsNo; Index++) {
-    PartitionDesc = Volume->PartitionDescs[Index];
-    if (PartitionDesc->PartitionNumber == PartitionNum) {
-      return PartitionDesc;
-    }
+  //
+  // Check if partition number matches Partition Descriptor found in Main Volume
+  // Descriptor Sequence.
+  //
+  if (Volume->PartitionDesc.PartitionNumber == PartitionNum) {
+    return &Volume->PartitionDesc;
   }
 
   return NULL;
@@ -329,13 +288,15 @@ GetLongAdLsn (
   PartitionDesc = GetPdFromLongAd (Volume, LongAd);
   ASSERT (PartitionDesc != NULL);
 
-  return (UINT64)PartitionDesc->PartitionStartingLocation +
-                 LongAd->ExtentLocation.LogicalBlockNumber;
+  return (UINT64)PartitionDesc->PartitionStartingLocation -
+    Volume->MainVdsStartLocation +
+    LongAd->ExtentLocation.LogicalBlockNumber;
 }
 
 /**
   Return logical sector number of a given Short Allocation Descriptor.
 
+  @param[in]  Volume              Volume pointer.
   @param[in]  PartitionDesc       Partition Descriptor pointer.
   @param[in]  ShortAd             Short Allocation Descriptor pointer.
 
@@ -344,14 +305,13 @@ GetLongAdLsn (
 **/
 UINT64
 GetShortAdLsn (
+  IN UDF_VOLUME_INFO                  *Volume,
   IN UDF_PARTITION_DESCRIPTOR         *PartitionDesc,
   IN UDF_SHORT_ALLOCATION_DESCRIPTOR  *ShortAd
   )
 {
-  ASSERT (PartitionDesc != NULL);
-
-  return (UINT64)PartitionDesc->PartitionStartingLocation +
-    ShortAd->ExtentPosition;
+  return (UINT64)PartitionDesc->PartitionStartingLocation -
+    Volume->MainVdsStartLocation + ShortAd->ExtentPosition;
 }
 
 /**
@@ -363,8 +323,6 @@ GetShortAdLsn (
   @param[in]  BlockIo             BlockIo interface.
   @param[in]  DiskIo              DiskIo interface.
   @param[in]  Volume              Volume information pointer.
-  @param[in]  LogicalVolDescNum   Index of Logical Volume Descriptor
-  @param[out] FileSetDesc         File Set Descriptor pointer.
 
   @retval EFI_SUCCESS             File Set Descriptor pointer found.
   @retval EFI_VOLUME_CORRUPTED    The file system structures are corrupted.
@@ -375,36 +333,42 @@ EFI_STATUS
 FindFileSetDescriptor (
   IN   EFI_BLOCK_IO_PROTOCOL    *BlockIo,
   IN   EFI_DISK_IO_PROTOCOL     *DiskIo,
-  IN   UDF_VOLUME_INFO          *Volume,
-  IN   UINTN                    LogicalVolDescNum,
-  OUT  UDF_FILE_SET_DESCRIPTOR  *FileSetDesc
+  IN   UDF_VOLUME_INFO          *Volume
   )
 {
   EFI_STATUS                     Status;
   UINT64                         Lsn;
   UDF_LOGICAL_VOLUME_DESCRIPTOR  *LogicalVolDesc;
+  UDF_DESCRIPTOR_TAG             *DescriptorTag;
 
-  LogicalVolDesc = Volume->LogicalVolDescs[LogicalVolDescNum];
+  LogicalVolDesc = &Volume->LogicalVolDesc;
   Lsn = GetLongAdLsn (Volume, &LogicalVolDesc->LogicalVolumeContentsUse);
 
   //
-  // Read extent (Long Ad).
+  // As per UDF 2.60 specification:
+  //
+  // There shall be exactly one File Set Descriptor recorded per Logical
+  // Volume.
+  //
+  // Read disk block
   //
   Status = DiskIo->ReadDisk (
     DiskIo,
     BlockIo->Media->MediaId,
     MultU64x32 (Lsn, LogicalVolDesc->LogicalBlockSize),
-    sizeof (UDF_FILE_SET_DESCRIPTOR),
-    (VOID *)FileSetDesc
+    sizeof (Volume->FileSetDesc),
+    &Volume->FileSetDesc
     );
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
+  DescriptorTag = &Volume->FileSetDesc.DescriptorTag;
+
   //
-  // Check if the read extent contains a valid FSD's tag identifier.
+  // Check if read block is a File Set Descriptor
   //
-  if (!IS_FSD (FileSetDesc)) {
+  if (DescriptorTag->TagIdentifier != UdfFileSetDescriptor) {
     return EFI_VOLUME_CORRUPTED;
   }
 
@@ -412,82 +376,6 @@ FindFileSetDescriptor (
 }
 
 /**
-  Get all File Set Descriptors for each Logical Volume Descriptor.
-
-  @param[in]      BlockIo         BlockIo interface.
-  @param[in]      DiskIo          DiskIo interface.
-  @param[in, out] Volume          Volume information pointer.
-
-  @retval EFI_SUCCESS             File Set Descriptors were got.
-  @retval EFI_OUT_OF_RESOURCES    File Set Descriptors were not got due to lack
-                                  of resources.
-  @retval other                   Error occured when finding File Set
-                                  Descriptor in Logical Volume Descriptor.
-
-**/
-EFI_STATUS
-GetFileSetDescriptors (
-  IN      EFI_BLOCK_IO_PROTOCOL  *BlockIo,
-  IN      EFI_DISK_IO_PROTOCOL   *DiskIo,
-  IN OUT  UDF_VOLUME_INFO        *Volume
-  )
-{
-  EFI_STATUS               Status;
-  UINTN                    Index;
-  UDF_FILE_SET_DESCRIPTOR  *FileSetDesc;
-  UINTN                    Count;
-
-  Volume->FileSetDescs =
-    (UDF_FILE_SET_DESCRIPTOR **)AllocateZeroPool (
-      Volume->LogicalVolDescsNo * sizeof (UDF_FILE_SET_DESCRIPTOR));
-  if (Volume->FileSetDescs == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) {
-    FileSetDesc = AllocateZeroPool (sizeof (UDF_FILE_SET_DESCRIPTOR));
-    if (FileSetDesc == NULL) {
-      Status = EFI_OUT_OF_RESOURCES;
-      goto Error_Alloc_Fsd;
-    }
-
-    //
-    // Find a FSD for this LVD.
-    //
-    Status = FindFileSetDescriptor (
-      BlockIo,
-      DiskIo,
-      Volume,
-      Index,
-      FileSetDesc
-      );
-    if (EFI_ERROR (Status)) {
-      goto Error_Find_Fsd;
-    }
-
-    //
-    // Got one. Save it.
-    //
-    Volume->FileSetDescs[Index] = FileSetDesc;
-  }
-
-  Volume->FileSetDescsNo = Volume->LogicalVolDescsNo;
-  return EFI_SUCCESS;
-
-Error_Find_Fsd:
-  Count = Index + 1;
-  for (Index = 0; Index < Count; Index++) {
-    FreePool ((VOID *)Volume->FileSetDescs[Index]);
-  }
-
-  FreePool ((VOID *)Volume->FileSetDescs);
-  Volume->FileSetDescs = NULL;
-
-Error_Alloc_Fsd:
-  return Status;
-}
-
-/**
   Read Volume and File Structure on an UDF file system.
 
   @param[in]   BlockIo            BlockIo interface.
@@ -507,9 +395,10 @@ ReadVolumeFileStructure (
 {
   EFI_STATUS                            Status;
   UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER  AnchorPoint;
+  UDF_EXTENT_AD                         *ExtentAd;
 
   //
-  // Find an AVDP.
+  // Find Anchor Volume Descriptor Pointer
   //
   Status = FindAnchorVolumeDescriptorPointer (
     BlockIo,
@@ -521,7 +410,14 @@ ReadVolumeFileStructure (
   }
 
   //
-  // AVDP has been found. Start MVDS.
+  // Save Main VDS start block number
+  //
+  ExtentAd = &AnchorPoint.MainVolumeDescriptorSequenceExtent;
+
+  Volume->MainVdsStartLocation = (UINT64)ExtentAd->ExtentLocation;
+
+  //
+  // Start Main Volume Descriptor Sequence.
   //
   Status = StartMainVolumeDescriptorSequence (
     BlockIo,
@@ -620,16 +516,19 @@ GetFileEntryData (
   OUT  UINT64  *Length
   )
 {
+  UDF_DESCRIPTOR_TAG       *DescriptorTag;
   UDF_EXTENDED_FILE_ENTRY  *ExtendedFileEntry;
   UDF_FILE_ENTRY           *FileEntry;
 
-  if (IS_EFE (FileEntryData)) {
+  DescriptorTag = FileEntryData;
+
+  if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
     ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
 
     *Length  = ExtendedFileEntry->InformationLength;
     *Data    = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
                         ExtendedFileEntry->LengthOfExtendedAttributes);
-  } else if (IS_FE (FileEntryData)) {
+  } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {
     FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
 
     *Length  = FileEntry->InformationLength;
@@ -654,16 +553,19 @@ GetAdsInformation (
   OUT  UINT64  *Length
   )
 {
+  UDF_DESCRIPTOR_TAG       *DescriptorTag;
   UDF_EXTENDED_FILE_ENTRY  *ExtendedFileEntry;
   UDF_FILE_ENTRY           *FileEntry;
 
-  if (IS_EFE (FileEntryData)) {
+  DescriptorTag = FileEntryData;
+
+  if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
     ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
 
     *Length = ExtendedFileEntry->LengthOfAllocationDescriptors;
     *AdsData = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
                         ExtendedFileEntry->LengthOfExtendedAttributes);
-  } else if (IS_FE (FileEntryData)) {
+  } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {
     FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
 
     *Length = FileEntry->LengthOfAllocationDescriptors;
@@ -850,6 +752,7 @@ GetAllocationDescriptorLsn (
     return GetLongAdLsn (Volume, (UDF_LONG_ALLOCATION_DESCRIPTOR *)Ad);
   } else if (RecordingFlags == ShortAdsSequence) {
     return GetShortAdLsn (
+      Volume,
       GetPdFromLongAd (Volume, ParentIcb),
       (UDF_SHORT_ALLOCATION_DESCRIPTOR *)Ad
       );
@@ -897,6 +800,7 @@ GetAedAdsOffset (
   VOID                              *Data;
   UINT32                            LogicalBlockSize;
   UDF_ALLOCATION_EXTENT_DESCRIPTOR  *AllocExtDesc;
+  UDF_DESCRIPTOR_TAG                *DescriptorTag;
 
   ExtentLength  = GET_EXTENT_LENGTH (RecordingFlags, Ad);
   Lsn           = GetAllocationDescriptorLsn (RecordingFlags,
@@ -909,7 +813,7 @@ GetAedAdsOffset (
     return EFI_OUT_OF_RESOURCES;
   }
 
-  LogicalBlockSize = LV_BLOCK_SIZE (Volume, UDF_DEFAULT_LV_NUM);
+  LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
 
   //
   // Read extent.
@@ -925,11 +829,14 @@ GetAedAdsOffset (
     goto Exit;
   }
 
+  AllocExtDesc = (UDF_ALLOCATION_EXTENT_DESCRIPTOR *)Data;
+
+  DescriptorTag = &AllocExtDesc->DescriptorTag;
+
   //
   // Check if read extent contains a valid tag identifier for AED.
   //
-  AllocExtDesc = (UDF_ALLOCATION_EXTENT_DESCRIPTOR *)Data;
-  if (!IS_AED (AllocExtDesc)) {
+  if (DescriptorTag->TagIdentifier != UdfAllocationExtentDescriptor) {
     Status = EFI_VOLUME_CORRUPTED;
     goto Exit;
   }
@@ -1102,7 +1009,7 @@ ReadFile (
   UINT32                  ExtentLength;
   UDF_FE_RECORDING_FLAGS  RecordingFlags;
 
-  LogicalBlockSize  = LV_BLOCK_SIZE (Volume, UDF_DEFAULT_LV_NUM);
+  LogicalBlockSize  = Volume->LogicalVolDesc.LogicalBlockSize;
   DoFreeAed         = FALSE;
 
   //
@@ -1444,7 +1351,7 @@ InternalFindFile (
   //
   // Check if parent file is really directory.
   //
-  if (!IS_FE_DIRECTORY (Parent->FileEntry)) {
+  if (FE_ICB_FILE_TYPE (Parent->FileEntry) != UdfFileEntryDirectory) {
     return EFI_NOT_FOUND;
   }
 
@@ -1489,7 +1396,7 @@ InternalFindFile (
       break;
     }
 
-    if (IS_FID_PARENT_FILE (FileIdentifierDesc)) {
+    if (FileIdentifierDesc->FileCharacteristics & PARENT_FILE) {
       //
       // This FID contains the location (FE/EFE) of the parent directory of this
       // directory (Parent), and if FileName is either ".." or "\\", then it's
@@ -1592,6 +1499,9 @@ ReadUdfVolumeInformation (
 {
   EFI_STATUS Status;
 
+  //
+  // Read all necessary UDF volume information and keep it private to the driver
+  //
   Status = ReadVolumeFileStructure (
     BlockIo,
     DiskIo,
@@ -1601,13 +1511,12 @@ ReadUdfVolumeInformation (
     return Status;
   }
 
-  Status = GetFileSetDescriptors (
-    BlockIo,
-    DiskIo,
-    Volume
-    );
+  //
+  // Find File Set Descriptor
+  //
+  Status = FindFileSetDescriptor (BlockIo, DiskIo, Volume);
   if (EFI_ERROR (Status)) {
-    CleanupVolumeInformation (Volume);
+    return Status;
   }
 
   return Status;
@@ -1644,7 +1553,7 @@ FindRootDirectory (
     BlockIo,
     DiskIo,
     Volume,
-    &Volume->FileSetDescs[0]->RootDirectoryIcb,
+    &Volume->FileSetDesc.RootDirectoryIcb,
     &File->FileEntry
     );
   if (EFI_ERROR (Status)) {
@@ -1661,7 +1570,7 @@ FindRootDirectory (
     L"\\",
     NULL,
     &Parent,
-    &Volume->FileSetDescs[0]->RootDirectoryIcb,
+    &Volume->FileSetDesc.RootDirectoryIcb,
     File
     );
   if (EFI_ERROR (Status)) {
@@ -1697,12 +1606,13 @@ FindFileEntry (
   OUT  VOID                            **FileEntry
   )
 {
-  EFI_STATUS  Status;
-  UINT64      Lsn;
-  UINT32      LogicalBlockSize;
+  EFI_STATUS          Status;
+  UINT64              Lsn;
+  UINT32              LogicalBlockSize;
+  UDF_DESCRIPTOR_TAG  *DescriptorTag;
 
   Lsn               = GetLongAdLsn (Volume, Icb);
-  LogicalBlockSize  = LV_BLOCK_SIZE (Volume, UDF_DEFAULT_LV_NUM);
+  LogicalBlockSize  = Volume->LogicalVolDesc.LogicalBlockSize;
 
   *FileEntry = AllocateZeroPool (Volume->FileEntrySize);
   if (*FileEntry == NULL) {
@@ -1723,11 +1633,14 @@ FindFileEntry (
     goto Error_Read_Disk_Blk;
   }
 
+  DescriptorTag = *FileEntry;
+
   //
   // Check if the read extent contains a valid Tag Identifier for the expected
   // FE/EFE.
   //
-  if (!IS_FE (*FileEntry) && !IS_EFE (*FileEntry)) {
+  if (DescriptorTag->TagIdentifier != UdfFileEntry &&
+      DescriptorTag->TagIdentifier != UdfExtendedFileEntry) {
     Status = EFI_VOLUME_CORRUPTED;
     goto Error_Invalid_Fe;
   }
@@ -1837,7 +1750,7 @@ FindFile (
     // If the found file is a symlink, then find its respective FE/EFE and
     // FID descriptors.
     //
-    if (IS_FE_SYMLINK (File->FileEntry)) {
+    if (FE_ICB_FILE_TYPE (File->FileEntry) == UdfFileEntrySymlink) {
       FreePool ((VOID *)File->FileIdentifierDesc);
 
       FileEntry = File->FileEntry;
@@ -1951,7 +1864,7 @@ ReadDirectoryEntry (
     // Update FidOffset to point to next FID.
     //
     ReadDirInfo->FidOffset += GetFidDescriptorLength (FileIdentifierDesc);
-  } while (IS_FID_DELETED_FILE (FileIdentifierDesc));
+  } while (FileIdentifierDesc->FileCharacteristics & DELETED_FILE);
 
   DuplicateFid (FileIdentifierDesc, FoundFid);
 
@@ -2197,43 +2110,6 @@ Error_Find_File:
 }
 
 /**
-  Clean up in-memory UDF volume information.
-
-  @param[in] Volume Volume information pointer.
-
-**/
-VOID
-CleanupVolumeInformation (
-  IN UDF_VOLUME_INFO *Volume
-  )
-{
-  UINTN Index;
-
-  if (Volume->LogicalVolDescs != NULL) {
-    for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) {
-      FreePool ((VOID *)Volume->LogicalVolDescs[Index]);
-    }
-    FreePool ((VOID *)Volume->LogicalVolDescs);
-  }
-
-  if (Volume->PartitionDescs != NULL) {
-    for (Index = 0; Index < Volume->PartitionDescsNo; Index++) {
-      FreePool ((VOID *)Volume->PartitionDescs[Index]);
-    }
-    FreePool ((VOID *)Volume->PartitionDescs);
-  }
-
-  if (Volume->FileSetDescs != NULL) {
-    for (Index = 0; Index < Volume->FileSetDescsNo; Index++) {
-      FreePool ((VOID *)Volume->FileSetDescs[Index]);
-    }
-    FreePool ((VOID *)Volume->FileSetDescs);
-  }
-
-  ZeroMem ((VOID *)Volume, sizeof (UDF_VOLUME_INFO));
-}
-
-/**
   Clean up in-memory UDF file information.
 
   @param[in] File File information pointer.
@@ -2333,6 +2209,7 @@ SetFileInfo (
   EFI_FILE_INFO            *FileInfo;
   UDF_FILE_ENTRY           *FileEntry;
   UDF_EXTENDED_FILE_ENTRY  *ExtendedFileEntry;
+  UDF_DESCRIPTOR_TAG       *DescriptorTag;
 
   //
   // Calculate the needed size for the EFI_FILE_INFO structure.
@@ -2367,7 +2244,9 @@ SetFileInfo (
     FileInfo->Attribute |= EFI_FILE_HIDDEN;
   }
 
-  if (IS_FE (File->FileEntry)) {
+  DescriptorTag = File->FileEntry;
+
+  if (DescriptorTag->TagIdentifier == UdfFileEntry) {
     FileEntry = (UDF_FILE_ENTRY *)File->FileEntry;
 
     //
@@ -2403,7 +2282,7 @@ SetFileInfo (
                                    FileEntry->AccessTime.Second;
     FileInfo->LastAccessTime.Nanosecond  =
                                    FileEntry->AccessTime.HundredsOfMicroseconds;
-  } else if (IS_EFE (File->FileEntry)) {
+  } else if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
     ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)File->FileEntry;
 
     //
@@ -2487,91 +2366,103 @@ GetVolumeSize (
   OUT  UINT64                 *FreeSpaceSize
   )
 {
-  UDF_EXTENT_AD                 ExtentAd;
-  UINT32                        LogicalBlockSize;
-  UINT64                        Lsn;
-  EFI_STATUS                    Status;
-  UDF_LOGICAL_VOLUME_INTEGRITY  *LogicalVolInt;
-  UINTN                         Index;
-  UINTN                         Length;
-  UINT32                        LsnsNo;
-
-  *VolumeSize     = 0;
-  *FreeSpaceSize  = 0;
-
-  for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) {
-    CopyMem ((VOID *)&ExtentAd,
-             (VOID *)&Volume->LogicalVolDescs[Index]->IntegritySequenceExtent,
-             sizeof (UDF_EXTENT_AD));
-    if (ExtentAd.ExtentLength == 0) {
-      continue;
-    }
+  EFI_STATUS                     Status;
+  UDF_LOGICAL_VOLUME_DESCRIPTOR  *LogicalVolDesc;
+  UDF_EXTENT_AD                  *ExtentAd;
+  UINT64                         Lsn;
+  UINT32                         LogicalBlockSize;
+  UDF_LOGICAL_VOLUME_INTEGRITY   *LogicalVolInt;
+  UDF_DESCRIPTOR_TAG             *DescriptorTag;
+  UINTN                          Index;
+  UINTN                          Length;
+  UINT32                         LsnsNo;
 
-    LogicalBlockSize = LV_BLOCK_SIZE (Volume, Index);
+  LogicalVolDesc = &Volume->LogicalVolDesc;
 
-  Read_Next_Sequence:
-    LogicalVolInt = (UDF_LOGICAL_VOLUME_INTEGRITY *)
-      AllocatePool (ExtentAd.ExtentLength);
-    if (LogicalVolInt == NULL) {
-      return EFI_OUT_OF_RESOURCES;
-    }
+  ExtentAd = &LogicalVolDesc->IntegritySequenceExtent;
+
+  if (ExtentAd->ExtentLength == 0) {
+    return EFI_VOLUME_CORRUPTED;
+  }
 
-    Lsn = (UINT64)ExtentAd.ExtentLocation;
+  LogicalVolInt = AllocatePool (ExtentAd->ExtentLength);
+  if (LogicalVolInt == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
 
-    Status = DiskIo->ReadDisk (
-      DiskIo,
-      BlockIo->Media->MediaId,
-      MultU64x32 (Lsn, LogicalBlockSize),
-      ExtentAd.ExtentLength,
-      (VOID *)LogicalVolInt
-      );
-    if (EFI_ERROR (Status)) {
-      FreePool ((VOID *)LogicalVolInt);
-      return Status;
-    }
+  //
+  // Get location of Logical Volume Integrity Descriptor
+  //
+  Lsn = (UINT64)ExtentAd->ExtentLocation - Volume->MainVdsStartLocation;
 
-    if (!IS_LVID (LogicalVolInt)) {
-      FreePool ((VOID *)LogicalVolInt);
-      return EFI_VOLUME_CORRUPTED;
-    }
+  LogicalBlockSize = LogicalVolDesc->LogicalBlockSize;
 
-    Length = LogicalVolInt->NumberOfPartitions;
-    for (Index = 0; Index < Length; Index += sizeof (UINT32)) {
-      LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
-      if (LsnsNo == 0xFFFFFFFFUL) {
-        //
-        // Size not specified.
-        //
-        continue;
-      }
+  //
+  // Read disk block
+  //
+  Status = DiskIo->ReadDisk (
+    DiskIo,
+    BlockIo->Media->MediaId,
+    MultU64x32 (Lsn, LogicalBlockSize),
+    ExtentAd->ExtentLength,
+    LogicalVolInt
+    );
+  if (EFI_ERROR (Status)) {
+    goto Out_Free;
+  }
 
-      *FreeSpaceSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
-    }
+  DescriptorTag = &LogicalVolInt->DescriptorTag;
 
-    Length = (LogicalVolInt->NumberOfPartitions * sizeof (UINT32)) << 1;
-    for (; Index < Length; Index += sizeof (UINT32)) {
-      LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
-      if (LsnsNo == 0xFFFFFFFFUL) {
-        //
-        // Size not specified.
-        //
-        continue;
-      }
+  //
+  // Check if read block is a Logical Volume Integrity Descriptor
+  //
+  if (DescriptorTag->TagIdentifier != UdfLogicalVolumeIntegrityDescriptor) {
+    Status = EFI_VOLUME_CORRUPTED;
+    goto Out_Free;
+  }
 
-      *VolumeSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
-    }
+  *VolumeSize = 0;
+  *FreeSpaceSize = 0;
 
-    CopyMem ((VOID *)&ExtentAd,(VOID *)&LogicalVolInt->NextIntegrityExtent,
-             sizeof (UDF_EXTENT_AD));
-    if (ExtentAd.ExtentLength > 0) {
-      FreePool ((VOID *)LogicalVolInt);
-      goto Read_Next_Sequence;
+  Length = LogicalVolInt->NumberOfPartitions;
+  for (Index = 0; Index < Length; Index += sizeof (UINT32)) {
+    LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
+    //
+    // Check if size is not specified
+    //
+    if (LsnsNo == 0xFFFFFFFFUL) {
+      continue;
     }
+    //
+    // Accumulate free space size
+    //
+    *FreeSpaceSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
+  }
 
-    FreePool ((VOID *)LogicalVolInt);
+  Length = LogicalVolInt->NumberOfPartitions * sizeof (UINT32) * 2;
+  for (; Index < Length; Index += sizeof (UINT32)) {
+    LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
+    //
+    // Check if size is not specified
+    //
+    if (LsnsNo == 0xFFFFFFFFUL) {
+      continue;
+    }
+    //
+    // Accumulate used volume space
+    //
+    *VolumeSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
   }
 
-  return EFI_SUCCESS;
+  Status = EFI_SUCCESS;
+
+Out_Free:
+  //
+  // Free Logical Volume Integrity Descriptor
+  //
+  FreePool (LogicalVolInt);
+
+  return Status;
 }
 
 /**
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.c b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.c
index 49dc7077b7..d4163b89ca 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.c
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.c
@@ -276,13 +276,6 @@ UdfDriverBindingStop (
       NULL
       );
 
-    //
-    // Check if there's any open file. If so, clean them up.
-    //
-    if (PrivFsData->OpenFiles > 0) {
-      CleanupVolumeInformation (&PrivFsData->Volume);
-    }
-
     FreePool ((VOID *)PrivFsData);
   }
 
diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
index 44c843fd4d..d441539d16 100644
--- a/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
+++ b/MdeModulePkg/Universal/Disk/UdfDxe/Udf.h
@@ -49,61 +49,34 @@
     { 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A }  \
   }
 
-#define UDF_DEFAULT_LV_NUM 0
-
-#define IS_PVD(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 1))
-#define IS_PD(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 5))
-#define IS_LVD(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 6))
-#define IS_TD(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 8))
-#define IS_FSD(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 256))
-#define IS_FE(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 261))
-#define IS_EFE(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 266))
-#define IS_FID(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 257))
-#define IS_AED(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 258))
-#define IS_LVID(_Pointer) \
-  ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 9))
-
-#define _GET_FILETYPE(_Pointer) \
-  (IS_FE (_Pointer) ? \
-   (((UDF_FILE_ENTRY *)(_Pointer))->IcbTag.FileType) \
-   : \
-   (((UDF_EXTENDED_FILE_ENTRY *)(_Pointer))->IcbTag.FileType))
-
-#define IS_FE_DIRECTORY(_Pointer) \
-  ((BOOLEAN)(_GET_FILETYPE (_Pointer) == 4))
-#define IS_FE_STANDARD_FILE(_Pointer) \
-  ((BOOLEAN)(_GET_FILETYPE (_Pointer) == 5))
-#define IS_FE_SYMLINK(_Pointer) \
-  ((BOOLEAN)(_GET_FILETYPE (_Pointer) == 12))
+#define FE_ICB_FILE_TYPE(_Ptr)                                      \
+  (UDF_FILE_ENTRY_TYPE)(                                            \
+    ((UDF_DESCRIPTOR_TAG *)(_Ptr))->TagIdentifier == UdfFileEntry ? \
+    ((UDF_FILE_ENTRY *)(_Ptr))->IcbTag.FileType :                   \
+    ((UDF_EXTENDED_FILE_ENTRY *)(_Ptr))->IcbTag.FileType)
+
+typedef enum {
+  UdfFileEntryDirectory = 4,
+  UdfFileEntryStandardFile = 5,
+  UdfFileEntrySymlink = 12,
+} UDF_FILE_ENTRY_TYPE;
 
 #define HIDDEN_FILE     (1 << 0)
 #define DIRECTORY_FILE  (1 << 1)
 #define DELETED_FILE    (1 << 2)
 #define PARENT_FILE     (1 << 3)
 
-#define _GET_FILE_CHARS(_Pointer) \
-  (((UDF_FILE_IDENTIFIER_DESCRIPTOR *)(_Pointer))->FileCharacteristics)
-
-#define IS_FID_HIDDEN_FILE(_Pointer) \
-  ((BOOLEAN)(_GET_FILE_CHARS (_Pointer) & HIDDEN_FILE))
-#define IS_FID_DIRECTORY_FILE(_Pointer) \
-  ((BOOLEAN)(_GET_FILE_CHARS (_Pointer) & DIRECTORY_FILE))
-#define IS_FID_DELETED_FILE(_Pointer) \
-  ((BOOLEAN)(_GET_FILE_CHARS (_Pointer) & DELETED_FILE))
-#define IS_FID_PARENT_FILE(_Pointer) \
-  ((BOOLEAN)(_GET_FILE_CHARS (_Pointer) & PARENT_FILE))
-#define IS_FID_NORMAL_FILE(_Pointer) \
-  ((BOOLEAN)(!IS_FID_DIRECTORY_FILE (_Pointer) && \
-         !IS_FID_PARENT_FILE (_Pointer)))
+#define IS_FID_HIDDEN_FILE(_Fid) \
+  (BOOLEAN)((_Fid)->FileCharacteristics & HIDDEN_FILE)
+#define IS_FID_DIRECTORY_FILE(_Fid) \
+  (BOOLEAN)((_Fid)->FileCharacteristics & DIRECTORY_FILE)
+#define IS_FID_DELETED_FILE(_Fid) \
+  (BOOLEAN)((_Fid)->FileCharacteristics & DELETED_FILE)
+#define IS_FID_PARENT_FILE(_Fid) \
+  (BOOLEAN)((_Fid)->FileCharacteristics & PARENT_FILE)
+#define IS_FID_NORMAL_FILE(_Fid) \
+  (BOOLEAN)(!IS_FID_DIRECTORY_FILE (_Fid) && \
+            !IS_FID_PARENT_FILE (_Fid))
 
 typedef enum {
   ShortAdsSequence,
@@ -152,14 +125,8 @@ typedef enum {
 #define IS_VALID_COMPRESSION_ID(_CompId) \
   ((BOOLEAN)((_CompId) == 8 || (_CompId) == 16))
 
-#define LV_BLOCK_SIZE(_Vol, _LvNum) \
-  (_Vol)->LogicalVolDescs[(_LvNum)]->LogicalBlockSize
-
 #define UDF_STANDARD_IDENTIFIER_LENGTH   5
 
-#define LV_UDF_REVISION(_Lv) \
-  *(UINT16 *)(UINTN)(_Lv)->DomainIdentifier.IdentifierSuffix
-
 #pragma pack(1)
 
 typedef struct {
@@ -186,17 +153,6 @@ typedef struct {
 #pragma pack(1)
 
 typedef struct {
-  UINT8           CharacterSetType;
-  UINT8           CharacterSetInfo[63];
-} UDF_CHAR_SPEC;
-
-typedef struct {
-  UINT8           Flags;
-  UINT8           Identifier[23];
-  UINT8           IdentifierSuffix[8];
-} UDF_ENTITY_ID;
-
-typedef struct {
   UINT16          TypeAndTimezone;
   INT16           Year;
   UINT8           Month;
@@ -210,17 +166,6 @@ typedef struct {
 } UDF_TIMESTAMP;
 
 typedef struct {
-  UINT32        LogicalBlockNumber;
-  UINT16        PartitionReferenceNumber;
-} UDF_LB_ADDR;
-
-typedef struct {
-  UINT32                           ExtentLength;
-  UDF_LB_ADDR                      ExtentLocation;
-  UINT8                            ImplementationUse[6];
-} UDF_LONG_ALLOCATION_DESCRIPTOR;
-
-typedef struct {
   UDF_DESCRIPTOR_TAG                 DescriptorTag;
   UINT32                             PrevAllocationExtentDescriptor;
   UINT32                             LengthOfAllocationDescriptors;
@@ -235,6 +180,17 @@ typedef struct {
 } UDF_VOLUME_DESCRIPTOR;
 
 typedef struct {
+  UDF_DESCRIPTOR_TAG             DescriptorTag;
+  UDF_TIMESTAMP                  RecordingDateTime;
+  UINT32                         IntegrityType;
+  UDF_EXTENT_AD                  NextIntegrityExtent;
+  UINT8                          LogicalVolumeContentsUse[32];
+  UINT32                         NumberOfPartitions;
+  UINT32                         LengthOfImplementationUse;
+  UINT8                          Data[0];
+} UDF_LOGICAL_VOLUME_INTEGRITY;
+
+typedef struct {
   UDF_DESCRIPTOR_TAG         DescriptorTag;
   UINT32                     VolumeDescriptorSequenceNumber;
   UINT16                     PartitionFlags;
@@ -251,33 +207,6 @@ typedef struct {
 
 typedef struct {
   UDF_DESCRIPTOR_TAG              DescriptorTag;
-  UINT32                          VolumeDescriptorSequenceNumber;
-  UDF_CHAR_SPEC                   DescriptorCharacterSet;
-  UINT8                           LogicalVolumeIdentifier[128];
-  UINT32                          LogicalBlockSize;
-  UDF_ENTITY_ID                   DomainIdentifier;
-  UDF_LONG_ALLOCATION_DESCRIPTOR  LogicalVolumeContentsUse;
-  UINT32                          MapTableLength;
-  UINT32                          NumberOfPartitionMaps;
-  UDF_ENTITY_ID                   ImplementationIdentifier;
-  UINT8                           ImplementationUse[128];
-  UDF_EXTENT_AD                   IntegritySequenceExtent;
-  UINT8                           PartitionMaps[6];
-} UDF_LOGICAL_VOLUME_DESCRIPTOR;
-
-typedef struct {
-  UDF_DESCRIPTOR_TAG             DescriptorTag;
-  UDF_TIMESTAMP                  RecordingDateTime;
-  UINT32                         IntegrityType;
-  UDF_EXTENT_AD                  NextIntegrityExtent;
-  UINT8                          LogicalVolumeContentsUse[32];
-  UINT32                         NumberOfPartitions;
-  UINT32                         LengthOfImplementationUse;
-  UINT8                          Data[0];
-} UDF_LOGICAL_VOLUME_INTEGRITY;
-
-typedef struct {
-  UDF_DESCRIPTOR_TAG              DescriptorTag;
   UDF_TIMESTAMP                   RecordingDateAndTime;
   UINT16                          InterchangeLevel;
   UINT16                          MaximumInterchangeLevel;
@@ -389,12 +318,10 @@ typedef struct {
 // UDF filesystem driver's private data
 //
 typedef struct {
-  UDF_LOGICAL_VOLUME_DESCRIPTOR  **LogicalVolDescs;
-  UINTN                          LogicalVolDescsNo;
-  UDF_PARTITION_DESCRIPTOR       **PartitionDescs;
-  UINTN                          PartitionDescsNo;
-  UDF_FILE_SET_DESCRIPTOR        **FileSetDescs;
-  UINTN                          FileSetDescsNo;
+  UINT64                         MainVdsStartLocation;
+  UDF_LOGICAL_VOLUME_DESCRIPTOR  LogicalVolDesc;
+  UDF_PARTITION_DESCRIPTOR       PartitionDesc;
+  UDF_FILE_SET_DESCRIPTOR        FileSetDesc;
   UINTN                          FileEntrySize;
 } UDF_VOLUME_INFO;
 
@@ -884,17 +811,6 @@ ResolveSymlink (
   );
 
 /**
-  Clean up in-memory UDF volume information.
-
-  @param[in] Volume Volume information pointer.
-
-**/
-VOID
-CleanupVolumeInformation (
-  IN UDF_VOLUME_INFO *Volume
-  );
-
-/**
   Clean up in-memory UDF file information.
 
   @param[in] File File information pointer.
-- 
2.13.3.windows.1



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 0/2] UDF partition driver fix
  2017-09-22 18:11 [PATCH v4 0/2] UDF partition driver fix Paulo Alcantara
  2017-09-22 18:11 ` [PATCH v4 1/2] MdePkg: Add UDF volume structure definitions Paulo Alcantara
  2017-09-22 18:11 ` [PATCH v4 2/2] MdeModulePkg/UDF: Fix creation of UDF logical partition Paulo Alcantara
@ 2017-09-25  0:31 ` Ni, Ruiyu
  2017-09-25  7:38   ` Zeng, Star
  2 siblings, 1 reply; 5+ messages in thread
From: Ni, Ruiyu @ 2017-09-25  0:31 UTC (permalink / raw)
  To: Paulo Alcantara, edk2-devel@lists.01.org
  Cc: Kinney, Michael D, Gao, Liming, Laszlo Ersek, Zeng, Star,
	Yao, Jiewen

Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>

-----Original Message-----
From: Paulo Alcantara [mailto:pcacjr@zytor.com] 
Sent: Saturday, September 23, 2017 2:12 AM
To: edk2-devel@lists.01.org
Cc: Paulo Alcantara <pcacjr@zytor.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming <liming.gao@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ni, Ruiyu <ruiyu.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Subject: [PATCH v4 0/2] UDF partition driver fix

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=707

Hi,

This patchset fixes a bug in Partition driver that created UDF logical partitions by using entire block device space and thus polluting protocol database with broken handles.

v1->v2:
 - Followed Laszlo's suggestions to submit a proper patchset. Thanks!
 - As I'm still waiting for Ruiyu and Star to test this fix, I took
   advantage of it and did some code cleanups :-)

v2->v3:
 - Followed Ruiyu's suggestions to improve code and add additional
   checks for ensuring a valid UDF file system and supported by current
   EDK2 UDF file system implementation. Also run Ecc.py to make sure the
   files I touched did not break EDK2 C Coding Style, as well as
   PatchCheck.py for mal-formed patches.

v3->v4:
 - Change 2/2's title as suggested by Star.
 - Remove UDF_TAG_ID() and refactor out UDF_ENTITY_ID structure as
   suggested by Ruiyu.
 - Tested build with VS2015 toolchain.

I've had a chance to test these changes with my 32GiB USB stick and formatted it on Windows 10 with `format` command. The UDF revisions I tested (by specifying it with "/R:revision") were 1.02, 1.50, 2.00,
2.01 (default) and 2.50. They all worked except the 2.50 revision which adds a Type 2 (Metadata) Partition and it's not supported by current
EDK2 UDF implementation -- which handles only Type 1 (Physical) Partitions. The UDF 2.60 revision I tested with the usual `sudo mkudffs -b 512 --media-type=hd /dev/sdX` command in Linux.

Remember, the *officially* supported revision is 2.60, however all revisions use the same volume structures as defined by ECMA 167 specification, and they usually differ from each other by means of new optional features, so that's why all those revisions worked with this implementation.

Well, at least this what I understood when looking at the specifications. Please correct me if I'm wrong.

Please, test building these changes in toolchains other than GCC and make sure they don't break the world :-)

Thanks!
Paulo

Repo:   https://github.com/pcacjr/edk2.git
Branch: udf-partition-fix-v4

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Reported-by: Ruiyu Ni <ruiyu.ni@intel.com>
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
---

Paulo Alcantara (2):
  MdePkg: Add UDF volume structure definitions
  MdeModulePkg/UDF: Fix creation of UDF logical partition

 MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c            | 366 ++++++++++--
 MdeModulePkg/Universal/Disk/UdfDxe/File.c                 |  16 +-
 MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 ++++++++------------
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c                  |   7 -
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.h                  | 158 ++---
 MdePkg/Include/IndustryStandard/Udf.h                     |  97 ++-
 6 files changed, 698 insertions(+), 573 deletions(-)

--
2.13.3.windows.1



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 0/2] UDF partition driver fix
  2017-09-25  0:31 ` [PATCH v4 0/2] UDF partition driver fix Ni, Ruiyu
@ 2017-09-25  7:38   ` Zeng, Star
  0 siblings, 0 replies; 5+ messages in thread
From: Zeng, Star @ 2017-09-25  7:38 UTC (permalink / raw)
  To: Ni, Ruiyu, Paulo Alcantara, edk2-devel@lists.01.org
  Cc: Kinney, Michael D, Gao, Liming, Laszlo Ersek, Yao, Jiewen,
	Zeng, Star

Pushed at https://github.com/tianocore/edk2/compare/e921f58d4458...baaa3cee1eaf.
Thanks all. :)

Star
-----Original Message-----
From: Ni, Ruiyu 
Sent: Monday, September 25, 2017 8:31 AM
To: Paulo Alcantara <pcacjr@zytor.com>; edk2-devel@lists.01.org
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming <liming.gao@intel.com>; Laszlo Ersek <lersek@redhat.com>; Zeng, Star <star.zeng@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Subject: RE: [PATCH v4 0/2] UDF partition driver fix

Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>

-----Original Message-----
From: Paulo Alcantara [mailto:pcacjr@zytor.com] 
Sent: Saturday, September 23, 2017 2:12 AM
To: edk2-devel@lists.01.org
Cc: Paulo Alcantara <pcacjr@zytor.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming <liming.gao@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ni, Ruiyu <ruiyu.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Subject: [PATCH v4 0/2] UDF partition driver fix

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=707

Hi,

This patchset fixes a bug in Partition driver that created UDF logical partitions by using entire block device space and thus polluting protocol database with broken handles.

v1->v2:
 - Followed Laszlo's suggestions to submit a proper patchset. Thanks!
 - As I'm still waiting for Ruiyu and Star to test this fix, I took
   advantage of it and did some code cleanups :-)

v2->v3:
 - Followed Ruiyu's suggestions to improve code and add additional
   checks for ensuring a valid UDF file system and supported by current
   EDK2 UDF file system implementation. Also run Ecc.py to make sure the
   files I touched did not break EDK2 C Coding Style, as well as
   PatchCheck.py for mal-formed patches.

v3->v4:
 - Change 2/2's title as suggested by Star.
 - Remove UDF_TAG_ID() and refactor out UDF_ENTITY_ID structure as
   suggested by Ruiyu.
 - Tested build with VS2015 toolchain.

I've had a chance to test these changes with my 32GiB USB stick and formatted it on Windows 10 with `format` command. The UDF revisions I tested (by specifying it with "/R:revision") were 1.02, 1.50, 2.00,
2.01 (default) and 2.50. They all worked except the 2.50 revision which adds a Type 2 (Metadata) Partition and it's not supported by current
EDK2 UDF implementation -- which handles only Type 1 (Physical) Partitions. The UDF 2.60 revision I tested with the usual `sudo mkudffs -b 512 --media-type=hd /dev/sdX` command in Linux.

Remember, the *officially* supported revision is 2.60, however all revisions use the same volume structures as defined by ECMA 167 specification, and they usually differ from each other by means of new optional features, so that's why all those revisions worked with this implementation.

Well, at least this what I understood when looking at the specifications. Please correct me if I'm wrong.

Please, test building these changes in toolchains other than GCC and make sure they don't break the world :-)

Thanks!
Paulo

Repo:   https://github.com/pcacjr/edk2.git
Branch: udf-partition-fix-v4

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Reported-by: Ruiyu Ni <ruiyu.ni@intel.com>
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
---

Paulo Alcantara (2):
  MdePkg: Add UDF volume structure definitions
  MdeModulePkg/UDF: Fix creation of UDF logical partition

 MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c            | 366 ++++++++++--
 MdeModulePkg/Universal/Disk/UdfDxe/File.c                 |  16 +-
 MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 ++++++++------------
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c                  |   7 -
 MdeModulePkg/Universal/Disk/UdfDxe/Udf.h                  | 158 ++---
 MdePkg/Include/IndustryStandard/Udf.h                     |  97 ++-
 6 files changed, 698 insertions(+), 573 deletions(-)

--
2.13.3.windows.1



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-09-25  7:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-22 18:11 [PATCH v4 0/2] UDF partition driver fix Paulo Alcantara
2017-09-22 18:11 ` [PATCH v4 1/2] MdePkg: Add UDF volume structure definitions Paulo Alcantara
2017-09-22 18:11 ` [PATCH v4 2/2] MdeModulePkg/UDF: Fix creation of UDF logical partition Paulo Alcantara
2017-09-25  0:31 ` [PATCH v4 0/2] UDF partition driver fix Ni, Ruiyu
2017-09-25  7:38   ` Zeng, Star

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox