OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 BlockSize;\r
- EFI_LBA EndLBA;\r
- EFI_LBA DescriptorLBAs[4];\r
- UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINT32 BlockSize;\r
+ EFI_LBA EndLBA;\r
+ EFI_LBA DescriptorLBAs[4];\r
+ UINTN Index;\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
\r
BlockSize = BlockIo->Media->BlockSize;\r
EndLBA = BlockIo->Media->LastBlock;\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
+ DescriptorTag = &AnchorPoint->DescriptorTag;\r
+\r
//\r
// Check if read LBA has a valid AVDP descriptor.\r
//\r
- if (IS_AVDP (AnchorPoint)) {\r
+ if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {\r
return EFI_SUCCESS;\r
}\r
}\r
}\r
\r
/**\r
- Check if block device supports a valid UDF file system as specified by OSTA\r
- Universal Disk Format Specification 2.60.\r
+ Find UDF volume identifiers in a Volume Recognition Sequence.\r
\r
- @param[in] BlockIo BlockIo interface.\r
- @param[in] DiskIo DiskIo interface.\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
\r
- @retval EFI_SUCCESS UDF file system found.\r
- @retval EFI_UNSUPPORTED UDF file system not found.\r
- @retval EFI_NO_MEDIA The device has no media.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_OUT_OF_RESOURCES The scan was not successful due to lack of\r
- resources.\r
+ @retval EFI_SUCCESS UDF volume identifiers were found.\r
+ @retval EFI_NOT_FOUND UDF volume identifiers were not found.\r
+ @retval other Failed to perform disk I/O.\r
\r
**/\r
EFI_STATUS\r
-SupportUdfFileSystem (\r
+FindUdfVolumeIdentifiers (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
IN EFI_DISK_IO_PROTOCOL *DiskIo\r
)\r
UINT64 EndDiskOffset;\r
CDROM_VOLUME_DESCRIPTOR VolDescriptor;\r
CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor;\r
- UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;\r
\r
ZeroMem ((VOID *)&TerminatingVolDescriptor, sizeof (CDROM_VOLUME_DESCRIPTOR));\r
\r
(CompareMem ((VOID *)&VolDescriptor,\r
(VOID *)&TerminatingVolDescriptor,\r
sizeof (CDROM_VOLUME_DESCRIPTOR)) == 0)) {\r
- return EFI_UNSUPPORTED;\r
+ return EFI_NOT_FOUND;\r
}\r
}\r
\r
//\r
Offset += UDF_LOGICAL_SECTOR_SIZE;\r
if (Offset >= EndDiskOffset) {\r
- return EFI_UNSUPPORTED;\r
+ return EFI_NOT_FOUND;\r
}\r
\r
Status = DiskIo->ReadDisk (\r
(CompareMem ((VOID *)VolDescriptor.Unknown.Id,\r
(VOID *)UDF_NSR3_IDENTIFIER,\r
sizeof (VolDescriptor.Unknown.Id)) != 0)) {\r
- return EFI_UNSUPPORTED;\r
+ return EFI_NOT_FOUND;\r
}\r
\r
//\r
//\r
Offset += UDF_LOGICAL_SECTOR_SIZE;\r
if (Offset >= EndDiskOffset) {\r
- return EFI_UNSUPPORTED;\r
+ return EFI_NOT_FOUND;\r
}\r
\r
Status = DiskIo->ReadDisk (\r
if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,\r
(VOID *)UDF_TEA_IDENTIFIER,\r
sizeof (VolDescriptor.Unknown.Id)) != 0) {\r
- return EFI_UNSUPPORTED;\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Check if Logical Volume Descriptor is supported by current EDK2 UDF file\r
+ system implementation.\r
+\r
+ @param[in] LogicalVolDesc Logical Volume Descriptor pointer.\r
+\r
+ @retval TRUE Logical Volume Descriptor is supported.\r
+ @retval FALSE Logical Volume Descriptor is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+IsLogicalVolumeDescriptorSupported (\r
+ UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc\r
+ )\r
+{\r
+ //\r
+ // Check for a valid UDF revision range\r
+ //\r
+ switch (LogicalVolDesc->DomainIdentifier.Suffix.Domain.UdfRevision) {\r
+ case 0x0102:\r
+ case 0x0150:\r
+ case 0x0200:\r
+ case 0x0201:\r
+ case 0x0250:\r
+ case 0x0260:\r
+ break;\r
+ default:\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Check for a single Partition Map\r
+ //\r
+ if (LogicalVolDesc->NumberOfPartitionMaps > 1) {\r
+ return FALSE;\r
+ }\r
+ //\r
+ // UDF 1.02 revision supports only Type 1 (Physical) partitions, but\r
+ // let's check it any way.\r
+ //\r
+ // PartitionMap[0] -> type\r
+ // PartitionMap[1] -> length (in bytes)\r
+ //\r
+ if (LogicalVolDesc->PartitionMaps[0] != 1 ||\r
+ LogicalVolDesc->PartitionMaps[1] != 6) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Find UDF logical volume location and whether it is supported by current EDK2\r
+ UDF file system implementation.\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[in] AnchorPoint Anchor volume descriptor pointer.\r
+ @param[out] MainVdsStartBlock Main VDS starting block number.\r
+ @param[out] MainVdsEndBlock Main VDS ending block number.\r
+\r
+ @retval EFI_SUCCESS UDF logical volume was found.\r
+ @retval EFI_VOLUME_CORRUPTED UDF file system structures are corrupted.\r
+ @retval EFI_UNSUPPORTED UDF logical volume is not supported.\r
+ @retval other Failed to perform disk I/O.\r
+\r
+**/\r
+EFI_STATUS\r
+FindLogicalVolumeLocation (\r
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint,\r
+ OUT UINT64 *MainVdsStartBlock,\r
+ OUT UINT64 *MainVdsEndBlock\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 BlockSize;\r
+ EFI_LBA LastBlock;\r
+ UDF_EXTENT_AD *ExtentAd;\r
+ UINT64 SeqBlocksNum;\r
+ UINT64 SeqStartBlock;\r
+ UINT64 GuardMainVdsStartBlock;\r
+ VOID *Buffer;\r
+ UINT64 SeqEndBlock;\r
+ BOOLEAN StopSequence;\r
+ UINTN LvdsCount;\r
+ UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
+\r
+ BlockSize = BlockIo->Media->BlockSize;\r
+ LastBlock = BlockIo->Media->LastBlock;\r
+ ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;\r
+\r
+ //\r
+ // UDF 2.60, 2.2.3.1 struct MainVolumeDescriptorSequenceExtent\r
+ //\r
+ // The Main Volume Descriptor Sequence Extent shall have a minimum length of\r
+ // 16 logical sectors.\r
+ //\r
+ // Also make sure it does not exceed maximum number of blocks in the disk.\r
+ //\r
+ SeqBlocksNum = DivU64x32 ((UINT64)ExtentAd->ExtentLength, BlockSize);\r
+ if (SeqBlocksNum < 16 || (EFI_LBA)SeqBlocksNum > LastBlock + 1) {\r
+ return EFI_VOLUME_CORRUPTED;\r
+ }\r
+\r
+ //\r
+ // Check for valid Volume Descriptor Sequence starting block number\r
+ //\r
+ SeqStartBlock = (UINT64)ExtentAd->ExtentLocation;\r
+ if (SeqStartBlock > LastBlock ||\r
+ SeqStartBlock + SeqBlocksNum - 1 > LastBlock) {\r
+ return EFI_VOLUME_CORRUPTED;\r
+ }\r
+\r
+ GuardMainVdsStartBlock = SeqStartBlock;\r
+\r
+ //\r
+ // Allocate buffer for reading disk blocks\r
+ //\r
+ Buffer = AllocateZeroPool ((UINTN)BlockSize);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ SeqEndBlock = SeqStartBlock + SeqBlocksNum;\r
+ StopSequence = FALSE;\r
+ LvdsCount = 0;\r
+ Status = EFI_VOLUME_CORRUPTED;\r
+ //\r
+ // Start Main Volume Descriptor Sequence\r
+ //\r
+ for (; SeqStartBlock < SeqEndBlock && !StopSequence; SeqStartBlock++) {\r
+ //\r
+ // Read disk block\r
+ //\r
+ Status = BlockIo->ReadBlocks (\r
+ BlockIo,\r
+ BlockIo->Media->MediaId,\r
+ SeqStartBlock,\r
+ BlockSize,\r
+ Buffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Out_Free;\r
+ }\r
+\r
+ DescriptorTag = Buffer;\r
+\r
+ //\r
+ // ECMA 167, 8.4.1 Contents of a Volume Descriptor Sequence\r
+ //\r
+ // - A Volume Descriptor Sequence shall contain one or more Primary Volume\r
+ // Descriptors.\r
+ // - A Volume Descriptor Sequence shall contain zero or more Implementation\r
+ // Use Volume Descriptors.\r
+ // - A Volume Descriptor Sequence shall contain zero or more Partition\r
+ // Descriptors.\r
+ // - A Volume Descriptor Sequence shall contain zero or more Logical Volume\r
+ // Descriptors.\r
+ // - A Volume Descriptor Sequence shall contain zero or more Unallocated\r
+ // Space Descriptors.\r
+ //\r
+ switch (DescriptorTag->TagIdentifier) {\r
+ case UdfPrimaryVolumeDescriptor:\r
+ case UdfImplemenationUseVolumeDescriptor:\r
+ case UdfPartitionDescriptor:\r
+ case UdfUnallocatedSpaceDescriptor:\r
+ break;\r
+\r
+ case UdfLogicalVolumeDescriptor:\r
+ LogicalVolDesc = Buffer;\r
+\r
+ //\r
+ // Check for existence of a single LVD and whether it is supported by\r
+ // current EDK2 UDF file system implementation.\r
+ //\r
+ if (++LvdsCount > 1 ||\r
+ !IsLogicalVolumeDescriptorSupported (LogicalVolDesc)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ StopSequence = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ case UdfTerminatingDescriptor:\r
+ //\r
+ // Stop the sequence when we find a Terminating Descriptor\r
+ // (aka Unallocated Sector), se we don't have to walk all the unallocated\r
+ // area unnecessarily.\r
+ //\r
+ StopSequence = TRUE;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // An invalid Volume Descriptor has been found in the sequece. Volume is\r
+ // corrupted.\r
+ //\r
+ Status = EFI_VOLUME_CORRUPTED;\r
+ goto Out_Free;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check if LVD was found\r
+ //\r
+ if (!EFI_ERROR (Status) && LvdsCount == 1) {\r
+ *MainVdsStartBlock = GuardMainVdsStartBlock;\r
+ //\r
+ // We do not need to read either LVD or PD descriptors to know the last\r
+ // valid block in the found UDF file system. It's already LastBlock.\r
+ //\r
+ *MainVdsEndBlock = LastBlock;\r
+\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+Out_Free:\r
+ //\r
+ // Free block read buffer\r
+ //\r
+ FreePool (Buffer);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Find a supported UDF file system in block device.\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[out] StartingLBA UDF file system starting LBA.\r
+ @param[out] EndingLBA UDF file system starting LBA.\r
+\r
+ @retval EFI_SUCCESS UDF file system was found.\r
+ @retval other UDF file system was not found.\r
+\r
+**/\r
+EFI_STATUS\r
+FindUdfFileSystem (\r
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
+ OUT EFI_LBA *StartingLBA,\r
+ OUT EFI_LBA *EndingLBA\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;\r
+\r
+ //\r
+ // Find UDF volume identifiers\r
+ //\r
+ Status = FindUdfVolumeIdentifiers (BlockIo, DiskIo);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
+ //\r
+ // Find Anchor Volume Descriptor Pointer\r
+ //\r
Status = FindAnchorVolumeDescriptorPointer (BlockIo, DiskIo, &AnchorPoint);\r
if (EFI_ERROR (Status)) {\r
- return EFI_UNSUPPORTED;\r
+ return Status;\r
}\r
\r
- return EFI_SUCCESS;\r
+ //\r
+ // Find Logical Volume location\r
+ //\r
+ Status = FindLogicalVolumeLocation (\r
+ BlockIo,\r
+ DiskIo,\r
+ &AnchorPoint,\r
+ (UINT64 *)StartingLBA,\r
+ (UINT64 *)EndingLBA\r
+ );\r
+\r
+ return Status;\r
}\r
\r
/**\r
UINT32 RemainderByMediaBlockSize;\r
EFI_STATUS Status;\r
EFI_BLOCK_IO_MEDIA *Media;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
- EFI_GUID *VendorDefinedGuid;\r
EFI_PARTITION_INFO_PROTOCOL PartitionInfo;\r
+ EFI_LBA StartingLBA;\r
+ EFI_LBA EndingLBA;\r
\r
Media = BlockIo->Media;\r
\r
return EFI_NOT_FOUND;\r
}\r
\r
- DevicePathNode = DevicePath;\r
- while (!IsDevicePathEnd (DevicePathNode)) {\r
- //\r
- // Do not allow checking for UDF file systems in CDROM "El Torito"\r
- // partitions, and skip duplicate installation of UDF file system child\r
- // nodes.\r
- //\r
- if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) {\r
- if (DevicePathSubType (DevicePathNode) == MEDIA_CDROM_DP) {\r
- return EFI_NOT_FOUND;\r
- }\r
- if (DevicePathSubType (DevicePathNode) == MEDIA_VENDOR_DP) {\r
- VendorDefinedGuid = (EFI_GUID *)((UINTN)DevicePathNode +\r
- OFFSET_OF (VENDOR_DEVICE_PATH, Guid));\r
- if (CompareGuid (VendorDefinedGuid, &gUdfDevPathGuid)) {\r
- return EFI_NOT_FOUND;\r
- }\r
- }\r
- }\r
- //\r
- // Try next device path node\r
- //\r
- DevicePathNode = NextDevicePathNode (DevicePathNode);\r
- }\r
-\r
//\r
- // Check if block device supports an UDF file system\r
+ // Search for an UDF file system on block device\r
//\r
- Status = SupportUdfFileSystem (BlockIo, DiskIo);\r
+ Status = FindUdfFileSystem (BlockIo, DiskIo, &StartingLBA, &EndingLBA);\r
if (EFI_ERROR (Status)) {\r
return EFI_NOT_FOUND;\r
}\r
DevicePath,\r
(EFI_DEVICE_PATH_PROTOCOL *)&gUdfDevicePath,\r
&PartitionInfo,\r
- 0,\r
- Media->LastBlock,\r
+ StartingLBA,\r
+ EndingLBA,\r
Media->BlockSize\r
);\r
- if (!EFI_ERROR (Status)) {\r
- Status = EFI_NOT_FOUND;\r
- }\r
\r
return Status;\r
}\r
OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 BlockSize;\r
- EFI_LBA EndLBA;\r
- EFI_LBA DescriptorLBAs[4];\r
- UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINT32 BlockSize;\r
+ EFI_LBA EndLBA;\r
+ EFI_LBA DescriptorLBAs[4];\r
+ UINTN Index;\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
\r
BlockSize = BlockIo->Media->BlockSize;\r
EndLBA = BlockIo->Media->LastBlock;\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
+ DescriptorTag = &AnchorPoint->DescriptorTag;\r
+\r
//\r
// Check if read LBA has a valid AVDP descriptor.\r
//\r
- if (IS_AVDP (AnchorPoint)) {\r
+ if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {\r
return EFI_SUCCESS;\r
}\r
}\r
OUT UDF_VOLUME_INFO *Volume\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 BlockSize;\r
- UDF_EXTENT_AD *ExtentAd;\r
- UINT64 StartingLsn;\r
- UINT64 EndingLsn;\r
- VOID *Buffer;\r
- UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;\r
- UDF_PARTITION_DESCRIPTOR *PartitionDesc;\r
- UINTN Index;\r
- UINT32 LogicalBlockSize;\r
+ EFI_STATUS Status;\r
+ UINT32 BlockSize;\r
+ UDF_EXTENT_AD *ExtentAd;\r
+ EFI_LBA SeqStartBlock;\r
+ EFI_LBA SeqEndBlock;\r
+ BOOLEAN StopSequence;\r
+ VOID *Buffer;\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
+ UINT32 LogicalBlockSize;\r
+\r
+ BlockSize = BlockIo->Media->BlockSize;\r
+ ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;\r
\r
//\r
- // We've already found an ADVP on the volume. It contains the extent\r
- // (MainVolumeDescriptorSequenceExtent) where the Main Volume Descriptor\r
- // Sequence starts. Therefore, we'll look for Logical Volume Descriptors and\r
- // Partitions Descriptors and save them in memory, accordingly.\r
- //\r
- // Note also that each descriptor will be aligned on a block size (BlockSize)\r
- // boundary, so we need to read one block at a time.\r
+ // Allocate buffer for reading disk blocks\r
//\r
- BlockSize = BlockIo->Media->BlockSize;\r
- ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;\r
- StartingLsn = (UINT64)ExtentAd->ExtentLocation;\r
- EndingLsn = StartingLsn + DivU64x32 (\r
- (UINT64)ExtentAd->ExtentLength,\r
- BlockSize\r
- );\r
-\r
- Volume->LogicalVolDescs =\r
- (UDF_LOGICAL_VOLUME_DESCRIPTOR **)AllocateZeroPool (ExtentAd->ExtentLength);\r
- if (Volume->LogicalVolDescs == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Volume->PartitionDescs =\r
- (UDF_PARTITION_DESCRIPTOR **)AllocateZeroPool (ExtentAd->ExtentLength);\r
- if (Volume->PartitionDescs == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error_Alloc_Pds;\r
- }\r
-\r
- Buffer = AllocateZeroPool (BlockSize);\r
+ Buffer = AllocateZeroPool ((UINTN)BlockSize);\r
if (Buffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error_Alloc_Buf;\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Volume->LogicalVolDescsNo = 0;\r
- Volume->PartitionDescsNo = 0;\r
-\r
- while (StartingLsn <= EndingLsn) {\r
- Status = DiskIo->ReadDisk (\r
- DiskIo,\r
+ //\r
+ // The logical partition created by Partition driver is relative to the main\r
+ // VDS extent location, so we start the Main Volume Descriptor Sequence at\r
+ // LBA 0.\r
+ //\r
+ // We don't need to check again if we have valid Volume Descriptors here since\r
+ // Partition driver already did.\r
+ //\r
+ SeqStartBlock = 0;\r
+ SeqEndBlock = SeqStartBlock + DivU64x32 ((UINT64)ExtentAd->ExtentLength,\r
+ BlockSize);\r
+ StopSequence = FALSE;\r
+ for (; SeqStartBlock < SeqEndBlock && !StopSequence; SeqStartBlock++) {\r
+ //\r
+ // Read disk block\r
+ //\r
+ Status = BlockIo->ReadBlocks (\r
+ BlockIo,\r
BlockIo->Media->MediaId,\r
- MultU64x32 (StartingLsn, BlockSize),\r
+ SeqStartBlock,\r
BlockSize,\r
Buffer\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Error_Read_Disk_Blk;\r
+ goto Out_Free;\r
}\r
\r
- if (IS_TD (Buffer)) {\r
+ DescriptorTag = Buffer;\r
+\r
+ switch (DescriptorTag->TagIdentifier) {\r
+ case UdfPartitionDescriptor:\r
//\r
- // Found a Terminating Descriptor. Stop the sequence then.\r
+ // Save Partition Descriptor\r
//\r
+ CopyMem (&Volume->PartitionDesc, Buffer, sizeof (Volume->PartitionDesc));\r
break;\r
- }\r
\r
- if (IS_LVD (Buffer)) {\r
+ case UdfLogicalVolumeDescriptor:\r
//\r
- // Found a Logical Volume Descriptor.\r
+ // Save Logical Volume Descriptor\r
//\r
- LogicalVolDesc =\r
- (UDF_LOGICAL_VOLUME_DESCRIPTOR *)\r
- AllocateZeroPool (sizeof (UDF_LOGICAL_VOLUME_DESCRIPTOR));\r
- if (LogicalVolDesc == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error_Alloc_Lvd;\r
- }\r
+ CopyMem (&Volume->LogicalVolDesc, Buffer, sizeof (Volume->LogicalVolDesc));\r
+ break;\r
\r
- CopyMem ((VOID *)LogicalVolDesc, Buffer,\r
- sizeof (UDF_LOGICAL_VOLUME_DESCRIPTOR));\r
- Volume->LogicalVolDescs[Volume->LogicalVolDescsNo++] = LogicalVolDesc;\r
- } else if (IS_PD (Buffer)) {\r
- //\r
- // Found a Partition Descriptor.\r
- //\r
- PartitionDesc =\r
- (UDF_PARTITION_DESCRIPTOR *)\r
- AllocateZeroPool (sizeof (UDF_PARTITION_DESCRIPTOR));\r
- if (PartitionDesc == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error_Alloc_Pd;\r
- }\r
+ case UdfTerminatingDescriptor:\r
+ StopSequence = TRUE;\r
+ break;\r
\r
- CopyMem ((VOID *)PartitionDesc, Buffer,\r
- sizeof (UDF_PARTITION_DESCRIPTOR));\r
- Volume->PartitionDescs[Volume->PartitionDescsNo++] = PartitionDesc;\r
+ default:\r
+ ;\r
}\r
-\r
- StartingLsn++;\r
}\r
\r
//\r
- // When an UDF volume (revision 2.00 or higher) contains a File Entry rather\r
- // than an Extended File Entry (which is not recommended as per spec), we need\r
- // to make sure the size of a FE will be _at least_ 2048\r
- // (UDF_LOGICAL_SECTOR_SIZE) bytes long to keep backward compatibility.\r
+ // Determine FE (File Entry) size\r
//\r
- LogicalBlockSize = LV_BLOCK_SIZE (Volume, UDF_DEFAULT_LV_NUM);\r
+ LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;\r
if (LogicalBlockSize >= UDF_LOGICAL_SECTOR_SIZE) {\r
- Volume->FileEntrySize = LogicalBlockSize;\r
+ Volume->FileEntrySize = (UINTN)LogicalBlockSize;\r
} else {\r
Volume->FileEntrySize = UDF_LOGICAL_SECTOR_SIZE;\r
}\r
\r
- FreePool (Buffer);\r
+ Status = EFI_SUCCESS;\r
\r
- return EFI_SUCCESS;\r
-\r
-Error_Alloc_Pd:\r
-Error_Alloc_Lvd:\r
- for (Index = 0; Index < Volume->PartitionDescsNo; Index++) {\r
- FreePool ((VOID *)Volume->PartitionDescs[Index]);\r
- }\r
-\r
- for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) {\r
- FreePool ((VOID *)Volume->LogicalVolDescs[Index]);\r
- }\r
-\r
-Error_Read_Disk_Blk:\r
+Out_Free:\r
+ //\r
+ // Free block read buffer\r
+ //\r
FreePool (Buffer);\r
\r
-Error_Alloc_Buf:\r
- FreePool ((VOID *)Volume->PartitionDescs);\r
- Volume->PartitionDescs = NULL;\r
-\r
-Error_Alloc_Pds:\r
- FreePool ((VOID *)Volume->LogicalVolDescs);\r
- Volume->LogicalVolDescs = NULL;\r
-\r
return Status;\r
}\r
\r
)\r
{\r
UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;\r
- UINTN Index;\r
- UDF_PARTITION_DESCRIPTOR *PartitionDesc;\r
UINT16 PartitionNum;\r
\r
- LogicalVolDesc = Volume->LogicalVolDescs[UDF_DEFAULT_LV_NUM];\r
+ LogicalVolDesc = &Volume->LogicalVolDesc;\r
\r
- switch (LV_UDF_REVISION (LogicalVolDesc)) {\r
+ switch (LogicalVolDesc->DomainIdentifier.Suffix.Domain.UdfRevision) {\r
case 0x0102:\r
+ case 0x0150:\r
+ case 0x0200:\r
+ case 0x0201:\r
+ case 0x0250:\r
+ case 0x0260:\r
//\r
- // As per UDF 1.02 specification:\r
+ // UDF 1.02 specification:\r
//\r
// There shall be exactly one prevailing Logical Volume Descriptor recorded\r
// per Volume Set. The Partition Maps field shall contain only Type 1\r
// Partition Maps.\r
//\r
- PartitionNum = *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]);\r
- break;\r
- case 0x0150:\r
+ // UDF 1.50 through 2.60 specs say:\r
//\r
- // Ensure Type 1 Partition map. Other types aren't supported in this\r
- // implementation.\r
+ // For the purpose of interchange partition maps shall be limited to\r
+ // Partition Map type 1, except type 2 maps as described in the document.\r
+ //\r
+ // NOTE: Only one Type 1 (Physical) Partition is supported. It has been\r
+ // checked already in Partition driver for existence of a single Type 1\r
+ // Partition map, so we don't have to double check here.\r
+ //\r
+ // Partition reference number can also be retrieved from\r
+ // LongAd->ExtentLocation.PartitionReferenceNumber, however the spec says\r
+ // it may be 0, so let's not rely on it.\r
//\r
- if (LogicalVolDesc->PartitionMaps[0] != 1 ||\r
- LogicalVolDesc->PartitionMaps[1] != 6) {\r
- return NULL;\r
- }\r
PartitionNum = *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]);\r
break;\r
- case 0x0260:\r
+\r
+ default:\r
//\r
- // Fall through.\r
+ // Unsupported UDF revision\r
//\r
- default:\r
- PartitionNum = LongAd->ExtentLocation.PartitionReferenceNumber;\r
- break;\r
+ return NULL;\r
}\r
\r
- for (Index = 0; Index < Volume->PartitionDescsNo; Index++) {\r
- PartitionDesc = Volume->PartitionDescs[Index];\r
- if (PartitionDesc->PartitionNumber == PartitionNum) {\r
- return PartitionDesc;\r
- }\r
+ //\r
+ // Check if partition number matches Partition Descriptor found in Main Volume\r
+ // Descriptor Sequence.\r
+ //\r
+ if (Volume->PartitionDesc.PartitionNumber == PartitionNum) {\r
+ return &Volume->PartitionDesc;\r
}\r
\r
return NULL;\r
PartitionDesc = GetPdFromLongAd (Volume, LongAd);\r
ASSERT (PartitionDesc != NULL);\r
\r
- return (UINT64)PartitionDesc->PartitionStartingLocation +\r
- LongAd->ExtentLocation.LogicalBlockNumber;\r
+ return (UINT64)PartitionDesc->PartitionStartingLocation -\r
+ Volume->MainVdsStartLocation +\r
+ LongAd->ExtentLocation.LogicalBlockNumber;\r
}\r
\r
/**\r
Return logical sector number of a given Short Allocation Descriptor.\r
\r
+ @param[in] Volume Volume pointer.\r
@param[in] PartitionDesc Partition Descriptor pointer.\r
@param[in] ShortAd Short Allocation Descriptor pointer.\r
\r
**/\r
UINT64\r
GetShortAdLsn (\r
+ IN UDF_VOLUME_INFO *Volume,\r
IN UDF_PARTITION_DESCRIPTOR *PartitionDesc,\r
IN UDF_SHORT_ALLOCATION_DESCRIPTOR *ShortAd\r
)\r
{\r
- ASSERT (PartitionDesc != NULL);\r
-\r
- return (UINT64)PartitionDesc->PartitionStartingLocation +\r
- ShortAd->ExtentPosition;\r
+ return (UINT64)PartitionDesc->PartitionStartingLocation -\r
+ Volume->MainVdsStartLocation + ShortAd->ExtentPosition;\r
}\r
\r
/**\r
@param[in] BlockIo BlockIo interface.\r
@param[in] DiskIo DiskIo interface.\r
@param[in] Volume Volume information pointer.\r
- @param[in] LogicalVolDescNum Index of Logical Volume Descriptor\r
- @param[out] FileSetDesc File Set Descriptor pointer.\r
\r
@retval EFI_SUCCESS File Set Descriptor pointer found.\r
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
FindFileSetDescriptor (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
- IN UDF_VOLUME_INFO *Volume,\r
- IN UINTN LogicalVolDescNum,\r
- OUT UDF_FILE_SET_DESCRIPTOR *FileSetDesc\r
+ IN UDF_VOLUME_INFO *Volume\r
)\r
{\r
EFI_STATUS Status;\r
UINT64 Lsn;\r
UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
\r
- LogicalVolDesc = Volume->LogicalVolDescs[LogicalVolDescNum];\r
+ LogicalVolDesc = &Volume->LogicalVolDesc;\r
Lsn = GetLongAdLsn (Volume, &LogicalVolDesc->LogicalVolumeContentsUse);\r
\r
//\r
- // Read extent (Long Ad).\r
+ // As per UDF 2.60 specification:\r
+ //\r
+ // There shall be exactly one File Set Descriptor recorded per Logical\r
+ // Volume.\r
+ //\r
+ // Read disk block\r
//\r
Status = DiskIo->ReadDisk (\r
DiskIo,\r
BlockIo->Media->MediaId,\r
MultU64x32 (Lsn, LogicalVolDesc->LogicalBlockSize),\r
- sizeof (UDF_FILE_SET_DESCRIPTOR),\r
- (VOID *)FileSetDesc\r
+ sizeof (Volume->FileSetDesc),\r
+ &Volume->FileSetDesc\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
+ DescriptorTag = &Volume->FileSetDesc.DescriptorTag;\r
+\r
//\r
- // Check if the read extent contains a valid FSD's tag identifier.\r
+ // Check if read block is a File Set Descriptor\r
//\r
- if (!IS_FSD (FileSetDesc)) {\r
+ if (DescriptorTag->TagIdentifier != UdfFileSetDescriptor) {\r
return EFI_VOLUME_CORRUPTED;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Get all File Set Descriptors for each Logical Volume Descriptor.\r
-\r
- @param[in] BlockIo BlockIo interface.\r
- @param[in] DiskIo DiskIo interface.\r
- @param[in, out] Volume Volume information pointer.\r
-\r
- @retval EFI_SUCCESS File Set Descriptors were got.\r
- @retval EFI_OUT_OF_RESOURCES File Set Descriptors were not got due to lack\r
- of resources.\r
- @retval other Error occured when finding File Set\r
- Descriptor in Logical Volume Descriptor.\r
-\r
-**/\r
-EFI_STATUS\r
-GetFileSetDescriptors (\r
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
- IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
- IN OUT UDF_VOLUME_INFO *Volume\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UDF_FILE_SET_DESCRIPTOR *FileSetDesc;\r
- UINTN Count;\r
-\r
- Volume->FileSetDescs =\r
- (UDF_FILE_SET_DESCRIPTOR **)AllocateZeroPool (\r
- Volume->LogicalVolDescsNo * sizeof (UDF_FILE_SET_DESCRIPTOR));\r
- if (Volume->FileSetDescs == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) {\r
- FileSetDesc = AllocateZeroPool (sizeof (UDF_FILE_SET_DESCRIPTOR));\r
- if (FileSetDesc == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error_Alloc_Fsd;\r
- }\r
-\r
- //\r
- // Find a FSD for this LVD.\r
- //\r
- Status = FindFileSetDescriptor (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- Index,\r
- FileSetDesc\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error_Find_Fsd;\r
- }\r
-\r
- //\r
- // Got one. Save it.\r
- //\r
- Volume->FileSetDescs[Index] = FileSetDesc;\r
- }\r
-\r
- Volume->FileSetDescsNo = Volume->LogicalVolDescsNo;\r
- return EFI_SUCCESS;\r
-\r
-Error_Find_Fsd:\r
- Count = Index + 1;\r
- for (Index = 0; Index < Count; Index++) {\r
- FreePool ((VOID *)Volume->FileSetDescs[Index]);\r
- }\r
-\r
- FreePool ((VOID *)Volume->FileSetDescs);\r
- Volume->FileSetDescs = NULL;\r
-\r
-Error_Alloc_Fsd:\r
- return Status;\r
-}\r
-\r
/**\r
Read Volume and File Structure on an UDF file system.\r
\r
{\r
EFI_STATUS Status;\r
UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint;\r
+ UDF_EXTENT_AD *ExtentAd;\r
\r
//\r
- // Find an AVDP.\r
+ // Find Anchor Volume Descriptor Pointer\r
//\r
Status = FindAnchorVolumeDescriptorPointer (\r
BlockIo,\r
}\r
\r
//\r
- // AVDP has been found. Start MVDS.\r
+ // Save Main VDS start block number\r
+ //\r
+ ExtentAd = &AnchorPoint.MainVolumeDescriptorSequenceExtent;\r
+\r
+ Volume->MainVdsStartLocation = (UINT64)ExtentAd->ExtentLocation;\r
+\r
+ //\r
+ // Start Main Volume Descriptor Sequence.\r
//\r
Status = StartMainVolumeDescriptorSequence (\r
BlockIo,\r
OUT UINT64 *Length\r
)\r
{\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;\r
UDF_FILE_ENTRY *FileEntry;\r
\r
- if (IS_EFE (FileEntryData)) {\r
+ DescriptorTag = FileEntryData;\r
+\r
+ if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {\r
ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;\r
\r
*Length = ExtendedFileEntry->InformationLength;\r
*Data = (VOID *)((UINT8 *)ExtendedFileEntry->Data +\r
ExtendedFileEntry->LengthOfExtendedAttributes);\r
- } else if (IS_FE (FileEntryData)) {\r
+ } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {\r
FileEntry = (UDF_FILE_ENTRY *)FileEntryData;\r
\r
*Length = FileEntry->InformationLength;\r
OUT UINT64 *Length\r
)\r
{\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;\r
UDF_FILE_ENTRY *FileEntry;\r
\r
- if (IS_EFE (FileEntryData)) {\r
+ DescriptorTag = FileEntryData;\r
+\r
+ if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {\r
ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;\r
\r
*Length = ExtendedFileEntry->LengthOfAllocationDescriptors;\r
*AdsData = (VOID *)((UINT8 *)ExtendedFileEntry->Data +\r
ExtendedFileEntry->LengthOfExtendedAttributes);\r
- } else if (IS_FE (FileEntryData)) {\r
+ } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {\r
FileEntry = (UDF_FILE_ENTRY *)FileEntryData;\r
\r
*Length = FileEntry->LengthOfAllocationDescriptors;\r
return GetLongAdLsn (Volume, (UDF_LONG_ALLOCATION_DESCRIPTOR *)Ad);\r
} else if (RecordingFlags == ShortAdsSequence) {\r
return GetShortAdLsn (\r
+ Volume,\r
GetPdFromLongAd (Volume, ParentIcb),\r
(UDF_SHORT_ALLOCATION_DESCRIPTOR *)Ad\r
);\r
VOID *Data;\r
UINT32 LogicalBlockSize;\r
UDF_ALLOCATION_EXTENT_DESCRIPTOR *AllocExtDesc;\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
\r
ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);\r
Lsn = GetAllocationDescriptorLsn (RecordingFlags,\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- LogicalBlockSize = LV_BLOCK_SIZE (Volume, UDF_DEFAULT_LV_NUM);\r
+ LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;\r
\r
//\r
// Read extent.\r
goto Exit;\r
}\r
\r
+ AllocExtDesc = (UDF_ALLOCATION_EXTENT_DESCRIPTOR *)Data;\r
+\r
+ DescriptorTag = &AllocExtDesc->DescriptorTag;\r
+\r
//\r
// Check if read extent contains a valid tag identifier for AED.\r
//\r
- AllocExtDesc = (UDF_ALLOCATION_EXTENT_DESCRIPTOR *)Data;\r
- if (!IS_AED (AllocExtDesc)) {\r
+ if (DescriptorTag->TagIdentifier != UdfAllocationExtentDescriptor) {\r
Status = EFI_VOLUME_CORRUPTED;\r
goto Exit;\r
}\r
UINT32 ExtentLength;\r
UDF_FE_RECORDING_FLAGS RecordingFlags;\r
\r
- LogicalBlockSize = LV_BLOCK_SIZE (Volume, UDF_DEFAULT_LV_NUM);\r
+ LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;\r
DoFreeAed = FALSE;\r
\r
//\r
//\r
// Check if parent file is really directory.\r
//\r
- if (!IS_FE_DIRECTORY (Parent->FileEntry)) {\r
+ if (FE_ICB_FILE_TYPE (Parent->FileEntry) != UdfFileEntryDirectory) {\r
return EFI_NOT_FOUND;\r
}\r
\r
break;\r
}\r
\r
- if (IS_FID_PARENT_FILE (FileIdentifierDesc)) {\r
+ if (FileIdentifierDesc->FileCharacteristics & PARENT_FILE) {\r
//\r
// This FID contains the location (FE/EFE) of the parent directory of this\r
// directory (Parent), and if FileName is either ".." or "\\", then it's\r
{\r
EFI_STATUS Status;\r
\r
+ //\r
+ // Read all necessary UDF volume information and keep it private to the driver\r
+ //\r
Status = ReadVolumeFileStructure (\r
BlockIo,\r
DiskIo,\r
return Status;\r
}\r
\r
- Status = GetFileSetDescriptors (\r
- BlockIo,\r
- DiskIo,\r
- Volume\r
- );\r
+ //\r
+ // Find File Set Descriptor\r
+ //\r
+ Status = FindFileSetDescriptor (BlockIo, DiskIo, Volume);\r
if (EFI_ERROR (Status)) {\r
- CleanupVolumeInformation (Volume);\r
+ return Status;\r
}\r
\r
return Status;\r
BlockIo,\r
DiskIo,\r
Volume,\r
- &Volume->FileSetDescs[0]->RootDirectoryIcb,\r
+ &Volume->FileSetDesc.RootDirectoryIcb,\r
&File->FileEntry\r
);\r
if (EFI_ERROR (Status)) {\r
L"\\",\r
NULL,\r
&Parent,\r
- &Volume->FileSetDescs[0]->RootDirectoryIcb,\r
+ &Volume->FileSetDesc.RootDirectoryIcb,\r
File\r
);\r
if (EFI_ERROR (Status)) {\r
OUT VOID **FileEntry\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT64 Lsn;\r
- UINT32 LogicalBlockSize;\r
+ EFI_STATUS Status;\r
+ UINT64 Lsn;\r
+ UINT32 LogicalBlockSize;\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
\r
Lsn = GetLongAdLsn (Volume, Icb);\r
- LogicalBlockSize = LV_BLOCK_SIZE (Volume, UDF_DEFAULT_LV_NUM);\r
+ LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;\r
\r
*FileEntry = AllocateZeroPool (Volume->FileEntrySize);\r
if (*FileEntry == NULL) {\r
goto Error_Read_Disk_Blk;\r
}\r
\r
+ DescriptorTag = *FileEntry;\r
+\r
//\r
// Check if the read extent contains a valid Tag Identifier for the expected\r
// FE/EFE.\r
//\r
- if (!IS_FE (*FileEntry) && !IS_EFE (*FileEntry)) {\r
+ if (DescriptorTag->TagIdentifier != UdfFileEntry &&\r
+ DescriptorTag->TagIdentifier != UdfExtendedFileEntry) {\r
Status = EFI_VOLUME_CORRUPTED;\r
goto Error_Invalid_Fe;\r
}\r
// If the found file is a symlink, then find its respective FE/EFE and\r
// FID descriptors.\r
//\r
- if (IS_FE_SYMLINK (File->FileEntry)) {\r
+ if (FE_ICB_FILE_TYPE (File->FileEntry) == UdfFileEntrySymlink) {\r
FreePool ((VOID *)File->FileIdentifierDesc);\r
\r
FileEntry = File->FileEntry;\r
// Update FidOffset to point to next FID.\r
//\r
ReadDirInfo->FidOffset += GetFidDescriptorLength (FileIdentifierDesc);\r
- } while (IS_FID_DELETED_FILE (FileIdentifierDesc));\r
+ } while (FileIdentifierDesc->FileCharacteristics & DELETED_FILE);\r
\r
DuplicateFid (FileIdentifierDesc, FoundFid);\r
\r
return Status;\r
}\r
\r
-/**\r
- Clean up in-memory UDF volume information.\r
-\r
- @param[in] Volume Volume information pointer.\r
-\r
-**/\r
-VOID\r
-CleanupVolumeInformation (\r
- IN UDF_VOLUME_INFO *Volume\r
- )\r
-{\r
- UINTN Index;\r
-\r
- if (Volume->LogicalVolDescs != NULL) {\r
- for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) {\r
- FreePool ((VOID *)Volume->LogicalVolDescs[Index]);\r
- }\r
- FreePool ((VOID *)Volume->LogicalVolDescs);\r
- }\r
-\r
- if (Volume->PartitionDescs != NULL) {\r
- for (Index = 0; Index < Volume->PartitionDescsNo; Index++) {\r
- FreePool ((VOID *)Volume->PartitionDescs[Index]);\r
- }\r
- FreePool ((VOID *)Volume->PartitionDescs);\r
- }\r
-\r
- if (Volume->FileSetDescs != NULL) {\r
- for (Index = 0; Index < Volume->FileSetDescsNo; Index++) {\r
- FreePool ((VOID *)Volume->FileSetDescs[Index]);\r
- }\r
- FreePool ((VOID *)Volume->FileSetDescs);\r
- }\r
-\r
- ZeroMem ((VOID *)Volume, sizeof (UDF_VOLUME_INFO));\r
-}\r
-\r
/**\r
Clean up in-memory UDF file information.\r
\r
EFI_FILE_INFO *FileInfo;\r
UDF_FILE_ENTRY *FileEntry;\r
UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
\r
//\r
// Calculate the needed size for the EFI_FILE_INFO structure.\r
FileInfo->Attribute |= EFI_FILE_HIDDEN;\r
}\r
\r
- if (IS_FE (File->FileEntry)) {\r
+ DescriptorTag = File->FileEntry;\r
+\r
+ if (DescriptorTag->TagIdentifier == UdfFileEntry) {\r
FileEntry = (UDF_FILE_ENTRY *)File->FileEntry;\r
\r
//\r
FileEntry->AccessTime.Second;\r
FileInfo->LastAccessTime.Nanosecond =\r
FileEntry->AccessTime.HundredsOfMicroseconds;\r
- } else if (IS_EFE (File->FileEntry)) {\r
+ } else if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {\r
ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)File->FileEntry;\r
\r
//\r
OUT UINT64 *FreeSpaceSize\r
)\r
{\r
- UDF_EXTENT_AD ExtentAd;\r
- UINT32 LogicalBlockSize;\r
- UINT64 Lsn;\r
- EFI_STATUS Status;\r
- UDF_LOGICAL_VOLUME_INTEGRITY *LogicalVolInt;\r
- UINTN Index;\r
- UINTN Length;\r
- UINT32 LsnsNo;\r
-\r
- *VolumeSize = 0;\r
- *FreeSpaceSize = 0;\r
-\r
- for (Index = 0; Index < Volume->LogicalVolDescsNo; Index++) {\r
- CopyMem ((VOID *)&ExtentAd,\r
- (VOID *)&Volume->LogicalVolDescs[Index]->IntegritySequenceExtent,\r
- sizeof (UDF_EXTENT_AD));\r
- if (ExtentAd.ExtentLength == 0) {\r
- continue;\r
- }\r
+ EFI_STATUS Status;\r
+ UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;\r
+ UDF_EXTENT_AD *ExtentAd;\r
+ UINT64 Lsn;\r
+ UINT32 LogicalBlockSize;\r
+ UDF_LOGICAL_VOLUME_INTEGRITY *LogicalVolInt;\r
+ UDF_DESCRIPTOR_TAG *DescriptorTag;\r
+ UINTN Index;\r
+ UINTN Length;\r
+ UINT32 LsnsNo;\r
\r
- LogicalBlockSize = LV_BLOCK_SIZE (Volume, Index);\r
+ LogicalVolDesc = &Volume->LogicalVolDesc;\r
\r
- Read_Next_Sequence:\r
- LogicalVolInt = (UDF_LOGICAL_VOLUME_INTEGRITY *)\r
- AllocatePool (ExtentAd.ExtentLength);\r
- if (LogicalVolInt == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ ExtentAd = &LogicalVolDesc->IntegritySequenceExtent;\r
+\r
+ if (ExtentAd->ExtentLength == 0) {\r
+ return EFI_VOLUME_CORRUPTED;\r
+ }\r
\r
- Lsn = (UINT64)ExtentAd.ExtentLocation;\r
+ LogicalVolInt = AllocatePool (ExtentAd->ExtentLength);\r
+ if (LogicalVolInt == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- Status = DiskIo->ReadDisk (\r
- DiskIo,\r
- BlockIo->Media->MediaId,\r
- MultU64x32 (Lsn, LogicalBlockSize),\r
- ExtentAd.ExtentLength,\r
- (VOID *)LogicalVolInt\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool ((VOID *)LogicalVolInt);\r
- return Status;\r
- }\r
+ //\r
+ // Get location of Logical Volume Integrity Descriptor\r
+ //\r
+ Lsn = (UINT64)ExtentAd->ExtentLocation - Volume->MainVdsStartLocation;\r
\r
- if (!IS_LVID (LogicalVolInt)) {\r
- FreePool ((VOID *)LogicalVolInt);\r
- return EFI_VOLUME_CORRUPTED;\r
- }\r
+ LogicalBlockSize = LogicalVolDesc->LogicalBlockSize;\r
\r
- Length = LogicalVolInt->NumberOfPartitions;\r
- for (Index = 0; Index < Length; Index += sizeof (UINT32)) {\r
- LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);\r
- if (LsnsNo == 0xFFFFFFFFUL) {\r
- //\r
- // Size not specified.\r
- //\r
- continue;\r
- }\r
+ //\r
+ // Read disk block\r
+ //\r
+ Status = DiskIo->ReadDisk (\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32 (Lsn, LogicalBlockSize),\r
+ ExtentAd->ExtentLength,\r
+ LogicalVolInt\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Out_Free;\r
+ }\r
\r
- *FreeSpaceSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);\r
- }\r
+ DescriptorTag = &LogicalVolInt->DescriptorTag;\r
\r
- Length = (LogicalVolInt->NumberOfPartitions * sizeof (UINT32)) << 1;\r
- for (; Index < Length; Index += sizeof (UINT32)) {\r
- LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);\r
- if (LsnsNo == 0xFFFFFFFFUL) {\r
- //\r
- // Size not specified.\r
- //\r
- continue;\r
- }\r
+ //\r
+ // Check if read block is a Logical Volume Integrity Descriptor\r
+ //\r
+ if (DescriptorTag->TagIdentifier != UdfLogicalVolumeIntegrityDescriptor) {\r
+ Status = EFI_VOLUME_CORRUPTED;\r
+ goto Out_Free;\r
+ }\r
\r
- *VolumeSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);\r
- }\r
+ *VolumeSize = 0;\r
+ *FreeSpaceSize = 0;\r
\r
- CopyMem ((VOID *)&ExtentAd,(VOID *)&LogicalVolInt->NextIntegrityExtent,\r
- sizeof (UDF_EXTENT_AD));\r
- if (ExtentAd.ExtentLength > 0) {\r
- FreePool ((VOID *)LogicalVolInt);\r
- goto Read_Next_Sequence;\r
+ Length = LogicalVolInt->NumberOfPartitions;\r
+ for (Index = 0; Index < Length; Index += sizeof (UINT32)) {\r
+ LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);\r
+ //\r
+ // Check if size is not specified\r
+ //\r
+ if (LsnsNo == 0xFFFFFFFFUL) {\r
+ continue;\r
}\r
+ //\r
+ // Accumulate free space size\r
+ //\r
+ *FreeSpaceSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);\r
+ }\r
\r
- FreePool ((VOID *)LogicalVolInt);\r
+ Length = LogicalVolInt->NumberOfPartitions * sizeof (UINT32) * 2;\r
+ for (; Index < Length; Index += sizeof (UINT32)) {\r
+ LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);\r
+ //\r
+ // Check if size is not specified\r
+ //\r
+ if (LsnsNo == 0xFFFFFFFFUL) {\r
+ continue;\r
+ }\r
+ //\r
+ // Accumulate used volume space\r
+ //\r
+ *VolumeSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);\r
}\r
\r
- return EFI_SUCCESS;\r
+ Status = EFI_SUCCESS;\r
+\r
+Out_Free:\r
+ //\r
+ // Free Logical Volume Integrity Descriptor\r
+ //\r
+ FreePool (LogicalVolInt);\r
+\r
+ return Status;\r
}\r
\r
/**\r
{ 0x89, 0x56, 0x73, 0xCD, 0xA3, 0x26, 0xCD, 0x0A } \\r
}\r
\r
-#define UDF_DEFAULT_LV_NUM 0\r
-\r
-#define IS_PVD(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 1))\r
-#define IS_PD(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 5))\r
-#define IS_LVD(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 6))\r
-#define IS_TD(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 8))\r
-#define IS_FSD(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 256))\r
-#define IS_FE(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 261))\r
-#define IS_EFE(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 266))\r
-#define IS_FID(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 257))\r
-#define IS_AED(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 258))\r
-#define IS_LVID(_Pointer) \\r
- ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 9))\r
-\r
-#define _GET_FILETYPE(_Pointer) \\r
- (IS_FE (_Pointer) ? \\r
- (((UDF_FILE_ENTRY *)(_Pointer))->IcbTag.FileType) \\r
- : \\r
- (((UDF_EXTENDED_FILE_ENTRY *)(_Pointer))->IcbTag.FileType))\r
-\r
-#define IS_FE_DIRECTORY(_Pointer) \\r
- ((BOOLEAN)(_GET_FILETYPE (_Pointer) == 4))\r
-#define IS_FE_STANDARD_FILE(_Pointer) \\r
- ((BOOLEAN)(_GET_FILETYPE (_Pointer) == 5))\r
-#define IS_FE_SYMLINK(_Pointer) \\r
- ((BOOLEAN)(_GET_FILETYPE (_Pointer) == 12))\r
+#define FE_ICB_FILE_TYPE(_Ptr) \\r
+ (UDF_FILE_ENTRY_TYPE)( \\r
+ ((UDF_DESCRIPTOR_TAG *)(_Ptr))->TagIdentifier == UdfFileEntry ? \\r
+ ((UDF_FILE_ENTRY *)(_Ptr))->IcbTag.FileType : \\r
+ ((UDF_EXTENDED_FILE_ENTRY *)(_Ptr))->IcbTag.FileType)\r
+\r
+typedef enum {\r
+ UdfFileEntryDirectory = 4,\r
+ UdfFileEntryStandardFile = 5,\r
+ UdfFileEntrySymlink = 12,\r
+} UDF_FILE_ENTRY_TYPE;\r
\r
#define HIDDEN_FILE (1 << 0)\r
#define DIRECTORY_FILE (1 << 1)\r
#define DELETED_FILE (1 << 2)\r
#define PARENT_FILE (1 << 3)\r
\r
-#define _GET_FILE_CHARS(_Pointer) \\r
- (((UDF_FILE_IDENTIFIER_DESCRIPTOR *)(_Pointer))->FileCharacteristics)\r
-\r
-#define IS_FID_HIDDEN_FILE(_Pointer) \\r
- ((BOOLEAN)(_GET_FILE_CHARS (_Pointer) & HIDDEN_FILE))\r
-#define IS_FID_DIRECTORY_FILE(_Pointer) \\r
- ((BOOLEAN)(_GET_FILE_CHARS (_Pointer) & DIRECTORY_FILE))\r
-#define IS_FID_DELETED_FILE(_Pointer) \\r
- ((BOOLEAN)(_GET_FILE_CHARS (_Pointer) & DELETED_FILE))\r
-#define IS_FID_PARENT_FILE(_Pointer) \\r
- ((BOOLEAN)(_GET_FILE_CHARS (_Pointer) & PARENT_FILE))\r
-#define IS_FID_NORMAL_FILE(_Pointer) \\r
- ((BOOLEAN)(!IS_FID_DIRECTORY_FILE (_Pointer) && \\r
- !IS_FID_PARENT_FILE (_Pointer)))\r
+#define IS_FID_HIDDEN_FILE(_Fid) \\r
+ (BOOLEAN)((_Fid)->FileCharacteristics & HIDDEN_FILE)\r
+#define IS_FID_DIRECTORY_FILE(_Fid) \\r
+ (BOOLEAN)((_Fid)->FileCharacteristics & DIRECTORY_FILE)\r
+#define IS_FID_DELETED_FILE(_Fid) \\r
+ (BOOLEAN)((_Fid)->FileCharacteristics & DELETED_FILE)\r
+#define IS_FID_PARENT_FILE(_Fid) \\r
+ (BOOLEAN)((_Fid)->FileCharacteristics & PARENT_FILE)\r
+#define IS_FID_NORMAL_FILE(_Fid) \\r
+ (BOOLEAN)(!IS_FID_DIRECTORY_FILE (_Fid) && \\r
+ !IS_FID_PARENT_FILE (_Fid))\r
\r
typedef enum {\r
ShortAdsSequence,\r
#define IS_VALID_COMPRESSION_ID(_CompId) \\r
((BOOLEAN)((_CompId) == 8 || (_CompId) == 16))\r
\r
-#define LV_BLOCK_SIZE(_Vol, _LvNum) \\r
- (_Vol)->LogicalVolDescs[(_LvNum)]->LogicalBlockSize\r
-\r
#define UDF_STANDARD_IDENTIFIER_LENGTH 5\r
\r
-#define LV_UDF_REVISION(_Lv) \\r
- *(UINT16 *)(UINTN)(_Lv)->DomainIdentifier.IdentifierSuffix\r
-\r
#pragma pack(1)\r
\r
typedef struct {\r
\r
#pragma pack(1)\r
\r
-typedef struct {\r
- UINT8 CharacterSetType;\r
- UINT8 CharacterSetInfo[63];\r
-} UDF_CHAR_SPEC;\r
-\r
-typedef struct {\r
- UINT8 Flags;\r
- UINT8 Identifier[23];\r
- UINT8 IdentifierSuffix[8];\r
-} UDF_ENTITY_ID;\r
-\r
typedef struct {\r
UINT16 TypeAndTimezone;\r
INT16 Year;\r
UINT8 Microseconds;\r
} UDF_TIMESTAMP;\r
\r
-typedef struct {\r
- UINT32 LogicalBlockNumber;\r
- UINT16 PartitionReferenceNumber;\r
-} UDF_LB_ADDR;\r
-\r
-typedef struct {\r
- UINT32 ExtentLength;\r
- UDF_LB_ADDR ExtentLocation;\r
- UINT8 ImplementationUse[6];\r
-} UDF_LONG_ALLOCATION_DESCRIPTOR;\r
-\r
typedef struct {\r
UDF_DESCRIPTOR_TAG DescriptorTag;\r
UINT32 PrevAllocationExtentDescriptor;\r
UINT8 StructureData[2040];\r
} UDF_VOLUME_DESCRIPTOR;\r
\r
+typedef struct {\r
+ UDF_DESCRIPTOR_TAG DescriptorTag;\r
+ UDF_TIMESTAMP RecordingDateTime;\r
+ UINT32 IntegrityType;\r
+ UDF_EXTENT_AD NextIntegrityExtent;\r
+ UINT8 LogicalVolumeContentsUse[32];\r
+ UINT32 NumberOfPartitions;\r
+ UINT32 LengthOfImplementationUse;\r
+ UINT8 Data[0];\r
+} UDF_LOGICAL_VOLUME_INTEGRITY;\r
+\r
typedef struct {\r
UDF_DESCRIPTOR_TAG DescriptorTag;\r
UINT32 VolumeDescriptorSequenceNumber;\r
UINT8 Reserved[156];\r
} UDF_PARTITION_DESCRIPTOR;\r
\r
-typedef struct {\r
- UDF_DESCRIPTOR_TAG DescriptorTag;\r
- UINT32 VolumeDescriptorSequenceNumber;\r
- UDF_CHAR_SPEC DescriptorCharacterSet;\r
- UINT8 LogicalVolumeIdentifier[128];\r
- UINT32 LogicalBlockSize;\r
- UDF_ENTITY_ID DomainIdentifier;\r
- UDF_LONG_ALLOCATION_DESCRIPTOR LogicalVolumeContentsUse;\r
- UINT32 MapTableLength;\r
- UINT32 NumberOfPartitionMaps;\r
- UDF_ENTITY_ID ImplementationIdentifier;\r
- UINT8 ImplementationUse[128];\r
- UDF_EXTENT_AD IntegritySequenceExtent;\r
- UINT8 PartitionMaps[6];\r
-} UDF_LOGICAL_VOLUME_DESCRIPTOR;\r
-\r
-typedef struct {\r
- UDF_DESCRIPTOR_TAG DescriptorTag;\r
- UDF_TIMESTAMP RecordingDateTime;\r
- UINT32 IntegrityType;\r
- UDF_EXTENT_AD NextIntegrityExtent;\r
- UINT8 LogicalVolumeContentsUse[32];\r
- UINT32 NumberOfPartitions;\r
- UINT32 LengthOfImplementationUse;\r
- UINT8 Data[0];\r
-} UDF_LOGICAL_VOLUME_INTEGRITY;\r
-\r
typedef struct {\r
UDF_DESCRIPTOR_TAG DescriptorTag;\r
UDF_TIMESTAMP RecordingDateAndTime;\r
// UDF filesystem driver's private data\r
//\r
typedef struct {\r
- UDF_LOGICAL_VOLUME_DESCRIPTOR **LogicalVolDescs;\r
- UINTN LogicalVolDescsNo;\r
- UDF_PARTITION_DESCRIPTOR **PartitionDescs;\r
- UINTN PartitionDescsNo;\r
- UDF_FILE_SET_DESCRIPTOR **FileSetDescs;\r
- UINTN FileSetDescsNo;\r
+ UINT64 MainVdsStartLocation;\r
+ UDF_LOGICAL_VOLUME_DESCRIPTOR LogicalVolDesc;\r
+ UDF_PARTITION_DESCRIPTOR PartitionDesc;\r
+ UDF_FILE_SET_DESCRIPTOR FileSetDesc;\r
UINTN FileEntrySize;\r
} UDF_VOLUME_INFO;\r
\r
OUT UDF_FILE_INFO *File\r
);\r
\r
-/**\r
- Clean up in-memory UDF volume information.\r
-\r
- @param[in] Volume Volume information pointer.\r
-\r
-**/\r
-VOID\r
-CleanupVolumeInformation (\r
- IN UDF_VOLUME_INFO *Volume\r
- );\r
-\r
/**\r
Clean up in-memory UDF file information.\r
\r