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];
47 BlockSize
= BlockIo
->Media
->BlockSize
;
48 EndLBA
= BlockIo
->Media
->LastBlock
;
49 DescriptorLBAs
[0] = 256;
50 DescriptorLBAs
[1] = EndLBA
- 256;
51 DescriptorLBAs
[2] = EndLBA
;
52 DescriptorLBAs
[3] = 512;
54 for (Index
= 0; Index
< ARRAY_SIZE (DescriptorLBAs
); Index
++) {
55 Status
= DiskIo
->ReadDisk (
57 BlockIo
->Media
->MediaId
,
58 MultU64x32 (DescriptorLBAs
[Index
], BlockSize
),
59 sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
),
62 if (EFI_ERROR (Status
)) {
66 // Check if read LBA has a valid AVDP descriptor.
68 if (IS_AVDP (AnchorPoint
)) {
75 return EFI_VOLUME_CORRUPTED
;
79 Save the content of Logical Volume Descriptors and Partitions Descriptors in
82 @param[in] BlockIo BlockIo interface.
83 @param[in] DiskIo DiskIo interface.
84 @param[in] AnchorPoint Anchor volume descriptor pointer.
85 @param[out] Volume UDF volume information structure.
87 @retval EFI_SUCCESS The descriptors were saved.
88 @retval EFI_OUT_OF_RESOURCES The descriptors were not saved due to lack of
90 @retval other The descriptors were not saved due to
95 StartMainVolumeDescriptorSequence (
96 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
97 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
98 IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
*AnchorPoint
,
99 OUT UDF_VOLUME_INFO
*Volume
104 UDF_EXTENT_AD
*ExtentAd
;
108 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
109 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
111 UINT32 LogicalBlockSize
;
114 // We've already found an ADVP on the volume. It contains the extent
115 // (MainVolumeDescriptorSequenceExtent) where the Main Volume Descriptor
116 // Sequence starts. Therefore, we'll look for Logical Volume Descriptors and
117 // Partitions Descriptors and save them in memory, accordingly.
119 // Note also that each descriptor will be aligned on a block size (BlockSize)
120 // boundary, so we need to read one block at a time.
122 BlockSize
= BlockIo
->Media
->BlockSize
;
123 ExtentAd
= &AnchorPoint
->MainVolumeDescriptorSequenceExtent
;
124 StartingLsn
= (UINT64
)ExtentAd
->ExtentLocation
;
125 EndingLsn
= StartingLsn
+ DivU64x32 (
126 (UINT64
)ExtentAd
->ExtentLength
,
130 Volume
->LogicalVolDescs
=
131 (UDF_LOGICAL_VOLUME_DESCRIPTOR
**)AllocateZeroPool (ExtentAd
->ExtentLength
);
132 if (Volume
->LogicalVolDescs
== NULL
) {
133 return EFI_OUT_OF_RESOURCES
;
136 Volume
->PartitionDescs
=
137 (UDF_PARTITION_DESCRIPTOR
**)AllocateZeroPool (ExtentAd
->ExtentLength
);
138 if (Volume
->PartitionDescs
== NULL
) {
139 Status
= EFI_OUT_OF_RESOURCES
;
140 goto Error_Alloc_Pds
;
143 Buffer
= AllocateZeroPool (BlockSize
);
144 if (Buffer
== NULL
) {
145 Status
= EFI_OUT_OF_RESOURCES
;
146 goto Error_Alloc_Buf
;
149 Volume
->LogicalVolDescsNo
= 0;
150 Volume
->PartitionDescsNo
= 0;
152 while (StartingLsn
<= EndingLsn
) {
153 Status
= DiskIo
->ReadDisk (
155 BlockIo
->Media
->MediaId
,
156 MultU64x32 (StartingLsn
, BlockSize
),
160 if (EFI_ERROR (Status
)) {
161 goto Error_Read_Disk_Blk
;
164 if (IS_TD (Buffer
)) {
166 // Found a Terminating Descriptor. Stop the sequence then.
171 if (IS_LVD (Buffer
)) {
173 // Found a Logical Volume Descriptor.
176 (UDF_LOGICAL_VOLUME_DESCRIPTOR
*)
177 AllocateZeroPool (sizeof (UDF_LOGICAL_VOLUME_DESCRIPTOR
));
178 if (LogicalVolDesc
== NULL
) {
179 Status
= EFI_OUT_OF_RESOURCES
;
180 goto Error_Alloc_Lvd
;
183 CopyMem ((VOID
*)LogicalVolDesc
, Buffer
,
184 sizeof (UDF_LOGICAL_VOLUME_DESCRIPTOR
));
185 Volume
->LogicalVolDescs
[Volume
->LogicalVolDescsNo
++] = LogicalVolDesc
;
186 } else if (IS_PD (Buffer
)) {
188 // Found a Partition Descriptor.
191 (UDF_PARTITION_DESCRIPTOR
*)
192 AllocateZeroPool (sizeof (UDF_PARTITION_DESCRIPTOR
));
193 if (PartitionDesc
== NULL
) {
194 Status
= EFI_OUT_OF_RESOURCES
;
198 CopyMem ((VOID
*)PartitionDesc
, Buffer
,
199 sizeof (UDF_PARTITION_DESCRIPTOR
));
200 Volume
->PartitionDescs
[Volume
->PartitionDescsNo
++] = PartitionDesc
;
207 // When an UDF volume (revision 2.00 or higher) contains a File Entry rather
208 // than an Extended File Entry (which is not recommended as per spec), we need
209 // to make sure the size of a FE will be _at least_ 2048
210 // (UDF_LOGICAL_SECTOR_SIZE) bytes long to keep backward compatibility.
212 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, UDF_DEFAULT_LV_NUM
);
213 if (LogicalBlockSize
>= UDF_LOGICAL_SECTOR_SIZE
) {
214 Volume
->FileEntrySize
= LogicalBlockSize
;
216 Volume
->FileEntrySize
= UDF_LOGICAL_SECTOR_SIZE
;
225 for (Index
= 0; Index
< Volume
->PartitionDescsNo
; Index
++) {
226 FreePool ((VOID
*)Volume
->PartitionDescs
[Index
]);
229 for (Index
= 0; Index
< Volume
->LogicalVolDescsNo
; Index
++) {
230 FreePool ((VOID
*)Volume
->LogicalVolDescs
[Index
]);
237 FreePool ((VOID
*)Volume
->PartitionDescs
);
238 Volume
->PartitionDescs
= NULL
;
241 FreePool ((VOID
*)Volume
->LogicalVolDescs
);
242 Volume
->LogicalVolDescs
= NULL
;
248 Return a Partition Descriptor given a Long Allocation Descriptor. This is
249 necessary to calculate the right extent (LongAd) offset which is added up
250 with partition's starting location.
252 @param[in] Volume Volume information pointer.
253 @param[in] LongAd Long Allocation Descriptor pointer.
255 @return A pointer to a Partition Descriptor.
258 UDF_PARTITION_DESCRIPTOR
*
260 IN UDF_VOLUME_INFO
*Volume
,
261 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
264 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
266 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
269 LogicalVolDesc
= Volume
->LogicalVolDescs
[UDF_DEFAULT_LV_NUM
];
271 switch (LV_UDF_REVISION (LogicalVolDesc
)) {
274 // As per UDF 1.02 specification:
276 // There shall be exactly one prevailing Logical Volume Descriptor recorded
277 // per Volume Set. The Partition Maps field shall contain only Type 1
280 PartitionNum
= *(UINT16
*)((UINTN
)&LogicalVolDesc
->PartitionMaps
[4]);
284 // Ensure Type 1 Partition map. Other types aren't supported in this
287 if (LogicalVolDesc
->PartitionMaps
[0] != 1 ||
288 LogicalVolDesc
->PartitionMaps
[1] != 6) {
291 PartitionNum
= *(UINT16
*)((UINTN
)&LogicalVolDesc
->PartitionMaps
[4]);
298 PartitionNum
= LongAd
->ExtentLocation
.PartitionReferenceNumber
;
302 for (Index
= 0; Index
< Volume
->PartitionDescsNo
; Index
++) {
303 PartitionDesc
= Volume
->PartitionDescs
[Index
];
304 if (PartitionDesc
->PartitionNumber
== PartitionNum
) {
305 return PartitionDesc
;
313 Return logical sector number of a given Long Allocation Descriptor.
315 @param[in] Volume Volume information pointer.
316 @param[in] LongAd Long Allocation Descriptor pointer.
318 @return The logical sector number of a given Long Allocation Descriptor.
323 IN UDF_VOLUME_INFO
*Volume
,
324 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
327 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
329 PartitionDesc
= GetPdFromLongAd (Volume
, LongAd
);
330 ASSERT (PartitionDesc
!= NULL
);
332 return (UINT64
)PartitionDesc
->PartitionStartingLocation
+
333 LongAd
->ExtentLocation
.LogicalBlockNumber
;
337 Return logical sector number of a given Short Allocation Descriptor.
339 @param[in] PartitionDesc Partition Descriptor pointer.
340 @param[in] ShortAd Short Allocation Descriptor pointer.
342 @return The logical sector number of a given Short Allocation Descriptor.
347 IN UDF_PARTITION_DESCRIPTOR
*PartitionDesc
,
348 IN UDF_SHORT_ALLOCATION_DESCRIPTOR
*ShortAd
351 ASSERT (PartitionDesc
!= NULL
);
353 return (UINT64
)PartitionDesc
->PartitionStartingLocation
+
354 ShortAd
->ExtentPosition
;
358 Find File Set Descriptor of a given Logical Volume Descriptor.
360 The found FSD will contain the extent (LogicalVolumeContentsUse) where our
363 @param[in] BlockIo BlockIo interface.
364 @param[in] DiskIo DiskIo interface.
365 @param[in] Volume Volume information pointer.
366 @param[in] LogicalVolDescNum Index of Logical Volume Descriptor
367 @param[out] FileSetDesc File Set Descriptor pointer.
369 @retval EFI_SUCCESS File Set Descriptor pointer found.
370 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
371 @retval other File Set Descriptor pointer not found.
375 FindFileSetDescriptor (
376 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
377 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
378 IN UDF_VOLUME_INFO
*Volume
,
379 IN UINTN LogicalVolDescNum
,
380 OUT UDF_FILE_SET_DESCRIPTOR
*FileSetDesc
385 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
387 LogicalVolDesc
= Volume
->LogicalVolDescs
[LogicalVolDescNum
];
388 Lsn
= GetLongAdLsn (Volume
, &LogicalVolDesc
->LogicalVolumeContentsUse
);
391 // Read extent (Long Ad).
393 Status
= DiskIo
->ReadDisk (
395 BlockIo
->Media
->MediaId
,
396 MultU64x32 (Lsn
, LogicalVolDesc
->LogicalBlockSize
),
397 sizeof (UDF_FILE_SET_DESCRIPTOR
),
400 if (EFI_ERROR (Status
)) {
405 // Check if the read extent contains a valid FSD's tag identifier.
407 if (!IS_FSD (FileSetDesc
)) {
408 return EFI_VOLUME_CORRUPTED
;
415 Get all File Set Descriptors for each Logical Volume Descriptor.
417 @param[in] BlockIo BlockIo interface.
418 @param[in] DiskIo DiskIo interface.
419 @param[in, out] Volume Volume information pointer.
421 @retval EFI_SUCCESS File Set Descriptors were got.
422 @retval EFI_OUT_OF_RESOURCES File Set Descriptors were not got due to lack
424 @retval other Error occured when finding File Set
425 Descriptor in Logical Volume Descriptor.
429 GetFileSetDescriptors (
430 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
431 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
432 IN OUT UDF_VOLUME_INFO
*Volume
437 UDF_FILE_SET_DESCRIPTOR
*FileSetDesc
;
440 Volume
->FileSetDescs
=
441 (UDF_FILE_SET_DESCRIPTOR
**)AllocateZeroPool (
442 Volume
->LogicalVolDescsNo
* sizeof (UDF_FILE_SET_DESCRIPTOR
));
443 if (Volume
->FileSetDescs
== NULL
) {
444 return EFI_OUT_OF_RESOURCES
;
447 for (Index
= 0; Index
< Volume
->LogicalVolDescsNo
; Index
++) {
448 FileSetDesc
= AllocateZeroPool (sizeof (UDF_FILE_SET_DESCRIPTOR
));
449 if (FileSetDesc
== NULL
) {
450 Status
= EFI_OUT_OF_RESOURCES
;
451 goto Error_Alloc_Fsd
;
455 // Find a FSD for this LVD.
457 Status
= FindFileSetDescriptor (
464 if (EFI_ERROR (Status
)) {
471 Volume
->FileSetDescs
[Index
] = FileSetDesc
;
474 Volume
->FileSetDescsNo
= Volume
->LogicalVolDescsNo
;
479 for (Index
= 0; Index
< Count
; Index
++) {
480 FreePool ((VOID
*)Volume
->FileSetDescs
[Index
]);
483 FreePool ((VOID
*)Volume
->FileSetDescs
);
484 Volume
->FileSetDescs
= NULL
;
491 Read Volume and File Structure on an UDF file system.
493 @param[in] BlockIo BlockIo interface.
494 @param[in] DiskIo DiskIo interface.
495 @param[out] Volume Volume information pointer.
497 @retval EFI_SUCCESS Volume and File Structure were read.
498 @retval other Volume and File Structure were not read.
502 ReadVolumeFileStructure (
503 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
504 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
505 OUT UDF_VOLUME_INFO
*Volume
509 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint
;
514 Status
= FindAnchorVolumeDescriptorPointer (
519 if (EFI_ERROR (Status
)) {
524 // AVDP has been found. Start MVDS.
526 Status
= StartMainVolumeDescriptorSequence (
532 if (EFI_ERROR (Status
)) {
540 Calculate length of a given File Identifier Descriptor.
542 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
544 @return The length of a given File Identifier Descriptor.
548 GetFidDescriptorLength (
549 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
553 (INTN
)((OFFSET_OF (UDF_FILE_IDENTIFIER_DESCRIPTOR
, Data
[0]) + 3 +
554 FileIdentifierDesc
->LengthOfFileIdentifier
+
555 FileIdentifierDesc
->LengthOfImplementationUse
) >> 2) << 2
560 Duplicate a given File Identifier Descriptor.
562 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
563 @param[out] NewFileIdentifierDesc The duplicated File Identifier Descriptor.
568 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
,
569 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR
**NewFileIdentifierDesc
572 *NewFileIdentifierDesc
=
573 (UDF_FILE_IDENTIFIER_DESCRIPTOR
*)AllocateCopyPool (
574 (UINTN
) GetFidDescriptorLength (FileIdentifierDesc
), FileIdentifierDesc
);
576 ASSERT (*NewFileIdentifierDesc
!= NULL
);
580 Duplicate either a given File Entry or a given Extended File Entry.
582 @param[in] BlockIo BlockIo interface.
583 @param[in] Volume Volume information pointer.
584 @param[in] FileEntry (Extended) File Entry pointer.
585 @param[out] NewFileEntry The duplicated (Extended) File Entry.
590 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
591 IN UDF_VOLUME_INFO
*Volume
,
593 OUT VOID
**NewFileEntry
596 *NewFileEntry
= AllocateCopyPool (Volume
->FileEntrySize
, FileEntry
);
598 ASSERT (*NewFileEntry
!= NULL
);
602 Get raw data + length of a given File Entry or Extended File Entry.
604 The file's recorded data can contain either real file content (inline) or
605 a sequence of extents (or Allocation Descriptors) which tells where file's
606 content is stored in.
608 NOTE: The FE/EFE can be thought it was an inode.
610 @param[in] FileEntryData (Extended) File Entry pointer.
611 @param[out] Data Buffer contains the raw data of a given
612 (Extended) File Entry.
613 @param[out] Length Length of the data in Buffer.
618 IN VOID
*FileEntryData
,
623 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
624 UDF_FILE_ENTRY
*FileEntry
;
626 if (IS_EFE (FileEntryData
)) {
627 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)FileEntryData
;
629 *Length
= ExtendedFileEntry
->InformationLength
;
630 *Data
= (VOID
*)((UINT8
*)ExtendedFileEntry
->Data
+
631 ExtendedFileEntry
->LengthOfExtendedAttributes
);
632 } else if (IS_FE (FileEntryData
)) {
633 FileEntry
= (UDF_FILE_ENTRY
*)FileEntryData
;
635 *Length
= FileEntry
->InformationLength
;
636 *Data
= (VOID
*)((UINT8
*)FileEntry
->Data
+
637 FileEntry
->LengthOfExtendedAttributes
);
642 Get Allocation Descriptors' data information from a given FE/EFE.
644 @param[in] FileEntryData (Extended) File Entry pointer.
645 @param[out] AdsData Buffer contains the Allocation Descriptors'
646 data from a given FE/EFE.
647 @param[out] Length Length of the data in AdsData.
652 IN VOID
*FileEntryData
,
657 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
658 UDF_FILE_ENTRY
*FileEntry
;
660 if (IS_EFE (FileEntryData
)) {
661 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)FileEntryData
;
663 *Length
= ExtendedFileEntry
->LengthOfAllocationDescriptors
;
664 *AdsData
= (VOID
*)((UINT8
*)ExtendedFileEntry
->Data
+
665 ExtendedFileEntry
->LengthOfExtendedAttributes
);
666 } else if (IS_FE (FileEntryData
)) {
667 FileEntry
= (UDF_FILE_ENTRY
*)FileEntryData
;
669 *Length
= FileEntry
->LengthOfAllocationDescriptors
;
670 *AdsData
= (VOID
*)((UINT8
*)FileEntry
->Data
+
671 FileEntry
->LengthOfExtendedAttributes
);
676 Read next Long Allocation Descriptor from a given file's data.
678 @param[in] Data File's data pointer.
679 @param[in,out] Offset Starting offset of the File's data to read.
680 @param[in] Length Length of the data to read.
681 @param[out] FoundLongAd Long Allocation Descriptor pointer.
683 @retval EFI_SUCCESS A Long Allocation Descriptor was found.
684 @retval EFI_DEVICE_ERROR No more Long Allocation Descriptors.
690 IN OUT UINT64
*Offset
,
692 OUT UDF_LONG_ALLOCATION_DESCRIPTOR
**FoundLongAd
695 UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
;
696 UDF_EXTENT_FLAGS ExtentFlags
;
699 if (*Offset
>= Length
) {
701 // No more Long Allocation Descriptors.
703 return EFI_DEVICE_ERROR
;
707 (UDF_LONG_ALLOCATION_DESCRIPTOR
*)((UINT8
*)Data
+ *Offset
);
710 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
711 // allocated AD, then return it.
713 ExtentFlags
= GET_EXTENT_FLAGS (LongAdsSequence
, LongAd
);
714 if (ExtentFlags
== ExtentIsNextExtent
||
715 ExtentFlags
== ExtentRecordedAndAllocated
) {
720 // This AD is either not recorded but allocated, or not recorded and not
721 // allocated. Skip it.
723 *Offset
+= AD_LENGTH (LongAdsSequence
);
726 *FoundLongAd
= LongAd
;
732 Read next Short Allocation Descriptor from a given file's data.
734 @param[in] Data File's data pointer.
735 @param[in,out] Offset Starting offset of the File's data to read.
736 @param[in] Length Length of the data to read.
737 @param[out] FoundShortAd Short Allocation Descriptor pointer.
739 @retval EFI_SUCCESS A Short Allocation Descriptor was found.
740 @retval EFI_DEVICE_ERROR No more Short Allocation Descriptors.
746 IN OUT UINT64
*Offset
,
748 OUT UDF_SHORT_ALLOCATION_DESCRIPTOR
**FoundShortAd
751 UDF_SHORT_ALLOCATION_DESCRIPTOR
*ShortAd
;
752 UDF_EXTENT_FLAGS ExtentFlags
;
755 if (*Offset
>= Length
) {
757 // No more Short Allocation Descriptors.
759 return EFI_DEVICE_ERROR
;
763 (UDF_SHORT_ALLOCATION_DESCRIPTOR
*)((UINT8
*)Data
+ *Offset
);
766 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
767 // allocated AD, then return it.
769 ExtentFlags
= GET_EXTENT_FLAGS (ShortAdsSequence
, ShortAd
);
770 if (ExtentFlags
== ExtentIsNextExtent
||
771 ExtentFlags
== ExtentRecordedAndAllocated
) {
776 // This AD is either not recorded but allocated, or not recorded and not
777 // allocated. Skip it.
779 *Offset
+= AD_LENGTH (ShortAdsSequence
);
782 *FoundShortAd
= ShortAd
;
788 Get either a Short Allocation Descriptor or a Long Allocation Descriptor from
791 @param[in] RecordingFlags Flag to indicate the type of descriptor.
792 @param[in] Data File's data pointer.
793 @param[in,out] Offset Starting offset of the File's data to read.
794 @param[in] Length Length of the data to read.
795 @param[out] FoundAd Allocation Descriptor pointer.
797 @retval EFI_SUCCESS A Short Allocation Descriptor was found.
798 @retval EFI_DEVICE_ERROR No more Allocation Descriptors.
799 Invalid type of descriptor was given.
803 GetAllocationDescriptor (
804 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
806 IN OUT UINT64
*Offset
,
811 if (RecordingFlags
== LongAdsSequence
) {
812 return GetLongAdFromAds (
816 (UDF_LONG_ALLOCATION_DESCRIPTOR
**)FoundAd
818 } else if (RecordingFlags
== ShortAdsSequence
) {
819 return GetShortAdFromAds (
823 (UDF_SHORT_ALLOCATION_DESCRIPTOR
**)FoundAd
827 return EFI_DEVICE_ERROR
;
831 Return logical sector number of either Short or Long Allocation Descriptor.
833 @param[in] RecordingFlags Flag to indicate the type of descriptor.
834 @param[in] Volume Volume information pointer.
835 @param[in] ParentIcb Long Allocation Descriptor pointer.
836 @param[in] Ad Allocation Descriptor pointer.
838 @return The logical sector number of the given Allocation Descriptor.
842 GetAllocationDescriptorLsn (
843 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
844 IN UDF_VOLUME_INFO
*Volume
,
845 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
849 if (RecordingFlags
== LongAdsSequence
) {
850 return GetLongAdLsn (Volume
, (UDF_LONG_ALLOCATION_DESCRIPTOR
*)Ad
);
851 } else if (RecordingFlags
== ShortAdsSequence
) {
852 return GetShortAdLsn (
853 GetPdFromLongAd (Volume
, ParentIcb
),
854 (UDF_SHORT_ALLOCATION_DESCRIPTOR
*)Ad
862 Return offset + length of a given indirect Allocation Descriptor (AED).
864 @param[in] BlockIo BlockIo interface.
865 @param[in] DiskIo DiskIo interface.
866 @param[in] Volume Volume information pointer.
867 @param[in] ParentIcb Long Allocation Descriptor pointer.
868 @param[in] RecordingFlags Flag to indicate the type of descriptor.
869 @param[in] Ad Allocation Descriptor pointer.
870 @param[out] Offset Offset of a given indirect Allocation
872 @param[out] Length Length of a given indirect Allocation
875 @retval EFI_SUCCESS The offset and length were returned.
876 @retval EFI_OUT_OF_RESOURCES The offset and length were not returned due
877 to lack of resources.
878 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
879 @retval other The offset and length were not returned.
884 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
885 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
886 IN UDF_VOLUME_INFO
*Volume
,
887 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
888 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
898 UINT32 LogicalBlockSize
;
899 UDF_ALLOCATION_EXTENT_DESCRIPTOR
*AllocExtDesc
;
901 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
902 Lsn
= GetAllocationDescriptorLsn (RecordingFlags
,
907 Data
= AllocatePool (ExtentLength
);
909 return EFI_OUT_OF_RESOURCES
;
912 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, UDF_DEFAULT_LV_NUM
);
917 Status
= DiskIo
->ReadDisk (
919 BlockIo
->Media
->MediaId
,
920 MultU64x32 (Lsn
, LogicalBlockSize
),
924 if (EFI_ERROR (Status
)) {
929 // Check if read extent contains a valid tag identifier for AED.
931 AllocExtDesc
= (UDF_ALLOCATION_EXTENT_DESCRIPTOR
*)Data
;
932 if (!IS_AED (AllocExtDesc
)) {
933 Status
= EFI_VOLUME_CORRUPTED
;
938 // Get AED's block offset and its length.
940 *Offset
= MultU64x32 (Lsn
, LogicalBlockSize
) +
941 sizeof (UDF_ALLOCATION_EXTENT_DESCRIPTOR
);
942 *Length
= AllocExtDesc
->LengthOfAllocationDescriptors
;
951 Read Allocation Extent Descriptor into memory.
953 @param[in] BlockIo BlockIo interface.
954 @param[in] DiskIo DiskIo interface.
955 @param[in] Volume Volume information pointer.
956 @param[in] ParentIcb Long Allocation Descriptor pointer.
957 @param[in] RecordingFlags Flag to indicate the type of descriptor.
958 @param[in] Ad Allocation Descriptor pointer.
959 @param[out] Data Buffer that contains the Allocation Extent
961 @param[out] Length Length of Data.
963 @retval EFI_SUCCESS The Allocation Extent Descriptor was read.
964 @retval EFI_OUT_OF_RESOURCES The Allocation Extent Descriptor was not read
965 due to lack of resources.
966 @retval other Fail to read the disk.
971 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
972 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
973 IN UDF_VOLUME_INFO
*Volume
,
974 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
975 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
985 // Get AED's offset + length.
987 Status
= GetAedAdsOffset (
997 if (EFI_ERROR (Status
)) {
1002 // Allocate buffer to read in AED's data.
1004 *Data
= AllocatePool ((UINTN
) (*Length
));
1005 if (*Data
== NULL
) {
1006 return EFI_OUT_OF_RESOURCES
;
1009 return DiskIo
->ReadDisk (
1011 BlockIo
->Media
->MediaId
,
1019 Function used to serialise reads of Allocation Descriptors.
1021 @param[in] RecordingFlags Flag to indicate the type of descriptor.
1022 @param[in] Ad Allocation Descriptor pointer.
1023 @param[in, out] Buffer Buffer to hold the next Allocation Descriptor.
1024 @param[in] Length Length of Buffer.
1026 @retval EFI_SUCCESS Buffer was grown to hold the next Allocation
1028 @retval EFI_OUT_OF_RESOURCES Buffer was not grown due to lack of resources.
1032 GrowUpBufferToNextAd (
1033 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
1035 IN OUT VOID
**Buffer
,
1039 UINT32 ExtentLength
;
1041 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
1043 if (*Buffer
== NULL
) {
1044 *Buffer
= AllocatePool (ExtentLength
);
1045 if (*Buffer
== NULL
) {
1046 return EFI_OUT_OF_RESOURCES
;
1049 *Buffer
= ReallocatePool ((UINTN
) Length
, (UINTN
) (Length
+ ExtentLength
), *Buffer
);
1050 if (*Buffer
== NULL
) {
1051 return EFI_OUT_OF_RESOURCES
;
1059 Read data or size of either a File Entry or an Extended File Entry.
1061 @param[in] BlockIo BlockIo interface.
1062 @param[in] DiskIo DiskIo interface.
1063 @param[in] Volume Volume information pointer.
1064 @param[in] ParentIcb Long Allocation Descriptor pointer.
1065 @param[in] FileEntryData FE/EFE structure pointer.
1066 @param[in, out] ReadFileInfo Read file information pointer.
1068 @retval EFI_SUCCESS Data or size of a FE/EFE was read.
1069 @retval EFI_OUT_OF_RESOURCES Data or size of a FE/EFE was not read due to
1071 @retval EFI_INVALID_PARAMETER The read file flag given in ReadFileInfo is
1073 @retval EFI_UNSUPPORTED The FE recording flag given in FileEntryData
1075 @retval other Data or size of a FE/EFE was not read.
1080 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1081 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1082 IN UDF_VOLUME_INFO
*Volume
,
1083 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
1084 IN VOID
*FileEntryData
,
1085 IN OUT UDF_READ_FILE_INFO
*ReadFileInfo
1089 UINT32 LogicalBlockSize
;
1096 UINT64 FilePosition
;
1101 BOOLEAN FinishedSeeking
;
1102 UINT32 ExtentLength
;
1103 UDF_FE_RECORDING_FLAGS RecordingFlags
;
1105 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, UDF_DEFAULT_LV_NUM
);
1109 // set BytesLeft to suppress incorrect compiler/analyzer warnings
1114 FinishedSeeking
= FALSE
;
1117 switch (ReadFileInfo
->Flags
) {
1118 case ReadFileGetFileSize
:
1119 case ReadFileAllocateAndRead
:
1121 // Initialise ReadFileInfo structure for either getting file size, or
1122 // reading file's recorded data.
1124 ReadFileInfo
->ReadLength
= 0;
1125 ReadFileInfo
->FileData
= NULL
;
1127 case ReadFileSeekAndRead
:
1129 // About to seek a file and/or read its data.
1131 Length
= ReadFileInfo
->FileSize
- ReadFileInfo
->FilePosition
;
1132 if (ReadFileInfo
->FileDataSize
> Length
) {
1134 // About to read beyond the EOF -- truncate it.
1136 ReadFileInfo
->FileDataSize
= Length
;
1140 // Initialise data to start seeking and/or reading a file.
1142 BytesLeft
= ReadFileInfo
->FileDataSize
;
1145 FinishedSeeking
= FALSE
;
1150 RecordingFlags
= GET_FE_RECORDING_FLAGS (FileEntryData
);
1151 switch (RecordingFlags
) {
1154 // There are no extents for this FE/EFE. All data is inline.
1156 GetFileEntryData (FileEntryData
, &Data
, &Length
);
1158 if (ReadFileInfo
->Flags
== ReadFileGetFileSize
) {
1159 ReadFileInfo
->ReadLength
= Length
;
1160 } else if (ReadFileInfo
->Flags
== ReadFileAllocateAndRead
) {
1162 // Allocate buffer for starting read data.
1164 ReadFileInfo
->FileData
= AllocatePool ((UINTN
) Length
);
1165 if (ReadFileInfo
->FileData
== NULL
) {
1166 return EFI_OUT_OF_RESOURCES
;
1170 // Read all inline data into ReadFileInfo->FileData
1172 CopyMem (ReadFileInfo
->FileData
, Data
, (UINTN
) Length
);
1173 ReadFileInfo
->ReadLength
= Length
;
1174 } else if (ReadFileInfo
->Flags
== ReadFileSeekAndRead
) {
1176 // If FilePosition is non-zero, seek file to FilePosition, read
1177 // FileDataSize bytes and then updates FilePosition.
1180 ReadFileInfo
->FileData
,
1181 (VOID
*)((UINT8
*)Data
+ ReadFileInfo
->FilePosition
),
1182 (UINTN
) ReadFileInfo
->FileDataSize
1185 ReadFileInfo
->FilePosition
+= ReadFileInfo
->FileDataSize
;
1188 return EFI_INVALID_PARAMETER
;
1191 Status
= EFI_SUCCESS
;
1194 case LongAdsSequence
:
1195 case ShortAdsSequence
:
1197 // This FE/EFE contains a run of Allocation Descriptors. Get data + size
1198 // for start reading them out.
1200 GetAdsInformation (FileEntryData
, &Data
, &Length
);
1207 Status
= GetAllocationDescriptor (
1214 if (Status
== EFI_DEVICE_ERROR
) {
1215 Status
= EFI_SUCCESS
;
1220 // Check if AD is an indirect AD. If so, read Allocation Extent
1221 // Descriptor and its extents (ADs).
1223 if (GET_EXTENT_FLAGS (RecordingFlags
, Ad
) == ExtentIsNextExtent
) {
1230 Status
= GetAedAdsData (
1240 if (EFI_ERROR (Status
)) {
1243 ASSERT (Data
!= NULL
);
1249 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
1251 Lsn
= GetAllocationDescriptorLsn (RecordingFlags
,
1256 switch (ReadFileInfo
->Flags
) {
1257 case ReadFileGetFileSize
:
1258 ReadFileInfo
->ReadLength
+= ExtentLength
;
1260 case ReadFileAllocateAndRead
:
1262 // Increase FileData (if necessary) to read next extent.
1264 Status
= GrowUpBufferToNextAd (
1267 &ReadFileInfo
->FileData
,
1268 ReadFileInfo
->ReadLength
1270 if (EFI_ERROR (Status
)) {
1271 goto Error_Alloc_Buffer_To_Next_Ad
;
1275 // Read extent's data into FileData.
1277 Status
= DiskIo
->ReadDisk (
1279 BlockIo
->Media
->MediaId
,
1280 MultU64x32 (Lsn
, LogicalBlockSize
),
1282 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1283 ReadFileInfo
->ReadLength
)
1285 if (EFI_ERROR (Status
)) {
1286 goto Error_Read_Disk_Blk
;
1289 ReadFileInfo
->ReadLength
+= ExtentLength
;
1291 case ReadFileSeekAndRead
:
1293 // Seek file first before reading in its data.
1295 if (FinishedSeeking
) {
1297 goto Skip_File_Seek
;
1300 if (FilePosition
+ ExtentLength
< ReadFileInfo
->FilePosition
) {
1301 FilePosition
+= ExtentLength
;
1305 if (FilePosition
+ ExtentLength
> ReadFileInfo
->FilePosition
) {
1306 Offset
= ReadFileInfo
->FilePosition
- FilePosition
;
1312 // Done with seeking file. Start reading its data.
1314 FinishedSeeking
= TRUE
;
1318 // Make sure we don't read more data than really wanted.
1320 if (ExtentLength
- Offset
> BytesLeft
) {
1321 DataLength
= BytesLeft
;
1323 DataLength
= ExtentLength
- Offset
;
1327 // Read extent's data into FileData.
1329 Status
= DiskIo
->ReadDisk (
1331 BlockIo
->Media
->MediaId
,
1332 Offset
+ MultU64x32 (Lsn
, LogicalBlockSize
),
1334 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1337 if (EFI_ERROR (Status
)) {
1338 goto Error_Read_Disk_Blk
;
1342 // Update current file's position.
1344 DataOffset
+= DataLength
;
1345 ReadFileInfo
->FilePosition
+= DataLength
;
1347 BytesLeft
-= DataLength
;
1348 if (BytesLeft
== 0) {
1350 // There is no more file data to read.
1352 Status
= EFI_SUCCESS
;
1361 // Point to the next AD (extent).
1363 AdOffset
+= AD_LENGTH (RecordingFlags
);
1367 case ExtendedAdsSequence
:
1368 // FIXME: Not supported. Got no volume with it, yet.
1370 Status
= EFI_UNSUPPORTED
;
1375 // A flag value reserved by the ECMA-167 standard (3rd Edition - June
1376 // 1997); 14.6 ICB Tag; 14.6.8 Flags (RBP 18); was found.
1378 Status
= EFI_UNSUPPORTED
;
1389 Error_Read_Disk_Blk
:
1390 Error_Alloc_Buffer_To_Next_Ad
:
1391 if (ReadFileInfo
->Flags
!= ReadFileSeekAndRead
) {
1392 FreePool (ReadFileInfo
->FileData
);
1404 Find a file by its filename from a given Parent file.
1406 @param[in] BlockIo BlockIo interface.
1407 @param[in] DiskIo DiskIo interface.
1408 @param[in] Volume Volume information pointer.
1409 @param[in] FileName File name string.
1410 @param[in] Parent Parent directory file.
1411 @param[in] Icb Long Allocation Descriptor pointer.
1412 @param[out] File Found file.
1414 @retval EFI_SUCCESS The file was found.
1415 @retval EFI_INVALID_PARAMETER One or more input parameters are invalid.
1416 @retval EFI_NOT_FOUND The file was not found.
1421 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1422 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1423 IN UDF_VOLUME_INFO
*Volume
,
1424 IN CHAR16
*FileName
,
1425 IN UDF_FILE_INFO
*Parent
,
1426 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1427 OUT UDF_FILE_INFO
*File
1431 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1432 UDF_READ_DIRECTORY_INFO ReadDirInfo
;
1434 CHAR16 FoundFileName
[UDF_FILENAME_LENGTH
];
1435 VOID
*CompareFileEntry
;
1438 // Check if both Parent->FileIdentifierDesc and Icb are NULL.
1440 if ((Parent
->FileIdentifierDesc
== NULL
) && (Icb
== NULL
)) {
1441 return EFI_INVALID_PARAMETER
;
1445 // Check if parent file is really directory.
1447 if (!IS_FE_DIRECTORY (Parent
->FileEntry
)) {
1448 return EFI_NOT_FOUND
;
1452 // If FileName is current file or working directory, just duplicate Parent's
1453 // FE/EFE and FID descriptors.
1455 if (StrCmp (FileName
, L
".") == 0) {
1456 if (Parent
->FileIdentifierDesc
== NULL
) {
1457 return EFI_INVALID_PARAMETER
;
1460 DuplicateFe (BlockIo
, Volume
, Parent
->FileEntry
, &File
->FileEntry
);
1461 DuplicateFid (Parent
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1467 // Start directory listing.
1469 ZeroMem ((VOID
*)&ReadDirInfo
, sizeof (UDF_READ_DIRECTORY_INFO
));
1473 Status
= ReadDirectoryEntry (
1477 (Parent
->FileIdentifierDesc
!= NULL
) ?
1478 &Parent
->FileIdentifierDesc
->Icb
:
1484 if (EFI_ERROR (Status
)) {
1485 if (Status
== EFI_DEVICE_ERROR
) {
1486 Status
= EFI_NOT_FOUND
;
1492 if (IS_FID_PARENT_FILE (FileIdentifierDesc
)) {
1494 // This FID contains the location (FE/EFE) of the parent directory of this
1495 // directory (Parent), and if FileName is either ".." or "\\", then it's
1496 // the expected FID.
1498 if (StrCmp (FileName
, L
"..") == 0 || StrCmp (FileName
, L
"\\") == 0) {
1503 Status
= GetFileNameFromFid (FileIdentifierDesc
, FoundFileName
);
1504 if (EFI_ERROR (Status
)) {
1508 if (StrCmp (FileName
, FoundFileName
) == 0) {
1510 // FID has been found. Prepare to find its respective FE/EFE.
1517 FreePool ((VOID
*)FileIdentifierDesc
);
1520 if (ReadDirInfo
.DirectoryData
!= NULL
) {
1522 // Free all allocated resources for the directory listing.
1524 FreePool (ReadDirInfo
.DirectoryData
);
1528 Status
= EFI_SUCCESS
;
1530 File
->FileIdentifierDesc
= FileIdentifierDesc
;
1533 // If the requested file is root directory, then the FE/EFE was already
1534 // retrieved in UdfOpenVolume() function, thus no need to find it again.
1536 // Otherwise, find FE/EFE from the respective FID.
1538 if (StrCmp (FileName
, L
"\\") != 0) {
1539 Status
= FindFileEntry (
1543 &FileIdentifierDesc
->Icb
,
1546 if (EFI_ERROR (Status
)) {
1551 // Make sure that both Parent's FE/EFE and found FE/EFE are not equal.
1553 if (CompareMem ((VOID
*)Parent
->FileEntry
, (VOID
*)CompareFileEntry
,
1554 Volume
->FileEntrySize
) != 0) {
1555 File
->FileEntry
= CompareFileEntry
;
1557 FreePool ((VOID
*)FileIdentifierDesc
);
1558 FreePool ((VOID
*)CompareFileEntry
);
1559 Status
= EFI_NOT_FOUND
;
1567 FreePool ((VOID
*)FileIdentifierDesc
);
1573 Read volume information on a medium which contains a valid UDF file system.
1575 @param[in] BlockIo BlockIo interface.
1576 @param[in] DiskIo DiskIo interface.
1577 @param[out] Volume UDF volume information structure.
1579 @retval EFI_SUCCESS Volume information read.
1580 @retval EFI_NO_MEDIA The device has no media.
1581 @retval EFI_DEVICE_ERROR The device reported an error.
1582 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1583 @retval EFI_OUT_OF_RESOURCES The volume was not read due to lack of resources.
1587 ReadUdfVolumeInformation (
1588 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1589 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1590 OUT UDF_VOLUME_INFO
*Volume
1595 Status
= ReadVolumeFileStructure (
1600 if (EFI_ERROR (Status
)) {
1604 Status
= GetFileSetDescriptors (
1609 if (EFI_ERROR (Status
)) {
1610 CleanupVolumeInformation (Volume
);
1617 Find the root directory on an UDF volume.
1619 @param[in] BlockIo BlockIo interface.
1620 @param[in] DiskIo DiskIo interface.
1621 @param[in] Volume UDF volume information structure.
1622 @param[out] File Root directory file.
1624 @retval EFI_SUCCESS Root directory found.
1625 @retval EFI_NO_MEDIA The device has no media.
1626 @retval EFI_DEVICE_ERROR The device reported an error.
1627 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1628 @retval EFI_OUT_OF_RESOURCES The root directory was not found due to lack of
1634 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1635 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1636 IN UDF_VOLUME_INFO
*Volume
,
1637 OUT UDF_FILE_INFO
*File
1641 UDF_FILE_INFO Parent
;
1643 Status
= FindFileEntry (
1647 &Volume
->FileSetDescs
[0]->RootDirectoryIcb
,
1650 if (EFI_ERROR (Status
)) {
1654 Parent
.FileEntry
= File
->FileEntry
;
1655 Parent
.FileIdentifierDesc
= NULL
;
1664 &Volume
->FileSetDescs
[0]->RootDirectoryIcb
,
1667 if (EFI_ERROR (Status
)) {
1668 FreePool (File
->FileEntry
);
1675 Find either a File Entry or a Extended File Entry from a given ICB.
1677 @param[in] BlockIo BlockIo interface.
1678 @param[in] DiskIo DiskIo interface.
1679 @param[in] Volume UDF volume information structure.
1680 @param[in] Icb ICB of the FID.
1681 @param[out] FileEntry File Entry or Extended File Entry.
1683 @retval EFI_SUCCESS File Entry or Extended File Entry found.
1684 @retval EFI_NO_MEDIA The device has no media.
1685 @retval EFI_DEVICE_ERROR The device reported an error.
1686 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1687 @retval EFI_OUT_OF_RESOURCES The FE/EFE entry was not found due to lack of
1693 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1694 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1695 IN UDF_VOLUME_INFO
*Volume
,
1696 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1697 OUT VOID
**FileEntry
1702 UINT32 LogicalBlockSize
;
1704 Lsn
= GetLongAdLsn (Volume
, Icb
);
1705 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, UDF_DEFAULT_LV_NUM
);
1707 *FileEntry
= AllocateZeroPool (Volume
->FileEntrySize
);
1708 if (*FileEntry
== NULL
) {
1709 return EFI_OUT_OF_RESOURCES
;
1715 Status
= DiskIo
->ReadDisk (
1717 BlockIo
->Media
->MediaId
,
1718 MultU64x32 (Lsn
, LogicalBlockSize
),
1719 Volume
->FileEntrySize
,
1722 if (EFI_ERROR (Status
)) {
1723 goto Error_Read_Disk_Blk
;
1727 // Check if the read extent contains a valid Tag Identifier for the expected
1730 if (!IS_FE (*FileEntry
) && !IS_EFE (*FileEntry
)) {
1731 Status
= EFI_VOLUME_CORRUPTED
;
1732 goto Error_Invalid_Fe
;
1738 Error_Read_Disk_Blk
:
1739 FreePool (*FileEntry
);
1745 Find a file given its absolute path on an UDF volume.
1747 @param[in] BlockIo BlockIo interface.
1748 @param[in] DiskIo DiskIo interface.
1749 @param[in] Volume UDF volume information structure.
1750 @param[in] FilePath File's absolute path.
1751 @param[in] Root Root directory file.
1752 @param[in] Parent Parent directory file.
1753 @param[in] Icb ICB of Parent.
1754 @param[out] File Found file.
1756 @retval EFI_SUCCESS FilePath was found.
1757 @retval EFI_NO_MEDIA The device has no media.
1758 @retval EFI_DEVICE_ERROR The device reported an error.
1759 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1760 @retval EFI_OUT_OF_RESOURCES The FilePath file was not found due to lack of
1766 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1767 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1768 IN UDF_VOLUME_INFO
*Volume
,
1769 IN CHAR16
*FilePath
,
1770 IN UDF_FILE_INFO
*Root
,
1771 IN UDF_FILE_INFO
*Parent
,
1772 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1773 OUT UDF_FILE_INFO
*File
1777 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
1778 CHAR16
*FileNamePointer
;
1779 UDF_FILE_INFO PreviousFile
;
1782 Status
= EFI_NOT_FOUND
;
1784 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
1785 while (*FilePath
!= L
'\0') {
1786 FileNamePointer
= FileName
;
1787 while (*FilePath
!= L
'\0' && *FilePath
!= L
'\\') {
1788 *FileNamePointer
++ = *FilePath
++;
1791 *FileNamePointer
= L
'\0';
1792 if (FileName
[0] == L
'\0') {
1794 // Open root directory.
1798 // There is no file found for the root directory yet. So, find only its
1801 // See UdfOpenVolume() function.
1803 Status
= InternalFindFile (BlockIo
,
1812 // We've already a file pointer (Root) for the root directory. Duplicate
1813 // its FE/EFE and FID descriptors.
1815 DuplicateFe (BlockIo
, Volume
, Root
->FileEntry
, &File
->FileEntry
);
1816 DuplicateFid (Root
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1817 Status
= EFI_SUCCESS
;
1821 // No root directory. Find filename from the current directory.
1823 Status
= InternalFindFile (BlockIo
,
1832 if (EFI_ERROR (Status
)) {
1837 // If the found file is a symlink, then find its respective FE/EFE and
1840 if (IS_FE_SYMLINK (File
->FileEntry
)) {
1841 FreePool ((VOID
*)File
->FileIdentifierDesc
);
1843 FileEntry
= File
->FileEntry
;
1845 Status
= ResolveSymlink (BlockIo
,
1852 FreePool (FileEntry
);
1854 if (EFI_ERROR (Status
)) {
1859 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
1860 sizeof (UDF_FILE_INFO
)) != 0) {
1861 CleanupFileInformation (&PreviousFile
);
1864 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
1865 if (*FilePath
!= L
'\0' && *FilePath
== L
'\\') {
1874 Read a directory entry at a time on an UDF volume.
1876 @param[in] BlockIo BlockIo interface.
1877 @param[in] DiskIo DiskIo interface.
1878 @param[in] Volume UDF volume information structure.
1879 @param[in] ParentIcb ICB of the parent file.
1880 @param[in] FileEntryData FE/EFE of the parent file.
1881 @param[in, out] ReadDirInfo Next read directory listing structure
1883 @param[out] FoundFid File Identifier Descriptor pointer.
1885 @retval EFI_SUCCESS Directory entry read.
1886 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
1887 @retval EFI_NO_MEDIA The device has no media.
1888 @retval EFI_DEVICE_ERROR The device reported an error.
1889 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1890 @retval EFI_OUT_OF_RESOURCES The directory entry was not read due to lack of
1895 ReadDirectoryEntry (
1896 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1897 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1898 IN UDF_VOLUME_INFO
*Volume
,
1899 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
1900 IN VOID
*FileEntryData
,
1901 IN OUT UDF_READ_DIRECTORY_INFO
*ReadDirInfo
,
1902 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR
**FoundFid
1906 UDF_READ_FILE_INFO ReadFileInfo
;
1907 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1909 if (ReadDirInfo
->DirectoryData
== NULL
) {
1911 // The directory's recorded data has not been read yet. So let's cache it
1912 // into memory and the next calls won't need to read it again.
1914 ReadFileInfo
.Flags
= ReadFileAllocateAndRead
;
1924 if (EFI_ERROR (Status
)) {
1929 // Fill in ReadDirInfo structure with the read directory's data information.
1931 ReadDirInfo
->DirectoryData
= ReadFileInfo
.FileData
;
1932 ReadDirInfo
->DirectoryLength
= ReadFileInfo
.ReadLength
;
1936 if (ReadDirInfo
->FidOffset
>= ReadDirInfo
->DirectoryLength
) {
1938 // There are no longer FIDs for this directory. By returning
1939 // EFI_DEVICE_ERROR to the callee will indicate end of directory
1942 return EFI_DEVICE_ERROR
;
1946 // Get FID for this entry.
1948 FileIdentifierDesc
= GET_FID_FROM_ADS (ReadDirInfo
->DirectoryData
,
1949 ReadDirInfo
->FidOffset
);
1951 // Update FidOffset to point to next FID.
1953 ReadDirInfo
->FidOffset
+= GetFidDescriptorLength (FileIdentifierDesc
);
1954 } while (IS_FID_DELETED_FILE (FileIdentifierDesc
));
1956 DuplicateFid (FileIdentifierDesc
, FoundFid
);
1962 Get a filename (encoded in OSTA-compressed format) from a File Identifier
1963 Descriptor on an UDF volume.
1965 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
1966 @param[out] FileName Decoded filename.
1968 @retval EFI_SUCCESS Filename decoded and read.
1969 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1972 GetFileNameFromFid (
1973 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
,
1974 OUT CHAR16
*FileName
1977 UINT8
*OstaCompressed
;
1978 UINT8 CompressionId
;
1984 (UINT8
*)FileIdentifierDesc
->Data
+
1985 FileIdentifierDesc
->LengthOfImplementationUse
1988 CompressionId
= OstaCompressed
[0];
1989 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
1990 return EFI_VOLUME_CORRUPTED
;
1996 Length
= FileIdentifierDesc
->LengthOfFileIdentifier
;
1997 for (Index
= 1; Index
< Length
; Index
++) {
1998 if (CompressionId
== 16) {
1999 *FileName
= OstaCompressed
[Index
++] << 8;
2004 if (Index
< Length
) {
2005 *FileName
|= (CHAR16
)(OstaCompressed
[Index
]);
2017 Resolve a symlink file on an UDF volume.
2019 @param[in] BlockIo BlockIo interface.
2020 @param[in] DiskIo DiskIo interface.
2021 @param[in] Volume UDF volume information structure.
2022 @param[in] Parent Parent file.
2023 @param[in] FileEntryData FE/EFE structure pointer.
2024 @param[out] File Resolved file.
2026 @retval EFI_SUCCESS Symlink file resolved.
2027 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2028 @retval EFI_NO_MEDIA The device has no media.
2029 @retval EFI_DEVICE_ERROR The device reported an error.
2030 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2031 @retval EFI_OUT_OF_RESOURCES The symlink file was not resolved due to lack of
2037 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2038 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2039 IN UDF_VOLUME_INFO
*Volume
,
2040 IN UDF_FILE_INFO
*Parent
,
2041 IN VOID
*FileEntryData
,
2042 OUT UDF_FILE_INFO
*File
2046 UDF_READ_FILE_INFO ReadFileInfo
;
2050 UDF_PATH_COMPONENT
*PathComp
;
2051 UINT8 PathCompLength
;
2052 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
2055 UINT8 CompressionId
;
2056 UDF_FILE_INFO PreviousFile
;
2059 // Symlink files on UDF volumes do not contain so much data other than
2060 // Path Components which resolves to real filenames, so it's OK to read in
2061 // all its data here -- usually the data will be inline with the FE/EFE for
2064 ReadFileInfo
.Flags
= ReadFileAllocateAndRead
;
2070 &Parent
->FileIdentifierDesc
->Icb
,
2074 if (EFI_ERROR (Status
)) {
2078 Length
= ReadFileInfo
.ReadLength
;
2080 Data
= (UINT8
*)ReadFileInfo
.FileData
;
2081 EndData
= Data
+ Length
;
2083 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
2086 PathComp
= (UDF_PATH_COMPONENT
*)Data
;
2088 PathCompLength
= PathComp
->LengthOfComponentIdentifier
;
2090 switch (PathComp
->ComponentType
) {
2093 // This Path Component specifies the root directory hierarchy subject to
2094 // agreement between the originator and recipient of the medium. Skip it.
2100 // "\\." of the current directory. Read next Path Component.
2102 goto Next_Path_Component
;
2105 // ".." (parent directory). Go to it.
2107 CopyMem ((VOID
*)FileName
, L
"..", 6);
2111 // "." (current file). Duplicate both FE/EFE and FID of this file.
2113 DuplicateFe (BlockIo
, Volume
, PreviousFile
.FileEntry
, &File
->FileEntry
);
2114 DuplicateFid (PreviousFile
.FileIdentifierDesc
,
2115 &File
->FileIdentifierDesc
);
2116 goto Next_Path_Component
;
2119 // This Path Component identifies an object, either a file or a
2120 // directory or an alias.
2122 // Decode it from the compressed data in ComponentIdentifier and find
2125 CompressionId
= PathComp
->ComponentIdentifier
[0];
2126 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
2127 return EFI_VOLUME_CORRUPTED
;
2131 for (Index
= 1; Index
< PathCompLength
; Index
++) {
2132 if (CompressionId
== 16) {
2133 *Char
= *(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+
2140 if (Index
< Length
) {
2141 *Char
|= (CHAR16
)(*(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+ Index
));
2152 // Find file from the read filename in symlink's file data.
2154 Status
= InternalFindFile (
2163 if (EFI_ERROR (Status
)) {
2164 goto Error_Find_File
;
2167 Next_Path_Component
:
2168 Data
+= sizeof (UDF_PATH_COMPONENT
) + PathCompLength
;
2169 if (Data
>= EndData
) {
2173 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2174 sizeof (UDF_FILE_INFO
)) != 0) {
2175 CleanupFileInformation (&PreviousFile
);
2178 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
2182 // Unmap the symlink file.
2184 FreePool (ReadFileInfo
.FileData
);
2189 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2190 sizeof (UDF_FILE_INFO
)) != 0) {
2191 CleanupFileInformation (&PreviousFile
);
2194 FreePool (ReadFileInfo
.FileData
);
2200 Clean up in-memory UDF volume information.
2202 @param[in] Volume Volume information pointer.
2206 CleanupVolumeInformation (
2207 IN UDF_VOLUME_INFO
*Volume
2212 if (Volume
->LogicalVolDescs
!= NULL
) {
2213 for (Index
= 0; Index
< Volume
->LogicalVolDescsNo
; Index
++) {
2214 FreePool ((VOID
*)Volume
->LogicalVolDescs
[Index
]);
2216 FreePool ((VOID
*)Volume
->LogicalVolDescs
);
2219 if (Volume
->PartitionDescs
!= NULL
) {
2220 for (Index
= 0; Index
< Volume
->PartitionDescsNo
; Index
++) {
2221 FreePool ((VOID
*)Volume
->PartitionDescs
[Index
]);
2223 FreePool ((VOID
*)Volume
->PartitionDescs
);
2226 if (Volume
->FileSetDescs
!= NULL
) {
2227 for (Index
= 0; Index
< Volume
->FileSetDescsNo
; Index
++) {
2228 FreePool ((VOID
*)Volume
->FileSetDescs
[Index
]);
2230 FreePool ((VOID
*)Volume
->FileSetDescs
);
2233 ZeroMem ((VOID
*)Volume
, sizeof (UDF_VOLUME_INFO
));
2237 Clean up in-memory UDF file information.
2239 @param[in] File File information pointer.
2243 CleanupFileInformation (
2244 IN UDF_FILE_INFO
*File
2247 if (File
->FileEntry
!= NULL
) {
2248 FreePool (File
->FileEntry
);
2250 if (File
->FileIdentifierDesc
!= NULL
) {
2251 FreePool ((VOID
*)File
->FileIdentifierDesc
);
2254 ZeroMem ((VOID
*)File
, sizeof (UDF_FILE_INFO
));
2258 Find a file from its absolute path on an UDF volume.
2260 @param[in] BlockIo BlockIo interface.
2261 @param[in] DiskIo DiskIo interface.
2262 @param[in] Volume UDF volume information structure.
2263 @param[in] File File information structure.
2264 @param[out] Size Size of the file.
2266 @retval EFI_SUCCESS File size calculated and set in Size.
2267 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2268 @retval EFI_NO_MEDIA The device has no media.
2269 @retval EFI_DEVICE_ERROR The device reported an error.
2270 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2271 @retval EFI_OUT_OF_RESOURCES The file size was not calculated due to lack of
2277 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2278 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2279 IN UDF_VOLUME_INFO
*Volume
,
2280 IN UDF_FILE_INFO
*File
,
2285 UDF_READ_FILE_INFO ReadFileInfo
;
2287 ReadFileInfo
.Flags
= ReadFileGetFileSize
;
2293 &File
->FileIdentifierDesc
->Icb
,
2297 if (EFI_ERROR (Status
)) {
2301 *Size
= ReadFileInfo
.ReadLength
;
2307 Set information about a file on an UDF volume.
2309 @param[in] File File pointer.
2310 @param[in] FileSize Size of the file.
2311 @param[in] FileName Filename of the file.
2312 @param[in, out] BufferSize Size of the returned file infomation.
2313 @param[out] Buffer Data of the returned file information.
2315 @retval EFI_SUCCESS File information set.
2316 @retval EFI_NO_MEDIA The device has no media.
2317 @retval EFI_DEVICE_ERROR The device reported an error.
2318 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2319 @retval EFI_OUT_OF_RESOURCES The file information was not set due to lack of
2325 IN UDF_FILE_INFO
*File
,
2327 IN CHAR16
*FileName
,
2328 IN OUT UINTN
*BufferSize
,
2332 UINTN FileInfoLength
;
2333 EFI_FILE_INFO
*FileInfo
;
2334 UDF_FILE_ENTRY
*FileEntry
;
2335 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
2338 // Calculate the needed size for the EFI_FILE_INFO structure.
2340 FileInfoLength
= sizeof (EFI_FILE_INFO
) + ((FileName
!= NULL
) ?
2341 StrSize (FileName
) :
2343 if (*BufferSize
< FileInfoLength
) {
2345 // The given Buffer has no size enough for EFI_FILE_INFO structure.
2347 *BufferSize
= FileInfoLength
;
2348 return EFI_BUFFER_TOO_SMALL
;
2352 // Buffer now contains room enough to store EFI_FILE_INFO structure.
2353 // Now, fill it in with all necessary information about the file.
2355 FileInfo
= (EFI_FILE_INFO
*)Buffer
;
2356 FileInfo
->Size
= FileInfoLength
;
2357 FileInfo
->Attribute
&= ~EFI_FILE_VALID_ATTR
;
2358 FileInfo
->Attribute
|= EFI_FILE_READ_ONLY
;
2360 if (IS_FID_DIRECTORY_FILE (File
->FileIdentifierDesc
)) {
2361 FileInfo
->Attribute
|= EFI_FILE_DIRECTORY
;
2362 } else if (IS_FID_NORMAL_FILE (File
->FileIdentifierDesc
)) {
2363 FileInfo
->Attribute
|= EFI_FILE_ARCHIVE
;
2366 if (IS_FID_HIDDEN_FILE (File
->FileIdentifierDesc
)) {
2367 FileInfo
->Attribute
|= EFI_FILE_HIDDEN
;
2370 if (IS_FE (File
->FileEntry
)) {
2371 FileEntry
= (UDF_FILE_ENTRY
*)File
->FileEntry
;
2374 // Check if FE has the system attribute set.
2376 if (FileEntry
->IcbTag
.Flags
& (1 << 10)) {
2377 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2380 FileInfo
->FileSize
= FileSize
;
2381 FileInfo
->PhysicalSize
= FileSize
;
2383 FileInfo
->CreateTime
.Year
= FileEntry
->AccessTime
.Year
;
2384 FileInfo
->CreateTime
.Month
= FileEntry
->AccessTime
.Month
;
2385 FileInfo
->CreateTime
.Day
= FileEntry
->AccessTime
.Day
;
2386 FileInfo
->CreateTime
.Hour
= FileEntry
->AccessTime
.Hour
;
2387 FileInfo
->CreateTime
.Minute
= FileEntry
->AccessTime
.Second
;
2388 FileInfo
->CreateTime
.Second
= FileEntry
->AccessTime
.Second
;
2389 FileInfo
->CreateTime
.Nanosecond
=
2390 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2392 FileInfo
->LastAccessTime
.Year
=
2393 FileEntry
->AccessTime
.Year
;
2394 FileInfo
->LastAccessTime
.Month
=
2395 FileEntry
->AccessTime
.Month
;
2396 FileInfo
->LastAccessTime
.Day
=
2397 FileEntry
->AccessTime
.Day
;
2398 FileInfo
->LastAccessTime
.Hour
=
2399 FileEntry
->AccessTime
.Hour
;
2400 FileInfo
->LastAccessTime
.Minute
=
2401 FileEntry
->AccessTime
.Minute
;
2402 FileInfo
->LastAccessTime
.Second
=
2403 FileEntry
->AccessTime
.Second
;
2404 FileInfo
->LastAccessTime
.Nanosecond
=
2405 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2406 } else if (IS_EFE (File
->FileEntry
)) {
2407 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)File
->FileEntry
;
2410 // Check if EFE has the system attribute set.
2412 if (ExtendedFileEntry
->IcbTag
.Flags
& (1 << 10)) {
2413 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2416 FileInfo
->FileSize
= FileSize
;
2417 FileInfo
->PhysicalSize
= FileSize
;
2419 FileInfo
->CreateTime
.Year
= ExtendedFileEntry
->CreationTime
.Year
;
2420 FileInfo
->CreateTime
.Month
= ExtendedFileEntry
->CreationTime
.Month
;
2421 FileInfo
->CreateTime
.Day
= ExtendedFileEntry
->CreationTime
.Day
;
2422 FileInfo
->CreateTime
.Hour
= ExtendedFileEntry
->CreationTime
.Hour
;
2423 FileInfo
->CreateTime
.Minute
= ExtendedFileEntry
->CreationTime
.Second
;
2424 FileInfo
->CreateTime
.Second
= ExtendedFileEntry
->CreationTime
.Second
;
2425 FileInfo
->CreateTime
.Nanosecond
=
2426 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2428 FileInfo
->LastAccessTime
.Year
=
2429 ExtendedFileEntry
->AccessTime
.Year
;
2430 FileInfo
->LastAccessTime
.Month
=
2431 ExtendedFileEntry
->AccessTime
.Month
;
2432 FileInfo
->LastAccessTime
.Day
=
2433 ExtendedFileEntry
->AccessTime
.Day
;
2434 FileInfo
->LastAccessTime
.Hour
=
2435 ExtendedFileEntry
->AccessTime
.Hour
;
2436 FileInfo
->LastAccessTime
.Minute
=
2437 ExtendedFileEntry
->AccessTime
.Minute
;
2438 FileInfo
->LastAccessTime
.Second
=
2439 ExtendedFileEntry
->AccessTime
.Second
;
2440 FileInfo
->LastAccessTime
.Nanosecond
=
2441 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2444 FileInfo
->CreateTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2445 FileInfo
->CreateTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2446 FileInfo
->LastAccessTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2447 FileInfo
->LastAccessTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2449 CopyMem ((VOID
*)&FileInfo
->ModificationTime
,
2450 (VOID
*)&FileInfo
->LastAccessTime
,
2453 if (FileName
!= NULL
) {
2454 StrCpyS (FileInfo
->FileName
, StrLen (FileName
) + 1, FileName
);
2456 FileInfo
->FileName
[0] = '\0';
2459 *BufferSize
= FileInfoLength
;
2465 Get volume and free space size information of an UDF volume.
2467 @param[in] BlockIo BlockIo interface.
2468 @param[in] DiskIo DiskIo interface.
2469 @param[in] Volume UDF volume information structure.
2470 @param[out] VolumeSize Volume size.
2471 @param[out] FreeSpaceSize Free space size.
2473 @retval EFI_SUCCESS Volume and free space size calculated.
2474 @retval EFI_NO_MEDIA The device has no media.
2475 @retval EFI_DEVICE_ERROR The device reported an error.
2476 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2477 @retval EFI_OUT_OF_RESOURCES The volume and free space size were not
2478 calculated due to lack of resources.
2483 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2484 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2485 IN UDF_VOLUME_INFO
*Volume
,
2486 OUT UINT64
*VolumeSize
,
2487 OUT UINT64
*FreeSpaceSize
2490 UDF_EXTENT_AD ExtentAd
;
2491 UINT32 LogicalBlockSize
;
2494 UDF_LOGICAL_VOLUME_INTEGRITY
*LogicalVolInt
;
2502 for (Index
= 0; Index
< Volume
->LogicalVolDescsNo
; Index
++) {
2503 CopyMem ((VOID
*)&ExtentAd
,
2504 (VOID
*)&Volume
->LogicalVolDescs
[Index
]->IntegritySequenceExtent
,
2505 sizeof (UDF_EXTENT_AD
));
2506 if (ExtentAd
.ExtentLength
== 0) {
2510 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, Index
);
2513 LogicalVolInt
= (UDF_LOGICAL_VOLUME_INTEGRITY
*)
2514 AllocatePool (ExtentAd
.ExtentLength
);
2515 if (LogicalVolInt
== NULL
) {
2516 return EFI_OUT_OF_RESOURCES
;
2519 Lsn
= (UINT64
)ExtentAd
.ExtentLocation
;
2521 Status
= DiskIo
->ReadDisk (
2523 BlockIo
->Media
->MediaId
,
2524 MultU64x32 (Lsn
, LogicalBlockSize
),
2525 ExtentAd
.ExtentLength
,
2526 (VOID
*)LogicalVolInt
2528 if (EFI_ERROR (Status
)) {
2529 FreePool ((VOID
*)LogicalVolInt
);
2533 if (!IS_LVID (LogicalVolInt
)) {
2534 FreePool ((VOID
*)LogicalVolInt
);
2535 return EFI_VOLUME_CORRUPTED
;
2538 Length
= LogicalVolInt
->NumberOfPartitions
;
2539 for (Index
= 0; Index
< Length
; Index
+= sizeof (UINT32
)) {
2540 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2541 if (LsnsNo
== 0xFFFFFFFFUL
) {
2543 // Size not specified.
2548 *FreeSpaceSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2551 Length
= (LogicalVolInt
->NumberOfPartitions
* sizeof (UINT32
)) << 1;
2552 for (; Index
< Length
; Index
+= sizeof (UINT32
)) {
2553 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2554 if (LsnsNo
== 0xFFFFFFFFUL
) {
2556 // Size not specified.
2561 *VolumeSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2564 CopyMem ((VOID
*)&ExtentAd
,(VOID
*)&LogicalVolInt
->NextIntegrityExtent
,
2565 sizeof (UDF_EXTENT_AD
));
2566 if (ExtentAd
.ExtentLength
> 0) {
2567 FreePool ((VOID
*)LogicalVolInt
);
2568 goto Read_Next_Sequence
;
2571 FreePool ((VOID
*)LogicalVolInt
);
2578 Seek a file and read its data into memory on an UDF volume.
2580 @param[in] BlockIo BlockIo interface.
2581 @param[in] DiskIo DiskIo interface.
2582 @param[in] Volume UDF volume information structure.
2583 @param[in] File File information structure.
2584 @param[in] FileSize Size of the file.
2585 @param[in, out] FilePosition File position.
2586 @param[in, out] Buffer File data.
2587 @param[in, out] BufferSize Read size.
2589 @retval EFI_SUCCESS File seeked and read.
2590 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2591 @retval EFI_NO_MEDIA The device has no media.
2592 @retval EFI_DEVICE_ERROR The device reported an error.
2593 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2594 @retval EFI_OUT_OF_RESOURCES The file's recorded data was not read due to lack
2600 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2601 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2602 IN UDF_VOLUME_INFO
*Volume
,
2603 IN UDF_FILE_INFO
*File
,
2605 IN OUT UINT64
*FilePosition
,
2606 IN OUT VOID
*Buffer
,
2607 IN OUT UINT64
*BufferSize
2611 UDF_READ_FILE_INFO ReadFileInfo
;
2613 ReadFileInfo
.Flags
= ReadFileSeekAndRead
;
2614 ReadFileInfo
.FilePosition
= *FilePosition
;
2615 ReadFileInfo
.FileData
= Buffer
;
2616 ReadFileInfo
.FileDataSize
= *BufferSize
;
2617 ReadFileInfo
.FileSize
= FileSize
;
2623 &File
->FileIdentifierDesc
->Icb
,
2627 if (EFI_ERROR (Status
)) {
2631 *BufferSize
= ReadFileInfo
.FileDataSize
;
2632 *FilePosition
= ReadFileInfo
.FilePosition
;
2638 Check if ControllerHandle supports an UDF file system.
2640 @param[in] This Protocol instance pointer.
2641 @param[in] ControllerHandle Handle of device to test.
2643 @retval EFI_SUCCESS UDF file system found.
2644 @retval EFI_UNSUPPORTED UDF file system not found.
2648 SupportUdfFileSystem (
2649 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2650 IN EFI_HANDLE ControllerHandle
2654 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2655 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
2656 EFI_DEVICE_PATH_PROTOCOL
*LastDevicePathNode
;
2657 EFI_GUID
*VendorDefinedGuid
;
2660 // Open Device Path protocol on ControllerHandle
2662 Status
= gBS
->OpenProtocol (
2664 &gEfiDevicePathProtocolGuid
,
2665 (VOID
**)&DevicePath
,
2666 This
->DriverBindingHandle
,
2668 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2670 if (EFI_ERROR (Status
)) {
2671 return EFI_UNSUPPORTED
;
2674 Status
= EFI_UNSUPPORTED
;
2677 // Get last Device Path node
2679 LastDevicePathNode
= NULL
;
2680 DevicePathNode
= DevicePath
;
2681 while (!IsDevicePathEnd (DevicePathNode
)) {
2682 LastDevicePathNode
= DevicePathNode
;
2683 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
2686 // Check if last Device Path node contains a Vendor-Defined Media Device Path
2687 // of an UDF file system.
2689 if (LastDevicePathNode
!= NULL
&&
2690 DevicePathType (LastDevicePathNode
) == MEDIA_DEVICE_PATH
&&
2691 DevicePathSubType (LastDevicePathNode
) == MEDIA_VENDOR_DP
) {
2692 VendorDefinedGuid
= (EFI_GUID
*)((UINTN
)LastDevicePathNode
+
2693 OFFSET_OF (VENDOR_DEVICE_PATH
, Guid
));
2694 if (CompareGuid (VendorDefinedGuid
, &gUdfDevPathGuid
)) {
2695 Status
= EFI_SUCCESS
;
2700 // Close Device Path protocol on ControllerHandle
2702 gBS
->CloseProtocol (
2704 &gEfiDevicePathProtocolGuid
,
2705 This
->DriverBindingHandle
,