Handle on-disk format and volume structures in UDF/ECMA-167 file systems.\r
\r
Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>\r
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License which accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
**/\r
\r
#include "Udf.h"\r
\r
+//\r
+// Vendor-Defined Device Path GUID for UDF file system\r
+//\r
+EFI_GUID gUdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;\r
+\r
+/**\r
+ Find the anchor volume descriptor pointer.\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[out] AnchorPoint Anchor volume descriptor pointer.\r
+\r
+ @retval EFI_SUCCESS Anchor volume descriptor pointer found.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval other Anchor volume descriptor pointer not found.\r
+\r
+**/\r
EFI_STATUS\r
FindAnchorVolumeDescriptorPointer (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\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
+ BlockSize = BlockIo->Media->BlockSize;\r
+ EndLBA = BlockIo->Media->LastBlock;\r
DescriptorLBAs[0] = 256;\r
DescriptorLBAs[1] = EndLBA - 256;\r
DescriptorLBAs[2] = EndLBA;\r
\r
for (Index = 0; Index < ARRAY_SIZE (DescriptorLBAs); Index++) {\r
Status = DiskIo->ReadDisk (\r
- DiskIo,\r
- BlockIo->Media->MediaId,\r
- MultU64x32 (DescriptorLBAs[Index], BlockSize),\r
- sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),\r
- (VOID *)AnchorPoint\r
- );\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32 (DescriptorLBAs[Index], BlockSize),\r
+ sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER),\r
+ (VOID *)AnchorPoint\r
+ );\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
// No AVDP found.\r
//\r
return EFI_VOLUME_CORRUPTED;\r
}\r
\r
+/**\r
+ Save the content of Logical Volume Descriptors and Partitions Descriptors in\r
+ memory.\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[in] AnchorPoint Anchor volume descriptor pointer.\r
+ @param[out] Volume UDF volume information structure.\r
+\r
+ @retval EFI_SUCCESS The descriptors were saved.\r
+ @retval EFI_OUT_OF_RESOURCES The descriptors were not saved due to lack of\r
+ resources.\r
+ @retval other The descriptors were not saved due to\r
+ ReadDisk error.\r
+\r
+**/\r
EFI_STATUS\r
StartMainVolumeDescriptorSequence (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\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
- BlockIo->Media->MediaId,\r
- MultU64x32 (StartingLsn, BlockSize),\r
- BlockSize,\r
- Buffer\r
- );\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 (\r
+ (UINT64)ExtentAd->ExtentLength,\r
+ BlockSize\r
+ );\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
+ 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
- //\r
- // Found a Terminating Descriptor. Stop the sequence then.\r
- //\r
- break;\r
- }\r
+ DescriptorTag = Buffer;\r
\r
- if (IS_LVD (Buffer)) {\r
- //\r
- // Found a 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
+ switch (DescriptorTag->TagIdentifier) {\r
+ case UdfPartitionDescriptor:\r
+ //\r
+ // Save Partition Descriptor\r
+ //\r
+ CopyMem (&Volume->PartitionDesc, Buffer, sizeof (Volume->PartitionDesc));\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 UdfLogicalVolumeDescriptor:\r
+ //\r
+ // Save Logical Volume Descriptor\r
+ //\r
+ CopyMem (&Volume->LogicalVolDesc, Buffer, sizeof (Volume->LogicalVolDesc));\r
+ break;\r
\r
- CopyMem ((VOID *)PartitionDesc, Buffer,\r
- sizeof (UDF_PARTITION_DESCRIPTOR));\r
- Volume->PartitionDescs[Volume->PartitionDescsNo++] = PartitionDesc;\r
- }\r
+ case UdfTerminatingDescriptor:\r
+ StopSequence = TRUE;\r
+ break;\r
\r
- StartingLsn++;\r
+ default:\r
+ ;\r
+ }\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
-\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
+ Status = EFI_SUCCESS;\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
-// Return a Partition Descriptor given a Long Allocation Descriptor. This is\r
-// necessary to calculate the right extent (LongAd) offset which is added up\r
-// with partition's starting location.\r
-//\r
+/**\r
+ Return a Partition Descriptor given a Long Allocation Descriptor. This is\r
+ necessary to calculate the right extent (LongAd) offset which is added up\r
+ with partition's starting location.\r
+\r
+ @param[in] Volume Volume information pointer.\r
+ @param[in] LongAd Long Allocation Descriptor pointer.\r
+\r
+ @return A pointer to a Partition Descriptor.\r
+\r
+**/\r
UDF_PARTITION_DESCRIPTOR *\r
GetPdFromLongAd (\r
IN UDF_VOLUME_INFO *Volume,\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
- case 0x0102:\r
- //\r
- // As per 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
- //\r
- // Ensure Type 1 Partition map. Other types aren't supported in this\r
- // implementation.\r
- //\r
- if (LogicalVolDesc->PartitionMaps[0] != 1 ||\r
- LogicalVolDesc->PartitionMaps[1] != 6) {\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
+ // 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
+ // UDF 1.50 through 2.60 specs say:\r
+ //\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. Hence, the 'PartitionReferenceNumber' field (the index\r
+ // used to access Partition Maps data within the Logical Volume Descriptor)\r
+ // in the Long Allocation Descriptor should be 0 to indicate there is only\r
+ // one partition.\r
+ //\r
+ if (LongAd->ExtentLocation.PartitionReferenceNumber != 0) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Since only one partition, get the first one directly.\r
+ //\r
+ PartitionNum = *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]);\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Unsupported UDF revision\r
+ //\r
return NULL;\r
- }\r
- PartitionNum = *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]);\r
- break;\r
- case 0x0260:\r
- //\r
- // Fall through.\r
- //\r
- default:\r
- PartitionNum = LongAd->ExtentLocation.PartitionReferenceNumber;\r
- break;\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
}\r
\r
-//\r
-// Return logical sector number of a given Long Allocation Descriptor.\r
-//\r
-UINT64\r
+/**\r
+ Return logical sector number of a given Long Allocation Descriptor.\r
+\r
+ @param[in] Volume Volume information pointer.\r
+ @param[in] LongAd Long Allocation Descriptor pointer.\r
+ @param[out] Lsn Logical sector number pointer.\r
+\r
+ @retval EFI_SUCCESS Logical sector number successfully returned.\r
+ @retval EFI_UNSUPPORTED Logical sector number is not returned due to\r
+ unrecognized format.\r
+\r
+**/\r
+EFI_STATUS\r
GetLongAdLsn (\r
- IN UDF_VOLUME_INFO *Volume,\r
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd\r
+ IN UDF_VOLUME_INFO *Volume,\r
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd,\r
+ OUT UINT64 *Lsn\r
)\r
{\r
- UDF_PARTITION_DESCRIPTOR *PartitionDesc;\r
+ UDF_PARTITION_DESCRIPTOR *PartitionDesc;\r
\r
PartitionDesc = GetPdFromLongAd (Volume, LongAd);\r
- ASSERT (PartitionDesc != NULL);\r
+ if (PartitionDesc == NULL) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "%a: Fail to get the Partition Descriptor from the given Long Allocation Descriptor.\n",\r
+ __FUNCTION__\r
+ ));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ *Lsn = (UINT64)PartitionDesc->PartitionStartingLocation -\r
+ Volume->MainVdsStartLocation +\r
+ LongAd->ExtentLocation.LogicalBlockNumber;\r
\r
- return (UINT64)PartitionDesc->PartitionStartingLocation +\r
- LongAd->ExtentLocation.LogicalBlockNumber;\r
+ return EFI_SUCCESS;\r
}\r
\r
-//\r
-// Return logical sector number of a given Short Allocation Descriptor.\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
+ @return The logical sector number of a given Short Allocation Descriptor.\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
- return (UINT64)PartitionDesc->PartitionStartingLocation +\r
- ShortAd->ExtentPosition;\r
+ return (UINT64)PartitionDesc->PartitionStartingLocation -\r
+ Volume->MainVdsStartLocation + ShortAd->ExtentPosition;\r
}\r
\r
-//\r
-// Find File Set Descriptor of a given Logical Volume Descriptor.\r
-//\r
-// The found FSD will contain the extent (LogicalVolumeContentsUse) where our\r
-// root directory is.\r
-//\r
+/**\r
+ Find File Set Descriptor of a given Logical Volume Descriptor.\r
+\r
+ The found FSD will contain the extent (LogicalVolumeContentsUse) where our\r
+ root directory is.\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[in] Volume Volume information pointer.\r
+\r
+ @retval EFI_SUCCESS File Set Descriptor pointer found.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval other File Set Descriptor pointer not found.\r
+\r
+**/\r
EFI_STATUS\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 EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,\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
- Lsn = GetLongAdLsn (Volume, &LogicalVolDesc->LogicalVolumeContentsUse);\r
+ LogicalVolDesc = &Volume->LogicalVolDesc;\r
+ Status = GetLongAdLsn (Volume, &LogicalVolDesc->LogicalVolumeContentsUse, &Lsn);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\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
- );\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32 (Lsn, LogicalVolDesc->LogicalBlockSize),\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
-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
+ Read Volume and File Structure on an UDF file system.\r
\r
- FreePool ((VOID *)Volume->FileSetDescs);\r
- Volume->FileSetDescs = NULL;\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[out] Volume Volume information pointer.\r
\r
-Error_Alloc_Fsd:\r
- return Status;\r
-}\r
+ @retval EFI_SUCCESS Volume and File Structure were read.\r
+ @retval other Volume and File Structure were not read.\r
\r
-//\r
-// Read Volume and File Structure on an UDF file system.\r
-//\r
+**/\r
EFI_STATUS\r
ReadVolumeFileStructure (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\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
- DiskIo,\r
- &AnchorPoint\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ &AnchorPoint\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\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
- DiskIo,\r
- &AnchorPoint,\r
- Volume\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ &AnchorPoint,\r
+ Volume\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
return Status;\r
}\r
\r
-//\r
-// Calculate length of a given File Identifier Descriptor.\r
-//\r
+/**\r
+ Calculate length of a given File Identifier Descriptor.\r
+\r
+ @param[in] FileIdentifierDesc File Identifier Descriptor pointer.\r
+\r
+ @return The length of a given File Identifier Descriptor.\r
+\r
+**/\r
UINT64\r
GetFidDescriptorLength (\r
IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc\r
)\r
{\r
return (UINT64)(\r
- (INTN)((OFFSET_OF (UDF_FILE_IDENTIFIER_DESCRIPTOR, Data[0]) + 3 +\r
- FileIdentifierDesc->LengthOfFileIdentifier +\r
- FileIdentifierDesc->LengthOfImplementationUse) >> 2) << 2\r
- );\r
+ (INTN)((OFFSET_OF (UDF_FILE_IDENTIFIER_DESCRIPTOR, Data[0]) + 3 +\r
+ FileIdentifierDesc->LengthOfFileIdentifier +\r
+ FileIdentifierDesc->LengthOfImplementationUse) >> 2) << 2\r
+ );\r
}\r
\r
-//\r
-// Duplicate a given File Identifier Descriptor.\r
-//\r
+/**\r
+ Duplicate a given File Identifier Descriptor.\r
+\r
+ @param[in] FileIdentifierDesc File Identifier Descriptor pointer.\r
+ @param[out] NewFileIdentifierDesc The duplicated File Identifier Descriptor.\r
+\r
+**/\r
VOID\r
DuplicateFid (\r
IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,\r
{\r
*NewFileIdentifierDesc =\r
(UDF_FILE_IDENTIFIER_DESCRIPTOR *)AllocateCopyPool (\r
- (UINTN) GetFidDescriptorLength (FileIdentifierDesc), FileIdentifierDesc);\r
+ (UINTN)GetFidDescriptorLength (FileIdentifierDesc),\r
+ FileIdentifierDesc\r
+ );\r
}\r
\r
-//\r
-// Duplicate either a given File Entry or a given Extended File Entry.\r
-//\r
+/**\r
+ Duplicate either a given File Entry or a given Extended File Entry.\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] Volume Volume information pointer.\r
+ @param[in] FileEntry (Extended) File Entry pointer.\r
+ @param[out] NewFileEntry The duplicated (Extended) File Entry.\r
+\r
+**/\r
VOID\r
DuplicateFe (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
*NewFileEntry = AllocateCopyPool (Volume->FileEntrySize, FileEntry);\r
}\r
\r
-//\r
-// Get raw data + length of a given File Entry or Extended File Entry.\r
-//\r
-// The file's recorded data can contain either real file content (inline) or\r
-// a sequence of extents (or Allocation Descriptors) which tells where file's\r
-// content is stored in.\r
-//\r
-// NOTE: The FE/EFE can be thought it was an inode.\r
-//\r
-VOID\r
+/**\r
+ Get raw data + length of a given File Entry or Extended File Entry.\r
+\r
+ The file's recorded data can contain either real file content (inline) or\r
+ a sequence of extents (or Allocation Descriptors) which tells where file's\r
+ content is stored in.\r
+\r
+ NOTE: The FE/EFE can be thought it was an inode.\r
+\r
+ @attention This is boundary function that may receive untrusted input.\r
+ @attention The input is from FileSystem.\r
+\r
+ The (Extended) File Entry is external input, so this routine will do basic\r
+ validation for (Extended) File Entry and report status.\r
+\r
+ @param[in] FileEntryData (Extended) File Entry pointer.\r
+ @param[in] FileEntrySize Size of the (Extended) File Entry specified\r
+ by FileEntryData.\r
+ @param[out] Data Buffer contains the raw data of a given\r
+ (Extended) File Entry.\r
+ @param[out] Length Length of the data in Buffer.\r
+\r
+ @retval EFI_SUCCESS Raw data and size of the FE/EFE was read.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+\r
+**/\r
+EFI_STATUS\r
GetFileEntryData (\r
IN VOID *FileEntryData,\r
+ IN UINTN FileEntrySize,\r
OUT VOID **Data,\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
+ *Length = ExtendedFileEntry->InformationLength;\r
+ *Data = (VOID *)((UINT8 *)ExtendedFileEntry->Data +\r
+ ExtendedFileEntry->LengthOfExtendedAttributes);\r
+ } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {\r
FileEntry = (UDF_FILE_ENTRY *)FileEntryData;\r
\r
- *Length = FileEntry->InformationLength;\r
- *Data = (VOID *)((UINT8 *)FileEntry->Data +\r
- FileEntry->LengthOfExtendedAttributes);\r
+ *Length = FileEntry->InformationLength;\r
+ *Data = (VOID *)((UINT8 *)FileEntry->Data +\r
+ FileEntry->LengthOfExtendedAttributes);\r
+ }\r
+\r
+ if ((*Length > FileEntrySize) ||\r
+ ((UINTN)FileEntryData > (UINTN)(*Data)) ||\r
+ ((UINTN)(*Data) - (UINTN)FileEntryData > FileEntrySize - *Length))\r
+ {\r
+ return EFI_VOLUME_CORRUPTED;\r
}\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
-//\r
-// Get Allocation Descriptors' data information from a given FE/EFE.\r
-//\r
-VOID\r
+/**\r
+ Get Allocation Descriptors' data information from a given FE/EFE.\r
+\r
+ @attention This is boundary function that may receive untrusted input.\r
+ @attention The input is from FileSystem.\r
+\r
+ The (Extended) File Entry is external input, so this routine will do basic\r
+ validation for (Extended) File Entry and report status.\r
+\r
+ @param[in] FileEntryData (Extended) File Entry pointer.\r
+ @param[in] FileEntrySize Size of the (Extended) File Entry specified\r
+ by FileEntryData.\r
+ @param[out] AdsData Buffer contains the Allocation Descriptors'\r
+ data from a given FE/EFE.\r
+ @param[out] Length Length of the data in AdsData.\r
+\r
+ @retval EFI_SUCCESS The data and size of Allocation Descriptors\r
+ were read from the FE/EFE.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+\r
+**/\r
+EFI_STATUS\r
GetAdsInformation (\r
IN VOID *FileEntryData,\r
+ IN UINTN FileEntrySize,\r
OUT VOID **AdsData,\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
+ *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
+ *Length = FileEntry->LengthOfAllocationDescriptors;\r
*AdsData = (VOID *)((UINT8 *)FileEntry->Data +\r
FileEntry->LengthOfExtendedAttributes);\r
}\r
+\r
+ if ((*Length > FileEntrySize) ||\r
+ ((UINTN)FileEntryData > (UINTN)(*AdsData)) ||\r
+ ((UINTN)(*AdsData) - (UINTN)FileEntryData > FileEntrySize - *Length))\r
+ {\r
+ return EFI_VOLUME_CORRUPTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
-//\r
-// Read next Long Allocation Descriptor from a given file's data.\r
-//\r
+/**\r
+ Read next Long Allocation Descriptor from a given file's data.\r
+\r
+ @param[in] Data File's data pointer.\r
+ @param[in,out] Offset Starting offset of the File's data to read.\r
+ @param[in] Length Length of the data to read.\r
+ @param[out] FoundLongAd Long Allocation Descriptor pointer.\r
+\r
+ @retval EFI_SUCCESS A Long Allocation Descriptor was found.\r
+ @retval EFI_DEVICE_ERROR No more Long Allocation Descriptors.\r
+\r
+**/\r
EFI_STATUS\r
GetLongAdFromAds (\r
IN VOID *Data,\r
UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd;\r
UDF_EXTENT_FLAGS ExtentFlags;\r
\r
- for (;;) {\r
+ for ( ; ;) {\r
if (*Offset >= Length) {\r
//\r
// No more Long Allocation Descriptors.\r
// If it's either an indirect AD (Extended Alllocation Descriptor) or an\r
// allocated AD, then return it.\r
//\r
- ExtentFlags = GET_EXTENT_FLAGS (LONG_ADS_SEQUENCE, LongAd);\r
- if (ExtentFlags == EXTENT_IS_NEXT_EXTENT ||\r
- ExtentFlags == EXTENT_RECORDED_AND_ALLOCATED) {\r
+ ExtentFlags = GET_EXTENT_FLAGS (LongAdsSequence, LongAd);\r
+ if ((ExtentFlags == ExtentIsNextExtent) ||\r
+ (ExtentFlags == ExtentRecordedAndAllocated))\r
+ {\r
break;\r
}\r
\r
// This AD is either not recorded but allocated, or not recorded and not\r
// allocated. Skip it.\r
//\r
- *Offset += AD_LENGTH (LONG_ADS_SEQUENCE);\r
+ *Offset += AD_LENGTH (LongAdsSequence);\r
}\r
\r
*FoundLongAd = LongAd;\r
return EFI_SUCCESS;\r
}\r
\r
-//\r
-// Read next Short Allocation Descriptor from a given file's data.\r
-//\r
+/**\r
+ Read next Short Allocation Descriptor from a given file's data.\r
+\r
+ @param[in] Data File's data pointer.\r
+ @param[in,out] Offset Starting offset of the File's data to read.\r
+ @param[in] Length Length of the data to read.\r
+ @param[out] FoundShortAd Short Allocation Descriptor pointer.\r
+\r
+ @retval EFI_SUCCESS A Short Allocation Descriptor was found.\r
+ @retval EFI_DEVICE_ERROR No more Short Allocation Descriptors.\r
+\r
+**/\r
EFI_STATUS\r
GetShortAdFromAds (\r
IN VOID *Data,\r
OUT UDF_SHORT_ALLOCATION_DESCRIPTOR **FoundShortAd\r
)\r
{\r
- UDF_SHORT_ALLOCATION_DESCRIPTOR *ShortAd;\r
- UDF_EXTENT_FLAGS ExtentFlags;\r
+ UDF_SHORT_ALLOCATION_DESCRIPTOR *ShortAd;\r
+ UDF_EXTENT_FLAGS ExtentFlags;\r
\r
- for (;;) {\r
+ for ( ; ;) {\r
if (*Offset >= Length) {\r
//\r
// No more Short Allocation Descriptors.\r
// If it's either an indirect AD (Extended Alllocation Descriptor) or an\r
// allocated AD, then return it.\r
//\r
- ExtentFlags = GET_EXTENT_FLAGS (SHORT_ADS_SEQUENCE, ShortAd);\r
- if (ExtentFlags == EXTENT_IS_NEXT_EXTENT ||\r
- ExtentFlags == EXTENT_RECORDED_AND_ALLOCATED) {\r
+ ExtentFlags = GET_EXTENT_FLAGS (ShortAdsSequence, ShortAd);\r
+ if ((ExtentFlags == ExtentIsNextExtent) ||\r
+ (ExtentFlags == ExtentRecordedAndAllocated))\r
+ {\r
break;\r
}\r
\r
// This AD is either not recorded but allocated, or not recorded and not\r
// allocated. Skip it.\r
//\r
- *Offset += AD_LENGTH (SHORT_ADS_SEQUENCE);\r
+ *Offset += AD_LENGTH (ShortAdsSequence);\r
}\r
\r
*FoundShortAd = ShortAd;\r
return EFI_SUCCESS;\r
}\r
\r
-//\r
-// Get either a Short Allocation Descriptor or a Long Allocation Descriptor from\r
-// file's data.\r
-//\r
+/**\r
+ Get either a Short Allocation Descriptor or a Long Allocation Descriptor from\r
+ file's data.\r
+\r
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.\r
+ @param[in] Data File's data pointer.\r
+ @param[in,out] Offset Starting offset of the File's data to read.\r
+ @param[in] Length Length of the data to read.\r
+ @param[out] FoundAd Allocation Descriptor pointer.\r
+\r
+ @retval EFI_SUCCESS A Short Allocation Descriptor was found.\r
+ @retval EFI_DEVICE_ERROR No more Allocation Descriptors.\r
+ Invalid type of descriptor was given.\r
+\r
+**/\r
EFI_STATUS\r
GetAllocationDescriptor (\r
IN UDF_FE_RECORDING_FLAGS RecordingFlags,\r
OUT VOID **FoundAd\r
)\r
{\r
- if (RecordingFlags == LONG_ADS_SEQUENCE) {\r
+ if (RecordingFlags == LongAdsSequence) {\r
return GetLongAdFromAds (\r
- Data,\r
- Offset,\r
- Length,\r
- (UDF_LONG_ALLOCATION_DESCRIPTOR **)FoundAd\r
- );\r
- } else if (RecordingFlags == SHORT_ADS_SEQUENCE) {\r
+ Data,\r
+ Offset,\r
+ Length,\r
+ (UDF_LONG_ALLOCATION_DESCRIPTOR **)FoundAd\r
+ );\r
+ } else if (RecordingFlags == ShortAdsSequence) {\r
return GetShortAdFromAds (\r
- Data,\r
- Offset,\r
- Length,\r
- (UDF_SHORT_ALLOCATION_DESCRIPTOR **)FoundAd\r
- );\r
+ Data,\r
+ Offset,\r
+ Length,\r
+ (UDF_SHORT_ALLOCATION_DESCRIPTOR **)FoundAd\r
+ );\r
}\r
\r
+ //\r
+ // Code should never reach here.\r
+ //\r
+ ASSERT (FALSE);\r
return EFI_DEVICE_ERROR;\r
}\r
\r
-//\r
-// Return logical sector number of either Short or Long Allocation Descriptor.\r
-//\r
-UINT64\r
+/**\r
+ Return logical sector number of either Short or Long Allocation Descriptor.\r
+\r
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.\r
+ @param[in] Volume Volume information pointer.\r
+ @param[in] ParentIcb Long Allocation Descriptor pointer.\r
+ @param[in] Ad Allocation Descriptor pointer.\r
+ @param[out] Lsn Logical sector number pointer.\r
+\r
+ @retval EFI_SUCCESS Logical sector number of the given Allocation\r
+ Descriptor successfully returned.\r
+ @retval EFI_UNSUPPORTED Logical sector number of the given Allocation\r
+ Descriptor is not returned due to unrecognized\r
+ format.\r
+\r
+**/\r
+EFI_STATUS\r
GetAllocationDescriptorLsn (\r
- IN UDF_FE_RECORDING_FLAGS RecordingFlags,\r
- IN UDF_VOLUME_INFO *Volume,\r
- IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,\r
- IN VOID *Ad\r
+ IN UDF_FE_RECORDING_FLAGS RecordingFlags,\r
+ IN UDF_VOLUME_INFO *Volume,\r
+ IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb,\r
+ IN VOID *Ad,\r
+ OUT UINT64 *Lsn\r
)\r
{\r
- if (RecordingFlags == LONG_ADS_SEQUENCE) {\r
- return GetLongAdLsn (Volume, (UDF_LONG_ALLOCATION_DESCRIPTOR *)Ad);\r
- } else if (RecordingFlags == SHORT_ADS_SEQUENCE) {\r
- return GetShortAdLsn (\r
- GetPdFromLongAd (Volume, ParentIcb),\r
- (UDF_SHORT_ALLOCATION_DESCRIPTOR *)Ad\r
- );\r
+ UDF_PARTITION_DESCRIPTOR *PartitionDesc;\r
+\r
+ if (RecordingFlags == LongAdsSequence) {\r
+ return GetLongAdLsn (Volume, (UDF_LONG_ALLOCATION_DESCRIPTOR *)Ad, Lsn);\r
+ } else if (RecordingFlags == ShortAdsSequence) {\r
+ PartitionDesc = GetPdFromLongAd (Volume, ParentIcb);\r
+ if (PartitionDesc == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ *Lsn = GetShortAdLsn (\r
+ Volume,\r
+ PartitionDesc,\r
+ (UDF_SHORT_ALLOCATION_DESCRIPTOR *)Ad\r
+ );\r
+ return EFI_SUCCESS;\r
}\r
\r
- return 0;\r
+ //\r
+ // Code should never reach here.\r
+ //\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
}\r
\r
-//\r
-// Return offset + length of a given indirect Allocation Descriptor (AED).\r
-//\r
+/**\r
+ Return offset + length of a given indirect Allocation Descriptor (AED).\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[in] Volume Volume information pointer.\r
+ @param[in] ParentIcb Long Allocation Descriptor pointer.\r
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.\r
+ @param[in] Ad Allocation Descriptor pointer.\r
+ @param[out] Offset Offset of a given indirect Allocation\r
+ Descriptor.\r
+ @param[out] Length Length of a given indirect Allocation\r
+ Descriptor.\r
+\r
+ @retval EFI_SUCCESS The offset and length were returned.\r
+ @retval EFI_OUT_OF_RESOURCES The offset and length were not returned due\r
+ to lack of resources.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval other The offset and length were not returned.\r
+\r
+**/\r
EFI_STATUS\r
GetAedAdsOffset (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\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
- Volume,\r
- ParentIcb,\r
- Ad);\r
+ ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);\r
+ Status = GetAllocationDescriptorLsn (\r
+ RecordingFlags,\r
+ Volume,\r
+ ParentIcb,\r
+ Ad,\r
+ &Lsn\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
Data = AllocatePool (ExtentLength);\r
if (Data == NULL) {\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
//\r
Status = DiskIo->ReadDisk (\r
- DiskIo,\r
- BlockIo->Media->MediaId,\r
- MultU64x32 (Lsn, LogicalBlockSize),\r
- ExtentLength,\r
- Data\r
- );\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32 (Lsn, LogicalBlockSize),\r
+ ExtentLength,\r
+ Data\r
+ );\r
if (EFI_ERROR (Status)) {\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
// Get AED's block offset and its length.\r
//\r
*Offset = MultU64x32 (Lsn, LogicalBlockSize) +\r
- sizeof (UDF_ALLOCATION_EXTENT_DESCRIPTOR);\r
+ sizeof (UDF_ALLOCATION_EXTENT_DESCRIPTOR);\r
*Length = AllocExtDesc->LengthOfAllocationDescriptors;\r
\r
Exit:\r
return Status;\r
}\r
\r
-//\r
-// Read Allocation Extent Descriptor into memory.\r
-//\r
+/**\r
+ Read Allocation Extent Descriptor into memory.\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[in] Volume Volume information pointer.\r
+ @param[in] ParentIcb Long Allocation Descriptor pointer.\r
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.\r
+ @param[in] Ad Allocation Descriptor pointer.\r
+ @param[out] Data Buffer that contains the Allocation Extent\r
+ Descriptor.\r
+ @param[out] Length Length of Data.\r
+\r
+ @retval EFI_SUCCESS The Allocation Extent Descriptor was read.\r
+ @retval EFI_OUT_OF_RESOURCES The Allocation Extent Descriptor was not read\r
+ due to lack of resources.\r
+ @retval other Fail to read the disk.\r
+\r
+**/\r
EFI_STATUS\r
GetAedAdsData (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
// Get AED's offset + length.\r
//\r
Status = GetAedAdsOffset (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- ParentIcb,\r
- RecordingFlags,\r
- Ad,\r
- &Offset,\r
- Length\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ ParentIcb,\r
+ RecordingFlags,\r
+ Ad,\r
+ &Offset,\r
+ Length\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
//\r
// Allocate buffer to read in AED's data.\r
//\r
- *Data = AllocatePool ((UINTN) (*Length));\r
+ *Data = AllocatePool ((UINTN)(*Length));\r
if (*Data == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
return DiskIo->ReadDisk (\r
- DiskIo,\r
- BlockIo->Media->MediaId,\r
- Offset,\r
- (UINTN) (*Length),\r
- *Data\r
- );\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ Offset,\r
+ (UINTN)(*Length),\r
+ *Data\r
+ );\r
}\r
\r
-//\r
-// Function used to serialise reads of Allocation Descriptors.\r
-//\r
+/**\r
+ Function used to serialise reads of Allocation Descriptors.\r
+\r
+ @param[in] RecordingFlags Flag to indicate the type of descriptor.\r
+ @param[in] Ad Allocation Descriptor pointer.\r
+ @param[in, out] Buffer Buffer to hold the next Allocation Descriptor.\r
+ @param[in] Length Length of Buffer.\r
+\r
+ @retval EFI_SUCCESS Buffer was grown to hold the next Allocation\r
+ Descriptor.\r
+ @retval EFI_OUT_OF_RESOURCES Buffer was not grown due to lack of resources.\r
+\r
+**/\r
EFI_STATUS\r
GrowUpBufferToNextAd (\r
IN UDF_FE_RECORDING_FLAGS RecordingFlags,\r
IN UINT64 Length\r
)\r
{\r
- UINT32 ExtentLength;\r
+ UINT32 ExtentLength;\r
\r
ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);\r
\r
return EFI_OUT_OF_RESOURCES;\r
}\r
} else {\r
- *Buffer = ReallocatePool ((UINTN) Length, (UINTN) (Length + ExtentLength), *Buffer);\r
+ *Buffer = ReallocatePool ((UINTN)Length, (UINTN)(Length + ExtentLength), *Buffer);\r
if (*Buffer == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
return EFI_SUCCESS;\r
}\r
\r
-//\r
-// Read data or size of either a File Entry or an Extended File Entry.\r
-//\r
+/**\r
+ Read data or size of either a File Entry or an Extended File Entry.\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[in] Volume Volume information pointer.\r
+ @param[in] ParentIcb Long Allocation Descriptor pointer.\r
+ @param[in] FileEntryData FE/EFE structure pointer.\r
+ @param[in, out] ReadFileInfo Read file information pointer.\r
+\r
+ @retval EFI_SUCCESS Data or size of a FE/EFE was read.\r
+ @retval EFI_OUT_OF_RESOURCES Data or size of a FE/EFE was not read due to\r
+ lack of resources.\r
+ @retval EFI_INVALID_PARAMETER The read file flag given in ReadFileInfo is\r
+ invalid.\r
+ @retval EFI_UNSUPPORTED The FE recording flag given in FileEntryData\r
+ is not supported.\r
+ @retval other Data or size of a FE/EFE was not read.\r
+\r
+**/\r
EFI_STATUS\r
ReadFile (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
EFI_STATUS Status;\r
UINT32 LogicalBlockSize;\r
VOID *Data;\r
+ VOID *DataBak;\r
UINT64 Length;\r
VOID *Ad;\r
UINT64 AdOffset;\r
UINT32 ExtentLength;\r
UDF_FE_RECORDING_FLAGS RecordingFlags;\r
\r
- LogicalBlockSize = LV_BLOCK_SIZE (Volume, UDF_DEFAULT_LV_NUM);\r
- DoFreeAed = FALSE;\r
+ LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;\r
+ DoFreeAed = FALSE;\r
+\r
+ //\r
+ // set BytesLeft to suppress incorrect compiler/analyzer warnings\r
+ //\r
+ BytesLeft = 0;\r
+ DataOffset = 0;\r
+ FilePosition = 0;\r
+ FinishedSeeking = FALSE;\r
+ Data = NULL;\r
\r
switch (ReadFileInfo->Flags) {\r
- case READ_FILE_GET_FILESIZE:\r
- case READ_FILE_ALLOCATE_AND_READ:\r
- //\r
- // Initialise ReadFileInfo structure for either getting file size, or\r
- // reading file's recorded data.\r
- //\r
- ReadFileInfo->ReadLength = 0;\r
- ReadFileInfo->FileData = NULL;\r
- break;\r
- case READ_FILE_SEEK_AND_READ:\r
- //\r
- // About to seek a file and/or read its data.\r
- //\r
- Length = ReadFileInfo->FileSize - ReadFileInfo->FilePosition;\r
- if (ReadFileInfo->FileDataSize > Length) {\r
+ case ReadFileGetFileSize:\r
+ case ReadFileAllocateAndRead:\r
//\r
- // About to read beyond the EOF -- truncate it.\r
+ // Initialise ReadFileInfo structure for either getting file size, or\r
+ // reading file's recorded data.\r
//\r
- ReadFileInfo->FileDataSize = Length;\r
- }\r
-\r
- //\r
- // Initialise data to start seeking and/or reading a file.\r
- //\r
- BytesLeft = ReadFileInfo->FileDataSize;\r
- DataOffset = 0;\r
- FilePosition = 0;\r
- FinishedSeeking = FALSE;\r
-\r
- break;\r
- }\r
-\r
- RecordingFlags = GET_FE_RECORDING_FLAGS (FileEntryData);\r
- switch (RecordingFlags) {\r
- case INLINE_DATA:\r
- //\r
- // There are no extents for this FE/EFE. All data is inline.\r
- //\r
- GetFileEntryData (FileEntryData, &Data, &Length);\r
-\r
- if (ReadFileInfo->Flags == READ_FILE_GET_FILESIZE) {\r
- ReadFileInfo->ReadLength = Length;\r
- } else if (ReadFileInfo->Flags == READ_FILE_ALLOCATE_AND_READ) {\r
+ ReadFileInfo->ReadLength = 0;\r
+ ReadFileInfo->FileData = NULL;\r
+ break;\r
+ case ReadFileSeekAndRead:\r
//\r
- // Allocate buffer for starting read data.\r
+ // About to seek a file and/or read its data.\r
//\r
- ReadFileInfo->FileData = AllocatePool ((UINTN) Length);\r
- if (ReadFileInfo->FileData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Length = ReadFileInfo->FileSize - ReadFileInfo->FilePosition;\r
+ if (ReadFileInfo->FileDataSize > Length) {\r
+ //\r
+ // About to read beyond the EOF -- truncate it.\r
+ //\r
+ ReadFileInfo->FileDataSize = Length;\r
}\r
\r
//\r
- // Read all inline data into ReadFileInfo->FileData\r
+ // Initialise data to start seeking and/or reading a file.\r
//\r
- CopyMem (ReadFileInfo->FileData, Data, (UINTN) Length);\r
- ReadFileInfo->ReadLength = Length;\r
- } else if (ReadFileInfo->Flags == READ_FILE_SEEK_AND_READ) {\r
- //\r
- // If FilePosition is non-zero, seek file to FilePosition, read\r
- // FileDataSize bytes and then updates FilePosition.\r
- //\r
- CopyMem (\r
- ReadFileInfo->FileData,\r
- (VOID *)((UINT8 *)Data + ReadFileInfo->FilePosition),\r
- (UINTN) ReadFileInfo->FileDataSize\r
- );\r
-\r
- ReadFileInfo->FilePosition += ReadFileInfo->FileDataSize;\r
- } else {\r
- ASSERT (FALSE);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ BytesLeft = ReadFileInfo->FileDataSize;\r
+ DataOffset = 0;\r
+ FilePosition = 0;\r
+ FinishedSeeking = FALSE;\r
\r
- Status = EFI_SUCCESS;\r
- break;\r
-\r
- case LONG_ADS_SEQUENCE:\r
- case SHORT_ADS_SEQUENCE:\r
- //\r
- // This FE/EFE contains a run of Allocation Descriptors. Get data + size\r
- // for start reading them out.\r
- //\r
- GetAdsInformation (FileEntryData, &Data, &Length);\r
- AdOffset = 0;\r
-\r
- for (;;) {\r
- //\r
- // Read AD.\r
- //\r
- Status = GetAllocationDescriptor (\r
- RecordingFlags,\r
- Data,\r
- &AdOffset,\r
- Length,\r
- &Ad\r
- );\r
- if (Status == EFI_DEVICE_ERROR) {\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
+ break;\r
+ }\r
\r
+ RecordingFlags = GET_FE_RECORDING_FLAGS (FileEntryData);\r
+ switch (RecordingFlags) {\r
+ case InlineData:\r
//\r
- // Check if AD is an indirect AD. If so, read Allocation Extent\r
- // Descriptor and its extents (ADs).\r
+ // There are no extents for this FE/EFE. All data is inline.\r
//\r
- if (GET_EXTENT_FLAGS (RecordingFlags, Ad) == EXTENT_IS_NEXT_EXTENT) {\r
- if (!DoFreeAed) {\r
- DoFreeAed = TRUE;\r
- } else {\r
- FreePool (Data);\r
- }\r
-\r
- Status = GetAedAdsData (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- ParentIcb,\r
- RecordingFlags,\r
- Ad,\r
- &Data,\r
- &Length\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error_Get_Aed;\r
- }\r
-\r
- AdOffset = 0;\r
- continue;\r
+ Status = GetFileEntryData (FileEntryData, Volume->FileEntrySize, &Data, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
- ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);\r
-\r
- Lsn = GetAllocationDescriptorLsn (RecordingFlags,\r
- Volume,\r
- ParentIcb,\r
- Ad);\r
-\r
- switch (ReadFileInfo->Flags) {\r
- case READ_FILE_GET_FILESIZE:\r
- ReadFileInfo->ReadLength += ExtentLength;\r
- break;\r
- case READ_FILE_ALLOCATE_AND_READ:\r
+ if (ReadFileInfo->Flags == ReadFileGetFileSize) {\r
+ ReadFileInfo->ReadLength = Length;\r
+ } else if (ReadFileInfo->Flags == ReadFileAllocateAndRead) {\r
//\r
- // Increase FileData (if necessary) to read next extent.\r
+ // Allocate buffer for starting read data.\r
//\r
- Status = GrowUpBufferToNextAd (\r
- RecordingFlags,\r
- Ad,\r
- &ReadFileInfo->FileData,\r
- ReadFileInfo->ReadLength\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error_Alloc_Buffer_To_Next_Ad;\r
+ ReadFileInfo->FileData = AllocatePool ((UINTN)Length);\r
+ if (ReadFileInfo->FileData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
//\r
- // Read extent's data into FileData.\r
+ // Read all inline data into ReadFileInfo->FileData\r
//\r
- Status = DiskIo->ReadDisk (\r
- DiskIo,\r
- BlockIo->Media->MediaId,\r
- MultU64x32 (Lsn, LogicalBlockSize),\r
- ExtentLength,\r
- (VOID *)((UINT8 *)ReadFileInfo->FileData +\r
- ReadFileInfo->ReadLength)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error_Read_Disk_Blk;\r
- }\r
-\r
- ReadFileInfo->ReadLength += ExtentLength;\r
- break;\r
- case READ_FILE_SEEK_AND_READ:\r
+ CopyMem (ReadFileInfo->FileData, Data, (UINTN)Length);\r
+ ReadFileInfo->ReadLength = Length;\r
+ } else if (ReadFileInfo->Flags == ReadFileSeekAndRead) {\r
//\r
- // Seek file first before reading in its data.\r
+ // If FilePosition is non-zero, seek file to FilePosition, read\r
+ // FileDataSize bytes and then updates FilePosition.\r
//\r
- if (FinishedSeeking) {\r
- Offset = 0;\r
- goto Skip_File_Seek;\r
- }\r
+ CopyMem (\r
+ ReadFileInfo->FileData,\r
+ (VOID *)((UINT8 *)Data + ReadFileInfo->FilePosition),\r
+ (UINTN)ReadFileInfo->FileDataSize\r
+ );\r
\r
- if (FilePosition + ExtentLength < ReadFileInfo->FilePosition) {\r
- FilePosition += ExtentLength;\r
- goto Skip_Ad;\r
- }\r
+ ReadFileInfo->FilePosition += ReadFileInfo->FileDataSize;\r
+ } else {\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- if (FilePosition + ExtentLength > ReadFileInfo->FilePosition) {\r
- Offset = ReadFileInfo->FilePosition - FilePosition;\r
- } else {\r
- Offset = 0;\r
- }\r
+ Status = EFI_SUCCESS;\r
+ break;\r
\r
- //\r
- // Done with seeking file. Start reading its data.\r
- //\r
- FinishedSeeking = TRUE;\r
+ case LongAdsSequence:\r
+ case ShortAdsSequence:\r
+ //\r
+ // This FE/EFE contains a run of Allocation Descriptors. Get data + size\r
+ // for start reading them out.\r
+ //\r
+ Status = GetAdsInformation (FileEntryData, Volume->FileEntrySize, &Data, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ AdOffset = 0;\r
\r
- Skip_File_Seek:\r
+ for ( ; ;) {\r
//\r
- // Make sure we don't read more data than really wanted.\r
+ // Read AD.\r
//\r
- if (ExtentLength - Offset > BytesLeft) {\r
- DataLength = BytesLeft;\r
- } else {\r
- DataLength = ExtentLength - Offset;\r
+ Status = GetAllocationDescriptor (\r
+ RecordingFlags,\r
+ Data,\r
+ &AdOffset,\r
+ Length,\r
+ &Ad\r
+ );\r
+ if (Status == EFI_DEVICE_ERROR) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
}\r
\r
//\r
- // Read extent's data into FileData.\r
+ // Check if AD is an indirect AD. If so, read Allocation Extent\r
+ // Descriptor and its extents (ADs).\r
//\r
- Status = DiskIo->ReadDisk (\r
- DiskIo,\r
- BlockIo->Media->MediaId,\r
- Offset + MultU64x32 (Lsn, LogicalBlockSize),\r
- (UINTN) DataLength,\r
- (VOID *)((UINT8 *)ReadFileInfo->FileData +\r
- DataOffset)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error_Read_Disk_Blk;\r
+ if (GET_EXTENT_FLAGS (RecordingFlags, Ad) == ExtentIsNextExtent) {\r
+ DataBak = Data;\r
+ Status = GetAedAdsData (\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ ParentIcb,\r
+ RecordingFlags,\r
+ Ad,\r
+ &Data,\r
+ &Length\r
+ );\r
+\r
+ if (!DoFreeAed) {\r
+ DoFreeAed = TRUE;\r
+ } else {\r
+ FreePool (DataBak);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error_Get_Aed;\r
+ }\r
+\r
+ ASSERT (Data != NULL);\r
+\r
+ AdOffset = 0;\r
+ continue;\r
}\r
\r
- //\r
- // Update current file's position.\r
- //\r
- DataOffset += DataLength;\r
- ReadFileInfo->FilePosition += DataLength;\r
+ ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);\r
\r
- BytesLeft -= DataLength;\r
- if (BytesLeft == 0) {\r
- //\r
- // There is no more file data to read.\r
- //\r
- Status = EFI_SUCCESS;\r
+ Status = GetAllocationDescriptorLsn (\r
+ RecordingFlags,\r
+ Volume,\r
+ ParentIcb,\r
+ Ad,\r
+ &Lsn\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
\r
- break;\r
+ switch (ReadFileInfo->Flags) {\r
+ case ReadFileGetFileSize:\r
+ ReadFileInfo->ReadLength += ExtentLength;\r
+ break;\r
+ case ReadFileAllocateAndRead:\r
+ //\r
+ // Increase FileData (if necessary) to read next extent.\r
+ //\r
+ Status = GrowUpBufferToNextAd (\r
+ RecordingFlags,\r
+ Ad,\r
+ &ReadFileInfo->FileData,\r
+ ReadFileInfo->ReadLength\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error_Alloc_Buffer_To_Next_Ad;\r
+ }\r
+\r
+ //\r
+ // Read extent's data into FileData.\r
+ //\r
+ Status = DiskIo->ReadDisk (\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32 (Lsn, LogicalBlockSize),\r
+ ExtentLength,\r
+ (VOID *)((UINT8 *)ReadFileInfo->FileData +\r
+ ReadFileInfo->ReadLength)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error_Read_Disk_Blk;\r
+ }\r
+\r
+ ReadFileInfo->ReadLength += ExtentLength;\r
+ break;\r
+ case ReadFileSeekAndRead:\r
+ //\r
+ // Seek file first before reading in its data.\r
+ //\r
+ if (FinishedSeeking) {\r
+ Offset = 0;\r
+ goto Skip_File_Seek;\r
+ }\r
+\r
+ if (FilePosition + ExtentLength < ReadFileInfo->FilePosition) {\r
+ FilePosition += ExtentLength;\r
+ goto Skip_Ad;\r
+ }\r
+\r
+ if (FilePosition + ExtentLength > ReadFileInfo->FilePosition) {\r
+ Offset = ReadFileInfo->FilePosition - FilePosition;\r
+ } else {\r
+ Offset = 0;\r
+ }\r
+\r
+ //\r
+ // Done with seeking file. Start reading its data.\r
+ //\r
+ FinishedSeeking = TRUE;\r
+\r
+Skip_File_Seek:\r
+ //\r
+ // Make sure we don't read more data than really wanted.\r
+ //\r
+ if (ExtentLength - Offset > BytesLeft) {\r
+ DataLength = BytesLeft;\r
+ } else {\r
+ DataLength = ExtentLength - Offset;\r
+ }\r
+\r
+ //\r
+ // Read extent's data into FileData.\r
+ //\r
+ Status = DiskIo->ReadDisk (\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ Offset + MultU64x32 (Lsn, LogicalBlockSize),\r
+ (UINTN)DataLength,\r
+ (VOID *)((UINT8 *)ReadFileInfo->FileData +\r
+ DataOffset)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error_Read_Disk_Blk;\r
+ }\r
+\r
+ //\r
+ // Update current file's position.\r
+ //\r
+ DataOffset += DataLength;\r
+ ReadFileInfo->FilePosition += DataLength;\r
+\r
+ BytesLeft -= DataLength;\r
+ if (BytesLeft == 0) {\r
+ //\r
+ // There is no more file data to read.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+Skip_Ad:\r
+ //\r
+ // Point to the next AD (extent).\r
+ //\r
+ AdOffset += AD_LENGTH (RecordingFlags);\r
}\r
\r
- Skip_Ad:\r
+ break;\r
+ case ExtendedAdsSequence:\r
+ // FIXME: Not supported. Got no volume with it, yet.\r
+ ASSERT (FALSE);\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+\r
+ default:\r
//\r
- // Point to the next AD (extent).\r
+ // A flag value reserved by the ECMA-167 standard (3rd Edition - June\r
+ // 1997); 14.6 ICB Tag; 14.6.8 Flags (RBP 18); was found.\r
//\r
- AdOffset += AD_LENGTH (RecordingFlags);\r
- }\r
-\r
- break;\r
- case EXTENDED_ADS_SEQUENCE:\r
- // FIXME: Not supported. Got no volume with it, yet.\r
- ASSERT (FALSE);\r
- Status = EFI_UNSUPPORTED;\r
- break;\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
}\r
\r
Done:\r
\r
Error_Read_Disk_Blk:\r
Error_Alloc_Buffer_To_Next_Ad:\r
- if (ReadFileInfo->Flags != READ_FILE_SEEK_AND_READ) {\r
+ if (ReadFileInfo->Flags != ReadFileSeekAndRead) {\r
FreePool (ReadFileInfo->FileData);\r
}\r
\r
return Status;\r
}\r
\r
-//\r
-// Find a file by its filename from a given Parent file.\r
-//\r
+/**\r
+ Find a file by its filename from a given Parent file.\r
+\r
+ @param[in] BlockIo BlockIo interface.\r
+ @param[in] DiskIo DiskIo interface.\r
+ @param[in] Volume Volume information pointer.\r
+ @param[in] FileName File name string.\r
+ @param[in] Parent Parent directory file.\r
+ @param[in] Icb Long Allocation Descriptor pointer.\r
+ @param[out] File Found file.\r
+\r
+ @retval EFI_SUCCESS The file was found.\r
+ @retval EFI_INVALID_PARAMETER One or more input parameters are invalid.\r
+ @retval EFI_NOT_FOUND The file was not found.\r
+\r
+**/\r
EFI_STATUS\r
InternalFindFile (\r
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
CHAR16 FoundFileName[UDF_FILENAME_LENGTH];\r
VOID *CompareFileEntry;\r
\r
+ //\r
+ // Check if both Parent->FileIdentifierDesc and Icb are NULL.\r
+ //\r
+ if ((Parent->FileIdentifierDesc == NULL) && (Icb == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\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
// FE/EFE and FID descriptors.\r
//\r
if (StrCmp (FileName, L".") == 0) {\r
+ if (Parent->FileIdentifierDesc == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
DuplicateFe (BlockIo, Volume, Parent->FileEntry, &File->FileEntry);\r
+ if (File->FileEntry == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
DuplicateFid (Parent->FileIdentifierDesc, &File->FileIdentifierDesc);\r
+ if (File->FileIdentifierDesc == NULL) {\r
+ FreePool (File->FileEntry);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
ZeroMem ((VOID *)&ReadDirInfo, sizeof (UDF_READ_DIRECTORY_INFO));\r
Found = FALSE;\r
\r
- for (;;) {\r
+ for ( ; ;) {\r
Status = ReadDirectoryEntry (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- Parent->FileIdentifierDesc ?\r
- &Parent->FileIdentifierDesc->Icb :\r
- Icb,\r
- Parent->FileEntry,\r
- &ReadDirInfo,\r
- &FileIdentifierDesc\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ (Parent->FileIdentifierDesc != NULL) ?\r
+ &Parent->FileIdentifierDesc->Icb :\r
+ Icb,\r
+ Parent->FileEntry,\r
+ &ReadDirInfo,\r
+ &FileIdentifierDesc\r
+ );\r
if (EFI_ERROR (Status)) {\r
if (Status == EFI_DEVICE_ERROR) {\r
Status = EFI_NOT_FOUND;\r
break;\r
}\r
\r
- if (IS_FID_PARENT_FILE (FileIdentifierDesc)) {\r
+ //\r
+ // After calling function ReadDirectoryEntry(), if 'FileIdentifierDesc' is\r
+ // NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the code\r
+ // reaches here, 'FileIdentifierDesc' must be not NULL.\r
+ //\r
+ // The ASSERT here is for addressing a false positive NULL pointer\r
+ // dereference issue raised from static analysis.\r
+ //\r
+ ASSERT (FileIdentifierDesc != NULL);\r
+\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
// the expected FID.\r
//\r
- if (StrCmp (FileName, L"..") == 0 || StrCmp (FileName, L"\\") == 0) {\r
+ if ((StrCmp (FileName, L"..") == 0) || (StrCmp (FileName, L"\\") == 0)) {\r
Found = TRUE;\r
break;\r
}\r
} else {\r
- Status = GetFileNameFromFid (FileIdentifierDesc, FoundFileName);\r
+ Status = GetFileNameFromFid (FileIdentifierDesc, ARRAY_SIZE (FoundFileName), FoundFileName);\r
if (EFI_ERROR (Status)) {\r
break;\r
}\r
//\r
if (StrCmp (FileName, L"\\") != 0) {\r
Status = FindFileEntry (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- &FileIdentifierDesc->Icb,\r
- &CompareFileEntry\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ &FileIdentifierDesc->Icb,\r
+ &CompareFileEntry\r
+ );\r
if (EFI_ERROR (Status)) {\r
goto Error_Find_Fe;\r
}\r
//\r
// Make sure that both Parent's FE/EFE and found FE/EFE are not equal.\r
//\r
- if (CompareMem ((VOID *)Parent->FileEntry, (VOID *)CompareFileEntry,\r
- Volume->FileEntrySize) != 0) {\r
+ if (CompareMem (\r
+ (VOID *)Parent->FileEntry,\r
+ (VOID *)CompareFileEntry,\r
+ Volume->FileEntrySize\r
+ ) != 0)\r
+ {\r
File->FileEntry = CompareFileEntry;\r
} else {\r
FreePool ((VOID *)FileIdentifierDesc);\r
OUT UDF_VOLUME_INFO *Volume\r
)\r
{\r
- EFI_STATUS Status;\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
- Volume\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume\r
+ );\r
if (EFI_ERROR (Status)) {\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
UDF_FILE_INFO Parent;\r
\r
Status = FindFileEntry (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- &Volume->FileSetDescs[0]->RootDirectoryIcb,\r
- &File->FileEntry\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ &Volume->FileSetDesc.RootDirectoryIcb,\r
+ &File->FileEntry\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Parent.FileEntry = File->FileEntry;\r
+ Parent.FileEntry = File->FileEntry;\r
Parent.FileIdentifierDesc = NULL;\r
\r
Status = FindFile (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- L"\\",\r
- NULL,\r
- &Parent,\r
- &Volume->FileSetDescs[0]->RootDirectoryIcb,\r
- File\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ L"\\",\r
+ NULL,\r
+ &Parent,\r
+ &Volume->FileSetDesc.RootDirectoryIcb,\r
+ File\r
+ );\r
if (EFI_ERROR (Status)) {\r
FreePool (File->FileEntry);\r
}\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
+ VOID *ReadBuffer;\r
+\r
+ Status = GetLongAdLsn (Volume, Icb, &Lsn);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\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
+ ReadBuffer = AllocateZeroPool (Volume->FileEntrySize);\r
+ if (ReadBuffer == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
// Read extent.\r
//\r
Status = DiskIo->ReadDisk (\r
- DiskIo,\r
- BlockIo->Media->MediaId,\r
- MultU64x32 (Lsn, LogicalBlockSize),\r
- Volume->FileEntrySize,\r
- *FileEntry\r
- );\r
+ DiskIo,\r
+ BlockIo->Media->MediaId,\r
+ MultU64x32 (Lsn, LogicalBlockSize),\r
+ Volume->FileEntrySize,\r
+ ReadBuffer\r
+ );\r
if (EFI_ERROR (Status)) {\r
goto Error_Read_Disk_Blk;\r
}\r
\r
+ DescriptorTag = ReadBuffer;\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
+ {\r
Status = EFI_VOLUME_CORRUPTED;\r
goto Error_Invalid_Fe;\r
}\r
\r
+ *FileEntry = ReadBuffer;\r
return EFI_SUCCESS;\r
\r
Error_Invalid_Fe:\r
Error_Read_Disk_Blk:\r
- FreePool (*FileEntry);\r
+ FreePool (ReadBuffer);\r
\r
return Status;\r
}\r
@param[in] FilePath File's absolute path.\r
@param[in] Root Root directory file.\r
@param[in] Parent Parent directory file.\r
+ @param[in] Icb ICB of Parent.\r
@param[out] File Found file.\r
\r
- @retval EFI_SUCCESS @p FilePath was found.\r
+ @retval EFI_SUCCESS FilePath was 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 @p FilePath file was not found due to lack of\r
+ @retval EFI_OUT_OF_RESOURCES The FilePath file was not found due to lack of\r
resources.\r
\r
**/\r
while (*FilePath != L'\0') {\r
FileNamePointer = FileName;\r
while (*FilePath != L'\0' && *FilePath != L'\\') {\r
+ if ((((UINTN)FileNamePointer - (UINTN)FileName) / sizeof (CHAR16)) >=\r
+ (ARRAY_SIZE (FileName) - 1))\r
+ {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
*FileNamePointer++ = *FilePath++;\r
}\r
\r
//\r
// See UdfOpenVolume() function.\r
//\r
- Status = InternalFindFile (BlockIo,\r
- DiskIo,\r
- Volume,\r
- L"\\",\r
- &PreviousFile,\r
- Icb,\r
- File);\r
+ Status = InternalFindFile (\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ L"\\",\r
+ &PreviousFile,\r
+ Icb,\r
+ File\r
+ );\r
} else {\r
//\r
// We've already a file pointer (Root) for the root directory. Duplicate\r
// its FE/EFE and FID descriptors.\r
//\r
- DuplicateFe (BlockIo, Volume, Root->FileEntry, &File->FileEntry);\r
- DuplicateFid (Root->FileIdentifierDesc, &File->FileIdentifierDesc);\r
Status = EFI_SUCCESS;\r
+ DuplicateFe (BlockIo, Volume, Root->FileEntry, &File->FileEntry);\r
+ if (File->FileEntry == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ //\r
+ // File->FileEntry is not NULL.\r
+ //\r
+ DuplicateFid (Root->FileIdentifierDesc, &File->FileIdentifierDesc);\r
+ if (File->FileIdentifierDesc == NULL) {\r
+ FreePool (File->FileEntry);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
}\r
} else {\r
//\r
// No root directory. Find filename from the current directory.\r
//\r
- Status = InternalFindFile (BlockIo,\r
- DiskIo,\r
- Volume,\r
- FileName,\r
- &PreviousFile,\r
- Icb,\r
- File);\r
+ Status = InternalFindFile (\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ FileName,\r
+ &PreviousFile,\r
+ Icb,\r
+ File\r
+ );\r
}\r
\r
if (EFI_ERROR (Status)) {\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
\r
- Status = ResolveSymlink (BlockIo,\r
- DiskIo,\r
- Volume,\r
- &PreviousFile,\r
- FileEntry,\r
- File);\r
+ Status = ResolveSymlink (\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ &PreviousFile,\r
+ FileEntry,\r
+ File\r
+ );\r
\r
FreePool (FileEntry);\r
\r
}\r
}\r
\r
- if (CompareMem ((VOID *)&PreviousFile, (VOID *)Parent,\r
- sizeof (UDF_FILE_INFO)) != 0) {\r
+ if (CompareMem (\r
+ (VOID *)&PreviousFile,\r
+ (VOID *)Parent,\r
+ sizeof (UDF_FILE_INFO)\r
+ ) != 0)\r
+ {\r
CleanupFileInformation (&PreviousFile);\r
}\r
\r
CopyMem ((VOID *)&PreviousFile, (VOID *)File, sizeof (UDF_FILE_INFO));\r
- if (*FilePath != L'\0' && *FilePath == L'\\') {\r
+ if ((*FilePath != L'\0') && (*FilePath == L'\\')) {\r
FilePath++;\r
}\r
}\r
@param[in] Volume UDF volume information structure.\r
@param[in] ParentIcb ICB of the parent file.\r
@param[in] FileEntryData FE/EFE of the parent file.\r
- @param[in out] ReadDirInfo Next read directory listing structure\r
+ @param[in, out] ReadDirInfo Next read directory listing structure\r
information.\r
@param[out] FoundFid File Identifier Descriptor pointer.\r
\r
// The directory's recorded data has not been read yet. So let's cache it\r
// into memory and the next calls won't need to read it again.\r
//\r
- ReadFileInfo.Flags = READ_FILE_ALLOCATE_AND_READ;\r
+ ReadFileInfo.Flags = ReadFileAllocateAndRead;\r
\r
Status = ReadFile (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- ParentIcb,\r
- FileEntryData,\r
- &ReadFileInfo\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ ParentIcb,\r
+ FileEntryData,\r
+ &ReadFileInfo\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
//\r
// Fill in ReadDirInfo structure with the read directory's data information.\r
//\r
- ReadDirInfo->DirectoryData = ReadFileInfo.FileData;\r
+ ReadDirInfo->DirectoryData = ReadFileInfo.FileData;\r
ReadDirInfo->DirectoryLength = ReadFileInfo.ReadLength;\r
}\r
\r
//\r
// Get FID for this entry.\r
//\r
- FileIdentifierDesc = GET_FID_FROM_ADS (ReadDirInfo->DirectoryData,\r
- ReadDirInfo->FidOffset);\r
+ FileIdentifierDesc = GET_FID_FROM_ADS (\r
+ ReadDirInfo->DirectoryData,\r
+ ReadDirInfo->FidOffset\r
+ );\r
//\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
+ if (*FoundFid == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
Get a filename (encoded in OSTA-compressed format) from a File Identifier\r
Descriptor on an UDF volume.\r
\r
+ @attention This is boundary function that may receive untrusted input.\r
+ @attention The input is from FileSystem.\r
+\r
+ The File Identifier Descriptor is external input, so this routine will do\r
+ basic validation for File Identifier Descriptor and report status.\r
+\r
@param[in] FileIdentifierDesc File Identifier Descriptor pointer.\r
+ @param[in] CharMax The maximum number of FileName Unicode char,\r
+ including terminating null char.\r
@param[out] FileName Decoded filename.\r
\r
@retval EFI_SUCCESS Filename decoded and read.\r
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_BUFFER_TOO_SMALL The string buffer FileName cannot hold the\r
+ decoded filename.\r
**/\r
EFI_STATUS\r
GetFileNameFromFid (\r
IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,\r
+ IN UINTN CharMax,\r
OUT CHAR16 *FileName\r
)\r
{\r
- UINT8 *OstaCompressed;\r
- UINT8 CompressionId;\r
- UINT8 Length;\r
- UINTN Index;\r
+ UINT8 *OstaCompressed;\r
+ UINT8 CompressionId;\r
+ UINT8 Length;\r
+ UINTN Index;\r
+ CHAR16 *FileNameBak;\r
+\r
+ if (CharMax == 0) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
\r
OstaCompressed =\r
(UINT8 *)(\r
- (UINT8 *)FileIdentifierDesc->Data +\r
- FileIdentifierDesc->LengthOfImplementationUse\r
- );\r
+ (UINT8 *)FileIdentifierDesc->Data +\r
+ FileIdentifierDesc->LengthOfImplementationUse\r
+ );\r
\r
CompressionId = OstaCompressed[0];\r
if (!IS_VALID_COMPRESSION_ID (CompressionId)) {\r
return EFI_VOLUME_CORRUPTED;\r
}\r
\r
+ FileNameBak = FileName;\r
+\r
//\r
// Decode filename.\r
//\r
Length = FileIdentifierDesc->LengthOfFileIdentifier;\r
+ if (CompressionId == 16) {\r
+ if (((UINTN)Length >> 1) > CharMax) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ } else {\r
+ if ((Length != 0) && ((UINTN)Length - 1 > CharMax)) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ }\r
+\r
for (Index = 1; Index < Length; Index++) {\r
if (CompressionId == 16) {\r
*FileName = OstaCompressed[Index++] << 8;\r
}\r
\r
if (Index < Length) {\r
- *FileName |= OstaCompressed[Index];\r
+ *FileName |= (CHAR16)(OstaCompressed[Index]);\r
}\r
\r
FileName++;\r
}\r
\r
- *FileName = L'\0';\r
+ Index = ((UINTN)FileName - (UINTN)FileNameBak) / sizeof (CHAR16);\r
+ if (Index > CharMax - 1) {\r
+ Index = CharMax - 1;\r
+ }\r
+\r
+ FileNameBak[Index] = L'\0';\r
\r
return EFI_SUCCESS;\r
}\r
/**\r
Resolve a symlink file on an UDF volume.\r
\r
+ @attention This is boundary function that may receive untrusted input.\r
+ @attention The input is from FileSystem.\r
+\r
+ The Path Component is external input, so this routine will do basic\r
+ validation for Path Component and report status.\r
+\r
@param[in] BlockIo BlockIo interface.\r
@param[in] DiskIo DiskIo interface.\r
@param[in] Volume UDF volume information structure.\r
UDF_PATH_COMPONENT *PathComp;\r
UINT8 PathCompLength;\r
CHAR16 FileName[UDF_FILENAME_LENGTH];\r
- CHAR16 *C;\r
+ CHAR16 *Char;\r
UINTN Index;\r
UINT8 CompressionId;\r
UDF_FILE_INFO PreviousFile;\r
+ BOOLEAN NotParent;\r
+ BOOLEAN NotFile;\r
+\r
+ ZeroMem ((VOID *)File, sizeof (UDF_FILE_INFO));\r
\r
//\r
// Symlink files on UDF volumes do not contain so much data other than\r
// all its data here -- usually the data will be inline with the FE/EFE for\r
// lower filenames.\r
//\r
- ReadFileInfo.Flags = READ_FILE_ALLOCATE_AND_READ;\r
+ ReadFileInfo.Flags = ReadFileAllocateAndRead;\r
\r
Status = ReadFile (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- &Parent->FileIdentifierDesc->Icb,\r
- FileEntryData,\r
- &ReadFileInfo\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ &Parent->FileIdentifierDesc->Icb,\r
+ FileEntryData,\r
+ &ReadFileInfo\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
Length = ReadFileInfo.ReadLength;\r
\r
- Data = (UINT8 *)ReadFileInfo.FileData;\r
+ Data = (UINT8 *)ReadFileInfo.FileData;\r
EndData = Data + Length;\r
\r
CopyMem ((VOID *)&PreviousFile, (VOID *)Parent, sizeof (UDF_FILE_INFO));\r
\r
- for (;;) {\r
+ for ( ; ;) {\r
PathComp = (UDF_PATH_COMPONENT *)Data;\r
\r
PathCompLength = PathComp->LengthOfComponentIdentifier;\r
\r
switch (PathComp->ComponentType) {\r
- case 1:\r
+ case 1:\r
//\r
// This Path Component specifies the root directory hierarchy subject to\r
// agreement between the originator and recipient of the medium. Skip it.\r
//\r
// Fall through.\r
//\r
- case 2:\r
- //\r
- // "\\." of the current directory. Read next Path Component.\r
- //\r
- goto Next_Path_Component;\r
- case 3:\r
- //\r
- // ".." (parent directory). Go to it.\r
- //\r
- CopyMem ((VOID *)FileName, L"..", 6);\r
- break;\r
- case 4:\r
- //\r
- // "." (current file). Duplicate both FE/EFE and FID of this file.\r
- //\r
- DuplicateFe (BlockIo, Volume, PreviousFile.FileEntry, &File->FileEntry);\r
- DuplicateFid (PreviousFile.FileIdentifierDesc,\r
- &File->FileIdentifierDesc);\r
- goto Next_Path_Component;\r
- case 5:\r
- //\r
- // This Path Component identifies an object, either a file or a\r
- // directory or an alias.\r
- //\r
- // Decode it from the compressed data in ComponentIdentifier and find\r
- // respective path.\r
- //\r
- CompressionId = PathComp->ComponentIdentifier[0];\r
- if (!IS_VALID_COMPRESSION_ID (CompressionId)) {\r
- return EFI_VOLUME_CORRUPTED;\r
- }\r
+ case 2:\r
+ //\r
+ // "\\." of the current directory. Read next Path Component.\r
+ //\r
+ goto Next_Path_Component;\r
+ case 3:\r
+ //\r
+ // ".." (parent directory). Go to it.\r
+ //\r
+ CopyMem ((VOID *)FileName, L"..", 6);\r
+ break;\r
+ case 4:\r
+ //\r
+ // "." (current file). Duplicate both FE/EFE and FID of this file.\r
+ //\r
+ DuplicateFe (BlockIo, Volume, PreviousFile.FileEntry, &File->FileEntry);\r
+ if (File->FileEntry == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error_Find_File;\r
+ }\r
\r
- C = FileName;\r
- for (Index = 1; Index < PathCompLength; Index++) {\r
- if (CompressionId == 16) {\r
- *C = *(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier +\r
- Index) << 8;\r
- Index++;\r
- } else {\r
- *C = 0;\r
+ DuplicateFid (\r
+ PreviousFile.FileIdentifierDesc,\r
+ &File->FileIdentifierDesc\r
+ );\r
+ if (File->FileIdentifierDesc == NULL) {\r
+ FreePool (File->FileEntry);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error_Find_File;\r
+ }\r
+\r
+ goto Next_Path_Component;\r
+ case 5:\r
+ //\r
+ // This Path Component identifies an object, either a file or a\r
+ // directory or an alias.\r
+ //\r
+ // Decode it from the compressed data in ComponentIdentifier and find\r
+ // respective path.\r
+ //\r
+ CompressionId = PathComp->ComponentIdentifier[0];\r
+ if (!IS_VALID_COMPRESSION_ID (CompressionId)) {\r
+ return EFI_VOLUME_CORRUPTED;\r
}\r
\r
- if (Index < Length) {\r
- *C |= *(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier + Index);\r
+ if ((UINTN)PathComp->ComponentIdentifier + PathCompLength > (UINTN)EndData) {\r
+ return EFI_VOLUME_CORRUPTED;\r
}\r
\r
- C++;\r
- }\r
+ Char = FileName;\r
+ for (Index = 1; Index < PathCompLength; Index++) {\r
+ if (CompressionId == 16) {\r
+ *Char = *(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier +\r
+ Index) << 8;\r
+ Index++;\r
+ } else {\r
+ if (Index > ARRAY_SIZE (FileName)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ *Char = 0;\r
+ }\r
+\r
+ if (Index < Length) {\r
+ *Char |= (CHAR16)(*(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier + Index));\r
+ }\r
+\r
+ Char++;\r
+ }\r
\r
- *C = L'\0';\r
- break;\r
+ Index = ((UINTN)Char - (UINTN)FileName) / sizeof (CHAR16);\r
+ if (Index > ARRAY_SIZE (FileName) - 1) {\r
+ Index = ARRAY_SIZE (FileName) - 1;\r
+ }\r
+\r
+ FileName[Index] = L'\0';\r
+ break;\r
+ default:\r
+ //\r
+ // According to the ECMA-167 standard (3rd Edition - June 1997), Section\r
+ // 14.16.1.1, all other values are reserved.\r
+ //\r
+ Status = EFI_VOLUME_CORRUPTED;\r
+ goto Error_Find_File;\r
}\r
\r
//\r
// Find file from the read filename in symlink's file data.\r
//\r
Status = InternalFindFile (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- FileName,\r
- &PreviousFile,\r
- NULL,\r
- File\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ FileName,\r
+ &PreviousFile,\r
+ NULL,\r
+ File\r
+ );\r
if (EFI_ERROR (Status)) {\r
goto Error_Find_File;\r
}\r
\r
- Next_Path_Component:\r
+Next_Path_Component:\r
Data += sizeof (UDF_PATH_COMPONENT) + PathCompLength;\r
if (Data >= EndData) {\r
break;\r
}\r
\r
- if (CompareMem ((VOID *)&PreviousFile, (VOID *)Parent,\r
- sizeof (UDF_FILE_INFO)) != 0) {\r
+ //\r
+ // Check the content in the file info pointed by File.\r
+ //\r
+ if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) {\r
+ Status = EFI_VOLUME_CORRUPTED;\r
+ goto Error_Find_File;\r
+ }\r
+\r
+ NotParent = (CompareMem (\r
+ (VOID *)&PreviousFile,\r
+ (VOID *)Parent,\r
+ sizeof (UDF_FILE_INFO)\r
+ ) != 0);\r
+ NotFile = (CompareMem (\r
+ (VOID *)&PreviousFile,\r
+ (VOID *)File,\r
+ sizeof (UDF_FILE_INFO)\r
+ ) != 0);\r
+\r
+ if (NotParent && NotFile) {\r
CleanupFileInformation (&PreviousFile);\r
}\r
\r
- CopyMem ((VOID *)&PreviousFile, (VOID *)File, sizeof (UDF_FILE_INFO));\r
+ if (NotFile) {\r
+ CopyMem ((VOID *)&PreviousFile, (VOID *)File, sizeof (UDF_FILE_INFO));\r
+ }\r
}\r
\r
//\r
//\r
FreePool (ReadFileInfo.FileData);\r
\r
+ //\r
+ // Check the content in the resolved file info.\r
+ //\r
+ if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) {\r
+ return EFI_VOLUME_CORRUPTED;\r
+ }\r
+\r
return EFI_SUCCESS;\r
\r
Error_Find_File:\r
- if (CompareMem ((VOID *)&PreviousFile, (VOID *)Parent,\r
- sizeof (UDF_FILE_INFO)) != 0) {\r
+ if (CompareMem (\r
+ (VOID *)&PreviousFile,\r
+ (VOID *)Parent,\r
+ sizeof (UDF_FILE_INFO)\r
+ ) != 0)\r
+ {\r
CleanupFileInformation (&PreviousFile);\r
}\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
**/\r
VOID\r
CleanupFileInformation (\r
- IN UDF_FILE_INFO *File\r
+ IN UDF_FILE_INFO *File\r
)\r
{\r
if (File->FileEntry != NULL) {\r
FreePool (File->FileEntry);\r
}\r
+\r
if (File->FileIdentifierDesc != NULL) {\r
FreePool ((VOID *)File->FileIdentifierDesc);\r
}\r
@param[in] File File information structure.\r
@param[out] Size Size of the file.\r
\r
- @retval EFI_SUCCESS File size calculated and set in @p Size.\r
+ @retval EFI_SUCCESS File size calculated and set in Size.\r
@retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.\r
@retval EFI_NO_MEDIA The device has no media.\r
@retval EFI_DEVICE_ERROR The device reported an error.\r
EFI_STATUS Status;\r
UDF_READ_FILE_INFO ReadFileInfo;\r
\r
- ReadFileInfo.Flags = READ_FILE_GET_FILESIZE;\r
+ ReadFileInfo.Flags = ReadFileGetFileSize;\r
\r
Status = ReadFile (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- &File->FileIdentifierDesc->Icb,\r
- File->FileEntry,\r
- &ReadFileInfo\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ &File->FileIdentifierDesc->Icb,\r
+ File->FileEntry,\r
+ &ReadFileInfo\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
@param[in] File File pointer.\r
@param[in] FileSize Size of the file.\r
@param[in] FileName Filename of the file.\r
- @param[in out] BufferSize Size of the returned file infomation.\r
+ @param[in, out] BufferSize Size of the returned file infomation.\r
@param[out] Buffer Data of the returned file information.\r
\r
@retval EFI_SUCCESS File information set.\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
//\r
- FileInfoLength = sizeof (EFI_FILE_INFO) + (FileName ?\r
+ FileInfoLength = sizeof (EFI_FILE_INFO) + ((FileName != NULL) ?\r
StrSize (FileName) :\r
sizeof (CHAR16));\r
if (*BufferSize < FileInfoLength) {\r
// Buffer now contains room enough to store EFI_FILE_INFO structure.\r
// Now, fill it in with all necessary information about the file.\r
//\r
- FileInfo = (EFI_FILE_INFO *)Buffer;\r
- FileInfo->Size = FileInfoLength;\r
- FileInfo->Attribute &= ~EFI_FILE_VALID_ATTR;\r
- FileInfo->Attribute |= EFI_FILE_READ_ONLY;\r
+ FileInfo = (EFI_FILE_INFO *)Buffer;\r
+ FileInfo->Size = FileInfoLength;\r
+ FileInfo->Attribute &= ~EFI_FILE_VALID_ATTR;\r
+ FileInfo->Attribute |= EFI_FILE_READ_ONLY;\r
\r
if (IS_FID_DIRECTORY_FILE (File->FileIdentifierDesc)) {\r
FileInfo->Attribute |= EFI_FILE_DIRECTORY;\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
FileInfo->Attribute |= EFI_FILE_SYSTEM;\r
}\r
\r
- FileInfo->FileSize = FileSize;\r
- FileInfo->PhysicalSize = FileSize;\r
-\r
- FileInfo->CreateTime.Year = FileEntry->AccessTime.Year;\r
- FileInfo->CreateTime.Month = FileEntry->AccessTime.Month;\r
- FileInfo->CreateTime.Day = FileEntry->AccessTime.Day;\r
- FileInfo->CreateTime.Hour = FileEntry->AccessTime.Hour;\r
- FileInfo->CreateTime.Minute = FileEntry->AccessTime.Second;\r
- FileInfo->CreateTime.Second = FileEntry->AccessTime.Second;\r
- FileInfo->CreateTime.Nanosecond =\r
- FileEntry->AccessTime.HundredsOfMicroseconds;\r
-\r
- FileInfo->LastAccessTime.Year =\r
- FileEntry->AccessTime.Year;\r
- FileInfo->LastAccessTime.Month =\r
- FileEntry->AccessTime.Month;\r
- FileInfo->LastAccessTime.Day =\r
- FileEntry->AccessTime.Day;\r
- FileInfo->LastAccessTime.Hour =\r
- FileEntry->AccessTime.Hour;\r
- FileInfo->LastAccessTime.Minute =\r
- FileEntry->AccessTime.Minute;\r
- FileInfo->LastAccessTime.Second =\r
- FileEntry->AccessTime.Second;\r
- FileInfo->LastAccessTime.Nanosecond =\r
- FileEntry->AccessTime.HundredsOfMicroseconds;\r
- } else if (IS_EFE (File->FileEntry)) {\r
+ FileInfo->FileSize = FileSize;\r
+ FileInfo->PhysicalSize = FileSize;\r
+\r
+ FileInfo->CreateTime.Year = FileEntry->AccessTime.Year;\r
+ FileInfo->CreateTime.Month = FileEntry->AccessTime.Month;\r
+ FileInfo->CreateTime.Day = FileEntry->AccessTime.Day;\r
+ FileInfo->CreateTime.Hour = FileEntry->AccessTime.Hour;\r
+ FileInfo->CreateTime.Minute = FileEntry->AccessTime.Minute;\r
+ FileInfo->CreateTime.Second = FileEntry->AccessTime.Second;\r
+ FileInfo->CreateTime.Nanosecond =\r
+ FileEntry->AccessTime.HundredsOfMicroseconds;\r
+\r
+ FileInfo->LastAccessTime.Year =\r
+ FileEntry->AccessTime.Year;\r
+ FileInfo->LastAccessTime.Month =\r
+ FileEntry->AccessTime.Month;\r
+ FileInfo->LastAccessTime.Day =\r
+ FileEntry->AccessTime.Day;\r
+ FileInfo->LastAccessTime.Hour =\r
+ FileEntry->AccessTime.Hour;\r
+ FileInfo->LastAccessTime.Minute =\r
+ FileEntry->AccessTime.Minute;\r
+ FileInfo->LastAccessTime.Second =\r
+ FileEntry->AccessTime.Second;\r
+ FileInfo->LastAccessTime.Nanosecond =\r
+ FileEntry->AccessTime.HundredsOfMicroseconds;\r
+ } else if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {\r
ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)File->FileEntry;\r
\r
//\r
FileInfo->Attribute |= EFI_FILE_SYSTEM;\r
}\r
\r
- FileInfo->FileSize = FileSize;\r
- FileInfo->PhysicalSize = FileSize;\r
-\r
- FileInfo->CreateTime.Year = ExtendedFileEntry->CreationTime.Year;\r
- FileInfo->CreateTime.Month = ExtendedFileEntry->CreationTime.Month;\r
- FileInfo->CreateTime.Day = ExtendedFileEntry->CreationTime.Day;\r
- FileInfo->CreateTime.Hour = ExtendedFileEntry->CreationTime.Hour;\r
- FileInfo->CreateTime.Minute = ExtendedFileEntry->CreationTime.Second;\r
- FileInfo->CreateTime.Second = ExtendedFileEntry->CreationTime.Second;\r
- FileInfo->CreateTime.Nanosecond =\r
- ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;\r
-\r
- FileInfo->LastAccessTime.Year =\r
- ExtendedFileEntry->AccessTime.Year;\r
- FileInfo->LastAccessTime.Month =\r
- ExtendedFileEntry->AccessTime.Month;\r
- FileInfo->LastAccessTime.Day =\r
- ExtendedFileEntry->AccessTime.Day;\r
- FileInfo->LastAccessTime.Hour =\r
- ExtendedFileEntry->AccessTime.Hour;\r
- FileInfo->LastAccessTime.Minute =\r
- ExtendedFileEntry->AccessTime.Minute;\r
- FileInfo->LastAccessTime.Second =\r
- ExtendedFileEntry->AccessTime.Second;\r
- FileInfo->LastAccessTime.Nanosecond =\r
- ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;\r
- }\r
-\r
- FileInfo->CreateTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
- FileInfo->CreateTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
- FileInfo->LastAccessTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
- FileInfo->LastAccessTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
-\r
- CopyMem ((VOID *)&FileInfo->ModificationTime,\r
- (VOID *)&FileInfo->LastAccessTime,\r
- sizeof (EFI_TIME));\r
+ FileInfo->FileSize = FileSize;\r
+ FileInfo->PhysicalSize = FileSize;\r
+\r
+ FileInfo->CreateTime.Year = ExtendedFileEntry->CreationTime.Year;\r
+ FileInfo->CreateTime.Month = ExtendedFileEntry->CreationTime.Month;\r
+ FileInfo->CreateTime.Day = ExtendedFileEntry->CreationTime.Day;\r
+ FileInfo->CreateTime.Hour = ExtendedFileEntry->CreationTime.Hour;\r
+ FileInfo->CreateTime.Minute = ExtendedFileEntry->CreationTime.Second;\r
+ FileInfo->CreateTime.Second = ExtendedFileEntry->CreationTime.Second;\r
+ FileInfo->CreateTime.Nanosecond =\r
+ ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;\r
+\r
+ FileInfo->LastAccessTime.Year =\r
+ ExtendedFileEntry->AccessTime.Year;\r
+ FileInfo->LastAccessTime.Month =\r
+ ExtendedFileEntry->AccessTime.Month;\r
+ FileInfo->LastAccessTime.Day =\r
+ ExtendedFileEntry->AccessTime.Day;\r
+ FileInfo->LastAccessTime.Hour =\r
+ ExtendedFileEntry->AccessTime.Hour;\r
+ FileInfo->LastAccessTime.Minute =\r
+ ExtendedFileEntry->AccessTime.Minute;\r
+ FileInfo->LastAccessTime.Second =\r
+ ExtendedFileEntry->AccessTime.Second;\r
+ FileInfo->LastAccessTime.Nanosecond =\r
+ ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;\r
+ }\r
+\r
+ FileInfo->CreateTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
+ FileInfo->CreateTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
+ FileInfo->LastAccessTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
+ FileInfo->LastAccessTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
+\r
+ CopyMem (\r
+ (VOID *)&FileInfo->ModificationTime,\r
+ (VOID *)&FileInfo->LastAccessTime,\r
+ sizeof (EFI_TIME)\r
+ );\r
\r
if (FileName != NULL) {\r
StrCpyS (FileInfo->FileName, StrLen (FileName) + 1, FileName);\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Get volume label of an UDF volume.\r
+\r
+ @attention This is boundary function that may receive untrusted input.\r
+ @attention The input is from FileSystem.\r
+\r
+ The File Set Descriptor is external input, so this routine will do basic\r
+ validation for File Set Descriptor and report status.\r
+\r
+ @param[in] Volume Volume information pointer.\r
+ @param[in] CharMax The maximum number of Unicode char in String,\r
+ including terminating null char.\r
+ @param[out] String String buffer pointer to store the volume label.\r
+\r
+ @retval EFI_SUCCESS Volume label is returned.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_BUFFER_TOO_SMALL The string buffer String cannot hold the\r
+ volume label.\r
+\r
+**/\r
+EFI_STATUS\r
+GetVolumeLabel (\r
+ IN UDF_VOLUME_INFO *Volume,\r
+ IN UINTN CharMax,\r
+ OUT CHAR16 *String\r
+ )\r
+{\r
+ UDF_FILE_SET_DESCRIPTOR *FileSetDesc;\r
+ UINTN Index;\r
+ UINT8 *OstaCompressed;\r
+ UINT8 CompressionId;\r
+ CHAR16 *StringBak;\r
+\r
+ FileSetDesc = &Volume->FileSetDesc;\r
+\r
+ OstaCompressed = &FileSetDesc->LogicalVolumeIdentifier[0];\r
+\r
+ CompressionId = OstaCompressed[0];\r
+ if (!IS_VALID_COMPRESSION_ID (CompressionId)) {\r
+ return EFI_VOLUME_CORRUPTED;\r
+ }\r
+\r
+ StringBak = String;\r
+ for (Index = 1; Index < 128; Index++) {\r
+ if (CompressionId == 16) {\r
+ if ((Index >> 1) > CharMax) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *String = *(UINT8 *)(OstaCompressed + Index) << 8;\r
+ Index++;\r
+ } else {\r
+ if (Index > CharMax) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *String = 0;\r
+ }\r
+\r
+ if (Index < 128) {\r
+ *String |= (CHAR16)(*(UINT8 *)(OstaCompressed + Index));\r
+ }\r
+\r
+ //\r
+ // Unlike FID Identifiers, Logical Volume Identifier is stored in a\r
+ // NULL-terminated OSTA compressed format, so we must check for the NULL\r
+ // character.\r
+ //\r
+ if (*String == L'\0') {\r
+ break;\r
+ }\r
+\r
+ String++;\r
+ }\r
+\r
+ Index = ((UINTN)String - (UINTN)StringBak) / sizeof (CHAR16);\r
+ if (Index > CharMax - 1) {\r
+ Index = CharMax - 1;\r
+ }\r
+\r
+ StringBak[Index] = L'\0';\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Get volume and free space size information of an UDF volume.\r
\r
+ @attention This is boundary function that may receive untrusted input.\r
+ @attention The input is from FileSystem.\r
+\r
+ The Logical Volume Descriptor and the Logical Volume Integrity Descriptor are\r
+ external inputs, so this routine will do basic validation for both descriptors\r
+ and report status.\r
+\r
@param[in] BlockIo BlockIo interface.\r
@param[in] DiskIo DiskIo interface.\r
@param[in] Volume UDF volume information structure.\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
- Lsn = (UINT64)ExtentAd.ExtentLocation;\r
+ if ((ExtentAd->ExtentLength == 0) ||\r
+ (ExtentAd->ExtentLength < sizeof (UDF_LOGICAL_VOLUME_INTEGRITY)))\r
+ {\r
+ return EFI_VOLUME_CORRUPTED;\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
+ LogicalVolInt = AllocatePool (ExtentAd->ExtentLength);\r
+ if (LogicalVolInt == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- if (!IS_LVID (LogicalVolInt)) {\r
- FreePool ((VOID *)LogicalVolInt);\r
- return EFI_VOLUME_CORRUPTED;\r
- }\r
+ //\r
+ // Get location of Logical Volume Integrity Descriptor\r
+ //\r
+ Lsn = (UINT64)ExtentAd->ExtentLocation - Volume->MainVdsStartLocation;\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
+ LogicalBlockSize = LogicalVolDesc->LogicalBlockSize;\r
\r
- *FreeSpaceSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);\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
- 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
+ DescriptorTag = &LogicalVolInt->DescriptorTag;\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
+ if ((LogicalVolInt->NumberOfPartitions > MAX_UINT32 / sizeof (UINT32) / 2) ||\r
+ (LogicalVolInt->NumberOfPartitions * sizeof (UINT32) * 2 >\r
+ ExtentAd->ExtentLength - sizeof (UDF_LOGICAL_VOLUME_INTEGRITY)))\r
+ {\r
+ Status = EFI_VOLUME_CORRUPTED;\r
+ goto Out_Free;\r
+ }\r
+\r
+ *VolumeSize = 0;\r
+ *FreeSpaceSize = 0;\r
\r
- *VolumeSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);\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
- 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
+ //\r
+ // Accumulate free space size\r
+ //\r
+ *FreeSpaceSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);\r
+ }\r
+\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
- FreePool ((VOID *)LogicalVolInt);\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
@param[in] Volume UDF volume information structure.\r
@param[in] File File information structure.\r
@param[in] FileSize Size of the file.\r
- @param[in out] FilePosition File position.\r
- @param[in out] Buffer File data.\r
- @param[in out] BufferSize Read size.\r
+ @param[in, out] FilePosition File position.\r
+ @param[in, out] Buffer File data.\r
+ @param[in, out] BufferSize Read size.\r
\r
@retval EFI_SUCCESS File seeked and read.\r
@retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.\r
EFI_STATUS Status;\r
UDF_READ_FILE_INFO ReadFileInfo;\r
\r
- ReadFileInfo.Flags = READ_FILE_SEEK_AND_READ;\r
- ReadFileInfo.FilePosition = *FilePosition;\r
- ReadFileInfo.FileData = Buffer;\r
- ReadFileInfo.FileDataSize = *BufferSize;\r
- ReadFileInfo.FileSize = FileSize;\r
+ ReadFileInfo.Flags = ReadFileSeekAndRead;\r
+ ReadFileInfo.FilePosition = *FilePosition;\r
+ ReadFileInfo.FileData = Buffer;\r
+ ReadFileInfo.FileDataSize = *BufferSize;\r
+ ReadFileInfo.FileSize = FileSize;\r
\r
Status = ReadFile (\r
- BlockIo,\r
- DiskIo,\r
- Volume,\r
- &File->FileIdentifierDesc->Icb,\r
- File->FileEntry,\r
- &ReadFileInfo\r
- );\r
+ BlockIo,\r
+ DiskIo,\r
+ Volume,\r
+ &File->FileIdentifierDesc->Icb,\r
+ File->FileEntry,\r
+ &ReadFileInfo\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- *BufferSize = ReadFileInfo.FileDataSize;\r
- *FilePosition = ReadFileInfo.FilePosition;\r
+ *BufferSize = ReadFileInfo.FileDataSize;\r
+ *FilePosition = ReadFileInfo.FilePosition;\r
\r
return EFI_SUCCESS;\r
}\r
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode;\r
EFI_GUID *VendorDefinedGuid;\r
- EFI_GUID UdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;\r
\r
//\r
// Open Device Path protocol on ControllerHandle\r
//\r
Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **)&DevicePath,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
+ ControllerHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **)&DevicePath,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
if (EFI_ERROR (Status)) {\r
return EFI_UNSUPPORTED;\r
}\r
// Get last Device Path node\r
//\r
LastDevicePathNode = NULL;\r
- DevicePathNode = DevicePath;\r
+ DevicePathNode = DevicePath;\r
while (!IsDevicePathEnd (DevicePathNode)) {\r
LastDevicePathNode = DevicePathNode;\r
- DevicePathNode = NextDevicePathNode (DevicePathNode);\r
+ DevicePathNode = NextDevicePathNode (DevicePathNode);\r
}\r
+\r
//\r
// Check if last Device Path node contains a Vendor-Defined Media Device Path\r
// of an UDF file system.\r
//\r
- if (LastDevicePathNode != NULL &&\r
- DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH &&\r
- DevicePathSubType (LastDevicePathNode) == MEDIA_VENDOR_DP) {\r
+ if ((LastDevicePathNode != NULL) &&\r
+ (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (LastDevicePathNode) == MEDIA_VENDOR_DP))\r
+ {\r
VendorDefinedGuid = (EFI_GUID *)((UINTN)LastDevicePathNode +\r
OFFSET_OF (VENDOR_DEVICE_PATH, Guid));\r
- if (CompareGuid (VendorDefinedGuid, &UdfDevPathGuid)) {\r
+ if (CompareGuid (VendorDefinedGuid, &gUdfDevPathGuid)) {\r
Status = EFI_SUCCESS;\r
}\r
}\r
// Close Device Path protocol on ControllerHandle\r
//\r
gBS->CloseProtocol (\r
- ControllerHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- ControllerHandle\r
- );\r
+ ControllerHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle\r
+ );\r
\r
return Status;\r
}\r