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 Find the anchor volume descriptor pointer.
20 @param[in] BlockIo BlockIo interface.
21 @param[in] DiskIo DiskIo interface.
22 @param[out] AnchorPoint Anchor volume descriptor pointer.
24 @retval EFI_SUCCESS Anchor volume descriptor pointer found.
25 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
26 @retval other Anchor volume descriptor pointer not found.
30 FindAnchorVolumeDescriptorPointer (
31 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
32 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
33 OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
*AnchorPoint
39 EFI_LBA DescriptorLBAs
[4];
42 BlockSize
= BlockIo
->Media
->BlockSize
;
43 EndLBA
= BlockIo
->Media
->LastBlock
;
44 DescriptorLBAs
[0] = 256;
45 DescriptorLBAs
[1] = EndLBA
- 256;
46 DescriptorLBAs
[2] = EndLBA
;
47 DescriptorLBAs
[3] = 512;
49 for (Index
= 0; Index
< ARRAY_SIZE (DescriptorLBAs
); Index
++) {
50 Status
= DiskIo
->ReadDisk (
52 BlockIo
->Media
->MediaId
,
53 MultU64x32 (DescriptorLBAs
[Index
], BlockSize
),
54 sizeof (UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
),
57 if (EFI_ERROR (Status
)) {
61 // Check if read LBA has a valid AVDP descriptor.
63 if (IS_AVDP (AnchorPoint
)) {
70 return EFI_VOLUME_CORRUPTED
;
74 Save the content of Logical Volume Descriptors and Partitions Descriptors in
77 @param[in] BlockIo BlockIo interface.
78 @param[in] DiskIo DiskIo interface.
79 @param[in] AnchorPoint Anchor volume descriptor pointer.
80 @param[out] Volume UDF volume information structure.
82 @retval EFI_SUCCESS The descriptors were saved.
83 @retval EFI_OUT_OF_RESOURCES The descriptors were not saved due to lack of
85 @retval other The descriptors were not saved due to
90 StartMainVolumeDescriptorSequence (
91 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
92 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
93 IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER
*AnchorPoint
,
94 OUT UDF_VOLUME_INFO
*Volume
99 UDF_EXTENT_AD
*ExtentAd
;
103 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
104 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
106 UINT32 LogicalBlockSize
;
109 // We've already found an ADVP on the volume. It contains the extent
110 // (MainVolumeDescriptorSequenceExtent) where the Main Volume Descriptor
111 // Sequence starts. Therefore, we'll look for Logical Volume Descriptors and
112 // Partitions Descriptors and save them in memory, accordingly.
114 // Note also that each descriptor will be aligned on a block size (BlockSize)
115 // boundary, so we need to read one block at a time.
117 BlockSize
= BlockIo
->Media
->BlockSize
;
118 ExtentAd
= &AnchorPoint
->MainVolumeDescriptorSequenceExtent
;
119 StartingLsn
= (UINT64
)ExtentAd
->ExtentLocation
;
120 EndingLsn
= StartingLsn
+ DivU64x32 (
121 (UINT64
)ExtentAd
->ExtentLength
,
125 Volume
->LogicalVolDescs
=
126 (UDF_LOGICAL_VOLUME_DESCRIPTOR
**)AllocateZeroPool (ExtentAd
->ExtentLength
);
127 if (Volume
->LogicalVolDescs
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
131 Volume
->PartitionDescs
=
132 (UDF_PARTITION_DESCRIPTOR
**)AllocateZeroPool (ExtentAd
->ExtentLength
);
133 if (Volume
->PartitionDescs
== NULL
) {
134 Status
= EFI_OUT_OF_RESOURCES
;
135 goto Error_Alloc_Pds
;
138 Buffer
= AllocateZeroPool (BlockSize
);
139 if (Buffer
== NULL
) {
140 Status
= EFI_OUT_OF_RESOURCES
;
141 goto Error_Alloc_Buf
;
144 Volume
->LogicalVolDescsNo
= 0;
145 Volume
->PartitionDescsNo
= 0;
147 while (StartingLsn
<= EndingLsn
) {
148 Status
= DiskIo
->ReadDisk (
150 BlockIo
->Media
->MediaId
,
151 MultU64x32 (StartingLsn
, BlockSize
),
155 if (EFI_ERROR (Status
)) {
156 goto Error_Read_Disk_Blk
;
159 if (IS_TD (Buffer
)) {
161 // Found a Terminating Descriptor. Stop the sequence then.
166 if (IS_LVD (Buffer
)) {
168 // Found a Logical Volume Descriptor.
171 (UDF_LOGICAL_VOLUME_DESCRIPTOR
*)
172 AllocateZeroPool (sizeof (UDF_LOGICAL_VOLUME_DESCRIPTOR
));
173 if (LogicalVolDesc
== NULL
) {
174 Status
= EFI_OUT_OF_RESOURCES
;
175 goto Error_Alloc_Lvd
;
178 CopyMem ((VOID
*)LogicalVolDesc
, Buffer
,
179 sizeof (UDF_LOGICAL_VOLUME_DESCRIPTOR
));
180 Volume
->LogicalVolDescs
[Volume
->LogicalVolDescsNo
++] = LogicalVolDesc
;
181 } else if (IS_PD (Buffer
)) {
183 // Found a Partition Descriptor.
186 (UDF_PARTITION_DESCRIPTOR
*)
187 AllocateZeroPool (sizeof (UDF_PARTITION_DESCRIPTOR
));
188 if (PartitionDesc
== NULL
) {
189 Status
= EFI_OUT_OF_RESOURCES
;
193 CopyMem ((VOID
*)PartitionDesc
, Buffer
,
194 sizeof (UDF_PARTITION_DESCRIPTOR
));
195 Volume
->PartitionDescs
[Volume
->PartitionDescsNo
++] = PartitionDesc
;
202 // When an UDF volume (revision 2.00 or higher) contains a File Entry rather
203 // than an Extended File Entry (which is not recommended as per spec), we need
204 // to make sure the size of a FE will be _at least_ 2048
205 // (UDF_LOGICAL_SECTOR_SIZE) bytes long to keep backward compatibility.
207 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, UDF_DEFAULT_LV_NUM
);
208 if (LogicalBlockSize
>= UDF_LOGICAL_SECTOR_SIZE
) {
209 Volume
->FileEntrySize
= LogicalBlockSize
;
211 Volume
->FileEntrySize
= UDF_LOGICAL_SECTOR_SIZE
;
220 for (Index
= 0; Index
< Volume
->PartitionDescsNo
; Index
++) {
221 FreePool ((VOID
*)Volume
->PartitionDescs
[Index
]);
224 for (Index
= 0; Index
< Volume
->LogicalVolDescsNo
; Index
++) {
225 FreePool ((VOID
*)Volume
->LogicalVolDescs
[Index
]);
232 FreePool ((VOID
*)Volume
->PartitionDescs
);
233 Volume
->PartitionDescs
= NULL
;
236 FreePool ((VOID
*)Volume
->LogicalVolDescs
);
237 Volume
->LogicalVolDescs
= NULL
;
243 Return a Partition Descriptor given a Long Allocation Descriptor. This is
244 necessary to calculate the right extent (LongAd) offset which is added up
245 with partition's starting location.
247 @param[in] Volume Volume information pointer.
248 @param[in] LongAd Long Allocation Descriptor pointer.
250 @return A pointer to a Partition Descriptor.
253 UDF_PARTITION_DESCRIPTOR
*
255 IN UDF_VOLUME_INFO
*Volume
,
256 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
259 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
261 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
264 LogicalVolDesc
= Volume
->LogicalVolDescs
[UDF_DEFAULT_LV_NUM
];
266 switch (LV_UDF_REVISION (LogicalVolDesc
)) {
269 // As per UDF 1.02 specification:
271 // There shall be exactly one prevailing Logical Volume Descriptor recorded
272 // per Volume Set. The Partition Maps field shall contain only Type 1
275 PartitionNum
= *(UINT16
*)((UINTN
)&LogicalVolDesc
->PartitionMaps
[4]);
279 // Ensure Type 1 Partition map. Other types aren't supported in this
282 if (LogicalVolDesc
->PartitionMaps
[0] != 1 ||
283 LogicalVolDesc
->PartitionMaps
[1] != 6) {
286 PartitionNum
= *(UINT16
*)((UINTN
)&LogicalVolDesc
->PartitionMaps
[4]);
293 PartitionNum
= LongAd
->ExtentLocation
.PartitionReferenceNumber
;
297 for (Index
= 0; Index
< Volume
->PartitionDescsNo
; Index
++) {
298 PartitionDesc
= Volume
->PartitionDescs
[Index
];
299 if (PartitionDesc
->PartitionNumber
== PartitionNum
) {
300 return PartitionDesc
;
308 Return logical sector number of a given Long Allocation Descriptor.
310 @param[in] Volume Volume information pointer.
311 @param[in] LongAd Long Allocation Descriptor pointer.
313 @return The logical sector number of a given Long Allocation Descriptor.
318 IN UDF_VOLUME_INFO
*Volume
,
319 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
322 UDF_PARTITION_DESCRIPTOR
*PartitionDesc
;
324 PartitionDesc
= GetPdFromLongAd (Volume
, LongAd
);
325 ASSERT (PartitionDesc
!= NULL
);
327 return (UINT64
)PartitionDesc
->PartitionStartingLocation
+
328 LongAd
->ExtentLocation
.LogicalBlockNumber
;
332 Return logical sector number of a given Short Allocation Descriptor.
334 @param[in] PartitionDesc Partition Descriptor pointer.
335 @param[in] ShortAd Short Allocation Descriptor pointer.
337 @return The logical sector number of a given Short Allocation Descriptor.
342 IN UDF_PARTITION_DESCRIPTOR
*PartitionDesc
,
343 IN UDF_SHORT_ALLOCATION_DESCRIPTOR
*ShortAd
346 ASSERT (PartitionDesc
!= NULL
);
348 return (UINT64
)PartitionDesc
->PartitionStartingLocation
+
349 ShortAd
->ExtentPosition
;
353 Find File Set Descriptor of a given Logical Volume Descriptor.
355 The found FSD will contain the extent (LogicalVolumeContentsUse) where our
358 @param[in] BlockIo BlockIo interface.
359 @param[in] DiskIo DiskIo interface.
360 @param[in] Volume Volume information pointer.
361 @param[in] LogicalVolDescNum Index of Logical Volume Descriptor
362 @param[out] FileSetDesc File Set Descriptor pointer.
364 @retval EFI_SUCCESS File Set Descriptor pointer found.
365 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
366 @retval other File Set Descriptor pointer not found.
370 FindFileSetDescriptor (
371 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
372 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
373 IN UDF_VOLUME_INFO
*Volume
,
374 IN UINTN LogicalVolDescNum
,
375 OUT UDF_FILE_SET_DESCRIPTOR
*FileSetDesc
380 UDF_LOGICAL_VOLUME_DESCRIPTOR
*LogicalVolDesc
;
382 LogicalVolDesc
= Volume
->LogicalVolDescs
[LogicalVolDescNum
];
383 Lsn
= GetLongAdLsn (Volume
, &LogicalVolDesc
->LogicalVolumeContentsUse
);
386 // Read extent (Long Ad).
388 Status
= DiskIo
->ReadDisk (
390 BlockIo
->Media
->MediaId
,
391 MultU64x32 (Lsn
, LogicalVolDesc
->LogicalBlockSize
),
392 sizeof (UDF_FILE_SET_DESCRIPTOR
),
395 if (EFI_ERROR (Status
)) {
400 // Check if the read extent contains a valid FSD's tag identifier.
402 if (!IS_FSD (FileSetDesc
)) {
403 return EFI_VOLUME_CORRUPTED
;
410 Get all File Set Descriptors for each Logical Volume Descriptor.
412 @param[in] BlockIo BlockIo interface.
413 @param[in] DiskIo DiskIo interface.
414 @param[in, out] Volume Volume information pointer.
416 @retval EFI_SUCCESS File Set Descriptors were got.
417 @retval EFI_OUT_OF_RESOURCES File Set Descriptors were not got due to lack
419 @retval other Error occured when finding File Set
420 Descriptor in Logical Volume Descriptor.
424 GetFileSetDescriptors (
425 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
426 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
427 IN OUT UDF_VOLUME_INFO
*Volume
432 UDF_FILE_SET_DESCRIPTOR
*FileSetDesc
;
435 Volume
->FileSetDescs
=
436 (UDF_FILE_SET_DESCRIPTOR
**)AllocateZeroPool (
437 Volume
->LogicalVolDescsNo
* sizeof (UDF_FILE_SET_DESCRIPTOR
));
438 if (Volume
->FileSetDescs
== NULL
) {
439 return EFI_OUT_OF_RESOURCES
;
442 for (Index
= 0; Index
< Volume
->LogicalVolDescsNo
; Index
++) {
443 FileSetDesc
= AllocateZeroPool (sizeof (UDF_FILE_SET_DESCRIPTOR
));
444 if (FileSetDesc
== NULL
) {
445 Status
= EFI_OUT_OF_RESOURCES
;
446 goto Error_Alloc_Fsd
;
450 // Find a FSD for this LVD.
452 Status
= FindFileSetDescriptor (
459 if (EFI_ERROR (Status
)) {
466 Volume
->FileSetDescs
[Index
] = FileSetDesc
;
469 Volume
->FileSetDescsNo
= Volume
->LogicalVolDescsNo
;
474 for (Index
= 0; Index
< Count
; Index
++) {
475 FreePool ((VOID
*)Volume
->FileSetDescs
[Index
]);
478 FreePool ((VOID
*)Volume
->FileSetDescs
);
479 Volume
->FileSetDescs
= NULL
;
486 Read Volume and File Structure on an UDF file system.
488 @param[in] BlockIo BlockIo interface.
489 @param[in] DiskIo DiskIo interface.
490 @param[out] Volume Volume information pointer.
492 @retval EFI_SUCCESS Volume and File Structure were read.
493 @retval other Volume and File Structure were not read.
497 ReadVolumeFileStructure (
498 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
499 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
500 OUT UDF_VOLUME_INFO
*Volume
504 UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint
;
509 Status
= FindAnchorVolumeDescriptorPointer (
514 if (EFI_ERROR (Status
)) {
519 // AVDP has been found. Start MVDS.
521 Status
= StartMainVolumeDescriptorSequence (
527 if (EFI_ERROR (Status
)) {
535 Calculate length of a given File Identifier Descriptor.
537 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
539 @return The length of a given File Identifier Descriptor.
543 GetFidDescriptorLength (
544 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
548 (INTN
)((OFFSET_OF (UDF_FILE_IDENTIFIER_DESCRIPTOR
, Data
[0]) + 3 +
549 FileIdentifierDesc
->LengthOfFileIdentifier
+
550 FileIdentifierDesc
->LengthOfImplementationUse
) >> 2) << 2
555 Duplicate a given File Identifier Descriptor.
557 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
558 @param[out] NewFileIdentifierDesc The duplicated File Identifier Descriptor.
563 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
,
564 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR
**NewFileIdentifierDesc
567 *NewFileIdentifierDesc
=
568 (UDF_FILE_IDENTIFIER_DESCRIPTOR
*)AllocateCopyPool (
569 (UINTN
) GetFidDescriptorLength (FileIdentifierDesc
), FileIdentifierDesc
);
571 ASSERT (*NewFileIdentifierDesc
!= NULL
);
575 Duplicate either a given File Entry or a given Extended File Entry.
577 @param[in] BlockIo BlockIo interface.
578 @param[in] Volume Volume information pointer.
579 @param[in] FileEntry (Extended) File Entry pointer.
580 @param[out] NewFileEntry The duplicated (Extended) File Entry.
585 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
586 IN UDF_VOLUME_INFO
*Volume
,
588 OUT VOID
**NewFileEntry
591 *NewFileEntry
= AllocateCopyPool (Volume
->FileEntrySize
, FileEntry
);
593 ASSERT (*NewFileEntry
!= NULL
);
597 Get raw data + length of a given File Entry or Extended File Entry.
599 The file's recorded data can contain either real file content (inline) or
600 a sequence of extents (or Allocation Descriptors) which tells where file's
601 content is stored in.
603 NOTE: The FE/EFE can be thought it was an inode.
605 @param[in] FileEntryData (Extended) File Entry pointer.
606 @param[out] Data Buffer contains the raw data of a given
607 (Extended) File Entry.
608 @param[out] Length Length of the data in Buffer.
613 IN VOID
*FileEntryData
,
618 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
619 UDF_FILE_ENTRY
*FileEntry
;
621 if (IS_EFE (FileEntryData
)) {
622 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)FileEntryData
;
624 *Length
= ExtendedFileEntry
->InformationLength
;
625 *Data
= (VOID
*)((UINT8
*)ExtendedFileEntry
->Data
+
626 ExtendedFileEntry
->LengthOfExtendedAttributes
);
627 } else if (IS_FE (FileEntryData
)) {
628 FileEntry
= (UDF_FILE_ENTRY
*)FileEntryData
;
630 *Length
= FileEntry
->InformationLength
;
631 *Data
= (VOID
*)((UINT8
*)FileEntry
->Data
+
632 FileEntry
->LengthOfExtendedAttributes
);
637 Get Allocation Descriptors' data information from a given FE/EFE.
639 @param[in] FileEntryData (Extended) File Entry pointer.
640 @param[out] AdsData Buffer contains the Allocation Descriptors'
641 data from a given FE/EFE.
642 @param[out] Length Length of the data in AdsData.
647 IN VOID
*FileEntryData
,
652 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
653 UDF_FILE_ENTRY
*FileEntry
;
655 if (IS_EFE (FileEntryData
)) {
656 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)FileEntryData
;
658 *Length
= ExtendedFileEntry
->LengthOfAllocationDescriptors
;
659 *AdsData
= (VOID
*)((UINT8
*)ExtendedFileEntry
->Data
+
660 ExtendedFileEntry
->LengthOfExtendedAttributes
);
661 } else if (IS_FE (FileEntryData
)) {
662 FileEntry
= (UDF_FILE_ENTRY
*)FileEntryData
;
664 *Length
= FileEntry
->LengthOfAllocationDescriptors
;
665 *AdsData
= (VOID
*)((UINT8
*)FileEntry
->Data
+
666 FileEntry
->LengthOfExtendedAttributes
);
671 Read next Long Allocation Descriptor from a given file's data.
673 @param[in] Data File's data pointer.
674 @param[in,out] Offset Starting offset of the File's data to read.
675 @param[in] Length Length of the data to read.
676 @param[out] FoundLongAd Long Allocation Descriptor pointer.
678 @retval EFI_SUCCESS A Long Allocation Descriptor was found.
679 @retval EFI_DEVICE_ERROR No more Long Allocation Descriptors.
685 IN OUT UINT64
*Offset
,
687 OUT UDF_LONG_ALLOCATION_DESCRIPTOR
**FoundLongAd
690 UDF_LONG_ALLOCATION_DESCRIPTOR
*LongAd
;
691 UDF_EXTENT_FLAGS ExtentFlags
;
694 if (*Offset
>= Length
) {
696 // No more Long Allocation Descriptors.
698 return EFI_DEVICE_ERROR
;
702 (UDF_LONG_ALLOCATION_DESCRIPTOR
*)((UINT8
*)Data
+ *Offset
);
705 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
706 // allocated AD, then return it.
708 ExtentFlags
= GET_EXTENT_FLAGS (LONG_ADS_SEQUENCE
, LongAd
);
709 if (ExtentFlags
== EXTENT_IS_NEXT_EXTENT
||
710 ExtentFlags
== EXTENT_RECORDED_AND_ALLOCATED
) {
715 // This AD is either not recorded but allocated, or not recorded and not
716 // allocated. Skip it.
718 *Offset
+= AD_LENGTH (LONG_ADS_SEQUENCE
);
721 *FoundLongAd
= LongAd
;
727 Read next Short Allocation Descriptor from a given file's data.
729 @param[in] Data File's data pointer.
730 @param[in,out] Offset Starting offset of the File's data to read.
731 @param[in] Length Length of the data to read.
732 @param[out] FoundShortAd Short Allocation Descriptor pointer.
734 @retval EFI_SUCCESS A Short Allocation Descriptor was found.
735 @retval EFI_DEVICE_ERROR No more Short Allocation Descriptors.
741 IN OUT UINT64
*Offset
,
743 OUT UDF_SHORT_ALLOCATION_DESCRIPTOR
**FoundShortAd
746 UDF_SHORT_ALLOCATION_DESCRIPTOR
*ShortAd
;
747 UDF_EXTENT_FLAGS ExtentFlags
;
750 if (*Offset
>= Length
) {
752 // No more Short Allocation Descriptors.
754 return EFI_DEVICE_ERROR
;
758 (UDF_SHORT_ALLOCATION_DESCRIPTOR
*)((UINT8
*)Data
+ *Offset
);
761 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
762 // allocated AD, then return it.
764 ExtentFlags
= GET_EXTENT_FLAGS (SHORT_ADS_SEQUENCE
, ShortAd
);
765 if (ExtentFlags
== EXTENT_IS_NEXT_EXTENT
||
766 ExtentFlags
== EXTENT_RECORDED_AND_ALLOCATED
) {
771 // This AD is either not recorded but allocated, or not recorded and not
772 // allocated. Skip it.
774 *Offset
+= AD_LENGTH (SHORT_ADS_SEQUENCE
);
777 *FoundShortAd
= ShortAd
;
783 Get either a Short Allocation Descriptor or a Long Allocation Descriptor from
786 @param[in] RecordingFlags Flag to indicate the type of descriptor.
787 @param[in] Data File's data pointer.
788 @param[in,out] Offset Starting offset of the File's data to read.
789 @param[in] Length Length of the data to read.
790 @param[out] FoundAd Allocation Descriptor pointer.
792 @retval EFI_SUCCESS A Short Allocation Descriptor was found.
793 @retval EFI_DEVICE_ERROR No more Allocation Descriptors.
794 Invalid type of descriptor was given.
798 GetAllocationDescriptor (
799 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
801 IN OUT UINT64
*Offset
,
806 if (RecordingFlags
== LONG_ADS_SEQUENCE
) {
807 return GetLongAdFromAds (
811 (UDF_LONG_ALLOCATION_DESCRIPTOR
**)FoundAd
813 } else if (RecordingFlags
== SHORT_ADS_SEQUENCE
) {
814 return GetShortAdFromAds (
818 (UDF_SHORT_ALLOCATION_DESCRIPTOR
**)FoundAd
822 return EFI_DEVICE_ERROR
;
826 Return logical sector number of either Short or Long Allocation Descriptor.
828 @param[in] RecordingFlags Flag to indicate the type of descriptor.
829 @param[in] Volume Volume information pointer.
830 @param[in] ParentIcb Long Allocation Descriptor pointer.
831 @param[in] Ad Allocation Descriptor pointer.
833 @return The logical sector number of the given Allocation Descriptor.
837 GetAllocationDescriptorLsn (
838 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
839 IN UDF_VOLUME_INFO
*Volume
,
840 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
844 if (RecordingFlags
== LONG_ADS_SEQUENCE
) {
845 return GetLongAdLsn (Volume
, (UDF_LONG_ALLOCATION_DESCRIPTOR
*)Ad
);
846 } else if (RecordingFlags
== SHORT_ADS_SEQUENCE
) {
847 return GetShortAdLsn (
848 GetPdFromLongAd (Volume
, ParentIcb
),
849 (UDF_SHORT_ALLOCATION_DESCRIPTOR
*)Ad
857 Return offset + length of a given indirect Allocation Descriptor (AED).
859 @param[in] BlockIo BlockIo interface.
860 @param[in] DiskIo DiskIo interface.
861 @param[in] Volume Volume information pointer.
862 @param[in] ParentIcb Long Allocation Descriptor pointer.
863 @param[in] RecordingFlags Flag to indicate the type of descriptor.
864 @param[in] Ad Allocation Descriptor pointer.
865 @param[out] Offset Offset of a given indirect Allocation
867 @param[out] Length Length of a given indirect Allocation
870 @retval EFI_SUCCESS The offset and length were returned.
871 @retval EFI_OUT_OF_RESOURCES The offset and length were not returned due
872 to lack of resources.
873 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
874 @retval other The offset and length were not returned.
879 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
880 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
881 IN UDF_VOLUME_INFO
*Volume
,
882 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
883 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
893 UINT32 LogicalBlockSize
;
894 UDF_ALLOCATION_EXTENT_DESCRIPTOR
*AllocExtDesc
;
896 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
897 Lsn
= GetAllocationDescriptorLsn (RecordingFlags
,
902 Data
= AllocatePool (ExtentLength
);
904 return EFI_OUT_OF_RESOURCES
;
907 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, UDF_DEFAULT_LV_NUM
);
912 Status
= DiskIo
->ReadDisk (
914 BlockIo
->Media
->MediaId
,
915 MultU64x32 (Lsn
, LogicalBlockSize
),
919 if (EFI_ERROR (Status
)) {
924 // Check if read extent contains a valid tag identifier for AED.
926 AllocExtDesc
= (UDF_ALLOCATION_EXTENT_DESCRIPTOR
*)Data
;
927 if (!IS_AED (AllocExtDesc
)) {
928 Status
= EFI_VOLUME_CORRUPTED
;
933 // Get AED's block offset and its length.
935 *Offset
= MultU64x32 (Lsn
, LogicalBlockSize
) +
936 sizeof (UDF_ALLOCATION_EXTENT_DESCRIPTOR
);
937 *Length
= AllocExtDesc
->LengthOfAllocationDescriptors
;
946 Read Allocation Extent Descriptor into memory.
948 @param[in] BlockIo BlockIo interface.
949 @param[in] DiskIo DiskIo interface.
950 @param[in] Volume Volume information pointer.
951 @param[in] ParentIcb Long Allocation Descriptor pointer.
952 @param[in] RecordingFlags Flag to indicate the type of descriptor.
953 @param[in] Ad Allocation Descriptor pointer.
954 @param[out] Data Buffer that contains the Allocation Extent
956 @param[out] Length Length of Data.
958 @retval EFI_SUCCESS The Allocation Extent Descriptor was read.
959 @retval EFI_OUT_OF_RESOURCES The Allocation Extent Descriptor was not read
960 due to lack of resources.
961 @retval other Fail to read the disk.
966 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
967 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
968 IN UDF_VOLUME_INFO
*Volume
,
969 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
970 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
980 // Get AED's offset + length.
982 Status
= GetAedAdsOffset (
992 if (EFI_ERROR (Status
)) {
997 // Allocate buffer to read in AED's data.
999 *Data
= AllocatePool ((UINTN
) (*Length
));
1000 if (*Data
== NULL
) {
1001 return EFI_OUT_OF_RESOURCES
;
1004 return DiskIo
->ReadDisk (
1006 BlockIo
->Media
->MediaId
,
1014 Function used to serialise reads of Allocation Descriptors.
1016 @param[in] RecordingFlags Flag to indicate the type of descriptor.
1017 @param[in] Ad Allocation Descriptor pointer.
1018 @param[in, out] Buffer Buffer to hold the next Allocation Descriptor.
1019 @param[in] Length Length of Buffer.
1021 @retval EFI_SUCCESS Buffer was grown to hold the next Allocation
1023 @retval EFI_OUT_OF_RESOURCES Buffer was not grown due to lack of resources.
1027 GrowUpBufferToNextAd (
1028 IN UDF_FE_RECORDING_FLAGS RecordingFlags
,
1030 IN OUT VOID
**Buffer
,
1034 UINT32 ExtentLength
;
1036 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
1038 if (*Buffer
== NULL
) {
1039 *Buffer
= AllocatePool (ExtentLength
);
1040 if (*Buffer
== NULL
) {
1041 return EFI_OUT_OF_RESOURCES
;
1044 *Buffer
= ReallocatePool ((UINTN
) Length
, (UINTN
) (Length
+ ExtentLength
), *Buffer
);
1045 if (*Buffer
== NULL
) {
1046 return EFI_OUT_OF_RESOURCES
;
1054 Read data or size of either a File Entry or an Extended File Entry.
1056 @param[in] BlockIo BlockIo interface.
1057 @param[in] DiskIo DiskIo interface.
1058 @param[in] Volume Volume information pointer.
1059 @param[in] ParentIcb Long Allocation Descriptor pointer.
1060 @param[in] FileEntryData FE/EFE structure pointer.
1061 @param[in, out] ReadFileInfo Read file information pointer.
1063 @retval EFI_SUCCESS Data or size of a FE/EFE was read.
1064 @retval EFI_OUT_OF_RESOURCES Data or size of a FE/EFE was not read due to
1066 @retval EFI_INVALID_PARAMETER The read file flag given in ReadFileInfo is
1068 @retval EFI_UNSUPPORTED The FE recording flag given in FileEntryData
1070 @retval other Data or size of a FE/EFE was not read.
1075 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1076 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1077 IN UDF_VOLUME_INFO
*Volume
,
1078 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
1079 IN VOID
*FileEntryData
,
1080 IN OUT UDF_READ_FILE_INFO
*ReadFileInfo
1084 UINT32 LogicalBlockSize
;
1091 UINT64 FilePosition
;
1096 BOOLEAN FinishedSeeking
;
1097 UINT32 ExtentLength
;
1098 UDF_FE_RECORDING_FLAGS RecordingFlags
;
1100 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, UDF_DEFAULT_LV_NUM
);
1104 // set BytesLeft to suppress incorrect compiler/analyzer warnings
1109 FinishedSeeking
= FALSE
;
1112 switch (ReadFileInfo
->Flags
) {
1113 case READ_FILE_GET_FILESIZE
:
1114 case READ_FILE_ALLOCATE_AND_READ
:
1116 // Initialise ReadFileInfo structure for either getting file size, or
1117 // reading file's recorded data.
1119 ReadFileInfo
->ReadLength
= 0;
1120 ReadFileInfo
->FileData
= NULL
;
1122 case READ_FILE_SEEK_AND_READ
:
1124 // About to seek a file and/or read its data.
1126 Length
= ReadFileInfo
->FileSize
- ReadFileInfo
->FilePosition
;
1127 if (ReadFileInfo
->FileDataSize
> Length
) {
1129 // About to read beyond the EOF -- truncate it.
1131 ReadFileInfo
->FileDataSize
= Length
;
1135 // Initialise data to start seeking and/or reading a file.
1137 BytesLeft
= ReadFileInfo
->FileDataSize
;
1140 FinishedSeeking
= FALSE
;
1145 RecordingFlags
= GET_FE_RECORDING_FLAGS (FileEntryData
);
1146 switch (RecordingFlags
) {
1149 // There are no extents for this FE/EFE. All data is inline.
1151 GetFileEntryData (FileEntryData
, &Data
, &Length
);
1153 if (ReadFileInfo
->Flags
== READ_FILE_GET_FILESIZE
) {
1154 ReadFileInfo
->ReadLength
= Length
;
1155 } else if (ReadFileInfo
->Flags
== READ_FILE_ALLOCATE_AND_READ
) {
1157 // Allocate buffer for starting read data.
1159 ReadFileInfo
->FileData
= AllocatePool ((UINTN
) Length
);
1160 if (ReadFileInfo
->FileData
== NULL
) {
1161 return EFI_OUT_OF_RESOURCES
;
1165 // Read all inline data into ReadFileInfo->FileData
1167 CopyMem (ReadFileInfo
->FileData
, Data
, (UINTN
) Length
);
1168 ReadFileInfo
->ReadLength
= Length
;
1169 } else if (ReadFileInfo
->Flags
== READ_FILE_SEEK_AND_READ
) {
1171 // If FilePosition is non-zero, seek file to FilePosition, read
1172 // FileDataSize bytes and then updates FilePosition.
1175 ReadFileInfo
->FileData
,
1176 (VOID
*)((UINT8
*)Data
+ ReadFileInfo
->FilePosition
),
1177 (UINTN
) ReadFileInfo
->FileDataSize
1180 ReadFileInfo
->FilePosition
+= ReadFileInfo
->FileDataSize
;
1183 return EFI_INVALID_PARAMETER
;
1186 Status
= EFI_SUCCESS
;
1189 case LONG_ADS_SEQUENCE
:
1190 case SHORT_ADS_SEQUENCE
:
1192 // This FE/EFE contains a run of Allocation Descriptors. Get data + size
1193 // for start reading them out.
1195 GetAdsInformation (FileEntryData
, &Data
, &Length
);
1202 Status
= GetAllocationDescriptor (
1209 if (Status
== EFI_DEVICE_ERROR
) {
1210 Status
= EFI_SUCCESS
;
1215 // Check if AD is an indirect AD. If so, read Allocation Extent
1216 // Descriptor and its extents (ADs).
1218 if (GET_EXTENT_FLAGS (RecordingFlags
, Ad
) == EXTENT_IS_NEXT_EXTENT
) {
1225 Status
= GetAedAdsData (
1235 if (EFI_ERROR (Status
)) {
1238 ASSERT (Data
!= NULL
);
1244 ExtentLength
= GET_EXTENT_LENGTH (RecordingFlags
, Ad
);
1246 Lsn
= GetAllocationDescriptorLsn (RecordingFlags
,
1251 switch (ReadFileInfo
->Flags
) {
1252 case READ_FILE_GET_FILESIZE
:
1253 ReadFileInfo
->ReadLength
+= ExtentLength
;
1255 case READ_FILE_ALLOCATE_AND_READ
:
1257 // Increase FileData (if necessary) to read next extent.
1259 Status
= GrowUpBufferToNextAd (
1262 &ReadFileInfo
->FileData
,
1263 ReadFileInfo
->ReadLength
1265 if (EFI_ERROR (Status
)) {
1266 goto Error_Alloc_Buffer_To_Next_Ad
;
1270 // Read extent's data into FileData.
1272 Status
= DiskIo
->ReadDisk (
1274 BlockIo
->Media
->MediaId
,
1275 MultU64x32 (Lsn
, LogicalBlockSize
),
1277 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1278 ReadFileInfo
->ReadLength
)
1280 if (EFI_ERROR (Status
)) {
1281 goto Error_Read_Disk_Blk
;
1284 ReadFileInfo
->ReadLength
+= ExtentLength
;
1286 case READ_FILE_SEEK_AND_READ
:
1288 // Seek file first before reading in its data.
1290 if (FinishedSeeking
) {
1292 goto Skip_File_Seek
;
1295 if (FilePosition
+ ExtentLength
< ReadFileInfo
->FilePosition
) {
1296 FilePosition
+= ExtentLength
;
1300 if (FilePosition
+ ExtentLength
> ReadFileInfo
->FilePosition
) {
1301 Offset
= ReadFileInfo
->FilePosition
- FilePosition
;
1307 // Done with seeking file. Start reading its data.
1309 FinishedSeeking
= TRUE
;
1313 // Make sure we don't read more data than really wanted.
1315 if (ExtentLength
- Offset
> BytesLeft
) {
1316 DataLength
= BytesLeft
;
1318 DataLength
= ExtentLength
- Offset
;
1322 // Read extent's data into FileData.
1324 Status
= DiskIo
->ReadDisk (
1326 BlockIo
->Media
->MediaId
,
1327 Offset
+ MultU64x32 (Lsn
, LogicalBlockSize
),
1329 (VOID
*)((UINT8
*)ReadFileInfo
->FileData
+
1332 if (EFI_ERROR (Status
)) {
1333 goto Error_Read_Disk_Blk
;
1337 // Update current file's position.
1339 DataOffset
+= DataLength
;
1340 ReadFileInfo
->FilePosition
+= DataLength
;
1342 BytesLeft
-= DataLength
;
1343 if (BytesLeft
== 0) {
1345 // There is no more file data to read.
1347 Status
= EFI_SUCCESS
;
1356 // Point to the next AD (extent).
1358 AdOffset
+= AD_LENGTH (RecordingFlags
);
1362 case EXTENDED_ADS_SEQUENCE
:
1363 // FIXME: Not supported. Got no volume with it, yet.
1365 Status
= EFI_UNSUPPORTED
;
1370 // A flag value reserved by the ECMA-167 standard (3rd Edition - June
1371 // 1997); 14.6 ICB Tag; 14.6.8 Flags (RBP 18); was found.
1373 Status
= EFI_UNSUPPORTED
;
1384 Error_Read_Disk_Blk
:
1385 Error_Alloc_Buffer_To_Next_Ad
:
1386 if (ReadFileInfo
->Flags
!= READ_FILE_SEEK_AND_READ
) {
1387 FreePool (ReadFileInfo
->FileData
);
1399 Find a file by its filename from a given Parent file.
1401 @param[in] BlockIo BlockIo interface.
1402 @param[in] DiskIo DiskIo interface.
1403 @param[in] Volume Volume information pointer.
1404 @param[in] FileName File name string.
1405 @param[in] Parent Parent directory file.
1406 @param[in] Icb Long Allocation Descriptor pointer.
1407 @param[out] File Found file.
1409 @retval EFI_SUCCESS The file was found.
1410 @retval EFI_INVALID_PARAMETER One or more input parameters are invalid.
1411 @retval EFI_NOT_FOUND The file was not found.
1416 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1417 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1418 IN UDF_VOLUME_INFO
*Volume
,
1419 IN CHAR16
*FileName
,
1420 IN UDF_FILE_INFO
*Parent
,
1421 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1422 OUT UDF_FILE_INFO
*File
1426 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1427 UDF_READ_DIRECTORY_INFO ReadDirInfo
;
1429 CHAR16 FoundFileName
[UDF_FILENAME_LENGTH
];
1430 VOID
*CompareFileEntry
;
1433 // Check if both Parent->FileIdentifierDesc and Icb are NULL.
1435 if ((Parent
->FileIdentifierDesc
== NULL
) && (Icb
== NULL
)) {
1436 return EFI_INVALID_PARAMETER
;
1440 // Check if parent file is really directory.
1442 if (!IS_FE_DIRECTORY (Parent
->FileEntry
)) {
1443 return EFI_NOT_FOUND
;
1447 // If FileName is current file or working directory, just duplicate Parent's
1448 // FE/EFE and FID descriptors.
1450 if (StrCmp (FileName
, L
".") == 0) {
1451 if (Parent
->FileIdentifierDesc
== NULL
) {
1452 return EFI_INVALID_PARAMETER
;
1455 DuplicateFe (BlockIo
, Volume
, Parent
->FileEntry
, &File
->FileEntry
);
1456 DuplicateFid (Parent
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1462 // Start directory listing.
1464 ZeroMem ((VOID
*)&ReadDirInfo
, sizeof (UDF_READ_DIRECTORY_INFO
));
1468 Status
= ReadDirectoryEntry (
1472 (Parent
->FileIdentifierDesc
!= NULL
) ?
1473 &Parent
->FileIdentifierDesc
->Icb
:
1479 if (EFI_ERROR (Status
)) {
1480 if (Status
== EFI_DEVICE_ERROR
) {
1481 Status
= EFI_NOT_FOUND
;
1487 if (IS_FID_PARENT_FILE (FileIdentifierDesc
)) {
1489 // This FID contains the location (FE/EFE) of the parent directory of this
1490 // directory (Parent), and if FileName is either ".." or "\\", then it's
1491 // the expected FID.
1493 if (StrCmp (FileName
, L
"..") == 0 || StrCmp (FileName
, L
"\\") == 0) {
1498 Status
= GetFileNameFromFid (FileIdentifierDesc
, FoundFileName
);
1499 if (EFI_ERROR (Status
)) {
1503 if (StrCmp (FileName
, FoundFileName
) == 0) {
1505 // FID has been found. Prepare to find its respective FE/EFE.
1512 FreePool ((VOID
*)FileIdentifierDesc
);
1515 if (ReadDirInfo
.DirectoryData
!= NULL
) {
1517 // Free all allocated resources for the directory listing.
1519 FreePool (ReadDirInfo
.DirectoryData
);
1523 Status
= EFI_SUCCESS
;
1525 File
->FileIdentifierDesc
= FileIdentifierDesc
;
1528 // If the requested file is root directory, then the FE/EFE was already
1529 // retrieved in UdfOpenVolume() function, thus no need to find it again.
1531 // Otherwise, find FE/EFE from the respective FID.
1533 if (StrCmp (FileName
, L
"\\") != 0) {
1534 Status
= FindFileEntry (
1538 &FileIdentifierDesc
->Icb
,
1541 if (EFI_ERROR (Status
)) {
1546 // Make sure that both Parent's FE/EFE and found FE/EFE are not equal.
1548 if (CompareMem ((VOID
*)Parent
->FileEntry
, (VOID
*)CompareFileEntry
,
1549 Volume
->FileEntrySize
) != 0) {
1550 File
->FileEntry
= CompareFileEntry
;
1552 FreePool ((VOID
*)FileIdentifierDesc
);
1553 FreePool ((VOID
*)CompareFileEntry
);
1554 Status
= EFI_NOT_FOUND
;
1562 FreePool ((VOID
*)FileIdentifierDesc
);
1568 Read volume information on a medium which contains a valid UDF file system.
1570 @param[in] BlockIo BlockIo interface.
1571 @param[in] DiskIo DiskIo interface.
1572 @param[out] Volume UDF volume information structure.
1574 @retval EFI_SUCCESS Volume information read.
1575 @retval EFI_NO_MEDIA The device has no media.
1576 @retval EFI_DEVICE_ERROR The device reported an error.
1577 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1578 @retval EFI_OUT_OF_RESOURCES The volume was not read due to lack of resources.
1582 ReadUdfVolumeInformation (
1583 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1584 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1585 OUT UDF_VOLUME_INFO
*Volume
1590 Status
= ReadVolumeFileStructure (
1595 if (EFI_ERROR (Status
)) {
1599 Status
= GetFileSetDescriptors (
1604 if (EFI_ERROR (Status
)) {
1605 CleanupVolumeInformation (Volume
);
1612 Find the root directory on an UDF volume.
1614 @param[in] BlockIo BlockIo interface.
1615 @param[in] DiskIo DiskIo interface.
1616 @param[in] Volume UDF volume information structure.
1617 @param[out] File Root directory file.
1619 @retval EFI_SUCCESS Root directory found.
1620 @retval EFI_NO_MEDIA The device has no media.
1621 @retval EFI_DEVICE_ERROR The device reported an error.
1622 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1623 @retval EFI_OUT_OF_RESOURCES The root directory was not found due to lack of
1629 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1630 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1631 IN UDF_VOLUME_INFO
*Volume
,
1632 OUT UDF_FILE_INFO
*File
1636 UDF_FILE_INFO Parent
;
1638 Status
= FindFileEntry (
1642 &Volume
->FileSetDescs
[0]->RootDirectoryIcb
,
1645 if (EFI_ERROR (Status
)) {
1649 Parent
.FileEntry
= File
->FileEntry
;
1650 Parent
.FileIdentifierDesc
= NULL
;
1659 &Volume
->FileSetDescs
[0]->RootDirectoryIcb
,
1662 if (EFI_ERROR (Status
)) {
1663 FreePool (File
->FileEntry
);
1670 Find either a File Entry or a Extended File Entry from a given ICB.
1672 @param[in] BlockIo BlockIo interface.
1673 @param[in] DiskIo DiskIo interface.
1674 @param[in] Volume UDF volume information structure.
1675 @param[in] Icb ICB of the FID.
1676 @param[out] FileEntry File Entry or Extended File Entry.
1678 @retval EFI_SUCCESS File Entry or Extended File Entry found.
1679 @retval EFI_NO_MEDIA The device has no media.
1680 @retval EFI_DEVICE_ERROR The device reported an error.
1681 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1682 @retval EFI_OUT_OF_RESOURCES The FE/EFE entry was not found due to lack of
1688 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1689 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1690 IN UDF_VOLUME_INFO
*Volume
,
1691 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1692 OUT VOID
**FileEntry
1697 UINT32 LogicalBlockSize
;
1699 Lsn
= GetLongAdLsn (Volume
, Icb
);
1700 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, UDF_DEFAULT_LV_NUM
);
1702 *FileEntry
= AllocateZeroPool (Volume
->FileEntrySize
);
1703 if (*FileEntry
== NULL
) {
1704 return EFI_OUT_OF_RESOURCES
;
1710 Status
= DiskIo
->ReadDisk (
1712 BlockIo
->Media
->MediaId
,
1713 MultU64x32 (Lsn
, LogicalBlockSize
),
1714 Volume
->FileEntrySize
,
1717 if (EFI_ERROR (Status
)) {
1718 goto Error_Read_Disk_Blk
;
1722 // Check if the read extent contains a valid Tag Identifier for the expected
1725 if (!IS_FE (*FileEntry
) && !IS_EFE (*FileEntry
)) {
1726 Status
= EFI_VOLUME_CORRUPTED
;
1727 goto Error_Invalid_Fe
;
1733 Error_Read_Disk_Blk
:
1734 FreePool (*FileEntry
);
1740 Find a file given its absolute path on an UDF volume.
1742 @param[in] BlockIo BlockIo interface.
1743 @param[in] DiskIo DiskIo interface.
1744 @param[in] Volume UDF volume information structure.
1745 @param[in] FilePath File's absolute path.
1746 @param[in] Root Root directory file.
1747 @param[in] Parent Parent directory file.
1748 @param[in] Icb ICB of Parent.
1749 @param[out] File Found file.
1751 @retval EFI_SUCCESS FilePath was found.
1752 @retval EFI_NO_MEDIA The device has no media.
1753 @retval EFI_DEVICE_ERROR The device reported an error.
1754 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1755 @retval EFI_OUT_OF_RESOURCES The FilePath file was not found due to lack of
1761 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1762 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1763 IN UDF_VOLUME_INFO
*Volume
,
1764 IN CHAR16
*FilePath
,
1765 IN UDF_FILE_INFO
*Root
,
1766 IN UDF_FILE_INFO
*Parent
,
1767 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*Icb
,
1768 OUT UDF_FILE_INFO
*File
1772 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
1773 CHAR16
*FileNamePointer
;
1774 UDF_FILE_INFO PreviousFile
;
1777 Status
= EFI_NOT_FOUND
;
1779 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
1780 while (*FilePath
!= L
'\0') {
1781 FileNamePointer
= FileName
;
1782 while (*FilePath
!= L
'\0' && *FilePath
!= L
'\\') {
1783 *FileNamePointer
++ = *FilePath
++;
1786 *FileNamePointer
= L
'\0';
1787 if (FileName
[0] == L
'\0') {
1789 // Open root directory.
1793 // There is no file found for the root directory yet. So, find only its
1796 // See UdfOpenVolume() function.
1798 Status
= InternalFindFile (BlockIo
,
1807 // We've already a file pointer (Root) for the root directory. Duplicate
1808 // its FE/EFE and FID descriptors.
1810 DuplicateFe (BlockIo
, Volume
, Root
->FileEntry
, &File
->FileEntry
);
1811 DuplicateFid (Root
->FileIdentifierDesc
, &File
->FileIdentifierDesc
);
1812 Status
= EFI_SUCCESS
;
1816 // No root directory. Find filename from the current directory.
1818 Status
= InternalFindFile (BlockIo
,
1827 if (EFI_ERROR (Status
)) {
1832 // If the found file is a symlink, then find its respective FE/EFE and
1835 if (IS_FE_SYMLINK (File
->FileEntry
)) {
1836 FreePool ((VOID
*)File
->FileIdentifierDesc
);
1838 FileEntry
= File
->FileEntry
;
1840 Status
= ResolveSymlink (BlockIo
,
1847 FreePool (FileEntry
);
1849 if (EFI_ERROR (Status
)) {
1854 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
1855 sizeof (UDF_FILE_INFO
)) != 0) {
1856 CleanupFileInformation (&PreviousFile
);
1859 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
1860 if (*FilePath
!= L
'\0' && *FilePath
== L
'\\') {
1869 Read a directory entry at a time on an UDF volume.
1871 @param[in] BlockIo BlockIo interface.
1872 @param[in] DiskIo DiskIo interface.
1873 @param[in] Volume UDF volume information structure.
1874 @param[in] ParentIcb ICB of the parent file.
1875 @param[in] FileEntryData FE/EFE of the parent file.
1876 @param[in, out] ReadDirInfo Next read directory listing structure
1878 @param[out] FoundFid File Identifier Descriptor pointer.
1880 @retval EFI_SUCCESS Directory entry read.
1881 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
1882 @retval EFI_NO_MEDIA The device has no media.
1883 @retval EFI_DEVICE_ERROR The device reported an error.
1884 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1885 @retval EFI_OUT_OF_RESOURCES The directory entry was not read due to lack of
1890 ReadDirectoryEntry (
1891 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
1892 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
1893 IN UDF_VOLUME_INFO
*Volume
,
1894 IN UDF_LONG_ALLOCATION_DESCRIPTOR
*ParentIcb
,
1895 IN VOID
*FileEntryData
,
1896 IN OUT UDF_READ_DIRECTORY_INFO
*ReadDirInfo
,
1897 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR
**FoundFid
1901 UDF_READ_FILE_INFO ReadFileInfo
;
1902 UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
;
1904 if (ReadDirInfo
->DirectoryData
== NULL
) {
1906 // The directory's recorded data has not been read yet. So let's cache it
1907 // into memory and the next calls won't need to read it again.
1909 ReadFileInfo
.Flags
= READ_FILE_ALLOCATE_AND_READ
;
1919 if (EFI_ERROR (Status
)) {
1924 // Fill in ReadDirInfo structure with the read directory's data information.
1926 ReadDirInfo
->DirectoryData
= ReadFileInfo
.FileData
;
1927 ReadDirInfo
->DirectoryLength
= ReadFileInfo
.ReadLength
;
1931 if (ReadDirInfo
->FidOffset
>= ReadDirInfo
->DirectoryLength
) {
1933 // There are no longer FIDs for this directory. By returning
1934 // EFI_DEVICE_ERROR to the callee will indicate end of directory
1937 return EFI_DEVICE_ERROR
;
1941 // Get FID for this entry.
1943 FileIdentifierDesc
= GET_FID_FROM_ADS (ReadDirInfo
->DirectoryData
,
1944 ReadDirInfo
->FidOffset
);
1946 // Update FidOffset to point to next FID.
1948 ReadDirInfo
->FidOffset
+= GetFidDescriptorLength (FileIdentifierDesc
);
1949 } while (IS_FID_DELETED_FILE (FileIdentifierDesc
));
1951 DuplicateFid (FileIdentifierDesc
, FoundFid
);
1957 Get a filename (encoded in OSTA-compressed format) from a File Identifier
1958 Descriptor on an UDF volume.
1960 @param[in] FileIdentifierDesc File Identifier Descriptor pointer.
1961 @param[out] FileName Decoded filename.
1963 @retval EFI_SUCCESS Filename decoded and read.
1964 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1967 GetFileNameFromFid (
1968 IN UDF_FILE_IDENTIFIER_DESCRIPTOR
*FileIdentifierDesc
,
1969 OUT CHAR16
*FileName
1972 UINT8
*OstaCompressed
;
1973 UINT8 CompressionId
;
1979 (UINT8
*)FileIdentifierDesc
->Data
+
1980 FileIdentifierDesc
->LengthOfImplementationUse
1983 CompressionId
= OstaCompressed
[0];
1984 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
1985 return EFI_VOLUME_CORRUPTED
;
1991 Length
= FileIdentifierDesc
->LengthOfFileIdentifier
;
1992 for (Index
= 1; Index
< Length
; Index
++) {
1993 if (CompressionId
== 16) {
1994 *FileName
= OstaCompressed
[Index
++] << 8;
1999 if (Index
< Length
) {
2000 *FileName
|= (CHAR16
)(OstaCompressed
[Index
]);
2012 Resolve a symlink file on an UDF volume.
2014 @param[in] BlockIo BlockIo interface.
2015 @param[in] DiskIo DiskIo interface.
2016 @param[in] Volume UDF volume information structure.
2017 @param[in] Parent Parent file.
2018 @param[in] FileEntryData FE/EFE structure pointer.
2019 @param[out] File Resolved file.
2021 @retval EFI_SUCCESS Symlink file resolved.
2022 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2023 @retval EFI_NO_MEDIA The device has no media.
2024 @retval EFI_DEVICE_ERROR The device reported an error.
2025 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2026 @retval EFI_OUT_OF_RESOURCES The symlink file was not resolved due to lack of
2032 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2033 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2034 IN UDF_VOLUME_INFO
*Volume
,
2035 IN UDF_FILE_INFO
*Parent
,
2036 IN VOID
*FileEntryData
,
2037 OUT UDF_FILE_INFO
*File
2041 UDF_READ_FILE_INFO ReadFileInfo
;
2045 UDF_PATH_COMPONENT
*PathComp
;
2046 UINT8 PathCompLength
;
2047 CHAR16 FileName
[UDF_FILENAME_LENGTH
];
2050 UINT8 CompressionId
;
2051 UDF_FILE_INFO PreviousFile
;
2054 // Symlink files on UDF volumes do not contain so much data other than
2055 // Path Components which resolves to real filenames, so it's OK to read in
2056 // all its data here -- usually the data will be inline with the FE/EFE for
2059 ReadFileInfo
.Flags
= READ_FILE_ALLOCATE_AND_READ
;
2065 &Parent
->FileIdentifierDesc
->Icb
,
2069 if (EFI_ERROR (Status
)) {
2073 Length
= ReadFileInfo
.ReadLength
;
2075 Data
= (UINT8
*)ReadFileInfo
.FileData
;
2076 EndData
= Data
+ Length
;
2078 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
, sizeof (UDF_FILE_INFO
));
2081 PathComp
= (UDF_PATH_COMPONENT
*)Data
;
2083 PathCompLength
= PathComp
->LengthOfComponentIdentifier
;
2085 switch (PathComp
->ComponentType
) {
2088 // This Path Component specifies the root directory hierarchy subject to
2089 // agreement between the originator and recipient of the medium. Skip it.
2095 // "\\." of the current directory. Read next Path Component.
2097 goto Next_Path_Component
;
2100 // ".." (parent directory). Go to it.
2102 CopyMem ((VOID
*)FileName
, L
"..", 6);
2106 // "." (current file). Duplicate both FE/EFE and FID of this file.
2108 DuplicateFe (BlockIo
, Volume
, PreviousFile
.FileEntry
, &File
->FileEntry
);
2109 DuplicateFid (PreviousFile
.FileIdentifierDesc
,
2110 &File
->FileIdentifierDesc
);
2111 goto Next_Path_Component
;
2114 // This Path Component identifies an object, either a file or a
2115 // directory or an alias.
2117 // Decode it from the compressed data in ComponentIdentifier and find
2120 CompressionId
= PathComp
->ComponentIdentifier
[0];
2121 if (!IS_VALID_COMPRESSION_ID (CompressionId
)) {
2122 return EFI_VOLUME_CORRUPTED
;
2126 for (Index
= 1; Index
< PathCompLength
; Index
++) {
2127 if (CompressionId
== 16) {
2128 *C
= *(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+
2135 if (Index
< Length
) {
2136 *C
|= (CHAR16
)(*(UINT8
*)((UINT8
*)PathComp
->ComponentIdentifier
+ Index
));
2147 // Find file from the read filename in symlink's file data.
2149 Status
= InternalFindFile (
2158 if (EFI_ERROR (Status
)) {
2159 goto Error_Find_File
;
2162 Next_Path_Component
:
2163 Data
+= sizeof (UDF_PATH_COMPONENT
) + PathCompLength
;
2164 if (Data
>= EndData
) {
2168 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2169 sizeof (UDF_FILE_INFO
)) != 0) {
2170 CleanupFileInformation (&PreviousFile
);
2173 CopyMem ((VOID
*)&PreviousFile
, (VOID
*)File
, sizeof (UDF_FILE_INFO
));
2177 // Unmap the symlink file.
2179 FreePool (ReadFileInfo
.FileData
);
2184 if (CompareMem ((VOID
*)&PreviousFile
, (VOID
*)Parent
,
2185 sizeof (UDF_FILE_INFO
)) != 0) {
2186 CleanupFileInformation (&PreviousFile
);
2189 FreePool (ReadFileInfo
.FileData
);
2195 Clean up in-memory UDF volume information.
2197 @param[in] Volume Volume information pointer.
2201 CleanupVolumeInformation (
2202 IN UDF_VOLUME_INFO
*Volume
2207 if (Volume
->LogicalVolDescs
!= NULL
) {
2208 for (Index
= 0; Index
< Volume
->LogicalVolDescsNo
; Index
++) {
2209 FreePool ((VOID
*)Volume
->LogicalVolDescs
[Index
]);
2211 FreePool ((VOID
*)Volume
->LogicalVolDescs
);
2214 if (Volume
->PartitionDescs
!= NULL
) {
2215 for (Index
= 0; Index
< Volume
->PartitionDescsNo
; Index
++) {
2216 FreePool ((VOID
*)Volume
->PartitionDescs
[Index
]);
2218 FreePool ((VOID
*)Volume
->PartitionDescs
);
2221 if (Volume
->FileSetDescs
!= NULL
) {
2222 for (Index
= 0; Index
< Volume
->FileSetDescsNo
; Index
++) {
2223 FreePool ((VOID
*)Volume
->FileSetDescs
[Index
]);
2225 FreePool ((VOID
*)Volume
->FileSetDescs
);
2228 ZeroMem ((VOID
*)Volume
, sizeof (UDF_VOLUME_INFO
));
2232 Clean up in-memory UDF file information.
2234 @param[in] File File information pointer.
2238 CleanupFileInformation (
2239 IN UDF_FILE_INFO
*File
2242 if (File
->FileEntry
!= NULL
) {
2243 FreePool (File
->FileEntry
);
2245 if (File
->FileIdentifierDesc
!= NULL
) {
2246 FreePool ((VOID
*)File
->FileIdentifierDesc
);
2249 ZeroMem ((VOID
*)File
, sizeof (UDF_FILE_INFO
));
2253 Find a file from its absolute path on an UDF volume.
2255 @param[in] BlockIo BlockIo interface.
2256 @param[in] DiskIo DiskIo interface.
2257 @param[in] Volume UDF volume information structure.
2258 @param[in] File File information structure.
2259 @param[out] Size Size of the file.
2261 @retval EFI_SUCCESS File size calculated and set in Size.
2262 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2263 @retval EFI_NO_MEDIA The device has no media.
2264 @retval EFI_DEVICE_ERROR The device reported an error.
2265 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2266 @retval EFI_OUT_OF_RESOURCES The file size was not calculated due to lack of
2272 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2273 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2274 IN UDF_VOLUME_INFO
*Volume
,
2275 IN UDF_FILE_INFO
*File
,
2280 UDF_READ_FILE_INFO ReadFileInfo
;
2282 ReadFileInfo
.Flags
= READ_FILE_GET_FILESIZE
;
2288 &File
->FileIdentifierDesc
->Icb
,
2292 if (EFI_ERROR (Status
)) {
2296 *Size
= ReadFileInfo
.ReadLength
;
2302 Set information about a file on an UDF volume.
2304 @param[in] File File pointer.
2305 @param[in] FileSize Size of the file.
2306 @param[in] FileName Filename of the file.
2307 @param[in, out] BufferSize Size of the returned file infomation.
2308 @param[out] Buffer Data of the returned file information.
2310 @retval EFI_SUCCESS File information set.
2311 @retval EFI_NO_MEDIA The device has no media.
2312 @retval EFI_DEVICE_ERROR The device reported an error.
2313 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2314 @retval EFI_OUT_OF_RESOURCES The file information was not set due to lack of
2320 IN UDF_FILE_INFO
*File
,
2322 IN CHAR16
*FileName
,
2323 IN OUT UINTN
*BufferSize
,
2327 UINTN FileInfoLength
;
2328 EFI_FILE_INFO
*FileInfo
;
2329 UDF_FILE_ENTRY
*FileEntry
;
2330 UDF_EXTENDED_FILE_ENTRY
*ExtendedFileEntry
;
2333 // Calculate the needed size for the EFI_FILE_INFO structure.
2335 FileInfoLength
= sizeof (EFI_FILE_INFO
) + ((FileName
!= NULL
) ?
2336 StrSize (FileName
) :
2338 if (*BufferSize
< FileInfoLength
) {
2340 // The given Buffer has no size enough for EFI_FILE_INFO structure.
2342 *BufferSize
= FileInfoLength
;
2343 return EFI_BUFFER_TOO_SMALL
;
2347 // Buffer now contains room enough to store EFI_FILE_INFO structure.
2348 // Now, fill it in with all necessary information about the file.
2350 FileInfo
= (EFI_FILE_INFO
*)Buffer
;
2351 FileInfo
->Size
= FileInfoLength
;
2352 FileInfo
->Attribute
&= ~EFI_FILE_VALID_ATTR
;
2353 FileInfo
->Attribute
|= EFI_FILE_READ_ONLY
;
2355 if (IS_FID_DIRECTORY_FILE (File
->FileIdentifierDesc
)) {
2356 FileInfo
->Attribute
|= EFI_FILE_DIRECTORY
;
2357 } else if (IS_FID_NORMAL_FILE (File
->FileIdentifierDesc
)) {
2358 FileInfo
->Attribute
|= EFI_FILE_ARCHIVE
;
2361 if (IS_FID_HIDDEN_FILE (File
->FileIdentifierDesc
)) {
2362 FileInfo
->Attribute
|= EFI_FILE_HIDDEN
;
2365 if (IS_FE (File
->FileEntry
)) {
2366 FileEntry
= (UDF_FILE_ENTRY
*)File
->FileEntry
;
2369 // Check if FE has the system attribute set.
2371 if (FileEntry
->IcbTag
.Flags
& (1 << 10)) {
2372 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2375 FileInfo
->FileSize
= FileSize
;
2376 FileInfo
->PhysicalSize
= FileSize
;
2378 FileInfo
->CreateTime
.Year
= FileEntry
->AccessTime
.Year
;
2379 FileInfo
->CreateTime
.Month
= FileEntry
->AccessTime
.Month
;
2380 FileInfo
->CreateTime
.Day
= FileEntry
->AccessTime
.Day
;
2381 FileInfo
->CreateTime
.Hour
= FileEntry
->AccessTime
.Hour
;
2382 FileInfo
->CreateTime
.Minute
= FileEntry
->AccessTime
.Second
;
2383 FileInfo
->CreateTime
.Second
= FileEntry
->AccessTime
.Second
;
2384 FileInfo
->CreateTime
.Nanosecond
=
2385 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2387 FileInfo
->LastAccessTime
.Year
=
2388 FileEntry
->AccessTime
.Year
;
2389 FileInfo
->LastAccessTime
.Month
=
2390 FileEntry
->AccessTime
.Month
;
2391 FileInfo
->LastAccessTime
.Day
=
2392 FileEntry
->AccessTime
.Day
;
2393 FileInfo
->LastAccessTime
.Hour
=
2394 FileEntry
->AccessTime
.Hour
;
2395 FileInfo
->LastAccessTime
.Minute
=
2396 FileEntry
->AccessTime
.Minute
;
2397 FileInfo
->LastAccessTime
.Second
=
2398 FileEntry
->AccessTime
.Second
;
2399 FileInfo
->LastAccessTime
.Nanosecond
=
2400 FileEntry
->AccessTime
.HundredsOfMicroseconds
;
2401 } else if (IS_EFE (File
->FileEntry
)) {
2402 ExtendedFileEntry
= (UDF_EXTENDED_FILE_ENTRY
*)File
->FileEntry
;
2405 // Check if EFE has the system attribute set.
2407 if (ExtendedFileEntry
->IcbTag
.Flags
& (1 << 10)) {
2408 FileInfo
->Attribute
|= EFI_FILE_SYSTEM
;
2411 FileInfo
->FileSize
= FileSize
;
2412 FileInfo
->PhysicalSize
= FileSize
;
2414 FileInfo
->CreateTime
.Year
= ExtendedFileEntry
->CreationTime
.Year
;
2415 FileInfo
->CreateTime
.Month
= ExtendedFileEntry
->CreationTime
.Month
;
2416 FileInfo
->CreateTime
.Day
= ExtendedFileEntry
->CreationTime
.Day
;
2417 FileInfo
->CreateTime
.Hour
= ExtendedFileEntry
->CreationTime
.Hour
;
2418 FileInfo
->CreateTime
.Minute
= ExtendedFileEntry
->CreationTime
.Second
;
2419 FileInfo
->CreateTime
.Second
= ExtendedFileEntry
->CreationTime
.Second
;
2420 FileInfo
->CreateTime
.Nanosecond
=
2421 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2423 FileInfo
->LastAccessTime
.Year
=
2424 ExtendedFileEntry
->AccessTime
.Year
;
2425 FileInfo
->LastAccessTime
.Month
=
2426 ExtendedFileEntry
->AccessTime
.Month
;
2427 FileInfo
->LastAccessTime
.Day
=
2428 ExtendedFileEntry
->AccessTime
.Day
;
2429 FileInfo
->LastAccessTime
.Hour
=
2430 ExtendedFileEntry
->AccessTime
.Hour
;
2431 FileInfo
->LastAccessTime
.Minute
=
2432 ExtendedFileEntry
->AccessTime
.Minute
;
2433 FileInfo
->LastAccessTime
.Second
=
2434 ExtendedFileEntry
->AccessTime
.Second
;
2435 FileInfo
->LastAccessTime
.Nanosecond
=
2436 ExtendedFileEntry
->AccessTime
.HundredsOfMicroseconds
;
2439 FileInfo
->CreateTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2440 FileInfo
->CreateTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2441 FileInfo
->LastAccessTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
2442 FileInfo
->LastAccessTime
.Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
2444 CopyMem ((VOID
*)&FileInfo
->ModificationTime
,
2445 (VOID
*)&FileInfo
->LastAccessTime
,
2448 if (FileName
!= NULL
) {
2449 StrCpyS (FileInfo
->FileName
, StrLen (FileName
) + 1, FileName
);
2451 FileInfo
->FileName
[0] = '\0';
2454 *BufferSize
= FileInfoLength
;
2460 Get volume and free space size information of an UDF volume.
2462 @param[in] BlockIo BlockIo interface.
2463 @param[in] DiskIo DiskIo interface.
2464 @param[in] Volume UDF volume information structure.
2465 @param[out] VolumeSize Volume size.
2466 @param[out] FreeSpaceSize Free space size.
2468 @retval EFI_SUCCESS Volume and free space size calculated.
2469 @retval EFI_NO_MEDIA The device has no media.
2470 @retval EFI_DEVICE_ERROR The device reported an error.
2471 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2472 @retval EFI_OUT_OF_RESOURCES The volume and free space size were not
2473 calculated due to lack of resources.
2478 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2479 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2480 IN UDF_VOLUME_INFO
*Volume
,
2481 OUT UINT64
*VolumeSize
,
2482 OUT UINT64
*FreeSpaceSize
2485 UDF_EXTENT_AD ExtentAd
;
2486 UINT32 LogicalBlockSize
;
2489 UDF_LOGICAL_VOLUME_INTEGRITY
*LogicalVolInt
;
2497 for (Index
= 0; Index
< Volume
->LogicalVolDescsNo
; Index
++) {
2498 CopyMem ((VOID
*)&ExtentAd
,
2499 (VOID
*)&Volume
->LogicalVolDescs
[Index
]->IntegritySequenceExtent
,
2500 sizeof (UDF_EXTENT_AD
));
2501 if (ExtentAd
.ExtentLength
== 0) {
2505 LogicalBlockSize
= LV_BLOCK_SIZE (Volume
, Index
);
2508 LogicalVolInt
= (UDF_LOGICAL_VOLUME_INTEGRITY
*)
2509 AllocatePool (ExtentAd
.ExtentLength
);
2510 if (LogicalVolInt
== NULL
) {
2511 return EFI_OUT_OF_RESOURCES
;
2514 Lsn
= (UINT64
)ExtentAd
.ExtentLocation
;
2516 Status
= DiskIo
->ReadDisk (
2518 BlockIo
->Media
->MediaId
,
2519 MultU64x32 (Lsn
, LogicalBlockSize
),
2520 ExtentAd
.ExtentLength
,
2521 (VOID
*)LogicalVolInt
2523 if (EFI_ERROR (Status
)) {
2524 FreePool ((VOID
*)LogicalVolInt
);
2528 if (!IS_LVID (LogicalVolInt
)) {
2529 FreePool ((VOID
*)LogicalVolInt
);
2530 return EFI_VOLUME_CORRUPTED
;
2533 Length
= LogicalVolInt
->NumberOfPartitions
;
2534 for (Index
= 0; Index
< Length
; Index
+= sizeof (UINT32
)) {
2535 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2536 if (LsnsNo
== 0xFFFFFFFFUL
) {
2538 // Size not specified.
2543 *FreeSpaceSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2546 Length
= (LogicalVolInt
->NumberOfPartitions
* sizeof (UINT32
)) << 1;
2547 for (; Index
< Length
; Index
+= sizeof (UINT32
)) {
2548 LsnsNo
= *(UINT32
*)((UINT8
*)LogicalVolInt
->Data
+ Index
);
2549 if (LsnsNo
== 0xFFFFFFFFUL
) {
2551 // Size not specified.
2556 *VolumeSize
+= MultU64x32 ((UINT64
)LsnsNo
, LogicalBlockSize
);
2559 CopyMem ((VOID
*)&ExtentAd
,(VOID
*)&LogicalVolInt
->NextIntegrityExtent
,
2560 sizeof (UDF_EXTENT_AD
));
2561 if (ExtentAd
.ExtentLength
> 0) {
2562 FreePool ((VOID
*)LogicalVolInt
);
2563 goto Read_Next_Sequence
;
2566 FreePool ((VOID
*)LogicalVolInt
);
2573 Seek a file and read its data into memory on an UDF volume.
2575 @param[in] BlockIo BlockIo interface.
2576 @param[in] DiskIo DiskIo interface.
2577 @param[in] Volume UDF volume information structure.
2578 @param[in] File File information structure.
2579 @param[in] FileSize Size of the file.
2580 @param[in, out] FilePosition File position.
2581 @param[in, out] Buffer File data.
2582 @param[in, out] BufferSize Read size.
2584 @retval EFI_SUCCESS File seeked and read.
2585 @retval EFI_UNSUPPORTED Extended Allocation Descriptors not supported.
2586 @retval EFI_NO_MEDIA The device has no media.
2587 @retval EFI_DEVICE_ERROR The device reported an error.
2588 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2589 @retval EFI_OUT_OF_RESOURCES The file's recorded data was not read due to lack
2595 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
2596 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
2597 IN UDF_VOLUME_INFO
*Volume
,
2598 IN UDF_FILE_INFO
*File
,
2600 IN OUT UINT64
*FilePosition
,
2601 IN OUT VOID
*Buffer
,
2602 IN OUT UINT64
*BufferSize
2606 UDF_READ_FILE_INFO ReadFileInfo
;
2608 ReadFileInfo
.Flags
= READ_FILE_SEEK_AND_READ
;
2609 ReadFileInfo
.FilePosition
= *FilePosition
;
2610 ReadFileInfo
.FileData
= Buffer
;
2611 ReadFileInfo
.FileDataSize
= *BufferSize
;
2612 ReadFileInfo
.FileSize
= FileSize
;
2618 &File
->FileIdentifierDesc
->Icb
,
2622 if (EFI_ERROR (Status
)) {
2626 *BufferSize
= ReadFileInfo
.FileDataSize
;
2627 *FilePosition
= ReadFileInfo
.FilePosition
;
2633 Check if ControllerHandle supports an UDF file system.
2635 @param[in] This Protocol instance pointer.
2636 @param[in] ControllerHandle Handle of device to test.
2638 @retval EFI_SUCCESS UDF file system found.
2639 @retval EFI_UNSUPPORTED UDF file system not found.
2643 SupportUdfFileSystem (
2644 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2645 IN EFI_HANDLE ControllerHandle
2649 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2650 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
2651 EFI_DEVICE_PATH_PROTOCOL
*LastDevicePathNode
;
2652 EFI_GUID
*VendorDefinedGuid
;
2653 EFI_GUID UdfDevPathGuid
= EFI_UDF_DEVICE_PATH_GUID
;
2656 // Open Device Path protocol on ControllerHandle
2658 Status
= gBS
->OpenProtocol (
2660 &gEfiDevicePathProtocolGuid
,
2661 (VOID
**)&DevicePath
,
2662 This
->DriverBindingHandle
,
2664 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2666 if (EFI_ERROR (Status
)) {
2667 return EFI_UNSUPPORTED
;
2670 Status
= EFI_UNSUPPORTED
;
2673 // Get last Device Path node
2675 LastDevicePathNode
= NULL
;
2676 DevicePathNode
= DevicePath
;
2677 while (!IsDevicePathEnd (DevicePathNode
)) {
2678 LastDevicePathNode
= DevicePathNode
;
2679 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
2682 // Check if last Device Path node contains a Vendor-Defined Media Device Path
2683 // of an UDF file system.
2685 if (LastDevicePathNode
!= NULL
&&
2686 DevicePathType (LastDevicePathNode
) == MEDIA_DEVICE_PATH
&&
2687 DevicePathSubType (LastDevicePathNode
) == MEDIA_VENDOR_DP
) {
2688 VendorDefinedGuid
= (EFI_GUID
*)((UINTN
)LastDevicePathNode
+
2689 OFFSET_OF (VENDOR_DEVICE_PATH
, Guid
));
2690 if (CompareGuid (VendorDefinedGuid
, &UdfDevPathGuid
)) {
2691 Status
= EFI_SUCCESS
;
2696 // Close Device Path protocol on ControllerHandle
2698 gBS
->CloseProtocol (
2700 &gEfiDevicePathProtocolGuid
,
2701 This
->DriverBindingHandle
,