2 Handle on-disk format and volume structures in UDF/ECMA-167 file systems.
4 Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
12 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // Vendor-Defined Device Path GUID for UDF file system
20 EFI_GUID gUdfDevPathGuid
= EFI_UDF_DEVICE_PATH_GUID
;
23 Find the anchor volume descriptor pointer.
25 @param[in] BlockIo BlockIo interface.
26 @param[in] DiskIo DiskIo interface.
27 @param[out] AnchorPoint Anchor volume descriptor pointer.
29 @retval EFI_SUCCESS Anchor volume descriptor pointer found.
30 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
31 @retval other Anchor volume descriptor pointer not found.
35 FindAnchorVolumeDescriptorPointer (
36 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
37 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
38 OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
*AnchorPoint
44 EFI_LBA DescriptorLBAs
[4];
46 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
48 BlockSize
= BlockIo
->Media
->BlockSize
;
49 EndLBA
= BlockIo
->Media
->LastBlock
;
50 DescriptorLBAs
[0] = 256;
51 DescriptorLBAs
[1] = EndLBA
- 256;
52 DescriptorLBAs
[2] = EndLBA
;
53 DescriptorLBAs
[3] = 512;
55 for (Index
= 0; Index
< ARRAY_SIZE (DescriptorLBAs
); Index
++) {
56 Status
= DiskIo
->ReadDisk (
58 BlockIo
->Media
->MediaId
,
59 MultU64x32 (DescriptorLBAs
[Index
], BlockSize
),
60 sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
),
63 if (EFI_ERROR (Status
)) {
67 DescriptorTag
= &AnchorPoint
->DescriptorTag
;
70 // Check if read LBA has a valid AVDP descriptor.
72 if (DescriptorTag
->TagIdentifier
== UdfAnchorVolumeDescriptorPointer
) {
79 return EFI_VOLUME_CORRUPTED
;
83 Save the content of Logical Volume Descriptors and Partitions Descriptors in
86 @param[in] BlockIo BlockIo interface.
87 @param[in] DiskIo DiskIo interface.
88 @param[in] AnchorPoint Anchor volume descriptor pointer.
89 @param[out] Volume UDF volume information structure.
91 @retval EFI_SUCCESS The descriptors were saved.
92 @retval EFI_OUT_OF_RESOURCES The descriptors were not saved due to lack of
94 @retval other The descriptors were not saved due to
99 StartMainVolumeDescriptorSequence (
100 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
101 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
102 IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
*AnchorPoint
,
103 OUT UDF_VOLUME_INFO
*Volume
108 UDF_EXTENT_AD
*ExtentAd
;
109 EFI_LBA SeqStartBlock
;
111 BOOLEAN StopSequence
;
113 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
114 UINT32 LogicalBlockSize
;
116 BlockSize
= BlockIo
->Media
->BlockSize
;
117 ExtentAd
= &AnchorPoint
->MainVolumeDescriptorSequenceExtent
;
120 // Allocate buffer for reading disk blocks
122 Buffer
= AllocateZeroPool ((UINTN
)BlockSize
);
123 if (Buffer
== NULL
) {
124 return EFI_OUT_OF_RESOURCES
;
128 // The logical partition created by Partition driver is relative to the main
129 // VDS extent location, so we start the Main Volume Descriptor Sequence at
132 // We don't need to check again if we have valid Volume Descriptors here since
133 // Partition driver already did.
136 SeqEndBlock
= SeqStartBlock
+ DivU64x32 ((UINT64
)ExtentAd
->ExtentLength
,
138 StopSequence
= FALSE
;
139 for (; SeqStartBlock
< SeqEndBlock
&& !StopSequence
; SeqStartBlock
++) {
143 Status
= BlockIo
->ReadBlocks (
145 BlockIo
->Media
->MediaId
,
150 if (EFI_ERROR (Status
)) {
154 DescriptorTag
= Buffer
;
156 switch (DescriptorTag
->TagIdentifier
) {
157 case UdfPartitionDescriptor
:
159 // Save Partition Descriptor
161 CopyMem (&Volume
->PartitionDesc
, Buffer
, sizeof (Volume
->PartitionDesc
));
164 case UdfLogicalVolumeDescriptor
:
166 // Save Logical Volume Descriptor
168 CopyMem (&Volume
->LogicalVolDesc
, Buffer
, sizeof (Volume
->LogicalVolDesc
));
171 case UdfTerminatingDescriptor
:
181 // Determine FE (File Entry) size
183 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
184 if (LogicalBlockSize
>= UDF_LOGICAL_SECTOR_SIZE
) {
185 Volume
->FileEntrySize
= (UINTN
)LogicalBlockSize
;
187 Volume
->FileEntrySize
= UDF_LOGICAL_SECTOR_SIZE
;
190 Status
= EFI_SUCCESS
;
194 // Free block read buffer
202 Return a Partition Descriptor given a Long Allocation Descriptor. This is
203 necessary to calculate the right extent (LongAd) offset which is added up
204 with partition's starting location.
206 @param[in] Volume Volume information pointer.
207 @param[in] LongAd Long Allocation Descriptor pointer.
209 @return A pointer to a Partition Descriptor.
212 UDF_PARTITION_DESCRIPTOR
*
214 IN UDF_VOLUME_INFO
*Volume
,
215 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
218 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
221 LogicalVolDesc
= &Volume
->LogicalVolDesc
;
223 switch (LogicalVolDesc
->DomainIdentifier
.Suffix
.Domain
.UdfRevision
) {
231 // UDF 1.02 specification:
233 // There shall be exactly one prevailing Logical Volume Descriptor recorded
234 // per Volume Set. The Partition Maps field shall contain only Type 1
237 // UDF 1.50 through 2.60 specs say:
239 // For the purpose of interchange partition maps shall be limited to
240 // Partition Map type 1, except type 2 maps as described in the document.
242 // NOTE: Only one Type 1 (Physical) Partition is supported. It has been
243 // checked already in Partition driver for existence of a single Type 1
244 // Partition map, so we don't have to double check here.
246 // Partition reference number can also be retrieved from
247 // LongAd->ExtentLocation.PartitionReferenceNumber, however the spec says
248 // it may be 0, so let's not rely on it.
250 PartitionNum
= *(UINT16
*)((UINTN
)&LogicalVolDesc
->PartitionMaps
[4]);
255 // Unsupported UDF revision
261 // Check if partition number matches Partition Descriptor found in Main Volume
262 // Descriptor Sequence.
264 if (Volume
->PartitionDesc
.PartitionNumber
== PartitionNum
) {
265 return &Volume
->PartitionDesc
;
272 Return logical sector number of a given Long Allocation Descriptor.
274 @param[in] Volume Volume information pointer.
275 @param[in] LongAd Long Allocation Descriptor pointer.
277 @return The logical sector number of a given Long Allocation Descriptor.
282 IN UDF_VOLUME_INFO
*Volume
,
283 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
286 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
288 PartitionDesc
= GetPdFromLongAd (Volume
, LongAd
);
289 ASSERT (PartitionDesc
!= NULL
);
291 return (UINT64
)PartitionDesc
->PartitionStartingLocation
-
292 Volume
->MainVdsStartLocation
+
293 LongAd
->ExtentLocation
.LogicalBlockNumber
;
297 Return logical sector number of a given Short Allocation Descriptor.
299 @param[in] Volume Volume pointer.
300 @param[in] PartitionDesc Partition Descriptor pointer.
301 @param[in] ShortAd Short Allocation Descriptor pointer.
303 @return The logical sector number of a given Short Allocation Descriptor.
308 IN UDF_VOLUME_INFO
*Volume
,
309 IN UDF_PARTITION_DESCRIPTOR
*PartitionDesc
,
310 IN UDF_SHORT_ALLOCATION_DESCRIPTOR
*ShortAd
313 return (UINT64
)PartitionDesc
->PartitionStartingLocation
-
314 Volume
->MainVdsStartLocation
+ ShortAd
->ExtentPosition
;
318 Find File Set Descriptor of a given Logical Volume Descriptor.
320 The found FSD will contain the extent (LogicalVolumeContentsUse) where our
323 @param[in] BlockIo BlockIo interface.
324 @param[in] DiskIo DiskIo interface.
325 @param[in] Volume Volume information pointer.
327 @retval EFI_SUCCESS File Set Descriptor pointer found.
328 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
329 @retval other File Set Descriptor pointer not found.
333 FindFileSetDescriptor (
334 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
335 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
336 IN UDF_VOLUME_INFO
*Volume
341 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
342 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
344 LogicalVolDesc
= &Volume
->LogicalVolDesc
;
345 Lsn
= GetLongAdLsn (Volume
, &LogicalVolDesc
->LogicalVolumeContentsUse
);
348 // As per UDF 2.60 specification:
350 // There shall be exactly one File Set Descriptor recorded per Logical
355 Status
= DiskIo
->ReadDisk (
357 BlockIo
->Media
->MediaId
,
358 MultU64x32 (Lsn
, LogicalVolDesc
->LogicalBlockSize
),
359 sizeof (Volume
->FileSetDesc
),
362 if (EFI_ERROR (Status
)) {
366 DescriptorTag
= &Volume
->FileSetDesc
.DescriptorTag
;
369 // Check if read block is a File Set Descriptor
371 if (DescriptorTag
->TagIdentifier
!= UdfFileSetDescriptor
) {
372 return EFI_VOLUME_CORRUPTED
;
379 Read Volume and File Structure on an UDF file system.
381 @param[in] BlockIo BlockIo interface.
382 @param[in] DiskIo DiskIo interface.
383 @param[out] Volume Volume information pointer.
385 @retval EFI_SUCCESS Volume and File Structure were read.
386 @retval other Volume and File Structure were not read.
390 ReadVolumeFileStructure (
391 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
392 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
393 OUT UDF_VOLUME_INFO
*Volume
397 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint
;
398 UDF_EXTENT_AD
*ExtentAd
;
401 // Find Anchor Volume Descriptor Pointer
403 Status
= FindAnchorVolumeDescriptorPointer (
408 if (EFI_ERROR (Status
)) {
413 // Save Main VDS start block number
415 ExtentAd
= &AnchorPoint
.MainVolumeDescriptorSequenceExtent
;
417 Volume
->MainVdsStartLocation
= (UINT64
)ExtentAd
->ExtentLocation
;
420 // Start Main Volume Descriptor Sequence.
422 Status
= StartMainVolumeDescriptorSequence (
428 if (EFI_ERROR (Status
)) {
436 Calculate length of a given File Identifier Descriptor.
438 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
440 @return The length of a given File Identifier Descriptor.
444 GetFidDescriptorLength (
445 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
449 (INTN
)((OFFSET_OF (UDF_FILE_IDENTIFIER_DESCRIPTOR
, Data
[0]) + 3 +
450 FileIdentifierDesc
->LengthOfFileIdentifier
+
451 FileIdentifierDesc
->LengthOfImplementationUse
) >> 2) << 2
456 Duplicate a given File Identifier Descriptor.
458 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
459 @param[out] NewFileIdentifierDesc The duplicated File Identifier Descriptor.
464 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
,
465 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR
**NewFileIdentifierDesc
468 *NewFileIdentifierDesc
=
469 (UDF_FILE_IDENTIFIER_DESCRIPTOR
*)AllocateCopyPool (
470 (UINTN
) GetFidDescriptorLength (FileIdentifierDesc
), FileIdentifierDesc
);
472 ASSERT (*NewFileIdentifierDesc
!= NULL
);
476 Duplicate either a given File Entry or a given Extended File Entry.
478 @param[in] BlockIo BlockIo interface.
479 @param[in] Volume Volume information pointer.
480 @param[in] FileEntry (Extended) File Entry pointer.
481 @param[out] NewFileEntry The duplicated (Extended) File Entry.
486 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
487 IN UDF_VOLUME_INFO
*Volume
,
489 OUT VOID
**NewFileEntry
492 *NewFileEntry
= AllocateCopyPool (Volume
->FileEntrySize
, FileEntry
);
494 ASSERT (*NewFileEntry
!= NULL
);
498 Get raw data + length of a given File Entry or Extended File Entry.
500 The file's recorded data can contain either real file content (inline) or
501 a sequence of extents (or Allocation Descriptors) which tells where file's
502 content is stored in.
504 NOTE: The FE/EFE can be thought it was an inode.
506 @param[in] FileEntryData (Extended) File Entry pointer.
507 @param[out] Data Buffer contains the raw data of a given
508 (Extended) File Entry.
509 @param[out] Length Length of the data in Buffer.
514 IN VOID
*FileEntryData
,
519 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
520 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
521 UDF_FILE_ENTRY
*FileEntry
;
523 DescriptorTag
= FileEntryData
;
525 if (DescriptorTag
->TagIdentifier
== UdfExtendedFileEntry
) {
526 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)FileEntryData
;
528 *Length
= ExtendedFileEntry
->InformationLength
;
529 *Data
= (VOID
*)((UINT8
*)ExtendedFileEntry
->Data
+
530 ExtendedFileEntry
->LengthOfExtendedAttributes
);
531 } else if (DescriptorTag
->TagIdentifier
== UdfFileEntry
) {
532 FileEntry
= (UDF_FILE_ENTRY
*)FileEntryData
;
534 *Length
= FileEntry
->InformationLength
;
535 *Data
= (VOID
*)((UINT8
*)FileEntry
->Data
+
536 FileEntry
->LengthOfExtendedAttributes
);
541 Get Allocation Descriptors' data information from a given FE/EFE.
543 @param[in] FileEntryData (Extended) File Entry pointer.
544 @param[out] AdsData Buffer contains the Allocation Descriptors'
545 data from a given FE/EFE.
546 @param[out] Length Length of the data in AdsData.
551 IN VOID
*FileEntryData
,
556 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
557 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
558 UDF_FILE_ENTRY
*FileEntry
;
560 DescriptorTag
= FileEntryData
;
562 if (DescriptorTag
->TagIdentifier
== UdfExtendedFileEntry
) {
563 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)FileEntryData
;
565 *Length
= ExtendedFileEntry
->LengthOfAllocationDescriptors
;
566 *AdsData
= (VOID
*)((UINT8
*)ExtendedFileEntry
->Data
+
567 ExtendedFileEntry
->LengthOfExtendedAttributes
);
568 } else if (DescriptorTag
->TagIdentifier
== UdfFileEntry
) {
569 FileEntry
= (UDF_FILE_ENTRY
*)FileEntryData
;
571 *Length
= FileEntry
->LengthOfAllocationDescriptors
;
572 *AdsData
= (VOID
*)((UINT8
*)FileEntry
->Data
+
573 FileEntry
->LengthOfExtendedAttributes
);
578 Read next Long Allocation Descriptor from a given file's data.
580 @param[in] Data File's data pointer.
581 @param[in,out] Offset Starting offset of the File's data to read.
582 @param[in] Length Length of the data to read.
583 @param[out] FoundLongAd Long Allocation Descriptor pointer.
585 @retval EFI_SUCCESS A Long Allocation Descriptor was found.
586 @retval EFI_DEVICE_ERROR No more Long Allocation Descriptors.
592 IN OUT UINT64
*Offset
,
594 OUT UDF_LONG_ALLOCATION_DESCRIPTOR
**FoundLongAd
597 UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
;
598 UDF_EXTENT_FLAGS ExtentFlags
;
601 if (*Offset
>= Length
) {
603 // No more Long Allocation Descriptors.
605 return EFI_DEVICE_ERROR
;
609 (UDF_LONG_ALLOCATION_DESCRIPTOR
*)((UINT8
*)Data
+ *Offset
);
612 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
613 // allocated AD, then return it.
615 ExtentFlags
= GET_EXTENT_FLAGS (LongAdsSequence
, LongAd
);
616 if (ExtentFlags
== ExtentIsNextExtent
||
617 ExtentFlags
== ExtentRecordedAndAllocated
) {
622 // This AD is either not recorded but allocated, or not recorded and not
623 // allocated. Skip it.
625 *Offset
+= AD_LENGTH (LongAdsSequence
);
628 *FoundLongAd
= LongAd
;
634 Read next Short Allocation Descriptor from a given file's data.
636 @param[in] Data File's data pointer.
637 @param[in,out] Offset Starting offset of the File's data to read.
638 @param[in] Length Length of the data to read.
639 @param[out] FoundShortAd Short Allocation Descriptor pointer.
641 @retval EFI_SUCCESS A Short Allocation Descriptor was found.
642 @retval EFI_DEVICE_ERROR No more Short Allocation Descriptors.
648 IN OUT UINT64
*Offset
,
650 OUT UDF_SHORT_ALLOCATION_DESCRIPTOR
**FoundShortAd
653 UDF_SHORT_ALLOCATION_DESCRIPTOR
*ShortAd
;
654 UDF_EXTENT_FLAGS ExtentFlags
;
657 if (*Offset
>= Length
) {
659 // No more Short Allocation Descriptors.
661 return EFI_DEVICE_ERROR
;
665 (UDF_SHORT_ALLOCATION_DESCRIPTOR
*)((UINT8
*)Data
+ *Offset
);
668 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
669 // allocated AD, then return it.
671 ExtentFlags
= GET_EXTENT_FLAGS (ShortAdsSequence
, ShortAd
);
672 if (ExtentFlags
== ExtentIsNextExtent
||
673 ExtentFlags
== ExtentRecordedAndAllocated
) {
678 // This AD is either not recorded but allocated, or not recorded and not
679 // allocated. Skip it.
681 *Offset
+= AD_LENGTH (ShortAdsSequence
);
684 *FoundShortAd
= ShortAd
;
690 Get either a Short Allocation Descriptor or a Long Allocation Descriptor from
693 @param[in] RecordingFlags Flag to indicate the type of descriptor.
694 @param[in] Data File's data pointer.
695 @param[in,out] Offset Starting offset of the File's data to read.
696 @param[in] Length Length of the data to read.
697 @param[out] FoundAd Allocation Descriptor pointer.
699 @retval EFI_SUCCESS A Short Allocation Descriptor was found.
700 @retval EFI_DEVICE_ERROR No more Allocation Descriptors.
701 Invalid type of descriptor was given.
705 GetAllocationDescriptor (
706 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
708 IN OUT UINT64
*Offset
,
713 if (RecordingFlags
== LongAdsSequence
) {
714 return GetLongAdFromAds (
718 (UDF_LONG_ALLOCATION_DESCRIPTOR
**)FoundAd
720 } else if (RecordingFlags
== ShortAdsSequence
) {
721 return GetShortAdFromAds (
725 (UDF_SHORT_ALLOCATION_DESCRIPTOR
**)FoundAd
729 return EFI_DEVICE_ERROR
;
733 Return logical sector number of either Short or Long Allocation Descriptor.
735 @param[in] RecordingFlags Flag to indicate the type of descriptor.
736 @param[in] Volume Volume information pointer.
737 @param[in] ParentIcb Long Allocation Descriptor pointer.
738 @param[in] Ad Allocation Descriptor pointer.
740 @return The logical sector number of the given Allocation Descriptor.
744 GetAllocationDescriptorLsn (
745 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
746 IN UDF_VOLUME_INFO
*Volume
,
747 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
751 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
753 if (RecordingFlags
== LongAdsSequence
) {
754 return GetLongAdLsn (Volume
, (UDF_LONG_ALLOCATION_DESCRIPTOR
*)Ad
);
755 } else if (RecordingFlags
== ShortAdsSequence
) {
756 PartitionDesc
= GetPdFromLongAd (Volume
, ParentIcb
);
757 ASSERT (PartitionDesc
!= NULL
);
759 return GetShortAdLsn (
762 (UDF_SHORT_ALLOCATION_DESCRIPTOR
*)Ad
770 Return offset + length of a given indirect Allocation Descriptor (AED).
772 @param[in] BlockIo BlockIo interface.
773 @param[in] DiskIo DiskIo interface.
774 @param[in] Volume Volume information pointer.
775 @param[in] ParentIcb Long Allocation Descriptor pointer.
776 @param[in] RecordingFlags Flag to indicate the type of descriptor.
777 @param[in] Ad Allocation Descriptor pointer.
778 @param[out] Offset Offset of a given indirect Allocation
780 @param[out] Length Length of a given indirect Allocation
783 @retval EFI_SUCCESS The offset and length were returned.
784 @retval EFI_OUT_OF_RESOURCES The offset and length were not returned due
785 to lack of resources.
786 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
787 @retval other The offset and length were not returned.
792 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
793 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
794 IN UDF_VOLUME_INFO
*Volume
,
795 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
796 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
806 UINT32 LogicalBlockSize
;
807 UDF_ALLOCATION_EXTENT_DESCRIPTOR
*AllocExtDesc
;
808 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
810 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
811 Lsn
= GetAllocationDescriptorLsn (RecordingFlags
,
816 Data
= AllocatePool (ExtentLength
);
818 return EFI_OUT_OF_RESOURCES
;
821 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
826 Status
= DiskIo
->ReadDisk (
828 BlockIo
->Media
->MediaId
,
829 MultU64x32 (Lsn
, LogicalBlockSize
),
833 if (EFI_ERROR (Status
)) {
837 AllocExtDesc
= (UDF_ALLOCATION_EXTENT_DESCRIPTOR
*)Data
;
839 DescriptorTag
= &AllocExtDesc
->DescriptorTag
;
842 // Check if read extent contains a valid tag identifier for AED.
844 if (DescriptorTag
->TagIdentifier
!= UdfAllocationExtentDescriptor
) {
845 Status
= EFI_VOLUME_CORRUPTED
;
850 // Get AED's block offset and its length.
852 *Offset
= MultU64x32 (Lsn
, LogicalBlockSize
) +
853 sizeof (UDF_ALLOCATION_EXTENT_DESCRIPTOR
);
854 *Length
= AllocExtDesc
->LengthOfAllocationDescriptors
;
863 Read Allocation Extent Descriptor into memory.
865 @param[in] BlockIo BlockIo interface.
866 @param[in] DiskIo DiskIo interface.
867 @param[in] Volume Volume information pointer.
868 @param[in] ParentIcb Long Allocation Descriptor pointer.
869 @param[in] RecordingFlags Flag to indicate the type of descriptor.
870 @param[in] Ad Allocation Descriptor pointer.
871 @param[out] Data Buffer that contains the Allocation Extent
873 @param[out] Length Length of Data.
875 @retval EFI_SUCCESS The Allocation Extent Descriptor was read.
876 @retval EFI_OUT_OF_RESOURCES The Allocation Extent Descriptor was not read
877 due to lack of resources.
878 @retval other Fail to read the disk.
883 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
884 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
885 IN UDF_VOLUME_INFO
*Volume
,
886 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
887 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
897 // Get AED's offset + length.
899 Status
= GetAedAdsOffset (
909 if (EFI_ERROR (Status
)) {
914 // Allocate buffer to read in AED's data.
916 *Data
= AllocatePool ((UINTN
) (*Length
));
918 return EFI_OUT_OF_RESOURCES
;
921 return DiskIo
->ReadDisk (
923 BlockIo
->Media
->MediaId
,
931 Function used to serialise reads of Allocation Descriptors.
933 @param[in] RecordingFlags Flag to indicate the type of descriptor.
934 @param[in] Ad Allocation Descriptor pointer.
935 @param[in, out] Buffer Buffer to hold the next Allocation Descriptor.
936 @param[in] Length Length of Buffer.
938 @retval EFI_SUCCESS Buffer was grown to hold the next Allocation
940 @retval EFI_OUT_OF_RESOURCES Buffer was not grown due to lack of resources.
944 GrowUpBufferToNextAd (
945 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
947 IN OUT VOID
**Buffer
,
953 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
955 if (*Buffer
== NULL
) {
956 *Buffer
= AllocatePool (ExtentLength
);
957 if (*Buffer
== NULL
) {
958 return EFI_OUT_OF_RESOURCES
;
961 *Buffer
= ReallocatePool ((UINTN
) Length
, (UINTN
) (Length
+ ExtentLength
), *Buffer
);
962 if (*Buffer
== NULL
) {
963 return EFI_OUT_OF_RESOURCES
;
971 Read data or size of either a File Entry or an Extended File Entry.
973 @param[in] BlockIo BlockIo interface.
974 @param[in] DiskIo DiskIo interface.
975 @param[in] Volume Volume information pointer.
976 @param[in] ParentIcb Long Allocation Descriptor pointer.
977 @param[in] FileEntryData FE/EFE structure pointer.
978 @param[in, out] ReadFileInfo Read file information pointer.
980 @retval EFI_SUCCESS Data or size of a FE/EFE was read.
981 @retval EFI_OUT_OF_RESOURCES Data or size of a FE/EFE was not read due to
983 @retval EFI_INVALID_PARAMETER The read file flag given in ReadFileInfo is
985 @retval EFI_UNSUPPORTED The FE recording flag given in FileEntryData
987 @retval other Data or size of a FE/EFE was not read.
992 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
993 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
994 IN UDF_VOLUME_INFO
*Volume
,
995 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
996 IN VOID
*FileEntryData
,
997 IN OUT UDF_READ_FILE_INFO
*ReadFileInfo
1001 UINT32 LogicalBlockSize
;
1008 UINT64 FilePosition
;
1013 BOOLEAN FinishedSeeking
;
1014 UINT32 ExtentLength
;
1015 UDF_FE_RECORDING_FLAGS RecordingFlags
;
1017 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
1021 // set BytesLeft to suppress incorrect compiler/analyzer warnings
1026 FinishedSeeking
= FALSE
;
1029 switch (ReadFileInfo
->Flags
) {
1030 case ReadFileGetFileSize
:
1031 case ReadFileAllocateAndRead
:
1033 // Initialise ReadFileInfo structure for either getting file size, or
1034 // reading file's recorded data.
1036 ReadFileInfo
->ReadLength
= 0;
1037 ReadFileInfo
->FileData
= NULL
;
1039 case ReadFileSeekAndRead
:
1041 // About to seek a file and/or read its data.
1043 Length
= ReadFileInfo
->FileSize
- ReadFileInfo
->FilePosition
;
1044 if (ReadFileInfo
->FileDataSize
> Length
) {
1046 // About to read beyond the EOF -- truncate it.
1048 ReadFileInfo
->FileDataSize
= Length
;
1052 // Initialise data to start seeking and/or reading a file.
1054 BytesLeft
= ReadFileInfo
->FileDataSize
;
1057 FinishedSeeking
= FALSE
;
1062 RecordingFlags
= GET_FE_RECORDING_FLAGS (FileEntryData
);
1063 switch (RecordingFlags
) {
1066 // There are no extents for this FE/EFE. All data is inline.
1068 GetFileEntryData (FileEntryData
, &Data
, &Length
);
1070 if (ReadFileInfo
->Flags
== ReadFileGetFileSize
) {
1071 ReadFileInfo
->ReadLength
= Length
;
1072 } else if (ReadFileInfo
->Flags
== ReadFileAllocateAndRead
) {
1074 // Allocate buffer for starting read data.
1076 ReadFileInfo
->FileData
= AllocatePool ((UINTN
) Length
);
1077 if (ReadFileInfo
->FileData
== NULL
) {
1078 return EFI_OUT_OF_RESOURCES
;
1082 // Read all inline data into ReadFileInfo->FileData
1084 CopyMem (ReadFileInfo
->FileData
, Data
, (UINTN
) Length
);
1085 ReadFileInfo
->ReadLength
= Length
;
1086 } else if (ReadFileInfo
->Flags
== ReadFileSeekAndRead
) {
1088 // If FilePosition is non-zero, seek file to FilePosition, read
1089 // FileDataSize bytes and then updates FilePosition.
1092 ReadFileInfo
->FileData
,
1093 (VOID
*)((UINT8
*)Data
+ ReadFileInfo
->FilePosition
),
1094 (UINTN
) ReadFileInfo
->FileDataSize
1097 ReadFileInfo
->FilePosition
+= ReadFileInfo
->FileDataSize
;
1100 return EFI_INVALID_PARAMETER
;
1103 Status
= EFI_SUCCESS
;
1106 case LongAdsSequence
:
1107 case ShortAdsSequence
:
1109 // This FE/EFE contains a run of Allocation Descriptors. Get data + size
1110 // for start reading them out.
1112 GetAdsInformation (FileEntryData
, &Data
, &Length
);
1119 Status
= GetAllocationDescriptor (
1126 if (Status
== EFI_DEVICE_ERROR
) {
1127 Status
= EFI_SUCCESS
;
1132 // Check if AD is an indirect AD. If so, read Allocation Extent
1133 // Descriptor and its extents (ADs).
1135 if (GET_EXTENT_FLAGS (RecordingFlags
, Ad
) == ExtentIsNextExtent
) {
1142 Status
= GetAedAdsData (
1152 if (EFI_ERROR (Status
)) {
1155 ASSERT (Data
!= NULL
);
1161 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
1163 Lsn
= GetAllocationDescriptorLsn (RecordingFlags
,
1168 switch (ReadFileInfo
->Flags
) {
1169 case ReadFileGetFileSize
:
1170 ReadFileInfo
->ReadLength
+= ExtentLength
;
1172 case ReadFileAllocateAndRead
:
1174 // Increase FileData (if necessary) to read next extent.
1176 Status
= GrowUpBufferToNextAd (
1179 &ReadFileInfo
->FileData
,
1180 ReadFileInfo
->ReadLength
1182 if (EFI_ERROR (Status
)) {
1183 goto Error_Alloc_Buffer_To_Next_Ad
;
1187 // Read extent's data into FileData.
1189 Status
= DiskIo
->ReadDisk (
1191 BlockIo
->Media
->MediaId
,
1192 MultU64x32 (Lsn
, LogicalBlockSize
),
1194 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1195 ReadFileInfo
->ReadLength
)
1197 if (EFI_ERROR (Status
)) {
1198 goto Error_Read_Disk_Blk
;
1201 ReadFileInfo
->ReadLength
+= ExtentLength
;
1203 case ReadFileSeekAndRead
:
1205 // Seek file first before reading in its data.
1207 if (FinishedSeeking
) {
1209 goto Skip_File_Seek
;
1212 if (FilePosition
+ ExtentLength
< ReadFileInfo
->FilePosition
) {
1213 FilePosition
+= ExtentLength
;
1217 if (FilePosition
+ ExtentLength
> ReadFileInfo
->FilePosition
) {
1218 Offset
= ReadFileInfo
->FilePosition
- FilePosition
;
1224 // Done with seeking file. Start reading its data.
1226 FinishedSeeking
= TRUE
;
1230 // Make sure we don't read more data than really wanted.
1232 if (ExtentLength
- Offset
> BytesLeft
) {
1233 DataLength
= BytesLeft
;
1235 DataLength
= ExtentLength
- Offset
;
1239 // Read extent's data into FileData.
1241 Status
= DiskIo
->ReadDisk (
1243 BlockIo
->Media
->MediaId
,
1244 Offset
+ MultU64x32 (Lsn
, LogicalBlockSize
),
1246 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1249 if (EFI_ERROR (Status
)) {
1250 goto Error_Read_Disk_Blk
;
1254 // Update current file's position.
1256 DataOffset
+= DataLength
;
1257 ReadFileInfo
->FilePosition
+= DataLength
;
1259 BytesLeft
-= DataLength
;
1260 if (BytesLeft
== 0) {
1262 // There is no more file data to read.
1264 Status
= EFI_SUCCESS
;
1273 // Point to the next AD (extent).
1275 AdOffset
+= AD_LENGTH (RecordingFlags
);
1279 case ExtendedAdsSequence
:
1280 // FIXME: Not supported. Got no volume with it, yet.
1282 Status
= EFI_UNSUPPORTED
;
1287 // A flag value reserved by the ECMA-167 standard (3rd Edition - June
1288 // 1997); 14.6 ICB Tag; 14.6.8 Flags (RBP 18); was found.
1290 Status
= EFI_UNSUPPORTED
;
1301 Error_Read_Disk_Blk
:
1302 Error_Alloc_Buffer_To_Next_Ad
:
1303 if (ReadFileInfo
->Flags
!= ReadFileSeekAndRead
) {
1304 FreePool (ReadFileInfo
->FileData
);
1316 Find a file by its filename from a given Parent file.
1318 @param[in] BlockIo BlockIo interface.
1319 @param[in] DiskIo DiskIo interface.
1320 @param[in] Volume Volume information pointer.
1321 @param[in] FileName File name string.
1322 @param[in] Parent Parent directory file.
1323 @param[in] Icb Long Allocation Descriptor pointer.
1324 @param[out] File Found file.
1326 @retval EFI_SUCCESS The file was found.
1327 @retval EFI_INVALID_PARAMETER One or more input parameters are invalid.
1328 @retval EFI_NOT_FOUND The file was not found.
1333 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1334 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1335 IN UDF_VOLUME_INFO
*Volume
,
1336 IN CHAR16
*FileName
,
1337 IN UDF_FILE_INFO
*Parent
,
1338 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1339 OUT UDF_FILE_INFO
*File
1343 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1344 UDF_READ_DIRECTORY_INFO ReadDirInfo
;
1346 CHAR16 FoundFileName
[UDF_FILENAME_LENGTH
];
1347 VOID
*CompareFileEntry
;
1350 // Check if both Parent->FileIdentifierDesc and Icb are NULL.
1352 if ((Parent
->FileIdentifierDesc
== NULL
) && (Icb
== NULL
)) {
1353 return EFI_INVALID_PARAMETER
;
1357 // Check if parent file is really directory.
1359 if (FE_ICB_FILE_TYPE (Parent
->FileEntry
) != UdfFileEntryDirectory
) {
1360 return EFI_NOT_FOUND
;
1364 // If FileName is current file or working directory, just duplicate Parent's
1365 // FE/EFE and FID descriptors.
1367 if (StrCmp (FileName
, L
".") == 0) {
1368 if (Parent
->FileIdentifierDesc
== NULL
) {
1369 return EFI_INVALID_PARAMETER
;
1372 DuplicateFe (BlockIo
, Volume
, Parent
->FileEntry
, &File
->FileEntry
);
1373 DuplicateFid (Parent
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1379 // Start directory listing.
1381 ZeroMem ((VOID
*)&ReadDirInfo
, sizeof (UDF_READ_DIRECTORY_INFO
));
1385 Status
= ReadDirectoryEntry (
1389 (Parent
->FileIdentifierDesc
!= NULL
) ?
1390 &Parent
->FileIdentifierDesc
->Icb
:
1396 if (EFI_ERROR (Status
)) {
1397 if (Status
== EFI_DEVICE_ERROR
) {
1398 Status
= EFI_NOT_FOUND
;
1404 if (FileIdentifierDesc
->FileCharacteristics
& PARENT_FILE
) {
1406 // This FID contains the location (FE/EFE) of the parent directory of this
1407 // directory (Parent), and if FileName is either ".." or "\\", then it's
1408 // the expected FID.
1410 if (StrCmp (FileName
, L
"..") == 0 || StrCmp (FileName
, L
"\\") == 0) {
1415 Status
= GetFileNameFromFid (FileIdentifierDesc
, FoundFileName
);
1416 if (EFI_ERROR (Status
)) {
1420 if (StrCmp (FileName
, FoundFileName
) == 0) {
1422 // FID has been found. Prepare to find its respective FE/EFE.
1429 FreePool ((VOID
*)FileIdentifierDesc
);
1432 if (ReadDirInfo
.DirectoryData
!= NULL
) {
1434 // Free all allocated resources for the directory listing.
1436 FreePool (ReadDirInfo
.DirectoryData
);
1440 Status
= EFI_SUCCESS
;
1442 File
->FileIdentifierDesc
= FileIdentifierDesc
;
1445 // If the requested file is root directory, then the FE/EFE was already
1446 // retrieved in UdfOpenVolume() function, thus no need to find it again.
1448 // Otherwise, find FE/EFE from the respective FID.
1450 if (StrCmp (FileName
, L
"\\") != 0) {
1451 Status
= FindFileEntry (
1455 &FileIdentifierDesc
->Icb
,
1458 if (EFI_ERROR (Status
)) {
1463 // Make sure that both Parent's FE/EFE and found FE/EFE are not equal.
1465 if (CompareMem ((VOID
*)Parent
->FileEntry
, (VOID
*)CompareFileEntry
,
1466 Volume
->FileEntrySize
) != 0) {
1467 File
->FileEntry
= CompareFileEntry
;
1469 FreePool ((VOID
*)FileIdentifierDesc
);
1470 FreePool ((VOID
*)CompareFileEntry
);
1471 Status
= EFI_NOT_FOUND
;
1479 FreePool ((VOID
*)FileIdentifierDesc
);
1485 Read volume information on a medium which contains a valid UDF file system.
1487 @param[in] BlockIo BlockIo interface.
1488 @param[in] DiskIo DiskIo interface.
1489 @param[out] Volume UDF volume information structure.
1491 @retval EFI_SUCCESS Volume information read.
1492 @retval EFI_NO_MEDIA The device has no media.
1493 @retval EFI_DEVICE_ERROR The device reported an error.
1494 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1495 @retval EFI_OUT_OF_RESOURCES The volume was not read due to lack of resources.
1499 ReadUdfVolumeInformation (
1500 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1501 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1502 OUT UDF_VOLUME_INFO
*Volume
1508 // Read all necessary UDF volume information and keep it private to the driver
1510 Status
= ReadVolumeFileStructure (
1515 if (EFI_ERROR (Status
)) {
1520 // Find File Set Descriptor
1522 Status
= FindFileSetDescriptor (BlockIo
, DiskIo
, Volume
);
1523 if (EFI_ERROR (Status
)) {
1531 Find the root directory on an UDF volume.
1533 @param[in] BlockIo BlockIo interface.
1534 @param[in] DiskIo DiskIo interface.
1535 @param[in] Volume UDF volume information structure.
1536 @param[out] File Root directory file.
1538 @retval EFI_SUCCESS Root directory found.
1539 @retval EFI_NO_MEDIA The device has no media.
1540 @retval EFI_DEVICE_ERROR The device reported an error.
1541 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1542 @retval EFI_OUT_OF_RESOURCES The root directory was not found due to lack of
1548 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1549 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1550 IN UDF_VOLUME_INFO
*Volume
,
1551 OUT UDF_FILE_INFO
*File
1555 UDF_FILE_INFO Parent
;
1557 Status
= FindFileEntry (
1561 &Volume
->FileSetDesc
.RootDirectoryIcb
,
1564 if (EFI_ERROR (Status
)) {
1568 Parent
.FileEntry
= File
->FileEntry
;
1569 Parent
.FileIdentifierDesc
= NULL
;
1578 &Volume
->FileSetDesc
.RootDirectoryIcb
,
1581 if (EFI_ERROR (Status
)) {
1582 FreePool (File
->FileEntry
);
1589 Find either a File Entry or a Extended File Entry from a given ICB.
1591 @param[in] BlockIo BlockIo interface.
1592 @param[in] DiskIo DiskIo interface.
1593 @param[in] Volume UDF volume information structure.
1594 @param[in] Icb ICB of the FID.
1595 @param[out] FileEntry File Entry or Extended File Entry.
1597 @retval EFI_SUCCESS File Entry or Extended File Entry found.
1598 @retval EFI_NO_MEDIA The device has no media.
1599 @retval EFI_DEVICE_ERROR The device reported an error.
1600 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1601 @retval EFI_OUT_OF_RESOURCES The FE/EFE entry was not found due to lack of
1607 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1608 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1609 IN UDF_VOLUME_INFO
*Volume
,
1610 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1611 OUT VOID
**FileEntry
1616 UINT32 LogicalBlockSize
;
1617 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
1620 Lsn
= GetLongAdLsn (Volume
, Icb
);
1621 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
1623 ReadBuffer
= AllocateZeroPool (Volume
->FileEntrySize
);
1624 if (ReadBuffer
== NULL
) {
1625 return EFI_OUT_OF_RESOURCES
;
1631 Status
= DiskIo
->ReadDisk (
1633 BlockIo
->Media
->MediaId
,
1634 MultU64x32 (Lsn
, LogicalBlockSize
),
1635 Volume
->FileEntrySize
,
1638 if (EFI_ERROR (Status
)) {
1639 goto Error_Read_Disk_Blk
;
1642 DescriptorTag
= ReadBuffer
;
1645 // Check if the read extent contains a valid Tag Identifier for the expected
1648 if (DescriptorTag
->TagIdentifier
!= UdfFileEntry
&&
1649 DescriptorTag
->TagIdentifier
!= UdfExtendedFileEntry
) {
1650 Status
= EFI_VOLUME_CORRUPTED
;
1651 goto Error_Invalid_Fe
;
1654 *FileEntry
= ReadBuffer
;
1658 Error_Read_Disk_Blk
:
1659 FreePool (ReadBuffer
);
1665 Find a file given its absolute path on an UDF volume.
1667 @param[in] BlockIo BlockIo interface.
1668 @param[in] DiskIo DiskIo interface.
1669 @param[in] Volume UDF volume information structure.
1670 @param[in] FilePath File's absolute path.
1671 @param[in] Root Root directory file.
1672 @param[in] Parent Parent directory file.
1673 @param[in] Icb ICB of Parent.
1674 @param[out] File Found file.
1676 @retval EFI_SUCCESS FilePath was found.
1677 @retval EFI_NO_MEDIA The device has no media.
1678 @retval EFI_DEVICE_ERROR The device reported an error.
1679 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1680 @retval EFI_OUT_OF_RESOURCES The FilePath file was not found due to lack of
1686 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1687 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1688 IN UDF_VOLUME_INFO
*Volume
,
1689 IN CHAR16
*FilePath
,
1690 IN UDF_FILE_INFO
*Root
,
1691 IN UDF_FILE_INFO
*Parent
,
1692 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1693 OUT UDF_FILE_INFO
*File
1697 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
1698 CHAR16
*FileNamePointer
;
1699 UDF_FILE_INFO PreviousFile
;
1702 Status
= EFI_NOT_FOUND
;
1704 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
1705 while (*FilePath
!= L
'\0') {
1706 FileNamePointer
= FileName
;
1707 while (*FilePath
!= L
'\0' && *FilePath
!= L
'\\') {
1708 *FileNamePointer
++ = *FilePath
++;
1711 *FileNamePointer
= L
'\0';
1712 if (FileName
[0] == L
'\0') {
1714 // Open root directory.
1718 // There is no file found for the root directory yet. So, find only its
1721 // See UdfOpenVolume() function.
1723 Status
= InternalFindFile (BlockIo
,
1732 // We've already a file pointer (Root) for the root directory. Duplicate
1733 // its FE/EFE and FID descriptors.
1735 DuplicateFe (BlockIo
, Volume
, Root
->FileEntry
, &File
->FileEntry
);
1736 DuplicateFid (Root
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1737 Status
= EFI_SUCCESS
;
1741 // No root directory. Find filename from the current directory.
1743 Status
= InternalFindFile (BlockIo
,
1752 if (EFI_ERROR (Status
)) {
1757 // If the found file is a symlink, then find its respective FE/EFE and
1760 if (FE_ICB_FILE_TYPE (File
->FileEntry
) == UdfFileEntrySymlink
) {
1761 FreePool ((VOID
*)File
->FileIdentifierDesc
);
1763 FileEntry
= File
->FileEntry
;
1765 Status
= ResolveSymlink (BlockIo
,
1772 FreePool (FileEntry
);
1774 if (EFI_ERROR (Status
)) {
1779 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
1780 sizeof (UDF_FILE_INFO
)) != 0) {
1781 CleanupFileInformation (&PreviousFile
);
1784 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
1785 if (*FilePath
!= L
'\0' && *FilePath
== L
'\\') {
1794 Read a directory entry at a time on an UDF volume.
1796 @param[in] BlockIo BlockIo interface.
1797 @param[in] DiskIo DiskIo interface.
1798 @param[in] Volume UDF volume information structure.
1799 @param[in] ParentIcb ICB of the parent file.
1800 @param[in] FileEntryData FE/EFE of the parent file.
1801 @param[in, out] ReadDirInfo Next read directory listing structure
1803 @param[out] FoundFid File Identifier Descriptor pointer.
1805 @retval EFI_SUCCESS Directory entry read.
1806 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
1807 @retval EFI_NO_MEDIA The device has no media.
1808 @retval EFI_DEVICE_ERROR The device reported an error.
1809 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1810 @retval EFI_OUT_OF_RESOURCES The directory entry was not read due to lack of
1815 ReadDirectoryEntry (
1816 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1817 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1818 IN UDF_VOLUME_INFO
*Volume
,
1819 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
1820 IN VOID
*FileEntryData
,
1821 IN OUT UDF_READ_DIRECTORY_INFO
*ReadDirInfo
,
1822 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR
**FoundFid
1826 UDF_READ_FILE_INFO ReadFileInfo
;
1827 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1829 if (ReadDirInfo
->DirectoryData
== NULL
) {
1831 // The directory's recorded data has not been read yet. So let's cache it
1832 // into memory and the next calls won't need to read it again.
1834 ReadFileInfo
.Flags
= ReadFileAllocateAndRead
;
1844 if (EFI_ERROR (Status
)) {
1849 // Fill in ReadDirInfo structure with the read directory's data information.
1851 ReadDirInfo
->DirectoryData
= ReadFileInfo
.FileData
;
1852 ReadDirInfo
->DirectoryLength
= ReadFileInfo
.ReadLength
;
1856 if (ReadDirInfo
->FidOffset
>= ReadDirInfo
->DirectoryLength
) {
1858 // There are no longer FIDs for this directory. By returning
1859 // EFI_DEVICE_ERROR to the callee will indicate end of directory
1862 return EFI_DEVICE_ERROR
;
1866 // Get FID for this entry.
1868 FileIdentifierDesc
= GET_FID_FROM_ADS (ReadDirInfo
->DirectoryData
,
1869 ReadDirInfo
->FidOffset
);
1871 // Update FidOffset to point to next FID.
1873 ReadDirInfo
->FidOffset
+= GetFidDescriptorLength (FileIdentifierDesc
);
1874 } while (FileIdentifierDesc
->FileCharacteristics
& DELETED_FILE
);
1876 DuplicateFid (FileIdentifierDesc
, FoundFid
);
1882 Get a filename (encoded in OSTA-compressed format) from a File Identifier
1883 Descriptor on an UDF volume.
1885 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
1886 @param[out] FileName Decoded filename.
1888 @retval EFI_SUCCESS Filename decoded and read.
1889 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1892 GetFileNameFromFid (
1893 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
,
1894 OUT CHAR16
*FileName
1897 UINT8
*OstaCompressed
;
1898 UINT8 CompressionId
;
1904 (UINT8
*)FileIdentifierDesc
->Data
+
1905 FileIdentifierDesc
->LengthOfImplementationUse
1908 CompressionId
= OstaCompressed
[0];
1909 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
1910 return EFI_VOLUME_CORRUPTED
;
1916 Length
= FileIdentifierDesc
->LengthOfFileIdentifier
;
1917 for (Index
= 1; Index
< Length
; Index
++) {
1918 if (CompressionId
== 16) {
1919 *FileName
= OstaCompressed
[Index
++] << 8;
1924 if (Index
< Length
) {
1925 *FileName
|= (CHAR16
)(OstaCompressed
[Index
]);
1937 Resolve a symlink file on an UDF volume.
1939 @param[in] BlockIo BlockIo interface.
1940 @param[in] DiskIo DiskIo interface.
1941 @param[in] Volume UDF volume information structure.
1942 @param[in] Parent Parent file.
1943 @param[in] FileEntryData FE/EFE structure pointer.
1944 @param[out] File Resolved file.
1946 @retval EFI_SUCCESS Symlink file resolved.
1947 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
1948 @retval EFI_NO_MEDIA The device has no media.
1949 @retval EFI_DEVICE_ERROR The device reported an error.
1950 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1951 @retval EFI_OUT_OF_RESOURCES The symlink file was not resolved due to lack of
1957 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1958 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1959 IN UDF_VOLUME_INFO
*Volume
,
1960 IN UDF_FILE_INFO
*Parent
,
1961 IN VOID
*FileEntryData
,
1962 OUT UDF_FILE_INFO
*File
1966 UDF_READ_FILE_INFO ReadFileInfo
;
1970 UDF_PATH_COMPONENT
*PathComp
;
1971 UINT8 PathCompLength
;
1972 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
1975 UINT8 CompressionId
;
1976 UDF_FILE_INFO PreviousFile
;
1979 // Symlink files on UDF volumes do not contain so much data other than
1980 // Path Components which resolves to real filenames, so it's OK to read in
1981 // all its data here -- usually the data will be inline with the FE/EFE for
1984 ReadFileInfo
.Flags
= ReadFileAllocateAndRead
;
1990 &Parent
->FileIdentifierDesc
->Icb
,
1994 if (EFI_ERROR (Status
)) {
1998 Length
= ReadFileInfo
.ReadLength
;
2000 Data
= (UINT8
*)ReadFileInfo
.FileData
;
2001 EndData
= Data
+ Length
;
2003 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
2006 PathComp
= (UDF_PATH_COMPONENT
*)Data
;
2008 PathCompLength
= PathComp
->LengthOfComponentIdentifier
;
2010 switch (PathComp
->ComponentType
) {
2013 // This Path Component specifies the root directory hierarchy subject to
2014 // agreement between the originator and recipient of the medium. Skip it.
2020 // "\\." of the current directory. Read next Path Component.
2022 goto Next_Path_Component
;
2025 // ".." (parent directory). Go to it.
2027 CopyMem ((VOID
*)FileName
, L
"..", 6);
2031 // "." (current file). Duplicate both FE/EFE and FID of this file.
2033 DuplicateFe (BlockIo
, Volume
, PreviousFile
.FileEntry
, &File
->FileEntry
);
2034 DuplicateFid (PreviousFile
.FileIdentifierDesc
,
2035 &File
->FileIdentifierDesc
);
2036 goto Next_Path_Component
;
2039 // This Path Component identifies an object, either a file or a
2040 // directory or an alias.
2042 // Decode it from the compressed data in ComponentIdentifier and find
2045 CompressionId
= PathComp
->ComponentIdentifier
[0];
2046 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
2047 return EFI_VOLUME_CORRUPTED
;
2051 for (Index
= 1; Index
< PathCompLength
; Index
++) {
2052 if (CompressionId
== 16) {
2053 *Char
= *(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+
2060 if (Index
< Length
) {
2061 *Char
|= (CHAR16
)(*(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+ Index
));
2072 // Find file from the read filename in symlink's file data.
2074 Status
= InternalFindFile (
2083 if (EFI_ERROR (Status
)) {
2084 goto Error_Find_File
;
2087 Next_Path_Component
:
2088 Data
+= sizeof (UDF_PATH_COMPONENT
) + PathCompLength
;
2089 if (Data
>= EndData
) {
2093 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2094 sizeof (UDF_FILE_INFO
)) != 0) {
2095 CleanupFileInformation (&PreviousFile
);
2098 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
2102 // Unmap the symlink file.
2104 FreePool (ReadFileInfo
.FileData
);
2109 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2110 sizeof (UDF_FILE_INFO
)) != 0) {
2111 CleanupFileInformation (&PreviousFile
);
2114 FreePool (ReadFileInfo
.FileData
);
2120 Clean up in-memory UDF file information.
2122 @param[in] File File information pointer.
2126 CleanupFileInformation (
2127 IN UDF_FILE_INFO
*File
2130 if (File
->FileEntry
!= NULL
) {
2131 FreePool (File
->FileEntry
);
2133 if (File
->FileIdentifierDesc
!= NULL
) {
2134 FreePool ((VOID
*)File
->FileIdentifierDesc
);
2137 ZeroMem ((VOID
*)File
, sizeof (UDF_FILE_INFO
));
2141 Find a file from its absolute path on an UDF volume.
2143 @param[in] BlockIo BlockIo interface.
2144 @param[in] DiskIo DiskIo interface.
2145 @param[in] Volume UDF volume information structure.
2146 @param[in] File File information structure.
2147 @param[out] Size Size of the file.
2149 @retval EFI_SUCCESS File size calculated and set in Size.
2150 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2151 @retval EFI_NO_MEDIA The device has no media.
2152 @retval EFI_DEVICE_ERROR The device reported an error.
2153 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2154 @retval EFI_OUT_OF_RESOURCES The file size was not calculated due to lack of
2160 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2161 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2162 IN UDF_VOLUME_INFO
*Volume
,
2163 IN UDF_FILE_INFO
*File
,
2168 UDF_READ_FILE_INFO ReadFileInfo
;
2170 ReadFileInfo
.Flags
= ReadFileGetFileSize
;
2176 &File
->FileIdentifierDesc
->Icb
,
2180 if (EFI_ERROR (Status
)) {
2184 *Size
= ReadFileInfo
.ReadLength
;
2190 Set information about a file on an UDF volume.
2192 @param[in] File File pointer.
2193 @param[in] FileSize Size of the file.
2194 @param[in] FileName Filename of the file.
2195 @param[in, out] BufferSize Size of the returned file infomation.
2196 @param[out] Buffer Data of the returned file information.
2198 @retval EFI_SUCCESS File information set.
2199 @retval EFI_NO_MEDIA The device has no media.
2200 @retval EFI_DEVICE_ERROR The device reported an error.
2201 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2202 @retval EFI_OUT_OF_RESOURCES The file information was not set due to lack of
2208 IN UDF_FILE_INFO
*File
,
2210 IN CHAR16
*FileName
,
2211 IN OUT UINTN
*BufferSize
,
2215 UINTN FileInfoLength
;
2216 EFI_FILE_INFO
*FileInfo
;
2217 UDF_FILE_ENTRY
*FileEntry
;
2218 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
2219 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
2222 // Calculate the needed size for the EFI_FILE_INFO structure.
2224 FileInfoLength
= sizeof (EFI_FILE_INFO
) + ((FileName
!= NULL
) ?
2225 StrSize (FileName
) :
2227 if (*BufferSize
< FileInfoLength
) {
2229 // The given Buffer has no size enough for EFI_FILE_INFO structure.
2231 *BufferSize
= FileInfoLength
;
2232 return EFI_BUFFER_TOO_SMALL
;
2236 // Buffer now contains room enough to store EFI_FILE_INFO structure.
2237 // Now, fill it in with all necessary information about the file.
2239 FileInfo
= (EFI_FILE_INFO
*)Buffer
;
2240 FileInfo
->Size
= FileInfoLength
;
2241 FileInfo
->Attribute
&= ~EFI_FILE_VALID_ATTR
;
2242 FileInfo
->Attribute
|= EFI_FILE_READ_ONLY
;
2244 if (IS_FID_DIRECTORY_FILE (File
->FileIdentifierDesc
)) {
2245 FileInfo
->Attribute
|= EFI_FILE_DIRECTORY
;
2246 } else if (IS_FID_NORMAL_FILE (File
->FileIdentifierDesc
)) {
2247 FileInfo
->Attribute
|= EFI_FILE_ARCHIVE
;
2250 if (IS_FID_HIDDEN_FILE (File
->FileIdentifierDesc
)) {
2251 FileInfo
->Attribute
|= EFI_FILE_HIDDEN
;
2254 DescriptorTag
= File
->FileEntry
;
2256 if (DescriptorTag
->TagIdentifier
== UdfFileEntry
) {
2257 FileEntry
= (UDF_FILE_ENTRY
*)File
->FileEntry
;
2260 // Check if FE has the system attribute set.
2262 if (FileEntry
->IcbTag
.Flags
& (1 << 10)) {
2263 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2266 FileInfo
->FileSize
= FileSize
;
2267 FileInfo
->PhysicalSize
= FileSize
;
2269 FileInfo
->CreateTime
.Year
= FileEntry
->AccessTime
.Year
;
2270 FileInfo
->CreateTime
.Month
= FileEntry
->AccessTime
.Month
;
2271 FileInfo
->CreateTime
.Day
= FileEntry
->AccessTime
.Day
;
2272 FileInfo
->CreateTime
.Hour
= FileEntry
->AccessTime
.Hour
;
2273 FileInfo
->CreateTime
.Minute
= FileEntry
->AccessTime
.Second
;
2274 FileInfo
->CreateTime
.Second
= FileEntry
->AccessTime
.Second
;
2275 FileInfo
->CreateTime
.Nanosecond
=
2276 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2278 FileInfo
->LastAccessTime
.Year
=
2279 FileEntry
->AccessTime
.Year
;
2280 FileInfo
->LastAccessTime
.Month
=
2281 FileEntry
->AccessTime
.Month
;
2282 FileInfo
->LastAccessTime
.Day
=
2283 FileEntry
->AccessTime
.Day
;
2284 FileInfo
->LastAccessTime
.Hour
=
2285 FileEntry
->AccessTime
.Hour
;
2286 FileInfo
->LastAccessTime
.Minute
=
2287 FileEntry
->AccessTime
.Minute
;
2288 FileInfo
->LastAccessTime
.Second
=
2289 FileEntry
->AccessTime
.Second
;
2290 FileInfo
->LastAccessTime
.Nanosecond
=
2291 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2292 } else if (DescriptorTag
->TagIdentifier
== UdfExtendedFileEntry
) {
2293 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)File
->FileEntry
;
2296 // Check if EFE has the system attribute set.
2298 if (ExtendedFileEntry
->IcbTag
.Flags
& (1 << 10)) {
2299 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2302 FileInfo
->FileSize
= FileSize
;
2303 FileInfo
->PhysicalSize
= FileSize
;
2305 FileInfo
->CreateTime
.Year
= ExtendedFileEntry
->CreationTime
.Year
;
2306 FileInfo
->CreateTime
.Month
= ExtendedFileEntry
->CreationTime
.Month
;
2307 FileInfo
->CreateTime
.Day
= ExtendedFileEntry
->CreationTime
.Day
;
2308 FileInfo
->CreateTime
.Hour
= ExtendedFileEntry
->CreationTime
.Hour
;
2309 FileInfo
->CreateTime
.Minute
= ExtendedFileEntry
->CreationTime
.Second
;
2310 FileInfo
->CreateTime
.Second
= ExtendedFileEntry
->CreationTime
.Second
;
2311 FileInfo
->CreateTime
.Nanosecond
=
2312 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2314 FileInfo
->LastAccessTime
.Year
=
2315 ExtendedFileEntry
->AccessTime
.Year
;
2316 FileInfo
->LastAccessTime
.Month
=
2317 ExtendedFileEntry
->AccessTime
.Month
;
2318 FileInfo
->LastAccessTime
.Day
=
2319 ExtendedFileEntry
->AccessTime
.Day
;
2320 FileInfo
->LastAccessTime
.Hour
=
2321 ExtendedFileEntry
->AccessTime
.Hour
;
2322 FileInfo
->LastAccessTime
.Minute
=
2323 ExtendedFileEntry
->AccessTime
.Minute
;
2324 FileInfo
->LastAccessTime
.Second
=
2325 ExtendedFileEntry
->AccessTime
.Second
;
2326 FileInfo
->LastAccessTime
.Nanosecond
=
2327 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2330 FileInfo
->CreateTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2331 FileInfo
->CreateTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2332 FileInfo
->LastAccessTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2333 FileInfo
->LastAccessTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2335 CopyMem ((VOID
*)&FileInfo
->ModificationTime
,
2336 (VOID
*)&FileInfo
->LastAccessTime
,
2339 if (FileName
!= NULL
) {
2340 StrCpyS (FileInfo
->FileName
, StrLen (FileName
) + 1, FileName
);
2342 FileInfo
->FileName
[0] = '\0';
2345 *BufferSize
= FileInfoLength
;
2351 Get volume and free space size information of an UDF volume.
2353 @param[in] BlockIo BlockIo interface.
2354 @param[in] DiskIo DiskIo interface.
2355 @param[in] Volume UDF volume information structure.
2356 @param[out] VolumeSize Volume size.
2357 @param[out] FreeSpaceSize Free space size.
2359 @retval EFI_SUCCESS Volume and free space size calculated.
2360 @retval EFI_NO_MEDIA The device has no media.
2361 @retval EFI_DEVICE_ERROR The device reported an error.
2362 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2363 @retval EFI_OUT_OF_RESOURCES The volume and free space size were not
2364 calculated due to lack of resources.
2369 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2370 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2371 IN UDF_VOLUME_INFO
*Volume
,
2372 OUT UINT64
*VolumeSize
,
2373 OUT UINT64
*FreeSpaceSize
2377 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
2378 UDF_EXTENT_AD
*ExtentAd
;
2380 UINT32 LogicalBlockSize
;
2381 UDF_LOGICAL_VOLUME_INTEGRITY
*LogicalVolInt
;
2382 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
2387 LogicalVolDesc
= &Volume
->LogicalVolDesc
;
2389 ExtentAd
= &LogicalVolDesc
->IntegritySequenceExtent
;
2391 if (ExtentAd
->ExtentLength
== 0) {
2392 return EFI_VOLUME_CORRUPTED
;
2395 LogicalVolInt
= AllocatePool (ExtentAd
->ExtentLength
);
2396 if (LogicalVolInt
== NULL
) {
2397 return EFI_OUT_OF_RESOURCES
;
2401 // Get location of Logical Volume Integrity Descriptor
2403 Lsn
= (UINT64
)ExtentAd
->ExtentLocation
- Volume
->MainVdsStartLocation
;
2405 LogicalBlockSize
= LogicalVolDesc
->LogicalBlockSize
;
2410 Status
= DiskIo
->ReadDisk (
2412 BlockIo
->Media
->MediaId
,
2413 MultU64x32 (Lsn
, LogicalBlockSize
),
2414 ExtentAd
->ExtentLength
,
2417 if (EFI_ERROR (Status
)) {
2421 DescriptorTag
= &LogicalVolInt
->DescriptorTag
;
2424 // Check if read block is a Logical Volume Integrity Descriptor
2426 if (DescriptorTag
->TagIdentifier
!= UdfLogicalVolumeIntegrityDescriptor
) {
2427 Status
= EFI_VOLUME_CORRUPTED
;
2434 Length
= LogicalVolInt
->NumberOfPartitions
;
2435 for (Index
= 0; Index
< Length
; Index
+= sizeof (UINT32
)) {
2436 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2438 // Check if size is not specified
2440 if (LsnsNo
== 0xFFFFFFFFUL
) {
2444 // Accumulate free space size
2446 *FreeSpaceSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2449 Length
= LogicalVolInt
->NumberOfPartitions
* sizeof (UINT32
) * 2;
2450 for (; Index
< Length
; Index
+= sizeof (UINT32
)) {
2451 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2453 // Check if size is not specified
2455 if (LsnsNo
== 0xFFFFFFFFUL
) {
2459 // Accumulate used volume space
2461 *VolumeSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2464 Status
= EFI_SUCCESS
;
2468 // Free Logical Volume Integrity Descriptor
2470 FreePool (LogicalVolInt
);
2476 Seek a file and read its data into memory on an UDF volume.
2478 @param[in] BlockIo BlockIo interface.
2479 @param[in] DiskIo DiskIo interface.
2480 @param[in] Volume UDF volume information structure.
2481 @param[in] File File information structure.
2482 @param[in] FileSize Size of the file.
2483 @param[in, out] FilePosition File position.
2484 @param[in, out] Buffer File data.
2485 @param[in, out] BufferSize Read size.
2487 @retval EFI_SUCCESS File seeked and read.
2488 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2489 @retval EFI_NO_MEDIA The device has no media.
2490 @retval EFI_DEVICE_ERROR The device reported an error.
2491 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2492 @retval EFI_OUT_OF_RESOURCES The file's recorded data was not read due to lack
2498 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2499 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2500 IN UDF_VOLUME_INFO
*Volume
,
2501 IN UDF_FILE_INFO
*File
,
2503 IN OUT UINT64
*FilePosition
,
2504 IN OUT VOID
*Buffer
,
2505 IN OUT UINT64
*BufferSize
2509 UDF_READ_FILE_INFO ReadFileInfo
;
2511 ReadFileInfo
.Flags
= ReadFileSeekAndRead
;
2512 ReadFileInfo
.FilePosition
= *FilePosition
;
2513 ReadFileInfo
.FileData
= Buffer
;
2514 ReadFileInfo
.FileDataSize
= *BufferSize
;
2515 ReadFileInfo
.FileSize
= FileSize
;
2521 &File
->FileIdentifierDesc
->Icb
,
2525 if (EFI_ERROR (Status
)) {
2529 *BufferSize
= ReadFileInfo
.FileDataSize
;
2530 *FilePosition
= ReadFileInfo
.FilePosition
;
2536 Check if ControllerHandle supports an UDF file system.
2538 @param[in] This Protocol instance pointer.
2539 @param[in] ControllerHandle Handle of device to test.
2541 @retval EFI_SUCCESS UDF file system found.
2542 @retval EFI_UNSUPPORTED UDF file system not found.
2546 SupportUdfFileSystem (
2547 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2548 IN EFI_HANDLE ControllerHandle
2552 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2553 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
2554 EFI_DEVICE_PATH_PROTOCOL
*LastDevicePathNode
;
2555 EFI_GUID
*VendorDefinedGuid
;
2558 // Open Device Path protocol on ControllerHandle
2560 Status
= gBS
->OpenProtocol (
2562 &gEfiDevicePathProtocolGuid
,
2563 (VOID
**)&DevicePath
,
2564 This
->DriverBindingHandle
,
2566 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2568 if (EFI_ERROR (Status
)) {
2569 return EFI_UNSUPPORTED
;
2572 Status
= EFI_UNSUPPORTED
;
2575 // Get last Device Path node
2577 LastDevicePathNode
= NULL
;
2578 DevicePathNode
= DevicePath
;
2579 while (!IsDevicePathEnd (DevicePathNode
)) {
2580 LastDevicePathNode
= DevicePathNode
;
2581 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
2584 // Check if last Device Path node contains a Vendor-Defined Media Device Path
2585 // of an UDF file system.
2587 if (LastDevicePathNode
!= NULL
&&
2588 DevicePathType (LastDevicePathNode
) == MEDIA_DEVICE_PATH
&&
2589 DevicePathSubType (LastDevicePathNode
) == MEDIA_VENDOR_DP
) {
2590 VendorDefinedGuid
= (EFI_GUID
*)((UINTN
)LastDevicePathNode
+
2591 OFFSET_OF (VENDOR_DEVICE_PATH
, Guid
));
2592 if (CompareGuid (VendorDefinedGuid
, &gUdfDevPathGuid
)) {
2593 Status
= EFI_SUCCESS
;
2598 // Close Device Path protocol on ControllerHandle
2600 gBS
->CloseProtocol (
2602 &gEfiDevicePathProtocolGuid
,
2603 This
->DriverBindingHandle
,