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
742 // Code should never reach here.
745 return EFI_DEVICE_ERROR
;
749 Return logical sector number of either Short or Long Allocation Descriptor.
751 @param[in] RecordingFlags Flag to indicate the type of descriptor.
752 @param[in] Volume Volume information pointer.
753 @param[in] ParentIcb Long Allocation Descriptor pointer.
754 @param[in] Ad Allocation Descriptor pointer.
755 @param[out] Lsn Logical sector number pointer.
757 @retval EFI_SUCCESS Logical sector number of the given Allocation
758 Descriptor successfully returned.
759 @retval EFI_UNSUPPORTED Logical sector number of the given Allocation
760 Descriptor is not returned due to unrecognized
765 GetAllocationDescriptorLsn (
766 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
767 IN UDF_VOLUME_INFO
*Volume
,
768 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
773 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
775 if (RecordingFlags
== LongAdsSequence
) {
776 return GetLongAdLsn (Volume
, (UDF_LONG_ALLOCATION_DESCRIPTOR
*)Ad
, Lsn
);
777 } else if (RecordingFlags
== ShortAdsSequence
) {
778 PartitionDesc
= GetPdFromLongAd (Volume
, ParentIcb
);
779 if (PartitionDesc
== NULL
) {
780 return EFI_UNSUPPORTED
;
783 *Lsn
= GetShortAdLsn (
786 (UDF_SHORT_ALLOCATION_DESCRIPTOR
*)Ad
792 // Code should never reach here.
795 return EFI_UNSUPPORTED
;
799 Return offset + length of a given indirect Allocation Descriptor (AED).
801 @param[in] BlockIo BlockIo interface.
802 @param[in] DiskIo DiskIo interface.
803 @param[in] Volume Volume information pointer.
804 @param[in] ParentIcb Long Allocation Descriptor pointer.
805 @param[in] RecordingFlags Flag to indicate the type of descriptor.
806 @param[in] Ad Allocation Descriptor pointer.
807 @param[out] Offset Offset of a given indirect Allocation
809 @param[out] Length Length of a given indirect Allocation
812 @retval EFI_SUCCESS The offset and length were returned.
813 @retval EFI_OUT_OF_RESOURCES The offset and length were not returned due
814 to lack of resources.
815 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
816 @retval other The offset and length were not returned.
821 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
822 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
823 IN UDF_VOLUME_INFO
*Volume
,
824 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
825 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
835 UINT32 LogicalBlockSize
;
836 UDF_ALLOCATION_EXTENT_DESCRIPTOR
*AllocExtDesc
;
837 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
839 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
840 Status
= GetAllocationDescriptorLsn (RecordingFlags
,
845 if (EFI_ERROR (Status
)) {
849 Data
= AllocatePool (ExtentLength
);
851 return EFI_OUT_OF_RESOURCES
;
854 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
859 Status
= DiskIo
->ReadDisk (
861 BlockIo
->Media
->MediaId
,
862 MultU64x32 (Lsn
, LogicalBlockSize
),
866 if (EFI_ERROR (Status
)) {
870 AllocExtDesc
= (UDF_ALLOCATION_EXTENT_DESCRIPTOR
*)Data
;
872 DescriptorTag
= &AllocExtDesc
->DescriptorTag
;
875 // Check if read extent contains a valid tag identifier for AED.
877 if (DescriptorTag
->TagIdentifier
!= UdfAllocationExtentDescriptor
) {
878 Status
= EFI_VOLUME_CORRUPTED
;
883 // Get AED's block offset and its length.
885 *Offset
= MultU64x32 (Lsn
, LogicalBlockSize
) +
886 sizeof (UDF_ALLOCATION_EXTENT_DESCRIPTOR
);
887 *Length
= AllocExtDesc
->LengthOfAllocationDescriptors
;
896 Read Allocation Extent Descriptor into memory.
898 @param[in] BlockIo BlockIo interface.
899 @param[in] DiskIo DiskIo interface.
900 @param[in] Volume Volume information pointer.
901 @param[in] ParentIcb Long Allocation Descriptor pointer.
902 @param[in] RecordingFlags Flag to indicate the type of descriptor.
903 @param[in] Ad Allocation Descriptor pointer.
904 @param[out] Data Buffer that contains the Allocation Extent
906 @param[out] Length Length of Data.
908 @retval EFI_SUCCESS The Allocation Extent Descriptor was read.
909 @retval EFI_OUT_OF_RESOURCES The Allocation Extent Descriptor was not read
910 due to lack of resources.
911 @retval other Fail to read the disk.
916 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
917 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
918 IN UDF_VOLUME_INFO
*Volume
,
919 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
920 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
930 // Get AED's offset + length.
932 Status
= GetAedAdsOffset (
942 if (EFI_ERROR (Status
)) {
947 // Allocate buffer to read in AED's data.
949 *Data
= AllocatePool ((UINTN
) (*Length
));
951 return EFI_OUT_OF_RESOURCES
;
954 return DiskIo
->ReadDisk (
956 BlockIo
->Media
->MediaId
,
964 Function used to serialise reads of Allocation Descriptors.
966 @param[in] RecordingFlags Flag to indicate the type of descriptor.
967 @param[in] Ad Allocation Descriptor pointer.
968 @param[in, out] Buffer Buffer to hold the next Allocation Descriptor.
969 @param[in] Length Length of Buffer.
971 @retval EFI_SUCCESS Buffer was grown to hold the next Allocation
973 @retval EFI_OUT_OF_RESOURCES Buffer was not grown due to lack of resources.
977 GrowUpBufferToNextAd (
978 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
980 IN OUT VOID
**Buffer
,
986 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
988 if (*Buffer
== NULL
) {
989 *Buffer
= AllocatePool (ExtentLength
);
990 if (*Buffer
== NULL
) {
991 return EFI_OUT_OF_RESOURCES
;
994 *Buffer
= ReallocatePool ((UINTN
) Length
, (UINTN
) (Length
+ ExtentLength
), *Buffer
);
995 if (*Buffer
== NULL
) {
996 return EFI_OUT_OF_RESOURCES
;
1004 Read data or size of either a File Entry or an Extended File Entry.
1006 @param[in] BlockIo BlockIo interface.
1007 @param[in] DiskIo DiskIo interface.
1008 @param[in] Volume Volume information pointer.
1009 @param[in] ParentIcb Long Allocation Descriptor pointer.
1010 @param[in] FileEntryData FE/EFE structure pointer.
1011 @param[in, out] ReadFileInfo Read file information pointer.
1013 @retval EFI_SUCCESS Data or size of a FE/EFE was read.
1014 @retval EFI_OUT_OF_RESOURCES Data or size of a FE/EFE was not read due to
1016 @retval EFI_INVALID_PARAMETER The read file flag given in ReadFileInfo is
1018 @retval EFI_UNSUPPORTED The FE recording flag given in FileEntryData
1020 @retval other Data or size of a FE/EFE was not read.
1025 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1026 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1027 IN UDF_VOLUME_INFO
*Volume
,
1028 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
1029 IN VOID
*FileEntryData
,
1030 IN OUT UDF_READ_FILE_INFO
*ReadFileInfo
1034 UINT32 LogicalBlockSize
;
1041 UINT64 FilePosition
;
1046 BOOLEAN FinishedSeeking
;
1047 UINT32 ExtentLength
;
1048 UDF_FE_RECORDING_FLAGS RecordingFlags
;
1050 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
1054 // set BytesLeft to suppress incorrect compiler/analyzer warnings
1059 FinishedSeeking
= FALSE
;
1062 switch (ReadFileInfo
->Flags
) {
1063 case ReadFileGetFileSize
:
1064 case ReadFileAllocateAndRead
:
1066 // Initialise ReadFileInfo structure for either getting file size, or
1067 // reading file's recorded data.
1069 ReadFileInfo
->ReadLength
= 0;
1070 ReadFileInfo
->FileData
= NULL
;
1072 case ReadFileSeekAndRead
:
1074 // About to seek a file and/or read its data.
1076 Length
= ReadFileInfo
->FileSize
- ReadFileInfo
->FilePosition
;
1077 if (ReadFileInfo
->FileDataSize
> Length
) {
1079 // About to read beyond the EOF -- truncate it.
1081 ReadFileInfo
->FileDataSize
= Length
;
1085 // Initialise data to start seeking and/or reading a file.
1087 BytesLeft
= ReadFileInfo
->FileDataSize
;
1090 FinishedSeeking
= FALSE
;
1095 RecordingFlags
= GET_FE_RECORDING_FLAGS (FileEntryData
);
1096 switch (RecordingFlags
) {
1099 // There are no extents for this FE/EFE. All data is inline.
1101 GetFileEntryData (FileEntryData
, &Data
, &Length
);
1103 if (ReadFileInfo
->Flags
== ReadFileGetFileSize
) {
1104 ReadFileInfo
->ReadLength
= Length
;
1105 } else if (ReadFileInfo
->Flags
== ReadFileAllocateAndRead
) {
1107 // Allocate buffer for starting read data.
1109 ReadFileInfo
->FileData
= AllocatePool ((UINTN
) Length
);
1110 if (ReadFileInfo
->FileData
== NULL
) {
1111 return EFI_OUT_OF_RESOURCES
;
1115 // Read all inline data into ReadFileInfo->FileData
1117 CopyMem (ReadFileInfo
->FileData
, Data
, (UINTN
) Length
);
1118 ReadFileInfo
->ReadLength
= Length
;
1119 } else if (ReadFileInfo
->Flags
== ReadFileSeekAndRead
) {
1121 // If FilePosition is non-zero, seek file to FilePosition, read
1122 // FileDataSize bytes and then updates FilePosition.
1125 ReadFileInfo
->FileData
,
1126 (VOID
*)((UINT8
*)Data
+ ReadFileInfo
->FilePosition
),
1127 (UINTN
) ReadFileInfo
->FileDataSize
1130 ReadFileInfo
->FilePosition
+= ReadFileInfo
->FileDataSize
;
1133 return EFI_INVALID_PARAMETER
;
1136 Status
= EFI_SUCCESS
;
1139 case LongAdsSequence
:
1140 case ShortAdsSequence
:
1142 // This FE/EFE contains a run of Allocation Descriptors. Get data + size
1143 // for start reading them out.
1145 GetAdsInformation (FileEntryData
, &Data
, &Length
);
1152 Status
= GetAllocationDescriptor (
1159 if (Status
== EFI_DEVICE_ERROR
) {
1160 Status
= EFI_SUCCESS
;
1165 // Check if AD is an indirect AD. If so, read Allocation Extent
1166 // Descriptor and its extents (ADs).
1168 if (GET_EXTENT_FLAGS (RecordingFlags
, Ad
) == ExtentIsNextExtent
) {
1175 Status
= GetAedAdsData (
1185 if (EFI_ERROR (Status
)) {
1188 ASSERT (Data
!= NULL
);
1194 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
1196 Status
= GetAllocationDescriptorLsn (RecordingFlags
,
1201 if (EFI_ERROR (Status
)) {
1205 switch (ReadFileInfo
->Flags
) {
1206 case ReadFileGetFileSize
:
1207 ReadFileInfo
->ReadLength
+= ExtentLength
;
1209 case ReadFileAllocateAndRead
:
1211 // Increase FileData (if necessary) to read next extent.
1213 Status
= GrowUpBufferToNextAd (
1216 &ReadFileInfo
->FileData
,
1217 ReadFileInfo
->ReadLength
1219 if (EFI_ERROR (Status
)) {
1220 goto Error_Alloc_Buffer_To_Next_Ad
;
1224 // Read extent's data into FileData.
1226 Status
= DiskIo
->ReadDisk (
1228 BlockIo
->Media
->MediaId
,
1229 MultU64x32 (Lsn
, LogicalBlockSize
),
1231 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1232 ReadFileInfo
->ReadLength
)
1234 if (EFI_ERROR (Status
)) {
1235 goto Error_Read_Disk_Blk
;
1238 ReadFileInfo
->ReadLength
+= ExtentLength
;
1240 case ReadFileSeekAndRead
:
1242 // Seek file first before reading in its data.
1244 if (FinishedSeeking
) {
1246 goto Skip_File_Seek
;
1249 if (FilePosition
+ ExtentLength
< ReadFileInfo
->FilePosition
) {
1250 FilePosition
+= ExtentLength
;
1254 if (FilePosition
+ ExtentLength
> ReadFileInfo
->FilePosition
) {
1255 Offset
= ReadFileInfo
->FilePosition
- FilePosition
;
1261 // Done with seeking file. Start reading its data.
1263 FinishedSeeking
= TRUE
;
1267 // Make sure we don't read more data than really wanted.
1269 if (ExtentLength
- Offset
> BytesLeft
) {
1270 DataLength
= BytesLeft
;
1272 DataLength
= ExtentLength
- Offset
;
1276 // Read extent's data into FileData.
1278 Status
= DiskIo
->ReadDisk (
1280 BlockIo
->Media
->MediaId
,
1281 Offset
+ MultU64x32 (Lsn
, LogicalBlockSize
),
1283 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1286 if (EFI_ERROR (Status
)) {
1287 goto Error_Read_Disk_Blk
;
1291 // Update current file's position.
1293 DataOffset
+= DataLength
;
1294 ReadFileInfo
->FilePosition
+= DataLength
;
1296 BytesLeft
-= DataLength
;
1297 if (BytesLeft
== 0) {
1299 // There is no more file data to read.
1301 Status
= EFI_SUCCESS
;
1310 // Point to the next AD (extent).
1312 AdOffset
+= AD_LENGTH (RecordingFlags
);
1316 case ExtendedAdsSequence
:
1317 // FIXME: Not supported. Got no volume with it, yet.
1319 Status
= EFI_UNSUPPORTED
;
1324 // A flag value reserved by the ECMA-167 standard (3rd Edition - June
1325 // 1997); 14.6 ICB Tag; 14.6.8 Flags (RBP 18); was found.
1327 Status
= EFI_UNSUPPORTED
;
1338 Error_Read_Disk_Blk
:
1339 Error_Alloc_Buffer_To_Next_Ad
:
1340 if (ReadFileInfo
->Flags
!= ReadFileSeekAndRead
) {
1341 FreePool (ReadFileInfo
->FileData
);
1353 Find a file by its filename from a given Parent file.
1355 @param[in] BlockIo BlockIo interface.
1356 @param[in] DiskIo DiskIo interface.
1357 @param[in] Volume Volume information pointer.
1358 @param[in] FileName File name string.
1359 @param[in] Parent Parent directory file.
1360 @param[in] Icb Long Allocation Descriptor pointer.
1361 @param[out] File Found file.
1363 @retval EFI_SUCCESS The file was found.
1364 @retval EFI_INVALID_PARAMETER One or more input parameters are invalid.
1365 @retval EFI_NOT_FOUND The file was not found.
1370 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1371 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1372 IN UDF_VOLUME_INFO
*Volume
,
1373 IN CHAR16
*FileName
,
1374 IN UDF_FILE_INFO
*Parent
,
1375 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1376 OUT UDF_FILE_INFO
*File
1380 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1381 UDF_READ_DIRECTORY_INFO ReadDirInfo
;
1383 CHAR16 FoundFileName
[UDF_FILENAME_LENGTH
];
1384 VOID
*CompareFileEntry
;
1387 // Check if both Parent->FileIdentifierDesc and Icb are NULL.
1389 if ((Parent
->FileIdentifierDesc
== NULL
) && (Icb
== NULL
)) {
1390 return EFI_INVALID_PARAMETER
;
1394 // Check if parent file is really directory.
1396 if (FE_ICB_FILE_TYPE (Parent
->FileEntry
) != UdfFileEntryDirectory
) {
1397 return EFI_NOT_FOUND
;
1401 // If FileName is current file or working directory, just duplicate Parent's
1402 // FE/EFE and FID descriptors.
1404 if (StrCmp (FileName
, L
".") == 0) {
1405 if (Parent
->FileIdentifierDesc
== NULL
) {
1406 return EFI_INVALID_PARAMETER
;
1409 DuplicateFe (BlockIo
, Volume
, Parent
->FileEntry
, &File
->FileEntry
);
1410 if (File
->FileEntry
== NULL
) {
1411 return EFI_OUT_OF_RESOURCES
;
1414 DuplicateFid (Parent
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1415 if (File
->FileIdentifierDesc
== NULL
) {
1416 FreePool (File
->FileEntry
);
1417 return EFI_OUT_OF_RESOURCES
;
1424 // Start directory listing.
1426 ZeroMem ((VOID
*)&ReadDirInfo
, sizeof (UDF_READ_DIRECTORY_INFO
));
1430 Status
= ReadDirectoryEntry (
1434 (Parent
->FileIdentifierDesc
!= NULL
) ?
1435 &Parent
->FileIdentifierDesc
->Icb
:
1441 if (EFI_ERROR (Status
)) {
1442 if (Status
== EFI_DEVICE_ERROR
) {
1443 Status
= EFI_NOT_FOUND
;
1449 // After calling function ReadDirectoryEntry(), if 'FileIdentifierDesc' is
1450 // NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the code
1451 // reaches here, 'FileIdentifierDesc' must be not NULL.
1453 // The ASSERT here is for addressing a false positive NULL pointer
1454 // dereference issue raised from static analysis.
1456 ASSERT (FileIdentifierDesc
!= NULL
);
1458 if (FileIdentifierDesc
->FileCharacteristics
& PARENT_FILE
) {
1460 // This FID contains the location (FE/EFE) of the parent directory of this
1461 // directory (Parent), and if FileName is either ".." or "\\", then it's
1462 // the expected FID.
1464 if (StrCmp (FileName
, L
"..") == 0 || StrCmp (FileName
, L
"\\") == 0) {
1469 Status
= GetFileNameFromFid (FileIdentifierDesc
, FoundFileName
);
1470 if (EFI_ERROR (Status
)) {
1474 if (StrCmp (FileName
, FoundFileName
) == 0) {
1476 // FID has been found. Prepare to find its respective FE/EFE.
1483 FreePool ((VOID
*)FileIdentifierDesc
);
1486 if (ReadDirInfo
.DirectoryData
!= NULL
) {
1488 // Free all allocated resources for the directory listing.
1490 FreePool (ReadDirInfo
.DirectoryData
);
1494 Status
= EFI_SUCCESS
;
1496 File
->FileIdentifierDesc
= FileIdentifierDesc
;
1499 // If the requested file is root directory, then the FE/EFE was already
1500 // retrieved in UdfOpenVolume() function, thus no need to find it again.
1502 // Otherwise, find FE/EFE from the respective FID.
1504 if (StrCmp (FileName
, L
"\\") != 0) {
1505 Status
= FindFileEntry (
1509 &FileIdentifierDesc
->Icb
,
1512 if (EFI_ERROR (Status
)) {
1517 // Make sure that both Parent's FE/EFE and found FE/EFE are not equal.
1519 if (CompareMem ((VOID
*)Parent
->FileEntry
, (VOID
*)CompareFileEntry
,
1520 Volume
->FileEntrySize
) != 0) {
1521 File
->FileEntry
= CompareFileEntry
;
1523 FreePool ((VOID
*)FileIdentifierDesc
);
1524 FreePool ((VOID
*)CompareFileEntry
);
1525 Status
= EFI_NOT_FOUND
;
1533 FreePool ((VOID
*)FileIdentifierDesc
);
1539 Read volume information on a medium which contains a valid UDF file system.
1541 @param[in] BlockIo BlockIo interface.
1542 @param[in] DiskIo DiskIo interface.
1543 @param[out] Volume UDF volume information structure.
1545 @retval EFI_SUCCESS Volume information read.
1546 @retval EFI_NO_MEDIA The device has no media.
1547 @retval EFI_DEVICE_ERROR The device reported an error.
1548 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1549 @retval EFI_OUT_OF_RESOURCES The volume was not read due to lack of resources.
1553 ReadUdfVolumeInformation (
1554 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1555 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1556 OUT UDF_VOLUME_INFO
*Volume
1562 // Read all necessary UDF volume information and keep it private to the driver
1564 Status
= ReadVolumeFileStructure (
1569 if (EFI_ERROR (Status
)) {
1574 // Find File Set Descriptor
1576 Status
= FindFileSetDescriptor (BlockIo
, DiskIo
, Volume
);
1577 if (EFI_ERROR (Status
)) {
1585 Find the root directory on an UDF volume.
1587 @param[in] BlockIo BlockIo interface.
1588 @param[in] DiskIo DiskIo interface.
1589 @param[in] Volume UDF volume information structure.
1590 @param[out] File Root directory file.
1592 @retval EFI_SUCCESS Root directory found.
1593 @retval EFI_NO_MEDIA The device has no media.
1594 @retval EFI_DEVICE_ERROR The device reported an error.
1595 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1596 @retval EFI_OUT_OF_RESOURCES The root directory was not found due to lack of
1602 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1603 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1604 IN UDF_VOLUME_INFO
*Volume
,
1605 OUT UDF_FILE_INFO
*File
1609 UDF_FILE_INFO Parent
;
1611 Status
= FindFileEntry (
1615 &Volume
->FileSetDesc
.RootDirectoryIcb
,
1618 if (EFI_ERROR (Status
)) {
1622 Parent
.FileEntry
= File
->FileEntry
;
1623 Parent
.FileIdentifierDesc
= NULL
;
1632 &Volume
->FileSetDesc
.RootDirectoryIcb
,
1635 if (EFI_ERROR (Status
)) {
1636 FreePool (File
->FileEntry
);
1643 Find either a File Entry or a Extended File Entry from a given ICB.
1645 @param[in] BlockIo BlockIo interface.
1646 @param[in] DiskIo DiskIo interface.
1647 @param[in] Volume UDF volume information structure.
1648 @param[in] Icb ICB of the FID.
1649 @param[out] FileEntry File Entry or Extended File Entry.
1651 @retval EFI_SUCCESS File Entry or Extended File Entry found.
1652 @retval EFI_NO_MEDIA The device has no media.
1653 @retval EFI_DEVICE_ERROR The device reported an error.
1654 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1655 @retval EFI_OUT_OF_RESOURCES The FE/EFE entry was not found due to lack of
1661 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1662 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1663 IN UDF_VOLUME_INFO
*Volume
,
1664 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1665 OUT VOID
**FileEntry
1670 UINT32 LogicalBlockSize
;
1671 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
1674 Status
= GetLongAdLsn (Volume
, Icb
, &Lsn
);
1675 if (EFI_ERROR (Status
)) {
1679 LogicalBlockSize
= Volume
->LogicalVolDesc
.LogicalBlockSize
;
1681 ReadBuffer
= AllocateZeroPool (Volume
->FileEntrySize
);
1682 if (ReadBuffer
== NULL
) {
1683 return EFI_OUT_OF_RESOURCES
;
1689 Status
= DiskIo
->ReadDisk (
1691 BlockIo
->Media
->MediaId
,
1692 MultU64x32 (Lsn
, LogicalBlockSize
),
1693 Volume
->FileEntrySize
,
1696 if (EFI_ERROR (Status
)) {
1697 goto Error_Read_Disk_Blk
;
1700 DescriptorTag
= ReadBuffer
;
1703 // Check if the read extent contains a valid Tag Identifier for the expected
1706 if (DescriptorTag
->TagIdentifier
!= UdfFileEntry
&&
1707 DescriptorTag
->TagIdentifier
!= UdfExtendedFileEntry
) {
1708 Status
= EFI_VOLUME_CORRUPTED
;
1709 goto Error_Invalid_Fe
;
1712 *FileEntry
= ReadBuffer
;
1716 Error_Read_Disk_Blk
:
1717 FreePool (ReadBuffer
);
1723 Find a file given its absolute path on an UDF volume.
1725 @param[in] BlockIo BlockIo interface.
1726 @param[in] DiskIo DiskIo interface.
1727 @param[in] Volume UDF volume information structure.
1728 @param[in] FilePath File's absolute path.
1729 @param[in] Root Root directory file.
1730 @param[in] Parent Parent directory file.
1731 @param[in] Icb ICB of Parent.
1732 @param[out] File Found file.
1734 @retval EFI_SUCCESS FilePath was found.
1735 @retval EFI_NO_MEDIA The device has no media.
1736 @retval EFI_DEVICE_ERROR The device reported an error.
1737 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1738 @retval EFI_OUT_OF_RESOURCES The FilePath file was not found due to lack of
1744 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1745 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1746 IN UDF_VOLUME_INFO
*Volume
,
1747 IN CHAR16
*FilePath
,
1748 IN UDF_FILE_INFO
*Root
,
1749 IN UDF_FILE_INFO
*Parent
,
1750 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1751 OUT UDF_FILE_INFO
*File
1755 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
1756 CHAR16
*FileNamePointer
;
1757 UDF_FILE_INFO PreviousFile
;
1760 Status
= EFI_NOT_FOUND
;
1762 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
1763 while (*FilePath
!= L
'\0') {
1764 FileNamePointer
= FileName
;
1765 while (*FilePath
!= L
'\0' && *FilePath
!= L
'\\') {
1766 *FileNamePointer
++ = *FilePath
++;
1769 *FileNamePointer
= L
'\0';
1770 if (FileName
[0] == L
'\0') {
1772 // Open root directory.
1776 // There is no file found for the root directory yet. So, find only its
1779 // See UdfOpenVolume() function.
1781 Status
= InternalFindFile (BlockIo
,
1790 // We've already a file pointer (Root) for the root directory. Duplicate
1791 // its FE/EFE and FID descriptors.
1793 Status
= EFI_SUCCESS
;
1794 DuplicateFe (BlockIo
, Volume
, Root
->FileEntry
, &File
->FileEntry
);
1795 if (File
->FileEntry
== NULL
) {
1796 Status
= EFI_OUT_OF_RESOURCES
;
1799 // File->FileEntry is not NULL.
1801 DuplicateFid (Root
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1802 if (File
->FileIdentifierDesc
== NULL
) {
1803 FreePool (File
->FileEntry
);
1804 Status
= EFI_OUT_OF_RESOURCES
;
1810 // No root directory. Find filename from the current directory.
1812 Status
= InternalFindFile (BlockIo
,
1821 if (EFI_ERROR (Status
)) {
1826 // If the found file is a symlink, then find its respective FE/EFE and
1829 if (FE_ICB_FILE_TYPE (File
->FileEntry
) == UdfFileEntrySymlink
) {
1830 FreePool ((VOID
*)File
->FileIdentifierDesc
);
1832 FileEntry
= File
->FileEntry
;
1834 Status
= ResolveSymlink (BlockIo
,
1841 FreePool (FileEntry
);
1843 if (EFI_ERROR (Status
)) {
1848 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
1849 sizeof (UDF_FILE_INFO
)) != 0) {
1850 CleanupFileInformation (&PreviousFile
);
1853 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
1854 if (*FilePath
!= L
'\0' && *FilePath
== L
'\\') {
1863 Read a directory entry at a time on an UDF volume.
1865 @param[in] BlockIo BlockIo interface.
1866 @param[in] DiskIo DiskIo interface.
1867 @param[in] Volume UDF volume information structure.
1868 @param[in] ParentIcb ICB of the parent file.
1869 @param[in] FileEntryData FE/EFE of the parent file.
1870 @param[in, out] ReadDirInfo Next read directory listing structure
1872 @param[out] FoundFid File Identifier Descriptor pointer.
1874 @retval EFI_SUCCESS Directory entry read.
1875 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
1876 @retval EFI_NO_MEDIA The device has no media.
1877 @retval EFI_DEVICE_ERROR The device reported an error.
1878 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1879 @retval EFI_OUT_OF_RESOURCES The directory entry was not read due to lack of
1884 ReadDirectoryEntry (
1885 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1886 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1887 IN UDF_VOLUME_INFO
*Volume
,
1888 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
1889 IN VOID
*FileEntryData
,
1890 IN OUT UDF_READ_DIRECTORY_INFO
*ReadDirInfo
,
1891 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR
**FoundFid
1895 UDF_READ_FILE_INFO ReadFileInfo
;
1896 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1898 if (ReadDirInfo
->DirectoryData
== NULL
) {
1900 // The directory's recorded data has not been read yet. So let's cache it
1901 // into memory and the next calls won't need to read it again.
1903 ReadFileInfo
.Flags
= ReadFileAllocateAndRead
;
1913 if (EFI_ERROR (Status
)) {
1918 // Fill in ReadDirInfo structure with the read directory's data information.
1920 ReadDirInfo
->DirectoryData
= ReadFileInfo
.FileData
;
1921 ReadDirInfo
->DirectoryLength
= ReadFileInfo
.ReadLength
;
1925 if (ReadDirInfo
->FidOffset
>= ReadDirInfo
->DirectoryLength
) {
1927 // There are no longer FIDs for this directory. By returning
1928 // EFI_DEVICE_ERROR to the callee will indicate end of directory
1931 return EFI_DEVICE_ERROR
;
1935 // Get FID for this entry.
1937 FileIdentifierDesc
= GET_FID_FROM_ADS (ReadDirInfo
->DirectoryData
,
1938 ReadDirInfo
->FidOffset
);
1940 // Update FidOffset to point to next FID.
1942 ReadDirInfo
->FidOffset
+= GetFidDescriptorLength (FileIdentifierDesc
);
1943 } while (FileIdentifierDesc
->FileCharacteristics
& DELETED_FILE
);
1945 DuplicateFid (FileIdentifierDesc
, FoundFid
);
1946 if (*FoundFid
== NULL
) {
1947 return EFI_OUT_OF_RESOURCES
;
1954 Get a filename (encoded in OSTA-compressed format) from a File Identifier
1955 Descriptor on an UDF volume.
1957 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
1958 @param[out] FileName Decoded filename.
1960 @retval EFI_SUCCESS Filename decoded and read.
1961 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1964 GetFileNameFromFid (
1965 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
,
1966 OUT CHAR16
*FileName
1969 UINT8
*OstaCompressed
;
1970 UINT8 CompressionId
;
1976 (UINT8
*)FileIdentifierDesc
->Data
+
1977 FileIdentifierDesc
->LengthOfImplementationUse
1980 CompressionId
= OstaCompressed
[0];
1981 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
1982 return EFI_VOLUME_CORRUPTED
;
1988 Length
= FileIdentifierDesc
->LengthOfFileIdentifier
;
1989 for (Index
= 1; Index
< Length
; Index
++) {
1990 if (CompressionId
== 16) {
1991 *FileName
= OstaCompressed
[Index
++] << 8;
1996 if (Index
< Length
) {
1997 *FileName
|= (CHAR16
)(OstaCompressed
[Index
]);
2009 Resolve a symlink file on an UDF volume.
2011 @param[in] BlockIo BlockIo interface.
2012 @param[in] DiskIo DiskIo interface.
2013 @param[in] Volume UDF volume information structure.
2014 @param[in] Parent Parent file.
2015 @param[in] FileEntryData FE/EFE structure pointer.
2016 @param[out] File Resolved file.
2018 @retval EFI_SUCCESS Symlink file resolved.
2019 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2020 @retval EFI_NO_MEDIA The device has no media.
2021 @retval EFI_DEVICE_ERROR The device reported an error.
2022 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2023 @retval EFI_OUT_OF_RESOURCES The symlink file was not resolved due to lack of
2029 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2030 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2031 IN UDF_VOLUME_INFO
*Volume
,
2032 IN UDF_FILE_INFO
*Parent
,
2033 IN VOID
*FileEntryData
,
2034 OUT UDF_FILE_INFO
*File
2038 UDF_READ_FILE_INFO ReadFileInfo
;
2042 UDF_PATH_COMPONENT
*PathComp
;
2043 UINT8 PathCompLength
;
2044 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
2047 UINT8 CompressionId
;
2048 UDF_FILE_INFO PreviousFile
;
2051 // Symlink files on UDF volumes do not contain so much data other than
2052 // Path Components which resolves to real filenames, so it's OK to read in
2053 // all its data here -- usually the data will be inline with the FE/EFE for
2056 ReadFileInfo
.Flags
= ReadFileAllocateAndRead
;
2062 &Parent
->FileIdentifierDesc
->Icb
,
2066 if (EFI_ERROR (Status
)) {
2070 Length
= ReadFileInfo
.ReadLength
;
2072 Data
= (UINT8
*)ReadFileInfo
.FileData
;
2073 EndData
= Data
+ Length
;
2075 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
2078 PathComp
= (UDF_PATH_COMPONENT
*)Data
;
2080 PathCompLength
= PathComp
->LengthOfComponentIdentifier
;
2082 switch (PathComp
->ComponentType
) {
2085 // This Path Component specifies the root directory hierarchy subject to
2086 // agreement between the originator and recipient of the medium. Skip it.
2092 // "\\." of the current directory. Read next Path Component.
2094 goto Next_Path_Component
;
2097 // ".." (parent directory). Go to it.
2099 CopyMem ((VOID
*)FileName
, L
"..", 6);
2103 // "." (current file). Duplicate both FE/EFE and FID of this file.
2105 DuplicateFe (BlockIo
, Volume
, PreviousFile
.FileEntry
, &File
->FileEntry
);
2106 if (File
->FileEntry
== NULL
) {
2107 Status
= EFI_OUT_OF_RESOURCES
;
2108 goto Error_Find_File
;
2111 DuplicateFid (PreviousFile
.FileIdentifierDesc
,
2112 &File
->FileIdentifierDesc
);
2113 if (File
->FileIdentifierDesc
== NULL
) {
2114 FreePool (File
->FileEntry
);
2115 Status
= EFI_OUT_OF_RESOURCES
;
2116 goto Error_Find_File
;
2118 goto Next_Path_Component
;
2121 // This Path Component identifies an object, either a file or a
2122 // directory or an alias.
2124 // Decode it from the compressed data in ComponentIdentifier and find
2127 CompressionId
= PathComp
->ComponentIdentifier
[0];
2128 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
2129 return EFI_VOLUME_CORRUPTED
;
2133 for (Index
= 1; Index
< PathCompLength
; Index
++) {
2134 if (CompressionId
== 16) {
2135 *Char
= *(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+
2142 if (Index
< Length
) {
2143 *Char
|= (CHAR16
)(*(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+ Index
));
2154 // Find file from the read filename in symlink's file data.
2156 Status
= InternalFindFile (
2165 if (EFI_ERROR (Status
)) {
2166 goto Error_Find_File
;
2169 Next_Path_Component
:
2170 Data
+= sizeof (UDF_PATH_COMPONENT
) + PathCompLength
;
2171 if (Data
>= EndData
) {
2175 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2176 sizeof (UDF_FILE_INFO
)) != 0) {
2177 CleanupFileInformation (&PreviousFile
);
2180 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
2184 // Unmap the symlink file.
2186 FreePool (ReadFileInfo
.FileData
);
2191 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2192 sizeof (UDF_FILE_INFO
)) != 0) {
2193 CleanupFileInformation (&PreviousFile
);
2196 FreePool (ReadFileInfo
.FileData
);
2202 Clean up in-memory UDF file information.
2204 @param[in] File File information pointer.
2208 CleanupFileInformation (
2209 IN UDF_FILE_INFO
*File
2212 if (File
->FileEntry
!= NULL
) {
2213 FreePool (File
->FileEntry
);
2215 if (File
->FileIdentifierDesc
!= NULL
) {
2216 FreePool ((VOID
*)File
->FileIdentifierDesc
);
2219 ZeroMem ((VOID
*)File
, sizeof (UDF_FILE_INFO
));
2223 Find a file from its absolute path on an UDF volume.
2225 @param[in] BlockIo BlockIo interface.
2226 @param[in] DiskIo DiskIo interface.
2227 @param[in] Volume UDF volume information structure.
2228 @param[in] File File information structure.
2229 @param[out] Size Size of the file.
2231 @retval EFI_SUCCESS File size calculated and set in Size.
2232 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2233 @retval EFI_NO_MEDIA The device has no media.
2234 @retval EFI_DEVICE_ERROR The device reported an error.
2235 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2236 @retval EFI_OUT_OF_RESOURCES The file size was not calculated due to lack of
2242 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2243 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2244 IN UDF_VOLUME_INFO
*Volume
,
2245 IN UDF_FILE_INFO
*File
,
2250 UDF_READ_FILE_INFO ReadFileInfo
;
2252 ReadFileInfo
.Flags
= ReadFileGetFileSize
;
2258 &File
->FileIdentifierDesc
->Icb
,
2262 if (EFI_ERROR (Status
)) {
2266 *Size
= ReadFileInfo
.ReadLength
;
2272 Set information about a file on an UDF volume.
2274 @param[in] File File pointer.
2275 @param[in] FileSize Size of the file.
2276 @param[in] FileName Filename of the file.
2277 @param[in, out] BufferSize Size of the returned file infomation.
2278 @param[out] Buffer Data of the returned file information.
2280 @retval EFI_SUCCESS File information set.
2281 @retval EFI_NO_MEDIA The device has no media.
2282 @retval EFI_DEVICE_ERROR The device reported an error.
2283 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2284 @retval EFI_OUT_OF_RESOURCES The file information was not set due to lack of
2290 IN UDF_FILE_INFO
*File
,
2292 IN CHAR16
*FileName
,
2293 IN OUT UINTN
*BufferSize
,
2297 UINTN FileInfoLength
;
2298 EFI_FILE_INFO
*FileInfo
;
2299 UDF_FILE_ENTRY
*FileEntry
;
2300 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
2301 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
2304 // Calculate the needed size for the EFI_FILE_INFO structure.
2306 FileInfoLength
= sizeof (EFI_FILE_INFO
) + ((FileName
!= NULL
) ?
2307 StrSize (FileName
) :
2309 if (*BufferSize
< FileInfoLength
) {
2311 // The given Buffer has no size enough for EFI_FILE_INFO structure.
2313 *BufferSize
= FileInfoLength
;
2314 return EFI_BUFFER_TOO_SMALL
;
2318 // Buffer now contains room enough to store EFI_FILE_INFO structure.
2319 // Now, fill it in with all necessary information about the file.
2321 FileInfo
= (EFI_FILE_INFO
*)Buffer
;
2322 FileInfo
->Size
= FileInfoLength
;
2323 FileInfo
->Attribute
&= ~EFI_FILE_VALID_ATTR
;
2324 FileInfo
->Attribute
|= EFI_FILE_READ_ONLY
;
2326 if (IS_FID_DIRECTORY_FILE (File
->FileIdentifierDesc
)) {
2327 FileInfo
->Attribute
|= EFI_FILE_DIRECTORY
;
2328 } else if (IS_FID_NORMAL_FILE (File
->FileIdentifierDesc
)) {
2329 FileInfo
->Attribute
|= EFI_FILE_ARCHIVE
;
2332 if (IS_FID_HIDDEN_FILE (File
->FileIdentifierDesc
)) {
2333 FileInfo
->Attribute
|= EFI_FILE_HIDDEN
;
2336 DescriptorTag
= File
->FileEntry
;
2338 if (DescriptorTag
->TagIdentifier
== UdfFileEntry
) {
2339 FileEntry
= (UDF_FILE_ENTRY
*)File
->FileEntry
;
2342 // Check if FE has the system attribute set.
2344 if (FileEntry
->IcbTag
.Flags
& (1 << 10)) {
2345 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2348 FileInfo
->FileSize
= FileSize
;
2349 FileInfo
->PhysicalSize
= FileSize
;
2351 FileInfo
->CreateTime
.Year
= FileEntry
->AccessTime
.Year
;
2352 FileInfo
->CreateTime
.Month
= FileEntry
->AccessTime
.Month
;
2353 FileInfo
->CreateTime
.Day
= FileEntry
->AccessTime
.Day
;
2354 FileInfo
->CreateTime
.Hour
= FileEntry
->AccessTime
.Hour
;
2355 FileInfo
->CreateTime
.Minute
= FileEntry
->AccessTime
.Second
;
2356 FileInfo
->CreateTime
.Second
= FileEntry
->AccessTime
.Second
;
2357 FileInfo
->CreateTime
.Nanosecond
=
2358 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2360 FileInfo
->LastAccessTime
.Year
=
2361 FileEntry
->AccessTime
.Year
;
2362 FileInfo
->LastAccessTime
.Month
=
2363 FileEntry
->AccessTime
.Month
;
2364 FileInfo
->LastAccessTime
.Day
=
2365 FileEntry
->AccessTime
.Day
;
2366 FileInfo
->LastAccessTime
.Hour
=
2367 FileEntry
->AccessTime
.Hour
;
2368 FileInfo
->LastAccessTime
.Minute
=
2369 FileEntry
->AccessTime
.Minute
;
2370 FileInfo
->LastAccessTime
.Second
=
2371 FileEntry
->AccessTime
.Second
;
2372 FileInfo
->LastAccessTime
.Nanosecond
=
2373 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2374 } else if (DescriptorTag
->TagIdentifier
== UdfExtendedFileEntry
) {
2375 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)File
->FileEntry
;
2378 // Check if EFE has the system attribute set.
2380 if (ExtendedFileEntry
->IcbTag
.Flags
& (1 << 10)) {
2381 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2384 FileInfo
->FileSize
= FileSize
;
2385 FileInfo
->PhysicalSize
= FileSize
;
2387 FileInfo
->CreateTime
.Year
= ExtendedFileEntry
->CreationTime
.Year
;
2388 FileInfo
->CreateTime
.Month
= ExtendedFileEntry
->CreationTime
.Month
;
2389 FileInfo
->CreateTime
.Day
= ExtendedFileEntry
->CreationTime
.Day
;
2390 FileInfo
->CreateTime
.Hour
= ExtendedFileEntry
->CreationTime
.Hour
;
2391 FileInfo
->CreateTime
.Minute
= ExtendedFileEntry
->CreationTime
.Second
;
2392 FileInfo
->CreateTime
.Second
= ExtendedFileEntry
->CreationTime
.Second
;
2393 FileInfo
->CreateTime
.Nanosecond
=
2394 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2396 FileInfo
->LastAccessTime
.Year
=
2397 ExtendedFileEntry
->AccessTime
.Year
;
2398 FileInfo
->LastAccessTime
.Month
=
2399 ExtendedFileEntry
->AccessTime
.Month
;
2400 FileInfo
->LastAccessTime
.Day
=
2401 ExtendedFileEntry
->AccessTime
.Day
;
2402 FileInfo
->LastAccessTime
.Hour
=
2403 ExtendedFileEntry
->AccessTime
.Hour
;
2404 FileInfo
->LastAccessTime
.Minute
=
2405 ExtendedFileEntry
->AccessTime
.Minute
;
2406 FileInfo
->LastAccessTime
.Second
=
2407 ExtendedFileEntry
->AccessTime
.Second
;
2408 FileInfo
->LastAccessTime
.Nanosecond
=
2409 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2412 FileInfo
->CreateTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2413 FileInfo
->CreateTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2414 FileInfo
->LastAccessTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2415 FileInfo
->LastAccessTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2417 CopyMem ((VOID
*)&FileInfo
->ModificationTime
,
2418 (VOID
*)&FileInfo
->LastAccessTime
,
2421 if (FileName
!= NULL
) {
2422 StrCpyS (FileInfo
->FileName
, StrLen (FileName
) + 1, FileName
);
2424 FileInfo
->FileName
[0] = '\0';
2427 *BufferSize
= FileInfoLength
;
2433 Get volume and free space size information of an UDF volume.
2435 @param[in] BlockIo BlockIo interface.
2436 @param[in] DiskIo DiskIo interface.
2437 @param[in] Volume UDF volume information structure.
2438 @param[out] VolumeSize Volume size.
2439 @param[out] FreeSpaceSize Free space size.
2441 @retval EFI_SUCCESS Volume and free space size calculated.
2442 @retval EFI_NO_MEDIA The device has no media.
2443 @retval EFI_DEVICE_ERROR The device reported an error.
2444 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2445 @retval EFI_OUT_OF_RESOURCES The volume and free space size were not
2446 calculated due to lack of resources.
2451 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2452 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2453 IN UDF_VOLUME_INFO
*Volume
,
2454 OUT UINT64
*VolumeSize
,
2455 OUT UINT64
*FreeSpaceSize
2459 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
2460 UDF_EXTENT_AD
*ExtentAd
;
2462 UINT32 LogicalBlockSize
;
2463 UDF_LOGICAL_VOLUME_INTEGRITY
*LogicalVolInt
;
2464 UDF_DESCRIPTOR_TAG
*DescriptorTag
;
2469 LogicalVolDesc
= &Volume
->LogicalVolDesc
;
2471 ExtentAd
= &LogicalVolDesc
->IntegritySequenceExtent
;
2473 if (ExtentAd
->ExtentLength
== 0) {
2474 return EFI_VOLUME_CORRUPTED
;
2477 LogicalVolInt
= AllocatePool (ExtentAd
->ExtentLength
);
2478 if (LogicalVolInt
== NULL
) {
2479 return EFI_OUT_OF_RESOURCES
;
2483 // Get location of Logical Volume Integrity Descriptor
2485 Lsn
= (UINT64
)ExtentAd
->ExtentLocation
- Volume
->MainVdsStartLocation
;
2487 LogicalBlockSize
= LogicalVolDesc
->LogicalBlockSize
;
2492 Status
= DiskIo
->ReadDisk (
2494 BlockIo
->Media
->MediaId
,
2495 MultU64x32 (Lsn
, LogicalBlockSize
),
2496 ExtentAd
->ExtentLength
,
2499 if (EFI_ERROR (Status
)) {
2503 DescriptorTag
= &LogicalVolInt
->DescriptorTag
;
2506 // Check if read block is a Logical Volume Integrity Descriptor
2508 if (DescriptorTag
->TagIdentifier
!= UdfLogicalVolumeIntegrityDescriptor
) {
2509 Status
= EFI_VOLUME_CORRUPTED
;
2516 Length
= LogicalVolInt
->NumberOfPartitions
;
2517 for (Index
= 0; Index
< Length
; Index
+= sizeof (UINT32
)) {
2518 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2520 // Check if size is not specified
2522 if (LsnsNo
== 0xFFFFFFFFUL
) {
2526 // Accumulate free space size
2528 *FreeSpaceSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2531 Length
= LogicalVolInt
->NumberOfPartitions
* sizeof (UINT32
) * 2;
2532 for (; Index
< Length
; Index
+= sizeof (UINT32
)) {
2533 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2535 // Check if size is not specified
2537 if (LsnsNo
== 0xFFFFFFFFUL
) {
2541 // Accumulate used volume space
2543 *VolumeSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2546 Status
= EFI_SUCCESS
;
2550 // Free Logical Volume Integrity Descriptor
2552 FreePool (LogicalVolInt
);
2558 Seek a file and read its data into memory on an UDF volume.
2560 @param[in] BlockIo BlockIo interface.
2561 @param[in] DiskIo DiskIo interface.
2562 @param[in] Volume UDF volume information structure.
2563 @param[in] File File information structure.
2564 @param[in] FileSize Size of the file.
2565 @param[in, out] FilePosition File position.
2566 @param[in, out] Buffer File data.
2567 @param[in, out] BufferSize Read size.
2569 @retval EFI_SUCCESS File seeked and read.
2570 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2571 @retval EFI_NO_MEDIA The device has no media.
2572 @retval EFI_DEVICE_ERROR The device reported an error.
2573 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2574 @retval EFI_OUT_OF_RESOURCES The file's recorded data was not read due to lack
2580 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2581 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2582 IN UDF_VOLUME_INFO
*Volume
,
2583 IN UDF_FILE_INFO
*File
,
2585 IN OUT UINT64
*FilePosition
,
2586 IN OUT VOID
*Buffer
,
2587 IN OUT UINT64
*BufferSize
2591 UDF_READ_FILE_INFO ReadFileInfo
;
2593 ReadFileInfo
.Flags
= ReadFileSeekAndRead
;
2594 ReadFileInfo
.FilePosition
= *FilePosition
;
2595 ReadFileInfo
.FileData
= Buffer
;
2596 ReadFileInfo
.FileDataSize
= *BufferSize
;
2597 ReadFileInfo
.FileSize
= FileSize
;
2603 &File
->FileIdentifierDesc
->Icb
,
2607 if (EFI_ERROR (Status
)) {
2611 *BufferSize
= ReadFileInfo
.FileDataSize
;
2612 *FilePosition
= ReadFileInfo
.FilePosition
;
2618 Check if ControllerHandle supports an UDF file system.
2620 @param[in] This Protocol instance pointer.
2621 @param[in] ControllerHandle Handle of device to test.
2623 @retval EFI_SUCCESS UDF file system found.
2624 @retval EFI_UNSUPPORTED UDF file system not found.
2628 SupportUdfFileSystem (
2629 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2630 IN EFI_HANDLE ControllerHandle
2634 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2635 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
2636 EFI_DEVICE_PATH_PROTOCOL
*LastDevicePathNode
;
2637 EFI_GUID
*VendorDefinedGuid
;
2640 // Open Device Path protocol on ControllerHandle
2642 Status
= gBS
->OpenProtocol (
2644 &gEfiDevicePathProtocolGuid
,
2645 (VOID
**)&DevicePath
,
2646 This
->DriverBindingHandle
,
2648 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2650 if (EFI_ERROR (Status
)) {
2651 return EFI_UNSUPPORTED
;
2654 Status
= EFI_UNSUPPORTED
;
2657 // Get last Device Path node
2659 LastDevicePathNode
= NULL
;
2660 DevicePathNode
= DevicePath
;
2661 while (!IsDevicePathEnd (DevicePathNode
)) {
2662 LastDevicePathNode
= DevicePathNode
;
2663 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
2666 // Check if last Device Path node contains a Vendor-Defined Media Device Path
2667 // of an UDF file system.
2669 if (LastDevicePathNode
!= NULL
&&
2670 DevicePathType (LastDevicePathNode
) == MEDIA_DEVICE_PATH
&&
2671 DevicePathSubType (LastDevicePathNode
) == MEDIA_VENDOR_DP
) {
2672 VendorDefinedGuid
= (EFI_GUID
*)((UINTN
)LastDevicePathNode
+
2673 OFFSET_OF (VENDOR_DEVICE_PATH
, Guid
));
2674 if (CompareGuid (VendorDefinedGuid
, &gUdfDevPathGuid
)) {
2675 Status
= EFI_SUCCESS
;
2680 // Close Device Path protocol on ControllerHandle
2682 gBS
->CloseProtocol (
2684 &gEfiDevicePathProtocolGuid
,
2685 This
->DriverBindingHandle
,