From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.zytor.com (terminus.zytor.com [65.50.211.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A95E121C9127B for ; Sun, 20 Aug 2017 11:16:50 -0700 (PDT) Received: from localhost.localdomain ([IPv6:2804:7f4:c480:955b:0:0:0:2]) (authenticated bits=0) by mail.zytor.com (8.15.2/8.15.2) with ESMTPSA id v7KIGt0e023554 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Sun, 20 Aug 2017 11:17:06 -0700 From: Paulo Alcantara To: edk2-devel@lists.01.org Cc: Paulo Alcantara , Star Zeng , Eric Dong , Laszlo Ersek Date: Sun, 20 Aug 2017 15:15:53 -0300 Message-Id: <20170820181557.28761-3-pcacjr@zytor.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170820181557.28761-1-pcacjr@zytor.com> References: <20170820181557.28761-1-pcacjr@zytor.com> Subject: [PATCH v2 2/6] MdeModulePkg/PartitionDxe: Add UDF file system support X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Aug 2017 18:16:50 -0000 Scan for UDF file system on all block devices, as specified by OSTA Universal Disk Format Specification 2.60, as well as install a HARDDRIVE_DEVICE_PATH device path for each one found. The HARDDRIVE_DEVICE_PATH does not support types other than MBR or GPT, so it fakes a MBR type and uses signature type of "0xF0" for identifying UDF file systems. The fake device path will be later checked by UdfDxe driver in order to identify valid UDF file systems and provide access to underlying file system. Cc: Star Zeng Cc: Eric Dong Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara --- .../Universal/Disk/PartitionDxe/Partition.c | 9 +- .../Universal/Disk/PartitionDxe/Partition.h | 32 ++- .../Universal/Disk/PartitionDxe/PartitionDxe.inf | 3 +- MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 307 +++++++++++++++++++++ 4 files changed, 344 insertions(+), 7 deletions(-) create mode 100644 MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c 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..3fbb3606b8 --- /dev/null +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c @@ -0,0 +1,307 @@ +/** @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" + +#define SIGNATURE_TYPE_UDF 0xF0 + +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 medium contains an UDF file system. + + @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; + HARDDRIVE_DEVICE_PATH *UdfDevPathPtr; + HARDDRIVE_DEVICE_PATH UdfDevPath; + 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. + // + if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH && + DevicePathSubType (DevicePathNode) == MEDIA_CDROM_DP) { + return EFI_NOT_FOUND; + } + // + // Avoid duplicate checking and installation of UDF file system child nodes + // + if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH && + DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP) { + UdfDevPathPtr = (HARDDRIVE_DEVICE_PATH *)DevicePathNode; + if (UdfDevPathPtr->MBRType == MBR_TYPE_PCAT && + UdfDevPathPtr->SignatureType == SIGNATURE_TYPE_UDF) { + return EFI_NOT_FOUND; + } + } + + DevicePathNode = NextDevicePathNode (DevicePathNode); + } + + // + // Check if block device supports a valid UDF file system + // + Status = SupportUdfFileSystem (BlockIo, DiskIo); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Create a fake MBR device path since there is no UDF one + // + ZeroMem (&UdfDevPath, sizeof (HARDDRIVE_DEVICE_PATH)); + UdfDevPath.Header.Type = MEDIA_DEVICE_PATH; + UdfDevPath.Header.SubType = MEDIA_HARDDRIVE_DP; + SetDevicePathNodeLength (&UdfDevPath.Header, sizeof (UdfDevPath)); + UdfDevPath.MBRType = MBR_TYPE_PCAT; + UdfDevPath.SignatureType = SIGNATURE_TYPE_UDF; + UdfDevPath.PartitionNumber = 1; + UdfDevPath.PartitionStart = 0; + UdfDevPath.PartitionSize = Media->LastBlock + 1; + + // + // 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 *)&UdfDevPath, + &PartitionInfo, + UdfDevPath.PartitionStart, + UdfDevPath.PartitionStart + UdfDevPath.PartitionSize - 1, + Media->BlockSize + ); + if (!EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + } + + return Status; +} -- 2.11.0