This patch adds support to finding UDF/ECMA-167 volumes on disks by looking at
the UDF Standard Identifiers (BEA01, NSR02/NSR03, TEA01) and the Anchor Volume
Descriptor Pointer (AVDP) at LBAs 256, N - 256 or N.
A new PcdsFeatureFlags (PcdUdfFileSystemSupport) has been added to
enable/disable such support -- it's disabled by default.
I'm currently using VENDOR_DEVICE_PATH for UDF since there isn't any defined for
it yet. Should we create one specific for it? Or should we keep using
VENDOR_DEVICE_PATH?
The tests were run under QEMU + OVMF:
$ qemu-kvm -m 1024 -L . -hda fat:hdd \
file=/dev/sdb,if=virtio,media=disk,cache=writeback \
-net none
Where /dev/sdb is a external HDD previously formatted as an UDF filesystem
through the following command:
$ mkudffs -b 512 --media-type=hd /dev/sdb
Besides, I've made a good progress on the filesystem driver (UdfDxe). It now
supports symlinks, handle inodes which are either File Entry or Extended File
Entry, handle both long and short allocation descriptors, as well as the usual
things: open, read and list files. I'm not going to send it now because I need
to test it more, rework the commit messages and a few cleanups which are always
good :-)
My development branches:
git://git.zytor.com/users/pcacjr/edk2.git partitiondxe (PartitionDxe)
git://git.zytor.com/users/pcacjr/edk2.git udf-next (UdfDxe)
Thanks,
-pcacjr
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Paulo Alcantara <[email protected]>
---
MdeModulePkg/MdeModulePkg.dec | 6 +
.../Universal/Disk/PartitionDxe/Partition.c | 1 +
.../Universal/Disk/PartitionDxe/Partition.h | 29 +++
.../Universal/Disk/PartitionDxe/PartitionDxe.inf | 9 +-
MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 277 +++++++++++++++++++++
MdePkg/Include/IndustryStandard/Udf.h | 88 +++++++
6 files changed, 409 insertions(+), 1 deletion(-)
create mode 100644 MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
create mode 100644 MdePkg/Include/IndustryStandard/Udf.h
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 60fb209..e320e1b 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -597,6 +597,12 @@
# @Prompt Enable S3 performance data support.
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwarePerformanceDataTableS3Support|TRUE|BOOLEAN|0x00010064
+ ## Indicates if UDF/ECMA-167 filesystem will be supported.<BR><BR>
+ # TRUE - UDF/ECMA-167 filesystem will be supported.<BR>
+ # FALSE - UDF/ECMA-167 filesystem will not be supported.<BR>
+ # @Prompt Enable UDF/ECMA-167 filesystem support.
+
gEfiMdeModulePkgTokenSpaceGuid.PcdUdfFileSystemSupport|FALSE|BOOLEAN|0x00010069
+
[PcdsFeatureFlag.IA32, PcdsFeatureFlag.X64]
## Indicates if DxeIpl should switch to long mode to enter DXE phase.
# It is assumed that 64-bit DxeCore is built in firmware if it is true;
otherwise 32-bit DxeCore
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
index 28639b0..27e460f 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
@@ -45,6 +45,7 @@ PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
PartitionInstallGptChildHandles,
PartitionInstallElToritoChildHandles,
PartitionInstallMbrChildHandles,
+ PartitionInstallUdfChildHandles,
NULL
};
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
index 06470f6..26107f0 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
@@ -38,6 +38,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
EXPRESS OR IMPLIED.
#include <IndustryStandard/Mbr.h>
#include <IndustryStandard/ElTorito.h>
+#include <IndustryStandard/Udf.h>
//
@@ -428,6 +429,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 6806263..1ce9b44 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
@@ -46,13 +46,14 @@
Mbr.c
Gpt.c
ElTorito.c
+ Udf.c
Partition.c
Partition.h
[Packages]
MdePkg/MdePkg.dec
-
+ MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
DevicePathLib
@@ -63,6 +64,7 @@
BaseLib
UefiDriverEntryPoint
DebugLib
+ PcdLib
[Guids]
@@ -85,5 +87,10 @@
gEfiDiskIoProtocolGuid ## TO_START
gEfiDiskIo2ProtocolGuid ## TO_START
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUdfFileSystemSupport ## CONSUMES
+
+
[UserExtensions.TianoCore."ExtraFiles"]
PartitionDxeExtra.uni
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
new file mode 100644
index 0000000..4c2fc4f
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c
@@ -0,0 +1,277 @@
+/** @file
+ Decode an UDF/ECMA-167 formatted medium
+
+Copyright (c) 2014 Paulo Alcantara <[email protected]><BR>
+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"
+
+
+EFI_GUID gUdfVolumeSignatureGuid = {
+ 0xC5BD4D42, 0x1A76, 0x4996,
+ { 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A }
+};
+
+UDF_STANDARD_IDENTIFIER gUdfStandardIdentifiers[NR_STANDARD_IDENTIFIERS] = {
+ { { 'B', 'E', 'A', '0', '1' } },
+ { { 'N', 'S', 'R', '0', '2' } },
+ { { 'N', 'S', 'R', '0', '3' } },
+ { { 'T', 'E', 'A', '0', '1' } },
+};
+
+typedef struct {
+ VENDOR_DEVICE_PATH DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} UDF_DEVICE_PATH;
+
+//
+// C5BD4D42-1A76-4996-8956-73CDA326CD0A
+//
+#define EFI_UDF_DEVICE_PATH_GUID \
+ { 0xC5BD4D42, 0x1A76, 0x4996, \
+ { 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A } \
+ }
+
+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;
+ EFI_LBA EndLBA;
+
+ BlockSize = BlockIo->Media->BlockSize;
+ EndLBA = BlockIo->Media->LastBlock;
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (0x100ULL, BlockSize),
+ sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),
+ (VOID *) AnchorPoint
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ Status = EFI_VOLUME_CORRUPTED;
+ if (IS_AVDP (AnchorPoint)) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (EndLBA - 0x100ULL, BlockSize),
+ sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),
+ (VOID *) AnchorPoint
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ if (IS_AVDP (AnchorPoint)) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32 (EndLBA, BlockSize),
+ sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),
+ (VOID *) AnchorPoint
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ if (IS_AVDP (AnchorPoint)) {
+ Status = EFI_SUCCESS;
+ }
+
+Exit:
+ return Status;
+}
+
+EFI_STATUS
+IsSupportedUdfVolume (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ OUT BOOLEAN *Supported
+ )
+{
+ EFI_STATUS Status;
+ UDF_NSR_DESCRIPTOR NsrDescriptor;
+ UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;
+
+ *Supported = FALSE;
+ //
+ // Start Volume Recognition Sequence
+ //
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ BEA_DESCRIPTOR_LSN_OFFSET,
+ sizeof (UDF_NSR_DESCRIPTOR),
+ (VOID *) &NsrDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ if (CompareMem (
+ (VOID *) &NsrDescriptor.StandardIdentifier,
+ (VOID *) &gUdfStandardIdentifiers[BEA_IDENTIFIER],
+ UDF_STANDARD_IDENTIFIER_LENGTH
+ )
+ ) {
+ goto Exit;
+ }
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ BEA_DESCRIPTOR_LSN_OFFSET + LOGICAL_SECTOR_SIZE,
+ sizeof (UDF_NSR_DESCRIPTOR),
+ (VOID *) &NsrDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ if (CompareMem (
+ (VOID *) &NsrDescriptor.StandardIdentifier,
+ (VOID *) &gUdfStandardIdentifiers[VSD_IDENTIFIER_0],
+ UDF_STANDARD_IDENTIFIER_LENGTH
+ )
+ &&
+ CompareMem (
+ (VOID *) &NsrDescriptor.StandardIdentifier,
+ (VOID *) &gUdfStandardIdentifiers[VSD_IDENTIFIER_1],
+ UDF_STANDARD_IDENTIFIER_LENGTH
+ )
+ ) {
+ goto Exit;
+ }
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ BEA_DESCRIPTOR_LSN_OFFSET + (LOGICAL_SECTOR_SIZE << 1),
+ sizeof (UDF_NSR_DESCRIPTOR),
+ (VOID *)&NsrDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ if (CompareMem (
+ (VOID *) &NsrDescriptor.StandardIdentifier,
+ (VOID *) &gUdfStandardIdentifiers[TEA_IDENTIFIER],
+ UDF_STANDARD_IDENTIFIER_LENGTH
+ )
+ ) {
+ goto Exit;
+ }
+
+ Status = FindAnchorVolumeDescriptorPointer (BlockIo, DiskIo, &AnchorPoint);
+ if (!EFI_ERROR (Status)) {
+ *Supported = TRUE;
+ }
+
+Exit:
+ return Status;
+}
+
+/**
+ 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;
+ BOOLEAN Supported;
+ EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
+ EFI_GUID *VendorDevGuid;
+ EFI_GUID UdfDevGuid = EFI_UDF_DEVICE_PATH_GUID;
+
+ if (!FeaturePcdGet (PcdUdfFileSystemSupport)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = IsSupportedUdfVolume (BlockIo, DiskIo, &Supported);
+ if (EFI_ERROR (Status) || !Supported) {
+ return EFI_NOT_FOUND;
+ }
+
+ LastDevicePathNode = NULL;
+ DevicePathNode = DevicePath;
+ while (!IsDevicePathEnd (DevicePathNode)) {
+ LastDevicePathNode = DevicePathNode;
+ DevicePathNode = NextDevicePathNode (DevicePathNode);
+ }
+ if (LastDevicePathNode) {
+ VendorDevGuid = (EFI_GUID *) ((UINT8 *) LastDevicePathNode + OFFSET_OF
(VENDOR_DEVICE_PATH, Guid));
+ if (DevicePathSubType (LastDevicePathNode) == MEDIA_VENDOR_DP &&
+ CompareGuid (VendorDevGuid, &UdfDevGuid)) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ Status = PartitionInstallChildHandle (
+ This,
+ Handle,
+ DiskIo,
+ DiskIo2,
+ BlockIo,
+ BlockIo2,
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)
&gUdfDevicePath,
+ 0,
+ BlockIo->Media->LastBlock,
+ BlockIo->Media->BlockSize,
+ FALSE
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ }
+ return Status;
+}
diff --git a/MdePkg/Include/IndustryStandard/Udf.h
b/MdePkg/Include/IndustryStandard/Udf.h
new file mode 100644
index 0000000..8b41d05
--- /dev/null
+++ b/MdePkg/Include/IndustryStandard/Udf.h
@@ -0,0 +1,88 @@
+/** @file
+ UDF/ECMA-167 Volume and File Structure Format Definition.
+
+Copyright (c) 2014 Paulo Alcantara <[email protected]><BR>
+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.
+
+**/
+
+#ifndef _UDF_H_
+#define _UDF_H_
+
+//
+// As specified in ECMA-167 specification, the logical sector size shall be
+// 2048 bytes.
+//
+#define LOGICAL_SECTOR_SIZE ((UINT64) 0x0000000000000800ULL)
+#define FIRST_ANCHOR_POINT_LSN ((UINT64) 0x0000000000000100ULL)
+#define BEA_DESCRIPTOR_LSN_OFFSET ((UINT64) 0x0000000000008000ULL)
+#define UDF_STANDARD_IDENTIFIER_LENGTH 5
+
+#define _GET_TAG_ID(_Pointer) \
+ (((UDF_DESCRIPTOR_TAG *) (_Pointer))->TagIdentifier)
+
+#define IS_PVD(_Pointer) \
+ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 1))
+#define IS_AVDP(_Pointer) \
+ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2))
+
+typedef struct {
+ UINT8 StandardIdentifier[UDF_STANDARD_IDENTIFIER_LENGTH];
+} UDF_STANDARD_IDENTIFIER;
+
+enum {
+ BEA_IDENTIFIER,
+ VSD_IDENTIFIER_0,
+ VSD_IDENTIFIER_1,
+ TEA_IDENTIFIER,
+ NR_STANDARD_IDENTIFIERS,
+};
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 TagIdentifier;
+ UINT16 DescriptorVersion;
+ UINT8 TagChecksum;
+ UINT8 Reserved;
+ UINT16 TagSerialNumber; // Ignored. Intended for disaster recovery.
+ UINT16 DescriptorCRC;
+ UINT16 DescriptorCRCLength;
+ UINT32 TagLocation;
+} UDF_DESCRIPTOR_TAG;
+
+//
+// ECMA 167 3/7.1
+//
+typedef struct {
+ UINT32 ExtentLength;
+ UINT32 ExtentLocation;
+} UDF_EXTENT_AD;
+
+//
+// ECMA 167 3/9.1
+//
+typedef struct {
+ UINT8 StructureType;
+ UINT8 StandardIdentifier[5];
+ UINT8 StructureVersion;
+ UINT8 Reserved;
+ UINT8 StructureData[2040];
+} UDF_NSR_DESCRIPTOR;
+
+typedef struct {
+ UDF_DESCRIPTOR_TAG DescriptorTag;
+ UDF_EXTENT_AD MainVolumeDescriptorSequenceExtent;
+ UDF_EXTENT_AD ReserveVolumeDescriptorSequenceExtent;
+ UINT8 Reserved[480];
+} UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER;
+
+#pragma pack()
+
+#endif // _UDF_H_
--
1.9.3
------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel