diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
index 5a7d119b43..f6030e0897 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
@@ -1,7 +1,7 @@
/** @file
Partition driver that produces logical BlockIo devices from a physical
BlockIo device. The logical BlockIo devices are based on the format
- of the raw block devices media. Currently "El Torito CD-ROM", Legacy
+ of the raw block devices media. Currently "El Torito CD-ROM", UDF, Legacy
MBR, and GPT partition schemes are supported.
Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
@@ -45,6 +45,7 @@ PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
PartitionInstallGptChildHandles,
PartitionInstallElToritoChildHandles,
PartitionInstallMbrChildHandles,
+ PartitionInstallUdfChildHandles,
NULL
};
@@ -305,9 +306,9 @@ PartitionDriverBindingStart (
if (BlockIo->Media->MediaPresent ||
(BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) {
//
- // Try for GPT, then El Torito, and then legacy MBR partition types. If the
- // media supports a given partition type install child handles to represent
- // the partitions described by the media.
+ // Try for GPT, then El Torito, then UDF, and then legacy MBR partition
+ // types. If the media supports a given partition type install child handles
+ // to represent the partitions described by the media.
//
Routine = &mPartitionDetectRoutineTable[0];
while (*Routine != NULL) {
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
index f2f6185317..c763c676a9 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
@@ -1,7 +1,7 @@
/** @file
Partition driver that produces logical BlockIo devices from a physical
BlockIo device. The logical BlockIo devices are based on the format
- of the raw block devices media. Currently "El Torito CD-ROM", Legacy
+ of the raw block devices media. Currently "El Torito CD-ROM", UDF, Legacy
MBR, and GPT partition schemes are supported.
Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
@@ -39,7 +39,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include
#include
-
+#include
//
// Partition private data
@@ -445,6 +445,34 @@ PartitionInstallMbrChildHandles (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
);
+/**
+ Install child handles if the Handle supports UDF/ECMA-167 volume format.
+
+ @param[in] This Calling context.
+ @param[in] Handle Parent Handle.
+ @param[in] DiskIo Parent DiskIo interface.
+ @param[in] DiskIo2 Parent DiskIo2 interface.
+ @param[in] BlockIo Parent BlockIo interface.
+ @param[in] BlockIo2 Parent BlockIo2 interface.
+ @param[in] DevicePath Parent Device Path
+
+
+ @retval EFI_SUCCESS Child handle(s) was added.
+ @retval EFI_MEDIA_CHANGED Media changed Detected.
+ @retval other no child handle was added.
+
+**/
+EFI_STATUS
+PartitionInstallUdfChildHandles (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
typedef
EFI_STATUS
(*PARTITION_DETECT_ROUTINE) (
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf b/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
index 48212773e8..fb2ea87a9d 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
@@ -4,7 +4,7 @@
# This module produces the logical Block I/O device that represents
# the bytes from Start to End of the Parent Block I/O device.
# The partition of physical BlockIo device supported is one of legacy MBR, GPT,
-# and "El Torito" partitions.
+# UDF and "El Torito" partitions.
#
# Caution: This module requires additional review when modified.
# This driver will have external input - disk partition.
@@ -46,6 +46,7 @@
Mbr.c
Gpt.c
ElTorito.c
+ Udf.c
Partition.c
Partition.h
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
new file mode 100644
index 0000000000..c1d44809bf
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
@@ -0,0 +1,318 @@
+/** @file
+ Scan for an UDF file system on a formatted media.
+
+ Copyright (C) 2014-2017 Paulo Alcantara
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "Partition.h"
+
+//
+// C5BD4D42-1A76-4996-8956-73CDA326CD0A
+//
+#define EFI_UDF_DEVICE_PATH_GUID \
+ { 0xC5BD4D42, 0x1A76, 0x4996, \
+ { 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A } \
+ }
+
+typedef struct {
+ VENDOR_DEVICE_PATH DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} UDF_DEVICE_PATH;
+
+//
+// Vendor-Defined Media Device Path for UDF file system
+//
+UDF_DEVICE_PATH gUdfDevicePath = {
+ { { MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,
+ { sizeof (VENDOR_DEVICE_PATH), 0 } },
+ EFI_UDF_DEVICE_PATH_GUID
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+ }
+};
+
+EFI_STATUS
+FindAnchorVolumeDescriptorPointer (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint
+ )
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize = BlockIo->Media->BlockSize;
+ EFI_LBA EndLBA = BlockIo->Media->LastBlock;
+ EFI_LBA DescriptorLBAs[] = { 256, EndLBA - 256, EndLBA, 512 };
+ UINTN Index;
+
+ 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;
+ }
+ //
+ // Check if read LBA has a valid AVDP descriptor.
+ //
+ if (IS_AVDP (AnchorPoint)) {
+ return EFI_SUCCESS;
+ }
+ }
+ //
+ // No AVDP found.
+ //
+ return EFI_VOLUME_CORRUPTED;
+}
+
+/**
+ Check if block device supports a valid UDF file system as specified by OSTA
+ 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 (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Offset;
+ UINT64 EndDiskOffset;
+ CDROM_VOLUME_DESCRIPTOR VolDescriptor;
+ CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor;
+ UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;
+
+ ZeroMem ((VOID *)&TerminatingVolDescriptor, sizeof (CDROM_VOLUME_DESCRIPTOR));
+
+ //
+ // Start Volume Recognition Sequence
+ //
+ EndDiskOffset = MultU64x32 (BlockIo->Media->LastBlock,
+ BlockIo->Media->BlockSize);
+
+ for (Offset = UDF_VRS_START_OFFSET; Offset < EndDiskOffset;
+ Offset += UDF_LOGICAL_SECTOR_SIZE) {
+ //
+ // Check if block device has a Volume Structure Descriptor and an Extended
+ // Area.
+ //
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ Offset,
+ sizeof (CDROM_VOLUME_DESCRIPTOR),
+ (VOID *)&VolDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
+ (VOID *)UDF_BEA_IDENTIFIER,
+ sizeof (VolDescriptor.Unknown.Id)) == 0) {
+ break;
+ }
+
+ if ((CompareMem ((VOID *)VolDescriptor.Unknown.Id,
+ (VOID *)CDVOL_ID,
+ sizeof (VolDescriptor.Unknown.Id)) != 0) ||
+ (CompareMem ((VOID *)&VolDescriptor,
+ (VOID *)&TerminatingVolDescriptor,
+ sizeof (CDROM_VOLUME_DESCRIPTOR)) == 0)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Look for "NSR0{2,3}" identifiers in the Extended Area.
+ //
+ Offset += UDF_LOGICAL_SECTOR_SIZE;
+ if (Offset >= EndDiskOffset) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ Offset,
+ sizeof (CDROM_VOLUME_DESCRIPTOR),
+ (VOID *)&VolDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((CompareMem ((VOID *)VolDescriptor.Unknown.Id,
+ (VOID *)UDF_NSR2_IDENTIFIER,
+ sizeof (VolDescriptor.Unknown.Id)) != 0) &&
+ (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
+ (VOID *)UDF_NSR3_IDENTIFIER,
+ sizeof (VolDescriptor.Unknown.Id)) != 0)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Look for "TEA01" identifier in the Extended Area
+ //
+ Offset += UDF_LOGICAL_SECTOR_SIZE;
+ if (Offset >= EndDiskOffset) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ Offset,
+ sizeof (CDROM_VOLUME_DESCRIPTOR),
+ (VOID *)&VolDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
+ (VOID *)UDF_TEA_IDENTIFIER,
+ sizeof (VolDescriptor.Unknown.Id)) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = FindAnchorVolumeDescriptorPointer (BlockIo, DiskIo, &AnchorPoint);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Install child handles if the Handle supports UDF/ECMA-167 volume format.
+
+ @param[in] This Calling context.
+ @param[in] Handle Parent Handle.
+ @param[in] DiskIo Parent DiskIo interface.
+ @param[in] DiskIo2 Parent DiskIo2 interface.
+ @param[in] BlockIo Parent BlockIo interface.
+ @param[in] BlockIo2 Parent BlockIo2 interface.
+ @param[in] DevicePath Parent Device Path
+
+
+ @retval EFI_SUCCESS Child handle(s) was added.
+ @retval EFI_MEDIA_CHANGED Media changed Detected.
+ @retval other no child handle was added.
+
+**/
+EFI_STATUS
+PartitionInstallUdfChildHandles (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
+ EFI_GUID *VendorDefinedGuid;
+ EFI_GUID UdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;
+ EFI_PARTITION_INFO_PROTOCOL PartitionInfo;
+
+ Media = BlockIo->Media;
+
+ //
+ // Check if UDF logical block size is multiple of underlying device block size
+ //
+ if ((UDF_LOGICAL_SECTOR_SIZE % Media->BlockSize) != 0 ||
+ Media->BlockSize > UDF_LOGICAL_SECTOR_SIZE) {
+ 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, &UdfDevPathGuid)) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ }
+ //
+ // Try next device path node
+ //
+ DevicePathNode = NextDevicePathNode (DevicePathNode);
+ }
+
+ //
+ // Check if block device supports an UDF file system
+ //
+ Status = SupportUdfFileSystem (BlockIo, DiskIo);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Create Partition Info protocol for UDF file system
+ //
+ ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
+ PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
+ PartitionInfo.Type = PARTITION_TYPE_OTHER;
+
+ //
+ // Install partition child handle for UDF file system
+ //
+ Status = PartitionInstallChildHandle (
+ This,
+ Handle,
+ DiskIo,
+ DiskIo2,
+ BlockIo,
+ BlockIo2,
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUdfDevicePath,
+ &PartitionInfo,
+ 0,
+ Media->LastBlock,
+ Media->BlockSize
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ }
+
+ return Status;
+}