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.
276 @param[out] Lsn Logical sector number pointer.
278 @retval EFI_SUCCESS Logical sector number successfully returned.
279 @retval EFI_UNSUPPORTED Logical sector number is not returned due to
285 IN UDF_VOLUME_INFO
*Volume
,
286 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
,
290 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
292 PartitionDesc
= GetPdFromLongAd (Volume
, LongAd
);
293 if (PartitionDesc
== NULL
) {
296 "%a: Fail to get the Partition Descriptor from the given Long Allocation Descriptor.\n",
299 return EFI_UNSUPPORTED
;
302 *Lsn
= (UINT64
)PartitionDesc
->PartitionStartingLocation
-
303 Volume
->MainVdsStartLocation
+
304 LongAd
->ExtentLocation
.LogicalBlockNumber
;
310 Return logical sector number of a given Short Allocation Descriptor.
312 @param[in] Volume Volume pointer.
313 @param[in] PartitionDesc Partition Descriptor pointer.
314 @param[in] ShortAd Short Allocation Descriptor pointer.
316 @return The logical sector number of a given Short Allocation Descriptor.
321 IN UDF_VOLUME_INFO
*Volume
,
322 IN UDF_PARTITION_DESCRIPTOR
*PartitionDesc
,
323 IN UDF_SHORT_ALLOCATION_DESCRIPTOR
*ShortAd
326 return (UINT64
)PartitionDesc
->PartitionStartingLocation
-
327 Volume
->MainVdsStartLocation
+ ShortAd
->ExtentPosition
;
331 Find File Set Descriptor of a given Logical Volume Descriptor.
333 The found FSD will contain the extent (LogicalVolumeContentsUse) where our
336 @param[in] BlockIo BlockIo interface.
337 @param[in] DiskIo DiskIo interface.
338 @param[in] Volume Volume information pointer.
340 @retval EFI_SUCCESS File Set Descriptor pointer found.
341 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
342 @retval other File Set Descriptor pointer not found.
346 FindFileSetDescriptor (
347 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
348 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
349 IN UDF_VOLUME_INFO
*Volume
354 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
355 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
357 LogicalVolDesc
= &Volume
->LogicalVolDesc
;
358 Status
= GetLongAdLsn (Volume
, &LogicalVolDesc
->LogicalVolumeContentsUse
, &Lsn
);
359 if (EFI_ERROR (Status
)) {
364 // As per UDF 2.60 specification:
366 // There shall be exactly one File Set Descriptor recorded per Logical
371 Status
= DiskIo
->ReadDisk (
373 BlockIo
->Media
->MediaId
,
374 MultU64x32 (Lsn
, LogicalVolDesc
->LogicalBlockSize
),
375 sizeof (Volume
->FileSetDesc
),
378 if (EFI_ERROR (Status
)) {
382 DescriptorTag
= &Volume
->FileSetDesc
.DescriptorTag
;
385 // Check if read block is a File Set Descriptor
387 if (DescriptorTag
->TagIdentifier
!= UdfFileSetDescriptor
) {
388 return EFI_VOLUME_CORRUPTED
;
395 Read Volume and File Structure on an UDF file system.
397 @param[in] BlockIo BlockIo interface.
398 @param[in] DiskIo DiskIo interface.
399 @param[out] Volume Volume information pointer.
401 @retval EFI_SUCCESS Volume and File Structure were read.
402 @retval other Volume and File Structure were not read.
406 ReadVolumeFileStructure (
407 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
408 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
409 OUT UDF_VOLUME_INFO
*Volume
413 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint
;
414 UDF_EXTENT_AD
*ExtentAd
;
417 // Find Anchor Volume Descriptor Pointer
419 Status
= FindAnchorVolumeDescriptorPointer (
424 if (EFI_ERROR (Status
)) {
429 // Save Main VDS start block number
431 ExtentAd
= &AnchorPoint
.MainVolumeDescriptorSequenceExtent
;
433 Volume
->MainVdsStartLocation
= (UINT64
)ExtentAd
->ExtentLocation
;
436 // Start Main Volume Descriptor Sequence.
438 Status
= StartMainVolumeDescriptorSequence (
444 if (EFI_ERROR (Status
)) {
452 Calculate length of a given File Identifier Descriptor.
454 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
456 @return The length of a given File Identifier Descriptor.
460 GetFidDescriptorLength (
461 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
465 (INTN
)((OFFSET_OF (UDF_FILE_IDENTIFIER_DESCRIPTOR
, Data
[0]) + 3 +
466 FileIdentifierDesc
->LengthOfFileIdentifier
+
467 FileIdentifierDesc
->LengthOfImplementationUse
) >> 2) << 2
472 Duplicate a given File Identifier Descriptor.
474 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
475 @param[out] NewFileIdentifierDesc The duplicated File Identifier Descriptor.
480 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
,
481 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR
**NewFileIdentifierDesc
484 *NewFileIdentifierDesc
=
485 (UDF_FILE_IDENTIFIER_DESCRIPTOR
*)AllocateCopyPool (
486 (UINTN
) GetFidDescriptorLength (FileIdentifierDesc
), FileIdentifierDesc
);
490 Duplicate either a given File Entry or a given Extended File Entry.
492 @param[in] BlockIo BlockIo interface.
493 @param[in] Volume Volume information pointer.
494 @param[in] FileEntry (Extended) File Entry pointer.
495 @param[out] NewFileEntry The duplicated (Extended) File Entry.
500 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
501 IN UDF_VOLUME_INFO
*Volume
,
503 OUT VOID
**NewFileEntry
506 *NewFileEntry
= AllocateCopyPool (Volume
->FileEntrySize
, FileEntry
);
510 Get raw data + length of a given File Entry or Extended File Entry.
512 The file's recorded data can contain either real file content (inline) or
513 a sequence of extents (or Allocation Descriptors) which tells where file's
514 content is stored in.
516 NOTE: The FE/EFE can be thought it was an inode.
518 @param[in] FileEntryData (Extended) File Entry pointer.
519 @param[out] Data Buffer contains the raw data of a given
520 (Extended) File Entry.
521 @param[out] Length Length of the data in Buffer.
526 IN VOID
*FileEntryData
,
531 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
532 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
533 UDF_FILE_ENTRY
*FileEntry
;
535 DescriptorTag
= FileEntryData
;
537 if (DescriptorTag
->TagIdentifier
== UdfExtendedFileEntry
) {
538 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)FileEntryData
;
540 *Length
= ExtendedFileEntry
->InformationLength
;
541 *Data
= (VOID
*)((UINT8
*)ExtendedFileEntry
->Data
+
542 ExtendedFileEntry
->LengthOfExtendedAttributes
);
543 } else if (DescriptorTag
->TagIdentifier
== UdfFileEntry
) {
544 FileEntry
= (UDF_FILE_ENTRY
*)FileEntryData
;
546 *Length
= FileEntry
->InformationLength
;
547 *Data
= (VOID
*)((UINT8
*)FileEntry
->Data
+
548 FileEntry
->LengthOfExtendedAttributes
);
553 Get Allocation Descriptors' data information from a given FE/EFE.
555 @param[in] FileEntryData (Extended) File Entry pointer.
556 @param[out] AdsData Buffer contains the Allocation Descriptors'
557 data from a given FE/EFE.
558 @param[out] Length Length of the data in AdsData.
563 IN VOID
*FileEntryData
,
568 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
569 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
570 UDF_FILE_ENTRY
*FileEntry
;
572 DescriptorTag
= FileEntryData
;
574 if (DescriptorTag
->TagIdentifier
== UdfExtendedFileEntry
) {
575 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)FileEntryData
;
577 *Length
= ExtendedFileEntry
->LengthOfAllocationDescriptors
;
578 *AdsData
= (VOID
*)((UINT8
*)ExtendedFileEntry
->Data
+
579 ExtendedFileEntry
->LengthOfExtendedAttributes
);
580 } else if (DescriptorTag
->TagIdentifier
== UdfFileEntry
) {
581 FileEntry
= (UDF_FILE_ENTRY
*)FileEntryData
;
583 *Length
= FileEntry
->LengthOfAllocationDescriptors
;
584 *AdsData
= (VOID
*)((UINT8
*)FileEntry
->Data
+
585 FileEntry
->LengthOfExtendedAttributes
);
590 Read next Long Allocation Descriptor from a given file's data.
592 @param[in] Data File's data pointer.
593 @param[in,out] Offset Starting offset of the File's data to read.
594 @param[in] Length Length of the data to read.
595 @param[out] FoundLongAd Long Allocation Descriptor pointer.
597 @retval EFI_SUCCESS A Long Allocation Descriptor was found.
598 @retval EFI_DEVICE_ERROR No more Long Allocation Descriptors.
604 IN OUT UINT64
*Offset
,
606 OUT UDF_LONG_ALLOCATION_DESCRIPTOR
**FoundLongAd
609 UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
;
610 UDF_EXTENT_FLAGS ExtentFlags
;
613 if (*Offset
>= Length
) {
615 // No more Long Allocation Descriptors.
617 return EFI_DEVICE_ERROR
;
621 (UDF_LONG_ALLOCATION_DESCRIPTOR
*)((UINT8
*)Data
+ *Offset
);
624 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
625 // allocated AD, then return it.
627 ExtentFlags
= GET_EXTENT_FLAGS (LongAdsSequence
, LongAd
);
628 if (ExtentFlags
== ExtentIsNextExtent
||
629 ExtentFlags
== ExtentRecordedAndAllocated
) {
634 // This AD is either not recorded but allocated, or not recorded and not
635 // allocated. Skip it.
637 *Offset
+= AD_LENGTH (LongAdsSequence
);
640 *FoundLongAd
= LongAd
;
646 Read next Short Allocation Descriptor from a given file's data.
648 @param[in] Data File's data pointer.
649 @param[in,out] Offset Starting offset of the File's data to read.
650 @param[in] Length Length of the data to read.
651 @param[out] FoundShortAd Short Allocation Descriptor pointer.
653 @retval EFI_SUCCESS A Short Allocation Descriptor was found.
654 @retval EFI_DEVICE_ERROR No more Short Allocation Descriptors.
660 IN OUT UINT64
*Offset
,
662 OUT UDF_SHORT_ALLOCATION_DESCRIPTOR
**FoundShortAd
665 UDF_SHORT_ALLOCATION_DESCRIPTOR
*ShortAd
;
666 UDF_EXTENT_FLAGS ExtentFlags
;
669 if (*Offset
>= Length
) {
671 // No more Short Allocation Descriptors.
673 return EFI_DEVICE_ERROR
;
677 (UDF_SHORT_ALLOCATION_DESCRIPTOR
*)((UINT8
*)Data
+ *Offset
);
680 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
681 // allocated AD, then return it.
683 ExtentFlags
= GET_EXTENT_FLAGS (ShortAdsSequence
, ShortAd
);
684 if (ExtentFlags
== ExtentIsNextExtent
||
685 ExtentFlags
== ExtentRecordedAndAllocated
) {
690 // This AD is either not recorded but allocated, or not recorded and not
691 // allocated. Skip it.
693 *Offset
+= AD_LENGTH (ShortAdsSequence
);
696 *FoundShortAd
= ShortAd
;
702 Get either a Short Allocation Descriptor or a Long Allocation Descriptor from
705 @param[in] RecordingFlags Flag to indicate the type of descriptor.
706 @param[in] Data File's data pointer.
707 @param[in,out] Offset Starting offset of the File's data to read.
708 @param[in] Length Length of the data to read.
709 @param[out] FoundAd Allocation Descriptor pointer.
711 @retval EFI_SUCCESS A Short Allocation Descriptor was found.
712 @retval EFI_DEVICE_ERROR No more Allocation Descriptors.
713 Invalid type of descriptor was given.
717 GetAllocationDescriptor (
718 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
720 IN OUT UINT64
*Offset
,
725 if (RecordingFlags
== LongAdsSequence
) {
726 return GetLongAdFromAds (
730 (UDF_LONG_ALLOCATION_DESCRIPTOR
**)FoundAd
732 } else if (RecordingFlags
== ShortAdsSequence
) {
733 return GetShortAdFromAds (
737 (UDF_SHORT_ALLOCATION_DESCRIPTOR
**)FoundAd
741 return EFI_DEVICE_ERROR
;
745 Return logical sector number of either Short or Long Allocation Descriptor.
747 @param[in] RecordingFlags Flag to indicate the type of descriptor.
748 @param[in] Volume Volume information pointer.
749 @param[in] ParentIcb Long Allocation Descriptor pointer.
750 @param[in] Ad Allocation Descriptor pointer.
751 @param[out] Lsn Logical sector number pointer.
753 @retval EFI_SUCCESS Logical sector number of the given Allocation
754 Descriptor successfully returned.
755 @retval EFI_UNSUPPORTED Logical sector number of the given Allocation
756 Descriptor is not returned due to unrecognized
761 GetAllocationDescriptorLsn (
762 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
763 IN UDF_VOLUME_INFO
*Volume
,
764 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
769 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
771 if (RecordingFlags
== LongAdsSequence
) {
772 return GetLongAdLsn (Volume
, (UDF_LONG_ALLOCATION_DESCRIPTOR
*)Ad
, Lsn
);
773 } else if (RecordingFlags
== ShortAdsSequence
) {
774 PartitionDesc
= GetPdFromLongAd (Volume
, ParentIcb
);
775 if (PartitionDesc
== NULL
) {
776 return EFI_UNSUPPORTED
;
779 *Lsn
= GetShortAdLsn (
782 (UDF_SHORT_ALLOCATION_DESCRIPTOR
*)Ad
787 return EFI_UNSUPPORTED
;
791 Return offset + length of a given indirect Allocation Descriptor (AED).
793 @param[in] BlockIo BlockIo interface.
794 @param[in] DiskIo DiskIo interface.
795 @param[in] Volume Volume information pointer.
796 @param[in] ParentIcb Long Allocation Descriptor pointer.
797 @param[in] RecordingFlags Flag to indicate the type of descriptor.
798 @param[in] Ad Allocation Descriptor pointer.
799 @param[out] Offset Offset of a given indirect Allocation
801 @param[out] Length Length of a given indirect Allocation
804 @retval EFI_SUCCESS The offset and length were returned.
805 @retval EFI_OUT_OF_RESOURCES The offset and length were not returned due
806 to lack of resources.
807 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
808 @retval other The offset and length were not returned.
813 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
814 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
815 IN UDF_VOLUME_INFO
*Volume
,
816 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
817 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
827 UINT32 LogicalBlockSize
;
828 UDF_ALLOCATION_EXTENT_DESCRIPTOR
*AllocExtDesc
;
829 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
831 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
832 Status
= GetAllocationDescriptorLsn (RecordingFlags
,
837 if (EFI_ERROR (Status
)) {
841 Data
= AllocatePool (ExtentLength
);
843 return EFI_OUT_OF_RESOURCES
;
846 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
851 Status
= DiskIo
->ReadDisk (
853 BlockIo
->Media
->MediaId
,
854 MultU64x32 (Lsn
, LogicalBlockSize
),
858 if (EFI_ERROR (Status
)) {
862 AllocExtDesc
= (UDF_ALLOCATION_EXTENT_DESCRIPTOR
*)Data
;
864 DescriptorTag
= &AllocExtDesc
->DescriptorTag
;
867 // Check if read extent contains a valid tag identifier for AED.
869 if (DescriptorTag
->TagIdentifier
!= UdfAllocationExtentDescriptor
) {
870 Status
= EFI_VOLUME_CORRUPTED
;
875 // Get AED's block offset and its length.
877 *Offset
= MultU64x32 (Lsn
, LogicalBlockSize
) +
878 sizeof (UDF_ALLOCATION_EXTENT_DESCRIPTOR
);
879 *Length
= AllocExtDesc
->LengthOfAllocationDescriptors
;
888 Read Allocation Extent Descriptor into memory.
890 @param[in] BlockIo BlockIo interface.
891 @param[in] DiskIo DiskIo interface.
892 @param[in] Volume Volume information pointer.
893 @param[in] ParentIcb Long Allocation Descriptor pointer.
894 @param[in] RecordingFlags Flag to indicate the type of descriptor.
895 @param[in] Ad Allocation Descriptor pointer.
896 @param[out] Data Buffer that contains the Allocation Extent
898 @param[out] Length Length of Data.
900 @retval EFI_SUCCESS The Allocation Extent Descriptor was read.
901 @retval EFI_OUT_OF_RESOURCES The Allocation Extent Descriptor was not read
902 due to lack of resources.
903 @retval other Fail to read the disk.
908 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
909 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
910 IN UDF_VOLUME_INFO
*Volume
,
911 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
912 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
922 // Get AED's offset + length.
924 Status
= GetAedAdsOffset (
934 if (EFI_ERROR (Status
)) {
939 // Allocate buffer to read in AED's data.
941 *Data
= AllocatePool ((UINTN
) (*Length
));
943 return EFI_OUT_OF_RESOURCES
;
946 return DiskIo
->ReadDisk (
948 BlockIo
->Media
->MediaId
,
956 Function used to serialise reads of Allocation Descriptors.
958 @param[in] RecordingFlags Flag to indicate the type of descriptor.
959 @param[in] Ad Allocation Descriptor pointer.
960 @param[in, out] Buffer Buffer to hold the next Allocation Descriptor.
961 @param[in] Length Length of Buffer.
963 @retval EFI_SUCCESS Buffer was grown to hold the next Allocation
965 @retval EFI_OUT_OF_RESOURCES Buffer was not grown due to lack of resources.
969 GrowUpBufferToNextAd (
970 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
972 IN OUT VOID
**Buffer
,
978 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
980 if (*Buffer
== NULL
) {
981 *Buffer
= AllocatePool (ExtentLength
);
982 if (*Buffer
== NULL
) {
983 return EFI_OUT_OF_RESOURCES
;
986 *Buffer
= ReallocatePool ((UINTN
) Length
, (UINTN
) (Length
+ ExtentLength
), *Buffer
);
987 if (*Buffer
== NULL
) {
988 return EFI_OUT_OF_RESOURCES
;
996 Read data or size of either a File Entry or an Extended File Entry.
998 @param[in] BlockIo BlockIo interface.
999 @param[in] DiskIo DiskIo interface.
1000 @param[in] Volume Volume information pointer.
1001 @param[in] ParentIcb Long Allocation Descriptor pointer.
1002 @param[in] FileEntryData FE/EFE structure pointer.
1003 @param[in, out] ReadFileInfo Read file information pointer.
1005 @retval EFI_SUCCESS Data or size of a FE/EFE was read.
1006 @retval EFI_OUT_OF_RESOURCES Data or size of a FE/EFE was not read due to
1008 @retval EFI_INVALID_PARAMETER The read file flag given in ReadFileInfo is
1010 @retval EFI_UNSUPPORTED The FE recording flag given in FileEntryData
1012 @retval other Data or size of a FE/EFE was not read.
1017 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1018 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1019 IN UDF_VOLUME_INFO
*Volume
,
1020 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
1021 IN VOID
*FileEntryData
,
1022 IN OUT UDF_READ_FILE_INFO
*ReadFileInfo
1026 UINT32 LogicalBlockSize
;
1033 UINT64 FilePosition
;
1038 BOOLEAN FinishedSeeking
;
1039 UINT32 ExtentLength
;
1040 UDF_FE_RECORDING_FLAGS RecordingFlags
;
1042 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
1046 // set BytesLeft to suppress incorrect compiler/analyzer warnings
1051 FinishedSeeking
= FALSE
;
1054 switch (ReadFileInfo
->Flags
) {
1055 case ReadFileGetFileSize
:
1056 case ReadFileAllocateAndRead
:
1058 // Initialise ReadFileInfo structure for either getting file size, or
1059 // reading file's recorded data.
1061 ReadFileInfo
->ReadLength
= 0;
1062 ReadFileInfo
->FileData
= NULL
;
1064 case ReadFileSeekAndRead
:
1066 // About to seek a file and/or read its data.
1068 Length
= ReadFileInfo
->FileSize
- ReadFileInfo
->FilePosition
;
1069 if (ReadFileInfo
->FileDataSize
> Length
) {
1071 // About to read beyond the EOF -- truncate it.
1073 ReadFileInfo
->FileDataSize
= Length
;
1077 // Initialise data to start seeking and/or reading a file.
1079 BytesLeft
= ReadFileInfo
->FileDataSize
;
1082 FinishedSeeking
= FALSE
;
1087 RecordingFlags
= GET_FE_RECORDING_FLAGS (FileEntryData
);
1088 switch (RecordingFlags
) {
1091 // There are no extents for this FE/EFE. All data is inline.
1093 GetFileEntryData (FileEntryData
, &Data
, &Length
);
1095 if (ReadFileInfo
->Flags
== ReadFileGetFileSize
) {
1096 ReadFileInfo
->ReadLength
= Length
;
1097 } else if (ReadFileInfo
->Flags
== ReadFileAllocateAndRead
) {
1099 // Allocate buffer for starting read data.
1101 ReadFileInfo
->FileData
= AllocatePool ((UINTN
) Length
);
1102 if (ReadFileInfo
->FileData
== NULL
) {
1103 return EFI_OUT_OF_RESOURCES
;
1107 // Read all inline data into ReadFileInfo->FileData
1109 CopyMem (ReadFileInfo
->FileData
, Data
, (UINTN
) Length
);
1110 ReadFileInfo
->ReadLength
= Length
;
1111 } else if (ReadFileInfo
->Flags
== ReadFileSeekAndRead
) {
1113 // If FilePosition is non-zero, seek file to FilePosition, read
1114 // FileDataSize bytes and then updates FilePosition.
1117 ReadFileInfo
->FileData
,
1118 (VOID
*)((UINT8
*)Data
+ ReadFileInfo
->FilePosition
),
1119 (UINTN
) ReadFileInfo
->FileDataSize
1122 ReadFileInfo
->FilePosition
+= ReadFileInfo
->FileDataSize
;
1125 return EFI_INVALID_PARAMETER
;
1128 Status
= EFI_SUCCESS
;
1131 case LongAdsSequence
:
1132 case ShortAdsSequence
:
1134 // This FE/EFE contains a run of Allocation Descriptors. Get data + size
1135 // for start reading them out.
1137 GetAdsInformation (FileEntryData
, &Data
, &Length
);
1144 Status
= GetAllocationDescriptor (
1151 if (Status
== EFI_DEVICE_ERROR
) {
1152 Status
= EFI_SUCCESS
;
1157 // Check if AD is an indirect AD. If so, read Allocation Extent
1158 // Descriptor and its extents (ADs).
1160 if (GET_EXTENT_FLAGS (RecordingFlags
, Ad
) == ExtentIsNextExtent
) {
1167 Status
= GetAedAdsData (
1177 if (EFI_ERROR (Status
)) {
1180 ASSERT (Data
!= NULL
);
1186 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
1188 Status
= GetAllocationDescriptorLsn (RecordingFlags
,
1193 if (EFI_ERROR (Status
)) {
1197 switch (ReadFileInfo
->Flags
) {
1198 case ReadFileGetFileSize
:
1199 ReadFileInfo
->ReadLength
+= ExtentLength
;
1201 case ReadFileAllocateAndRead
:
1203 // Increase FileData (if necessary) to read next extent.
1205 Status
= GrowUpBufferToNextAd (
1208 &ReadFileInfo
->FileData
,
1209 ReadFileInfo
->ReadLength
1211 if (EFI_ERROR (Status
)) {
1212 goto Error_Alloc_Buffer_To_Next_Ad
;
1216 // Read extent's data into FileData.
1218 Status
= DiskIo
->ReadDisk (
1220 BlockIo
->Media
->MediaId
,
1221 MultU64x32 (Lsn
, LogicalBlockSize
),
1223 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1224 ReadFileInfo
->ReadLength
)
1226 if (EFI_ERROR (Status
)) {
1227 goto Error_Read_Disk_Blk
;
1230 ReadFileInfo
->ReadLength
+= ExtentLength
;
1232 case ReadFileSeekAndRead
:
1234 // Seek file first before reading in its data.
1236 if (FinishedSeeking
) {
1238 goto Skip_File_Seek
;
1241 if (FilePosition
+ ExtentLength
< ReadFileInfo
->FilePosition
) {
1242 FilePosition
+= ExtentLength
;
1246 if (FilePosition
+ ExtentLength
> ReadFileInfo
->FilePosition
) {
1247 Offset
= ReadFileInfo
->FilePosition
- FilePosition
;
1253 // Done with seeking file. Start reading its data.
1255 FinishedSeeking
= TRUE
;
1259 // Make sure we don't read more data than really wanted.
1261 if (ExtentLength
- Offset
> BytesLeft
) {
1262 DataLength
= BytesLeft
;
1264 DataLength
= ExtentLength
- Offset
;
1268 // Read extent's data into FileData.
1270 Status
= DiskIo
->ReadDisk (
1272 BlockIo
->Media
->MediaId
,
1273 Offset
+ MultU64x32 (Lsn
, LogicalBlockSize
),
1275 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1278 if (EFI_ERROR (Status
)) {
1279 goto Error_Read_Disk_Blk
;
1283 // Update current file's position.
1285 DataOffset
+= DataLength
;
1286 ReadFileInfo
->FilePosition
+= DataLength
;
1288 BytesLeft
-= DataLength
;
1289 if (BytesLeft
== 0) {
1291 // There is no more file data to read.
1293 Status
= EFI_SUCCESS
;
1302 // Point to the next AD (extent).
1304 AdOffset
+= AD_LENGTH (RecordingFlags
);
1308 case ExtendedAdsSequence
:
1309 // FIXME: Not supported. Got no volume with it, yet.
1311 Status
= EFI_UNSUPPORTED
;
1316 // A flag value reserved by the ECMA-167 standard (3rd Edition - June
1317 // 1997); 14.6 ICB Tag; 14.6.8 Flags (RBP 18); was found.
1319 Status
= EFI_UNSUPPORTED
;
1330 Error_Read_Disk_Blk
:
1331 Error_Alloc_Buffer_To_Next_Ad
:
1332 if (ReadFileInfo
->Flags
!= ReadFileSeekAndRead
) {
1333 FreePool (ReadFileInfo
->FileData
);
1345 Find a file by its filename from a given Parent file.
1347 @param[in] BlockIo BlockIo interface.
1348 @param[in] DiskIo DiskIo interface.
1349 @param[in] Volume Volume information pointer.
1350 @param[in] FileName File name string.
1351 @param[in] Parent Parent directory file.
1352 @param[in] Icb Long Allocation Descriptor pointer.
1353 @param[out] File Found file.
1355 @retval EFI_SUCCESS The file was found.
1356 @retval EFI_INVALID_PARAMETER One or more input parameters are invalid.
1357 @retval EFI_NOT_FOUND The file was not found.
1362 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1363 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1364 IN UDF_VOLUME_INFO
*Volume
,
1365 IN CHAR16
*FileName
,
1366 IN UDF_FILE_INFO
*Parent
,
1367 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1368 OUT UDF_FILE_INFO
*File
1372 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1373 UDF_READ_DIRECTORY_INFO ReadDirInfo
;
1375 CHAR16 FoundFileName
[UDF_FILENAME_LENGTH
];
1376 VOID
*CompareFileEntry
;
1379 // Check if both Parent->FileIdentifierDesc and Icb are NULL.
1381 if ((Parent
->FileIdentifierDesc
== NULL
) && (Icb
== NULL
)) {
1382 return EFI_INVALID_PARAMETER
;
1386 // Check if parent file is really directory.
1388 if (FE_ICB_FILE_TYPE (Parent
->FileEntry
) != UdfFileEntryDirectory
) {
1389 return EFI_NOT_FOUND
;
1393 // If FileName is current file or working directory, just duplicate Parent's
1394 // FE/EFE and FID descriptors.
1396 if (StrCmp (FileName
, L
".") == 0) {
1397 if (Parent
->FileIdentifierDesc
== NULL
) {
1398 return EFI_INVALID_PARAMETER
;
1401 DuplicateFe (BlockIo
, Volume
, Parent
->FileEntry
, &File
->FileEntry
);
1402 if (File
->FileEntry
== NULL
) {
1403 return EFI_OUT_OF_RESOURCES
;
1406 DuplicateFid (Parent
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1407 if (File
->FileIdentifierDesc
== NULL
) {
1408 FreePool (File
->FileEntry
);
1409 return EFI_OUT_OF_RESOURCES
;
1416 // Start directory listing.
1418 ZeroMem ((VOID
*)&ReadDirInfo
, sizeof (UDF_READ_DIRECTORY_INFO
));
1422 Status
= ReadDirectoryEntry (
1426 (Parent
->FileIdentifierDesc
!= NULL
) ?
1427 &Parent
->FileIdentifierDesc
->Icb
:
1433 if (EFI_ERROR (Status
)) {
1434 if (Status
== EFI_DEVICE_ERROR
) {
1435 Status
= EFI_NOT_FOUND
;
1441 // After calling function ReadDirectoryEntry(), if 'FileIdentifierDesc' is
1442 // NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the code
1443 // reaches here, 'FileIdentifierDesc' must be not NULL.
1445 // The ASSERT here is for addressing a false positive NULL pointer
1446 // dereference issue raised from static analysis.
1448 ASSERT (FileIdentifierDesc
!= NULL
);
1450 if (FileIdentifierDesc
->FileCharacteristics
& PARENT_FILE
) {
1452 // This FID contains the location (FE/EFE) of the parent directory of this
1453 // directory (Parent), and if FileName is either ".." or "\\", then it's
1454 // the expected FID.
1456 if (StrCmp (FileName
, L
"..") == 0 || StrCmp (FileName
, L
"\\") == 0) {
1461 Status
= GetFileNameFromFid (FileIdentifierDesc
, FoundFileName
);
1462 if (EFI_ERROR (Status
)) {
1466 if (StrCmp (FileName
, FoundFileName
) == 0) {
1468 // FID has been found. Prepare to find its respective FE/EFE.
1475 FreePool ((VOID
*)FileIdentifierDesc
);
1478 if (ReadDirInfo
.DirectoryData
!= NULL
) {
1480 // Free all allocated resources for the directory listing.
1482 FreePool (ReadDirInfo
.DirectoryData
);
1486 Status
= EFI_SUCCESS
;
1488 File
->FileIdentifierDesc
= FileIdentifierDesc
;
1491 // If the requested file is root directory, then the FE/EFE was already
1492 // retrieved in UdfOpenVolume() function, thus no need to find it again.
1494 // Otherwise, find FE/EFE from the respective FID.
1496 if (StrCmp (FileName
, L
"\\") != 0) {
1497 Status
= FindFileEntry (
1501 &FileIdentifierDesc
->Icb
,
1504 if (EFI_ERROR (Status
)) {
1509 // Make sure that both Parent's FE/EFE and found FE/EFE are not equal.
1511 if (CompareMem ((VOID
*)Parent
->FileEntry
, (VOID
*)CompareFileEntry
,
1512 Volume
->FileEntrySize
) != 0) {
1513 File
->FileEntry
= CompareFileEntry
;
1515 FreePool ((VOID
*)FileIdentifierDesc
);
1516 FreePool ((VOID
*)CompareFileEntry
);
1517 Status
= EFI_NOT_FOUND
;
1525 FreePool ((VOID
*)FileIdentifierDesc
);
1531 Read volume information on a medium which contains a valid UDF file system.
1533 @param[in] BlockIo BlockIo interface.
1534 @param[in] DiskIo DiskIo interface.
1535 @param[out] Volume UDF volume information structure.
1537 @retval EFI_SUCCESS Volume information read.
1538 @retval EFI_NO_MEDIA The device has no media.
1539 @retval EFI_DEVICE_ERROR The device reported an error.
1540 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1541 @retval EFI_OUT_OF_RESOURCES The volume was not read due to lack of resources.
1545 ReadUdfVolumeInformation (
1546 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1547 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1548 OUT UDF_VOLUME_INFO
*Volume
1554 // Read all necessary UDF volume information and keep it private to the driver
1556 Status
= ReadVolumeFileStructure (
1561 if (EFI_ERROR (Status
)) {
1566 // Find File Set Descriptor
1568 Status
= FindFileSetDescriptor (BlockIo
, DiskIo
, Volume
);
1569 if (EFI_ERROR (Status
)) {
1577 Find the root directory on an UDF volume.
1579 @param[in] BlockIo BlockIo interface.
1580 @param[in] DiskIo DiskIo interface.
1581 @param[in] Volume UDF volume information structure.
1582 @param[out] File Root directory file.
1584 @retval EFI_SUCCESS Root directory found.
1585 @retval EFI_NO_MEDIA The device has no media.
1586 @retval EFI_DEVICE_ERROR The device reported an error.
1587 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1588 @retval EFI_OUT_OF_RESOURCES The root directory was not found due to lack of
1594 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1595 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1596 IN UDF_VOLUME_INFO
*Volume
,
1597 OUT UDF_FILE_INFO
*File
1601 UDF_FILE_INFO Parent
;
1603 Status
= FindFileEntry (
1607 &Volume
->FileSetDesc
.RootDirectoryIcb
,
1610 if (EFI_ERROR (Status
)) {
1614 Parent
.FileEntry
= File
->FileEntry
;
1615 Parent
.FileIdentifierDesc
= NULL
;
1624 &Volume
->FileSetDesc
.RootDirectoryIcb
,
1627 if (EFI_ERROR (Status
)) {
1628 FreePool (File
->FileEntry
);
1635 Find either a File Entry or a Extended File Entry from a given ICB.
1637 @param[in] BlockIo BlockIo interface.
1638 @param[in] DiskIo DiskIo interface.
1639 @param[in] Volume UDF volume information structure.
1640 @param[in] Icb ICB of the FID.
1641 @param[out] FileEntry File Entry or Extended File Entry.
1643 @retval EFI_SUCCESS File Entry or Extended File Entry found.
1644 @retval EFI_NO_MEDIA The device has no media.
1645 @retval EFI_DEVICE_ERROR The device reported an error.
1646 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1647 @retval EFI_OUT_OF_RESOURCES The FE/EFE entry was not found due to lack of
1653 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1654 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1655 IN UDF_VOLUME_INFO
*Volume
,
1656 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1657 OUT VOID
**FileEntry
1662 UINT32 LogicalBlockSize
;
1663 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
1666 Status
= GetLongAdLsn (Volume
, Icb
, &Lsn
);
1667 if (EFI_ERROR (Status
)) {
1671 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
1673 ReadBuffer
= AllocateZeroPool (Volume
->FileEntrySize
);
1674 if (ReadBuffer
== NULL
) {
1675 return EFI_OUT_OF_RESOURCES
;
1681 Status
= DiskIo
->ReadDisk (
1683 BlockIo
->Media
->MediaId
,
1684 MultU64x32 (Lsn
, LogicalBlockSize
),
1685 Volume
->FileEntrySize
,
1688 if (EFI_ERROR (Status
)) {
1689 goto Error_Read_Disk_Blk
;
1692 DescriptorTag
= ReadBuffer
;
1695 // Check if the read extent contains a valid Tag Identifier for the expected
1698 if (DescriptorTag
->TagIdentifier
!= UdfFileEntry
&&
1699 DescriptorTag
->TagIdentifier
!= UdfExtendedFileEntry
) {
1700 Status
= EFI_VOLUME_CORRUPTED
;
1701 goto Error_Invalid_Fe
;
1704 *FileEntry
= ReadBuffer
;
1708 Error_Read_Disk_Blk
:
1709 FreePool (ReadBuffer
);
1715 Find a file given its absolute path on an UDF volume.
1717 @param[in] BlockIo BlockIo interface.
1718 @param[in] DiskIo DiskIo interface.
1719 @param[in] Volume UDF volume information structure.
1720 @param[in] FilePath File's absolute path.
1721 @param[in] Root Root directory file.
1722 @param[in] Parent Parent directory file.
1723 @param[in] Icb ICB of Parent.
1724 @param[out] File Found file.
1726 @retval EFI_SUCCESS FilePath was found.
1727 @retval EFI_NO_MEDIA The device has no media.
1728 @retval EFI_DEVICE_ERROR The device reported an error.
1729 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1730 @retval EFI_OUT_OF_RESOURCES The FilePath file was not found due to lack of
1736 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1737 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1738 IN UDF_VOLUME_INFO
*Volume
,
1739 IN CHAR16
*FilePath
,
1740 IN UDF_FILE_INFO
*Root
,
1741 IN UDF_FILE_INFO
*Parent
,
1742 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1743 OUT UDF_FILE_INFO
*File
1747 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
1748 CHAR16
*FileNamePointer
;
1749 UDF_FILE_INFO PreviousFile
;
1752 Status
= EFI_NOT_FOUND
;
1754 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
1755 while (*FilePath
!= L
'\0') {
1756 FileNamePointer
= FileName
;
1757 while (*FilePath
!= L
'\0' && *FilePath
!= L
'\\') {
1758 *FileNamePointer
++ = *FilePath
++;
1761 *FileNamePointer
= L
'\0';
1762 if (FileName
[0] == L
'\0') {
1764 // Open root directory.
1768 // There is no file found for the root directory yet. So, find only its
1771 // See UdfOpenVolume() function.
1773 Status
= InternalFindFile (BlockIo
,
1782 // We've already a file pointer (Root) for the root directory. Duplicate
1783 // its FE/EFE and FID descriptors.
1785 Status
= EFI_SUCCESS
;
1786 DuplicateFe (BlockIo
, Volume
, Root
->FileEntry
, &File
->FileEntry
);
1787 if (File
->FileEntry
== NULL
) {
1788 Status
= EFI_OUT_OF_RESOURCES
;
1791 // File->FileEntry is not NULL.
1793 DuplicateFid (Root
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1794 if (File
->FileIdentifierDesc
== NULL
) {
1795 FreePool (File
->FileEntry
);
1796 Status
= EFI_OUT_OF_RESOURCES
;
1802 // No root directory. Find filename from the current directory.
1804 Status
= InternalFindFile (BlockIo
,
1813 if (EFI_ERROR (Status
)) {
1818 // If the found file is a symlink, then find its respective FE/EFE and
1821 if (FE_ICB_FILE_TYPE (File
->FileEntry
) == UdfFileEntrySymlink
) {
1822 FreePool ((VOID
*)File
->FileIdentifierDesc
);
1824 FileEntry
= File
->FileEntry
;
1826 Status
= ResolveSymlink (BlockIo
,
1833 FreePool (FileEntry
);
1835 if (EFI_ERROR (Status
)) {
1840 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
1841 sizeof (UDF_FILE_INFO
)) != 0) {
1842 CleanupFileInformation (&PreviousFile
);
1845 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
1846 if (*FilePath
!= L
'\0' && *FilePath
== L
'\\') {
1855 Read a directory entry at a time on an UDF volume.
1857 @param[in] BlockIo BlockIo interface.
1858 @param[in] DiskIo DiskIo interface.
1859 @param[in] Volume UDF volume information structure.
1860 @param[in] ParentIcb ICB of the parent file.
1861 @param[in] FileEntryData FE/EFE of the parent file.
1862 @param[in, out] ReadDirInfo Next read directory listing structure
1864 @param[out] FoundFid File Identifier Descriptor pointer.
1866 @retval EFI_SUCCESS Directory entry read.
1867 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
1868 @retval EFI_NO_MEDIA The device has no media.
1869 @retval EFI_DEVICE_ERROR The device reported an error.
1870 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1871 @retval EFI_OUT_OF_RESOURCES The directory entry was not read due to lack of
1876 ReadDirectoryEntry (
1877 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1878 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1879 IN UDF_VOLUME_INFO
*Volume
,
1880 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
1881 IN VOID
*FileEntryData
,
1882 IN OUT UDF_READ_DIRECTORY_INFO
*ReadDirInfo
,
1883 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR
**FoundFid
1887 UDF_READ_FILE_INFO ReadFileInfo
;
1888 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1890 if (ReadDirInfo
->DirectoryData
== NULL
) {
1892 // The directory's recorded data has not been read yet. So let's cache it
1893 // into memory and the next calls won't need to read it again.
1895 ReadFileInfo
.Flags
= ReadFileAllocateAndRead
;
1905 if (EFI_ERROR (Status
)) {
1910 // Fill in ReadDirInfo structure with the read directory's data information.
1912 ReadDirInfo
->DirectoryData
= ReadFileInfo
.FileData
;
1913 ReadDirInfo
->DirectoryLength
= ReadFileInfo
.ReadLength
;
1917 if (ReadDirInfo
->FidOffset
>= ReadDirInfo
->DirectoryLength
) {
1919 // There are no longer FIDs for this directory. By returning
1920 // EFI_DEVICE_ERROR to the callee will indicate end of directory
1923 return EFI_DEVICE_ERROR
;
1927 // Get FID for this entry.
1929 FileIdentifierDesc
= GET_FID_FROM_ADS (ReadDirInfo
->DirectoryData
,
1930 ReadDirInfo
->FidOffset
);
1932 // Update FidOffset to point to next FID.
1934 ReadDirInfo
->FidOffset
+= GetFidDescriptorLength (FileIdentifierDesc
);
1935 } while (FileIdentifierDesc
->FileCharacteristics
& DELETED_FILE
);
1937 DuplicateFid (FileIdentifierDesc
, FoundFid
);
1938 if (*FoundFid
== NULL
) {
1939 return EFI_OUT_OF_RESOURCES
;
1946 Get a filename (encoded in OSTA-compressed format) from a File Identifier
1947 Descriptor on an UDF volume.
1949 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
1950 @param[out] FileName Decoded filename.
1952 @retval EFI_SUCCESS Filename decoded and read.
1953 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1956 GetFileNameFromFid (
1957 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
,
1958 OUT CHAR16
*FileName
1961 UINT8
*OstaCompressed
;
1962 UINT8 CompressionId
;
1968 (UINT8
*)FileIdentifierDesc
->Data
+
1969 FileIdentifierDesc
->LengthOfImplementationUse
1972 CompressionId
= OstaCompressed
[0];
1973 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
1974 return EFI_VOLUME_CORRUPTED
;
1980 Length
= FileIdentifierDesc
->LengthOfFileIdentifier
;
1981 for (Index
= 1; Index
< Length
; Index
++) {
1982 if (CompressionId
== 16) {
1983 *FileName
= OstaCompressed
[Index
++] << 8;
1988 if (Index
< Length
) {
1989 *FileName
|= (CHAR16
)(OstaCompressed
[Index
]);
2001 Resolve a symlink file on an UDF volume.
2003 @param[in] BlockIo BlockIo interface.
2004 @param[in] DiskIo DiskIo interface.
2005 @param[in] Volume UDF volume information structure.
2006 @param[in] Parent Parent file.
2007 @param[in] FileEntryData FE/EFE structure pointer.
2008 @param[out] File Resolved file.
2010 @retval EFI_SUCCESS Symlink file resolved.
2011 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2012 @retval EFI_NO_MEDIA The device has no media.
2013 @retval EFI_DEVICE_ERROR The device reported an error.
2014 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2015 @retval EFI_OUT_OF_RESOURCES The symlink file was not resolved due to lack of
2021 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2022 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2023 IN UDF_VOLUME_INFO
*Volume
,
2024 IN UDF_FILE_INFO
*Parent
,
2025 IN VOID
*FileEntryData
,
2026 OUT UDF_FILE_INFO
*File
2030 UDF_READ_FILE_INFO ReadFileInfo
;
2034 UDF_PATH_COMPONENT
*PathComp
;
2035 UINT8 PathCompLength
;
2036 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
2039 UINT8 CompressionId
;
2040 UDF_FILE_INFO PreviousFile
;
2043 // Symlink files on UDF volumes do not contain so much data other than
2044 // Path Components which resolves to real filenames, so it's OK to read in
2045 // all its data here -- usually the data will be inline with the FE/EFE for
2048 ReadFileInfo
.Flags
= ReadFileAllocateAndRead
;
2054 &Parent
->FileIdentifierDesc
->Icb
,
2058 if (EFI_ERROR (Status
)) {
2062 Length
= ReadFileInfo
.ReadLength
;
2064 Data
= (UINT8
*)ReadFileInfo
.FileData
;
2065 EndData
= Data
+ Length
;
2067 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
2070 PathComp
= (UDF_PATH_COMPONENT
*)Data
;
2072 PathCompLength
= PathComp
->LengthOfComponentIdentifier
;
2074 switch (PathComp
->ComponentType
) {
2077 // This Path Component specifies the root directory hierarchy subject to
2078 // agreement between the originator and recipient of the medium. Skip it.
2084 // "\\." of the current directory. Read next Path Component.
2086 goto Next_Path_Component
;
2089 // ".." (parent directory). Go to it.
2091 CopyMem ((VOID
*)FileName
, L
"..", 6);
2095 // "." (current file). Duplicate both FE/EFE and FID of this file.
2097 DuplicateFe (BlockIo
, Volume
, PreviousFile
.FileEntry
, &File
->FileEntry
);
2098 if (File
->FileEntry
== NULL
) {
2099 Status
= EFI_OUT_OF_RESOURCES
;
2100 goto Error_Find_File
;
2103 DuplicateFid (PreviousFile
.FileIdentifierDesc
,
2104 &File
->FileIdentifierDesc
);
2105 if (File
->FileIdentifierDesc
== NULL
) {
2106 FreePool (File
->FileEntry
);
2107 Status
= EFI_OUT_OF_RESOURCES
;
2108 goto Error_Find_File
;
2110 goto Next_Path_Component
;
2113 // This Path Component identifies an object, either a file or a
2114 // directory or an alias.
2116 // Decode it from the compressed data in ComponentIdentifier and find
2119 CompressionId
= PathComp
->ComponentIdentifier
[0];
2120 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
2121 return EFI_VOLUME_CORRUPTED
;
2125 for (Index
= 1; Index
< PathCompLength
; Index
++) {
2126 if (CompressionId
== 16) {
2127 *Char
= *(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+
2134 if (Index
< Length
) {
2135 *Char
|= (CHAR16
)(*(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+ Index
));
2146 // Find file from the read filename in symlink's file data.
2148 Status
= InternalFindFile (
2157 if (EFI_ERROR (Status
)) {
2158 goto Error_Find_File
;
2161 Next_Path_Component
:
2162 Data
+= sizeof (UDF_PATH_COMPONENT
) + PathCompLength
;
2163 if (Data
>= EndData
) {
2167 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2168 sizeof (UDF_FILE_INFO
)) != 0) {
2169 CleanupFileInformation (&PreviousFile
);
2172 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
2176 // Unmap the symlink file.
2178 FreePool (ReadFileInfo
.FileData
);
2183 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2184 sizeof (UDF_FILE_INFO
)) != 0) {
2185 CleanupFileInformation (&PreviousFile
);
2188 FreePool (ReadFileInfo
.FileData
);
2194 Clean up in-memory UDF file information.
2196 @param[in] File File information pointer.
2200 CleanupFileInformation (
2201 IN UDF_FILE_INFO
*File
2204 if (File
->FileEntry
!= NULL
) {
2205 FreePool (File
->FileEntry
);
2207 if (File
->FileIdentifierDesc
!= NULL
) {
2208 FreePool ((VOID
*)File
->FileIdentifierDesc
);
2211 ZeroMem ((VOID
*)File
, sizeof (UDF_FILE_INFO
));
2215 Find a file from its absolute path on an UDF volume.
2217 @param[in] BlockIo BlockIo interface.
2218 @param[in] DiskIo DiskIo interface.
2219 @param[in] Volume UDF volume information structure.
2220 @param[in] File File information structure.
2221 @param[out] Size Size of the file.
2223 @retval EFI_SUCCESS File size calculated and set in Size.
2224 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2225 @retval EFI_NO_MEDIA The device has no media.
2226 @retval EFI_DEVICE_ERROR The device reported an error.
2227 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2228 @retval EFI_OUT_OF_RESOURCES The file size was not calculated due to lack of
2234 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2235 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2236 IN UDF_VOLUME_INFO
*Volume
,
2237 IN UDF_FILE_INFO
*File
,
2242 UDF_READ_FILE_INFO ReadFileInfo
;
2244 ReadFileInfo
.Flags
= ReadFileGetFileSize
;
2250 &File
->FileIdentifierDesc
->Icb
,
2254 if (EFI_ERROR (Status
)) {
2258 *Size
= ReadFileInfo
.ReadLength
;
2264 Set information about a file on an UDF volume.
2266 @param[in] File File pointer.
2267 @param[in] FileSize Size of the file.
2268 @param[in] FileName Filename of the file.
2269 @param[in, out] BufferSize Size of the returned file infomation.
2270 @param[out] Buffer Data of the returned file information.
2272 @retval EFI_SUCCESS File information set.
2273 @retval EFI_NO_MEDIA The device has no media.
2274 @retval EFI_DEVICE_ERROR The device reported an error.
2275 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2276 @retval EFI_OUT_OF_RESOURCES The file information was not set due to lack of
2282 IN UDF_FILE_INFO
*File
,
2284 IN CHAR16
*FileName
,
2285 IN OUT UINTN
*BufferSize
,
2289 UINTN FileInfoLength
;
2290 EFI_FILE_INFO
*FileInfo
;
2291 UDF_FILE_ENTRY
*FileEntry
;
2292 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
2293 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
2296 // Calculate the needed size for the EFI_FILE_INFO structure.
2298 FileInfoLength
= sizeof (EFI_FILE_INFO
) + ((FileName
!= NULL
) ?
2299 StrSize (FileName
) :
2301 if (*BufferSize
< FileInfoLength
) {
2303 // The given Buffer has no size enough for EFI_FILE_INFO structure.
2305 *BufferSize
= FileInfoLength
;
2306 return EFI_BUFFER_TOO_SMALL
;
2310 // Buffer now contains room enough to store EFI_FILE_INFO structure.
2311 // Now, fill it in with all necessary information about the file.
2313 FileInfo
= (EFI_FILE_INFO
*)Buffer
;
2314 FileInfo
->Size
= FileInfoLength
;
2315 FileInfo
->Attribute
&= ~EFI_FILE_VALID_ATTR
;
2316 FileInfo
->Attribute
|= EFI_FILE_READ_ONLY
;
2318 if (IS_FID_DIRECTORY_FILE (File
->FileIdentifierDesc
)) {
2319 FileInfo
->Attribute
|= EFI_FILE_DIRECTORY
;
2320 } else if (IS_FID_NORMAL_FILE (File
->FileIdentifierDesc
)) {
2321 FileInfo
->Attribute
|= EFI_FILE_ARCHIVE
;
2324 if (IS_FID_HIDDEN_FILE (File
->FileIdentifierDesc
)) {
2325 FileInfo
->Attribute
|= EFI_FILE_HIDDEN
;
2328 DescriptorTag
= File
->FileEntry
;
2330 if (DescriptorTag
->TagIdentifier
== UdfFileEntry
) {
2331 FileEntry
= (UDF_FILE_ENTRY
*)File
->FileEntry
;
2334 // Check if FE has the system attribute set.
2336 if (FileEntry
->IcbTag
.Flags
& (1 << 10)) {
2337 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2340 FileInfo
->FileSize
= FileSize
;
2341 FileInfo
->PhysicalSize
= FileSize
;
2343 FileInfo
->CreateTime
.Year
= FileEntry
->AccessTime
.Year
;
2344 FileInfo
->CreateTime
.Month
= FileEntry
->AccessTime
.Month
;
2345 FileInfo
->CreateTime
.Day
= FileEntry
->AccessTime
.Day
;
2346 FileInfo
->CreateTime
.Hour
= FileEntry
->AccessTime
.Hour
;
2347 FileInfo
->CreateTime
.Minute
= FileEntry
->AccessTime
.Second
;
2348 FileInfo
->CreateTime
.Second
= FileEntry
->AccessTime
.Second
;
2349 FileInfo
->CreateTime
.Nanosecond
=
2350 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2352 FileInfo
->LastAccessTime
.Year
=
2353 FileEntry
->AccessTime
.Year
;
2354 FileInfo
->LastAccessTime
.Month
=
2355 FileEntry
->AccessTime
.Month
;
2356 FileInfo
->LastAccessTime
.Day
=
2357 FileEntry
->AccessTime
.Day
;
2358 FileInfo
->LastAccessTime
.Hour
=
2359 FileEntry
->AccessTime
.Hour
;
2360 FileInfo
->LastAccessTime
.Minute
=
2361 FileEntry
->AccessTime
.Minute
;
2362 FileInfo
->LastAccessTime
.Second
=
2363 FileEntry
->AccessTime
.Second
;
2364 FileInfo
->LastAccessTime
.Nanosecond
=
2365 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2366 } else if (DescriptorTag
->TagIdentifier
== UdfExtendedFileEntry
) {
2367 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)File
->FileEntry
;
2370 // Check if EFE has the system attribute set.
2372 if (ExtendedFileEntry
->IcbTag
.Flags
& (1 << 10)) {
2373 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2376 FileInfo
->FileSize
= FileSize
;
2377 FileInfo
->PhysicalSize
= FileSize
;
2379 FileInfo
->CreateTime
.Year
= ExtendedFileEntry
->CreationTime
.Year
;
2380 FileInfo
->CreateTime
.Month
= ExtendedFileEntry
->CreationTime
.Month
;
2381 FileInfo
->CreateTime
.Day
= ExtendedFileEntry
->CreationTime
.Day
;
2382 FileInfo
->CreateTime
.Hour
= ExtendedFileEntry
->CreationTime
.Hour
;
2383 FileInfo
->CreateTime
.Minute
= ExtendedFileEntry
->CreationTime
.Second
;
2384 FileInfo
->CreateTime
.Second
= ExtendedFileEntry
->CreationTime
.Second
;
2385 FileInfo
->CreateTime
.Nanosecond
=
2386 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2388 FileInfo
->LastAccessTime
.Year
=
2389 ExtendedFileEntry
->AccessTime
.Year
;
2390 FileInfo
->LastAccessTime
.Month
=
2391 ExtendedFileEntry
->AccessTime
.Month
;
2392 FileInfo
->LastAccessTime
.Day
=
2393 ExtendedFileEntry
->AccessTime
.Day
;
2394 FileInfo
->LastAccessTime
.Hour
=
2395 ExtendedFileEntry
->AccessTime
.Hour
;
2396 FileInfo
->LastAccessTime
.Minute
=
2397 ExtendedFileEntry
->AccessTime
.Minute
;
2398 FileInfo
->LastAccessTime
.Second
=
2399 ExtendedFileEntry
->AccessTime
.Second
;
2400 FileInfo
->LastAccessTime
.Nanosecond
=
2401 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2404 FileInfo
->CreateTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2405 FileInfo
->CreateTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2406 FileInfo
->LastAccessTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2407 FileInfo
->LastAccessTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2409 CopyMem ((VOID
*)&FileInfo
->ModificationTime
,
2410 (VOID
*)&FileInfo
->LastAccessTime
,
2413 if (FileName
!= NULL
) {
2414 StrCpyS (FileInfo
->FileName
, StrLen (FileName
) + 1, FileName
);
2416 FileInfo
->FileName
[0] = '\0';
2419 *BufferSize
= FileInfoLength
;
2425 Get volume and free space size information of an UDF volume.
2427 @param[in] BlockIo BlockIo interface.
2428 @param[in] DiskIo DiskIo interface.
2429 @param[in] Volume UDF volume information structure.
2430 @param[out] VolumeSize Volume size.
2431 @param[out] FreeSpaceSize Free space size.
2433 @retval EFI_SUCCESS Volume and free space size calculated.
2434 @retval EFI_NO_MEDIA The device has no media.
2435 @retval EFI_DEVICE_ERROR The device reported an error.
2436 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2437 @retval EFI_OUT_OF_RESOURCES The volume and free space size were not
2438 calculated due to lack of resources.
2443 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2444 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2445 IN UDF_VOLUME_INFO
*Volume
,
2446 OUT UINT64
*VolumeSize
,
2447 OUT UINT64
*FreeSpaceSize
2451 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
2452 UDF_EXTENT_AD
*ExtentAd
;
2454 UINT32 LogicalBlockSize
;
2455 UDF_LOGICAL_VOLUME_INTEGRITY
*LogicalVolInt
;
2456 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
2461 LogicalVolDesc
= &Volume
->LogicalVolDesc
;
2463 ExtentAd
= &LogicalVolDesc
->IntegritySequenceExtent
;
2465 if (ExtentAd
->ExtentLength
== 0) {
2466 return EFI_VOLUME_CORRUPTED
;
2469 LogicalVolInt
= AllocatePool (ExtentAd
->ExtentLength
);
2470 if (LogicalVolInt
== NULL
) {
2471 return EFI_OUT_OF_RESOURCES
;
2475 // Get location of Logical Volume Integrity Descriptor
2477 Lsn
= (UINT64
)ExtentAd
->ExtentLocation
- Volume
->MainVdsStartLocation
;
2479 LogicalBlockSize
= LogicalVolDesc
->LogicalBlockSize
;
2484 Status
= DiskIo
->ReadDisk (
2486 BlockIo
->Media
->MediaId
,
2487 MultU64x32 (Lsn
, LogicalBlockSize
),
2488 ExtentAd
->ExtentLength
,
2491 if (EFI_ERROR (Status
)) {
2495 DescriptorTag
= &LogicalVolInt
->DescriptorTag
;
2498 // Check if read block is a Logical Volume Integrity Descriptor
2500 if (DescriptorTag
->TagIdentifier
!= UdfLogicalVolumeIntegrityDescriptor
) {
2501 Status
= EFI_VOLUME_CORRUPTED
;
2508 Length
= LogicalVolInt
->NumberOfPartitions
;
2509 for (Index
= 0; Index
< Length
; Index
+= sizeof (UINT32
)) {
2510 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2512 // Check if size is not specified
2514 if (LsnsNo
== 0xFFFFFFFFUL
) {
2518 // Accumulate free space size
2520 *FreeSpaceSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2523 Length
= LogicalVolInt
->NumberOfPartitions
* sizeof (UINT32
) * 2;
2524 for (; Index
< Length
; Index
+= sizeof (UINT32
)) {
2525 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2527 // Check if size is not specified
2529 if (LsnsNo
== 0xFFFFFFFFUL
) {
2533 // Accumulate used volume space
2535 *VolumeSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2538 Status
= EFI_SUCCESS
;
2542 // Free Logical Volume Integrity Descriptor
2544 FreePool (LogicalVolInt
);
2550 Seek a file and read its data into memory on an UDF volume.
2552 @param[in] BlockIo BlockIo interface.
2553 @param[in] DiskIo DiskIo interface.
2554 @param[in] Volume UDF volume information structure.
2555 @param[in] File File information structure.
2556 @param[in] FileSize Size of the file.
2557 @param[in, out] FilePosition File position.
2558 @param[in, out] Buffer File data.
2559 @param[in, out] BufferSize Read size.
2561 @retval EFI_SUCCESS File seeked and read.
2562 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2563 @retval EFI_NO_MEDIA The device has no media.
2564 @retval EFI_DEVICE_ERROR The device reported an error.
2565 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2566 @retval EFI_OUT_OF_RESOURCES The file's recorded data was not read due to lack
2572 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2573 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2574 IN UDF_VOLUME_INFO
*Volume
,
2575 IN UDF_FILE_INFO
*File
,
2577 IN OUT UINT64
*FilePosition
,
2578 IN OUT VOID
*Buffer
,
2579 IN OUT UINT64
*BufferSize
2583 UDF_READ_FILE_INFO ReadFileInfo
;
2585 ReadFileInfo
.Flags
= ReadFileSeekAndRead
;
2586 ReadFileInfo
.FilePosition
= *FilePosition
;
2587 ReadFileInfo
.FileData
= Buffer
;
2588 ReadFileInfo
.FileDataSize
= *BufferSize
;
2589 ReadFileInfo
.FileSize
= FileSize
;
2595 &File
->FileIdentifierDesc
->Icb
,
2599 if (EFI_ERROR (Status
)) {
2603 *BufferSize
= ReadFileInfo
.FileDataSize
;
2604 *FilePosition
= ReadFileInfo
.FilePosition
;
2610 Check if ControllerHandle supports an UDF file system.
2612 @param[in] This Protocol instance pointer.
2613 @param[in] ControllerHandle Handle of device to test.
2615 @retval EFI_SUCCESS UDF file system found.
2616 @retval EFI_UNSUPPORTED UDF file system not found.
2620 SupportUdfFileSystem (
2621 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2622 IN EFI_HANDLE ControllerHandle
2626 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2627 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
2628 EFI_DEVICE_PATH_PROTOCOL
*LastDevicePathNode
;
2629 EFI_GUID
*VendorDefinedGuid
;
2632 // Open Device Path protocol on ControllerHandle
2634 Status
= gBS
->OpenProtocol (
2636 &gEfiDevicePathProtocolGuid
,
2637 (VOID
**)&DevicePath
,
2638 This
->DriverBindingHandle
,
2640 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2642 if (EFI_ERROR (Status
)) {
2643 return EFI_UNSUPPORTED
;
2646 Status
= EFI_UNSUPPORTED
;
2649 // Get last Device Path node
2651 LastDevicePathNode
= NULL
;
2652 DevicePathNode
= DevicePath
;
2653 while (!IsDevicePathEnd (DevicePathNode
)) {
2654 LastDevicePathNode
= DevicePathNode
;
2655 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
2658 // Check if last Device Path node contains a Vendor-Defined Media Device Path
2659 // of an UDF file system.
2661 if (LastDevicePathNode
!= NULL
&&
2662 DevicePathType (LastDevicePathNode
) == MEDIA_DEVICE_PATH
&&
2663 DevicePathSubType (LastDevicePathNode
) == MEDIA_VENDOR_DP
) {
2664 VendorDefinedGuid
= (EFI_GUID
*)((UINTN
)LastDevicePathNode
+
2665 OFFSET_OF (VENDOR_DEVICE_PATH
, Guid
));
2666 if (CompareGuid (VendorDefinedGuid
, &gUdfDevPathGuid
)) {
2667 Status
= EFI_SUCCESS
;
2672 // Close Device Path protocol on ControllerHandle
2674 gBS
->CloseProtocol (
2676 &gEfiDevicePathProtocolGuid
,
2677 This
->DriverBindingHandle
,