TianoCore EDK2 master
Loading...
Searching...
No Matches
FileSystemOperations.c
Go to the documentation of this file.
1
10#include "Udf.h"
11
12//
13// Vendor-Defined Device Path GUID for UDF file system
14//
15EFI_GUID gUdfDevPathGuid = EFI_UDF_DEVICE_PATH_GUID;
16
34 )
35{
36 EFI_STATUS Status;
37 UINT32 BlockSize;
38 EFI_LBA EndLBA;
39 EFI_LBA DescriptorLBAs[4];
40 UINTN Index;
41 UDF_DESCRIPTOR_TAG *DescriptorTag;
42
43 BlockSize = BlockIo->Media->BlockSize;
44 EndLBA = BlockIo->Media->LastBlock;
45 DescriptorLBAs[0] = 256;
46 DescriptorLBAs[1] = EndLBA - 256;
47 DescriptorLBAs[2] = EndLBA;
48 DescriptorLBAs[3] = 512;
49
50 for (Index = 0; Index < ARRAY_SIZE (DescriptorLBAs); Index++) {
51 Status = DiskIo->ReadDisk (
52 DiskIo,
53 BlockIo->Media->MediaId,
54 MultU64x32 (DescriptorLBAs[Index], BlockSize),
56 (VOID *)AnchorPoint
57 );
58 if (EFI_ERROR (Status)) {
59 return Status;
60 }
61
62 DescriptorTag = &AnchorPoint->DescriptorTag;
63
64 //
65 // Check if read LBA has a valid AVDP descriptor.
66 //
67 if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) {
68 return EFI_SUCCESS;
69 }
70 }
71
72 //
73 // No AVDP found.
74 //
75 return EFI_VOLUME_CORRUPTED;
76}
77
99 OUT UDF_VOLUME_INFO *Volume
100 )
101{
102 EFI_STATUS Status;
103 UINT32 BlockSize;
104 UDF_EXTENT_AD *ExtentAd;
105 EFI_LBA SeqStartBlock;
106 EFI_LBA SeqEndBlock;
107 BOOLEAN StopSequence;
108 VOID *Buffer;
109 UDF_DESCRIPTOR_TAG *DescriptorTag;
110 UINT32 LogicalBlockSize;
111
112 BlockSize = BlockIo->Media->BlockSize;
113 ExtentAd = &AnchorPoint->MainVolumeDescriptorSequenceExtent;
114
115 //
116 // Allocate buffer for reading disk blocks
117 //
118 Buffer = AllocateZeroPool ((UINTN)BlockSize);
119 if (Buffer == NULL) {
120 return EFI_OUT_OF_RESOURCES;
121 }
122
123 //
124 // The logical partition created by Partition driver is relative to the main
125 // VDS extent location, so we start the Main Volume Descriptor Sequence at
126 // LBA 0.
127 //
128 // We don't need to check again if we have valid Volume Descriptors here since
129 // Partition driver already did.
130 //
131 SeqStartBlock = 0;
132 SeqEndBlock = SeqStartBlock + DivU64x32 (
133 (UINT64)ExtentAd->ExtentLength,
134 BlockSize
135 );
136 StopSequence = FALSE;
137 for ( ; SeqStartBlock < SeqEndBlock && !StopSequence; SeqStartBlock++) {
138 //
139 // Read disk block
140 //
141 Status = BlockIo->ReadBlocks (
142 BlockIo,
143 BlockIo->Media->MediaId,
144 SeqStartBlock,
145 BlockSize,
146 Buffer
147 );
148 if (EFI_ERROR (Status)) {
149 goto Out_Free;
150 }
151
152 DescriptorTag = Buffer;
153
154 switch (DescriptorTag->TagIdentifier) {
155 case UdfPartitionDescriptor:
156 //
157 // Save Partition Descriptor
158 //
159 CopyMem (&Volume->PartitionDesc, Buffer, sizeof (Volume->PartitionDesc));
160 break;
161
162 case UdfLogicalVolumeDescriptor:
163 //
164 // Save Logical Volume Descriptor
165 //
166 CopyMem (&Volume->LogicalVolDesc, Buffer, sizeof (Volume->LogicalVolDesc));
167 break;
168
169 case UdfTerminatingDescriptor:
170 StopSequence = TRUE;
171 break;
172
173 default:
174 ;
175 }
176 }
177
178 //
179 // Determine FE (File Entry) size
180 //
181 LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
182 if (LogicalBlockSize >= UDF_LOGICAL_SECTOR_SIZE) {
183 Volume->FileEntrySize = (UINTN)LogicalBlockSize;
184 } else {
185 Volume->FileEntrySize = UDF_LOGICAL_SECTOR_SIZE;
186 }
187
188 Status = EFI_SUCCESS;
189
190Out_Free:
191 //
192 // Free block read buffer
193 //
194 FreePool (Buffer);
195
196 return Status;
197}
198
212 IN UDF_VOLUME_INFO *Volume,
214 )
215{
216 UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
217 UINT16 PartitionNum;
218
219 LogicalVolDesc = &Volume->LogicalVolDesc;
220
221 switch (LogicalVolDesc->DomainIdentifier.Suffix.Domain.UdfRevision) {
222 case 0x0102:
223 case 0x0150:
224 case 0x0200:
225 case 0x0201:
226 case 0x0250:
227 case 0x0260:
228 //
229 // UDF 1.02 specification:
230 //
231 // There shall be exactly one prevailing Logical Volume Descriptor recorded
232 // per Volume Set. The Partition Maps field shall contain only Type 1
233 // Partition Maps.
234 //
235 // UDF 1.50 through 2.60 specs say:
236 //
237 // For the purpose of interchange partition maps shall be limited to
238 // Partition Map type 1, except type 2 maps as described in the document.
239 //
240 // NOTE: Only one Type 1 (Physical) Partition is supported. It has been
241 // checked already in Partition driver for existence of a single Type 1
242 // Partition map. Hence, the 'PartitionReferenceNumber' field (the index
243 // used to access Partition Maps data within the Logical Volume Descriptor)
244 // in the Long Allocation Descriptor should be 0 to indicate there is only
245 // one partition.
246 //
247 if (LongAd->ExtentLocation.PartitionReferenceNumber != 0) {
248 return NULL;
249 }
250
251 //
252 // Since only one partition, get the first one directly.
253 //
254 PartitionNum = *(UINT16 *)((UINTN)&LogicalVolDesc->PartitionMaps[4]);
255 break;
256
257 default:
258 //
259 // Unsupported UDF revision
260 //
261 return NULL;
262 }
263
264 //
265 // Check if partition number matches Partition Descriptor found in Main Volume
266 // Descriptor Sequence.
267 //
268 if (Volume->PartitionDesc.PartitionNumber == PartitionNum) {
269 return &Volume->PartitionDesc;
270 }
271
272 return NULL;
273}
274
289 IN UDF_VOLUME_INFO *Volume,
291 OUT UINT64 *Lsn
292 )
293{
294 UDF_PARTITION_DESCRIPTOR *PartitionDesc;
295
296 PartitionDesc = GetPdFromLongAd (Volume, LongAd);
297 if (PartitionDesc == NULL) {
298 DEBUG ((
299 DEBUG_ERROR,
300 "%a: Fail to get the Partition Descriptor from the given Long Allocation Descriptor.\n",
301 __func__
302 ));
303 return EFI_UNSUPPORTED;
304 }
305
306 *Lsn = (UINT64)PartitionDesc->PartitionStartingLocation -
307 Volume->MainVdsStartLocation +
308 LongAd->ExtentLocation.LogicalBlockNumber;
309
310 return EFI_SUCCESS;
311}
312
323UINT64
325 IN UDF_VOLUME_INFO *Volume,
326 IN UDF_PARTITION_DESCRIPTOR *PartitionDesc,
328 )
329{
330 return (UINT64)PartitionDesc->PartitionStartingLocation -
331 Volume->MainVdsStartLocation + ShortAd->ExtentPosition;
332}
333
351 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
352 IN EFI_DISK_IO_PROTOCOL *DiskIo,
353 IN UDF_VOLUME_INFO *Volume
354 )
355{
356 EFI_STATUS Status;
357 UINT64 Lsn;
358 UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
359 UDF_DESCRIPTOR_TAG *DescriptorTag;
360
361 LogicalVolDesc = &Volume->LogicalVolDesc;
362 Status = GetLongAdLsn (Volume, &LogicalVolDesc->LogicalVolumeContentsUse, &Lsn);
363 if (EFI_ERROR (Status)) {
364 return Status;
365 }
366
367 //
368 // As per UDF 2.60 specification:
369 //
370 // There shall be exactly one File Set Descriptor recorded per Logical
371 // Volume.
372 //
373 // Read disk block
374 //
375 Status = DiskIo->ReadDisk (
376 DiskIo,
377 BlockIo->Media->MediaId,
378 MultU64x32 (Lsn, LogicalVolDesc->LogicalBlockSize),
379 sizeof (Volume->FileSetDesc),
380 &Volume->FileSetDesc
381 );
382 if (EFI_ERROR (Status)) {
383 return Status;
384 }
385
386 DescriptorTag = &Volume->FileSetDesc.DescriptorTag;
387
388 //
389 // Check if read block is a File Set Descriptor
390 //
391 if (DescriptorTag->TagIdentifier != UdfFileSetDescriptor) {
392 return EFI_VOLUME_CORRUPTED;
393 }
394
395 return EFI_SUCCESS;
396}
397
411 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
412 IN EFI_DISK_IO_PROTOCOL *DiskIo,
413 OUT UDF_VOLUME_INFO *Volume
414 )
415{
416 EFI_STATUS Status;
418 UDF_EXTENT_AD *ExtentAd;
419
420 //
421 // Find Anchor Volume Descriptor Pointer
422 //
424 BlockIo,
425 DiskIo,
426 &AnchorPoint
427 );
428 if (EFI_ERROR (Status)) {
429 return Status;
430 }
431
432 //
433 // Save Main VDS start block number
434 //
435 ExtentAd = &AnchorPoint.MainVolumeDescriptorSequenceExtent;
436
437 Volume->MainVdsStartLocation = (UINT64)ExtentAd->ExtentLocation;
438
439 //
440 // Start Main Volume Descriptor Sequence.
441 //
443 BlockIo,
444 DiskIo,
445 &AnchorPoint,
446 Volume
447 );
448 if (EFI_ERROR (Status)) {
449 return Status;
450 }
451
452 return Status;
453}
454
463UINT64
465 IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc
466 )
467{
468 return (UINT64)(
470 FileIdentifierDesc->LengthOfFileIdentifier +
471 FileIdentifierDesc->LengthOfImplementationUse) >> 2) << 2
472 );
473}
474
482VOID
484 IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,
485 OUT UDF_FILE_IDENTIFIER_DESCRIPTOR **NewFileIdentifierDesc
486 )
487{
488 *NewFileIdentifierDesc =
490 (UINTN)GetFidDescriptorLength (FileIdentifierDesc),
491 FileIdentifierDesc
492 );
493}
494
504VOID
506 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
507 IN UDF_VOLUME_INFO *Volume,
508 IN VOID *FileEntry,
509 OUT VOID **NewFileEntry
510 )
511{
512 *NewFileEntry = AllocateCopyPool (Volume->FileEntrySize, FileEntry);
513}
514
543 IN VOID *FileEntryData,
544 IN UINTN FileEntrySize,
545 OUT VOID **Data,
546 OUT UINT64 *Length
547 )
548{
549 UDF_DESCRIPTOR_TAG *DescriptorTag;
550 UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;
551 UDF_FILE_ENTRY *FileEntry;
552
553 DescriptorTag = FileEntryData;
554
555 if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
556 ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
557
558 *Length = ExtendedFileEntry->InformationLength;
559 *Data = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
560 ExtendedFileEntry->LengthOfExtendedAttributes);
561 } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {
562 FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
563
564 *Length = FileEntry->InformationLength;
565 *Data = (VOID *)((UINT8 *)FileEntry->Data +
566 FileEntry->LengthOfExtendedAttributes);
567 }
568
569 if ((*Length > FileEntrySize) ||
570 ((UINTN)FileEntryData > (UINTN)(*Data)) ||
571 ((UINTN)(*Data) - (UINTN)FileEntryData > FileEntrySize - *Length))
572 {
573 return EFI_VOLUME_CORRUPTED;
574 }
575
576 return EFI_SUCCESS;
577}
578
602 IN VOID *FileEntryData,
603 IN UINTN FileEntrySize,
604 OUT VOID **AdsData,
605 OUT UINT64 *Length
606 )
607{
608 UDF_DESCRIPTOR_TAG *DescriptorTag;
609 UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;
610 UDF_FILE_ENTRY *FileEntry;
611
612 DescriptorTag = FileEntryData;
613
614 if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
615 ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)FileEntryData;
616
617 *Length = ExtendedFileEntry->LengthOfAllocationDescriptors;
618 *AdsData = (VOID *)((UINT8 *)ExtendedFileEntry->Data +
619 ExtendedFileEntry->LengthOfExtendedAttributes);
620 } else if (DescriptorTag->TagIdentifier == UdfFileEntry) {
621 FileEntry = (UDF_FILE_ENTRY *)FileEntryData;
622
623 *Length = FileEntry->LengthOfAllocationDescriptors;
624 *AdsData = (VOID *)((UINT8 *)FileEntry->Data +
625 FileEntry->LengthOfExtendedAttributes);
626 }
627
628 if ((*Length > FileEntrySize) ||
629 ((UINTN)FileEntryData > (UINTN)(*AdsData)) ||
630 ((UINTN)(*AdsData) - (UINTN)FileEntryData > FileEntrySize - *Length))
631 {
632 return EFI_VOLUME_CORRUPTED;
633 }
634
635 return EFI_SUCCESS;
636}
637
652 IN VOID *Data,
653 IN OUT UINT64 *Offset,
654 IN UINT64 Length,
656 )
657{
659 UDF_EXTENT_FLAGS ExtentFlags;
660
661 for ( ; ;) {
662 if (*Offset >= Length) {
663 //
664 // No more Long Allocation Descriptors.
665 //
666 return EFI_DEVICE_ERROR;
667 }
668
669 LongAd =
670 (UDF_LONG_ALLOCATION_DESCRIPTOR *)((UINT8 *)Data + *Offset);
671
672 //
673 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
674 // allocated AD, then return it.
675 //
676 ExtentFlags = GET_EXTENT_FLAGS (LongAdsSequence, LongAd);
677 if ((ExtentFlags == ExtentIsNextExtent) ||
678 (ExtentFlags == ExtentRecordedAndAllocated))
679 {
680 break;
681 }
682
683 //
684 // This AD is either not recorded but allocated, or not recorded and not
685 // allocated. Skip it.
686 //
687 *Offset += AD_LENGTH (LongAdsSequence);
688 }
689
690 *FoundLongAd = LongAd;
691
692 return EFI_SUCCESS;
693}
694
709 IN VOID *Data,
710 IN OUT UINT64 *Offset,
711 IN UINT64 Length,
713 )
714{
716 UDF_EXTENT_FLAGS ExtentFlags;
717
718 for ( ; ;) {
719 if (*Offset >= Length) {
720 //
721 // No more Short Allocation Descriptors.
722 //
723 return EFI_DEVICE_ERROR;
724 }
725
726 ShortAd =
727 (UDF_SHORT_ALLOCATION_DESCRIPTOR *)((UINT8 *)Data + *Offset);
728
729 //
730 // If it's either an indirect AD (Extended Alllocation Descriptor) or an
731 // allocated AD, then return it.
732 //
733 ExtentFlags = GET_EXTENT_FLAGS (ShortAdsSequence, ShortAd);
734 if ((ExtentFlags == ExtentIsNextExtent) ||
735 (ExtentFlags == ExtentRecordedAndAllocated))
736 {
737 break;
738 }
739
740 //
741 // This AD is either not recorded but allocated, or not recorded and not
742 // allocated. Skip it.
743 //
744 *Offset += AD_LENGTH (ShortAdsSequence);
745 }
746
747 *FoundShortAd = ShortAd;
748
749 return EFI_SUCCESS;
750}
751
769 IN UDF_FE_RECORDING_FLAGS RecordingFlags,
770 IN VOID *Data,
771 IN OUT UINT64 *Offset,
772 IN UINT64 Length,
773 OUT VOID **FoundAd
774 )
775{
776 if (RecordingFlags == LongAdsSequence) {
777 return GetLongAdFromAds (
778 Data,
779 Offset,
780 Length,
782 );
783 } else if (RecordingFlags == ShortAdsSequence) {
784 return GetShortAdFromAds (
785 Data,
786 Offset,
787 Length,
789 );
790 }
791
792 //
793 // Code should never reach here.
794 //
795 ASSERT (FALSE);
796 return EFI_DEVICE_ERROR;
797}
798
817 IN UDF_FE_RECORDING_FLAGS RecordingFlags,
818 IN UDF_VOLUME_INFO *Volume,
820 IN VOID *Ad,
821 OUT UINT64 *Lsn
822 )
823{
824 UDF_PARTITION_DESCRIPTOR *PartitionDesc;
825
826 if (RecordingFlags == LongAdsSequence) {
827 return GetLongAdLsn (Volume, (UDF_LONG_ALLOCATION_DESCRIPTOR *)Ad, Lsn);
828 } else if (RecordingFlags == ShortAdsSequence) {
829 PartitionDesc = GetPdFromLongAd (Volume, ParentIcb);
830 if (PartitionDesc == NULL) {
831 return EFI_UNSUPPORTED;
832 }
833
834 *Lsn = GetShortAdLsn (
835 Volume,
836 PartitionDesc,
838 );
839 return EFI_SUCCESS;
840 }
841
842 //
843 // Code should never reach here.
844 //
845 ASSERT (FALSE);
846 return EFI_UNSUPPORTED;
847}
848
872 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
873 IN EFI_DISK_IO_PROTOCOL *DiskIo,
874 IN UDF_VOLUME_INFO *Volume,
876 IN UDF_FE_RECORDING_FLAGS RecordingFlags,
877 IN VOID *Ad,
878 OUT UINT64 *Offset,
879 OUT UINT64 *Length
880 )
881{
882 EFI_STATUS Status;
883 UINT32 ExtentLength;
884 UINT64 Lsn;
885 VOID *Data;
886 UINT32 LogicalBlockSize;
888 UDF_DESCRIPTOR_TAG *DescriptorTag;
889
890 ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);
892 RecordingFlags,
893 Volume,
894 ParentIcb,
895 Ad,
896 &Lsn
897 );
898 if (EFI_ERROR (Status)) {
899 return Status;
900 }
901
902 Data = AllocatePool (ExtentLength);
903 if (Data == NULL) {
904 return EFI_OUT_OF_RESOURCES;
905 }
906
907 LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
908
909 //
910 // Read extent.
911 //
912 Status = DiskIo->ReadDisk (
913 DiskIo,
914 BlockIo->Media->MediaId,
915 MultU64x32 (Lsn, LogicalBlockSize),
916 ExtentLength,
917 Data
918 );
919 if (EFI_ERROR (Status)) {
920 goto Exit;
921 }
922
923 AllocExtDesc = (UDF_ALLOCATION_EXTENT_DESCRIPTOR *)Data;
924
925 DescriptorTag = &AllocExtDesc->DescriptorTag;
926
927 //
928 // Check if read extent contains a valid tag identifier for AED.
929 //
930 if (DescriptorTag->TagIdentifier != UdfAllocationExtentDescriptor) {
931 Status = EFI_VOLUME_CORRUPTED;
932 goto Exit;
933 }
934
935 //
936 // Get AED's block offset and its length.
937 //
938 *Offset = MultU64x32 (Lsn, LogicalBlockSize) +
940 *Length = AllocExtDesc->LengthOfAllocationDescriptors;
941
942Exit:
943 FreePool (Data);
944
945 return Status;
946}
947
969 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
970 IN EFI_DISK_IO_PROTOCOL *DiskIo,
971 IN UDF_VOLUME_INFO *Volume,
973 IN UDF_FE_RECORDING_FLAGS RecordingFlags,
974 IN VOID *Ad,
975 OUT VOID **Data,
976 OUT UINT64 *Length
977 )
978{
979 EFI_STATUS Status;
980 UINT64 Offset;
981
982 //
983 // Get AED's offset + length.
984 //
985 Status = GetAedAdsOffset (
986 BlockIo,
987 DiskIo,
988 Volume,
989 ParentIcb,
990 RecordingFlags,
991 Ad,
992 &Offset,
993 Length
994 );
995 if (EFI_ERROR (Status)) {
996 return Status;
997 }
998
999 //
1000 // Allocate buffer to read in AED's data.
1001 //
1002 *Data = AllocatePool ((UINTN)(*Length));
1003 if (*Data == NULL) {
1004 return EFI_OUT_OF_RESOURCES;
1005 }
1006
1007 return DiskIo->ReadDisk (
1008 DiskIo,
1009 BlockIo->Media->MediaId,
1010 Offset,
1011 (UINTN)(*Length),
1012 *Data
1013 );
1014}
1015
1031 IN UDF_FE_RECORDING_FLAGS RecordingFlags,
1032 IN VOID *Ad,
1033 IN OUT VOID **Buffer,
1034 IN UINT64 Length
1035 )
1036{
1037 UINT32 ExtentLength;
1038
1039 ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);
1040
1041 if (*Buffer == NULL) {
1042 *Buffer = AllocatePool (ExtentLength);
1043 if (*Buffer == NULL) {
1044 return EFI_OUT_OF_RESOURCES;
1045 }
1046 } else {
1047 *Buffer = ReallocatePool ((UINTN)Length, (UINTN)(Length + ExtentLength), *Buffer);
1048 if (*Buffer == NULL) {
1049 return EFI_OUT_OF_RESOURCES;
1050 }
1051 }
1052
1053 return EFI_SUCCESS;
1054}
1055
1078 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
1079 IN EFI_DISK_IO_PROTOCOL *DiskIo,
1080 IN UDF_VOLUME_INFO *Volume,
1082 IN VOID *FileEntryData,
1083 IN OUT UDF_READ_FILE_INFO *ReadFileInfo
1084 )
1085{
1086 EFI_STATUS Status;
1087 UINT32 LogicalBlockSize;
1088 VOID *Data;
1089 VOID *DataBak;
1090 UINT64 Length;
1091 VOID *Ad;
1092 UINT64 AdOffset;
1093 UINT64 Lsn;
1094 BOOLEAN DoFreeAed;
1095 UINT64 FilePosition;
1096 UINT64 Offset;
1097 UINT64 DataOffset;
1098 UINT64 BytesLeft;
1099 UINT64 DataLength;
1100 BOOLEAN FinishedSeeking;
1101 UINT32 ExtentLength;
1102 UDF_FE_RECORDING_FLAGS RecordingFlags;
1103
1104 LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
1105 DoFreeAed = FALSE;
1106
1107 //
1108 // set BytesLeft to suppress incorrect compiler/analyzer warnings
1109 //
1110 BytesLeft = 0;
1111 DataOffset = 0;
1112 FilePosition = 0;
1113 FinishedSeeking = FALSE;
1114 Data = NULL;
1115
1116 switch (ReadFileInfo->Flags) {
1117 case ReadFileGetFileSize:
1118 case ReadFileAllocateAndRead:
1119 //
1120 // Initialise ReadFileInfo structure for either getting file size, or
1121 // reading file's recorded data.
1122 //
1123 ReadFileInfo->ReadLength = 0;
1124 ReadFileInfo->FileData = NULL;
1125 break;
1126 case ReadFileSeekAndRead:
1127 //
1128 // About to seek a file and/or read its data.
1129 //
1130 Length = ReadFileInfo->FileSize - ReadFileInfo->FilePosition;
1131 if (ReadFileInfo->FileDataSize > Length) {
1132 //
1133 // About to read beyond the EOF -- truncate it.
1134 //
1135 ReadFileInfo->FileDataSize = Length;
1136 }
1137
1138 //
1139 // Initialise data to start seeking and/or reading a file.
1140 //
1141 BytesLeft = ReadFileInfo->FileDataSize;
1142 DataOffset = 0;
1143 FilePosition = 0;
1144 FinishedSeeking = FALSE;
1145
1146 break;
1147 }
1148
1149 RecordingFlags = GET_FE_RECORDING_FLAGS (FileEntryData);
1150 switch (RecordingFlags) {
1151 case InlineData:
1152 //
1153 // There are no extents for this FE/EFE. All data is inline.
1154 //
1155 Status = GetFileEntryData (FileEntryData, Volume->FileEntrySize, &Data, &Length);
1156 if (EFI_ERROR (Status)) {
1157 return Status;
1158 }
1159
1160 if (ReadFileInfo->Flags == ReadFileGetFileSize) {
1161 ReadFileInfo->ReadLength = Length;
1162 } else if (ReadFileInfo->Flags == ReadFileAllocateAndRead) {
1163 //
1164 // Allocate buffer for starting read data.
1165 //
1166 ReadFileInfo->FileData = AllocatePool ((UINTN)Length);
1167 if (ReadFileInfo->FileData == NULL) {
1168 return EFI_OUT_OF_RESOURCES;
1169 }
1170
1171 //
1172 // Read all inline data into ReadFileInfo->FileData
1173 //
1174 CopyMem (ReadFileInfo->FileData, Data, (UINTN)Length);
1175 ReadFileInfo->ReadLength = Length;
1176 } else if (ReadFileInfo->Flags == ReadFileSeekAndRead) {
1177 //
1178 // If FilePosition is non-zero, seek file to FilePosition, read
1179 // FileDataSize bytes and then updates FilePosition.
1180 //
1181 CopyMem (
1182 ReadFileInfo->FileData,
1183 (VOID *)((UINT8 *)Data + ReadFileInfo->FilePosition),
1184 (UINTN)ReadFileInfo->FileDataSize
1185 );
1186
1187 ReadFileInfo->FilePosition += ReadFileInfo->FileDataSize;
1188 } else {
1189 ASSERT (FALSE);
1190 return EFI_INVALID_PARAMETER;
1191 }
1192
1193 Status = EFI_SUCCESS;
1194 break;
1195
1196 case LongAdsSequence:
1197 case ShortAdsSequence:
1198 //
1199 // This FE/EFE contains a run of Allocation Descriptors. Get data + size
1200 // for start reading them out.
1201 //
1202 Status = GetAdsInformation (FileEntryData, Volume->FileEntrySize, &Data, &Length);
1203 if (EFI_ERROR (Status)) {
1204 return Status;
1205 }
1206
1207 AdOffset = 0;
1208
1209 for ( ; ;) {
1210 //
1211 // Read AD.
1212 //
1213 Status = GetAllocationDescriptor (
1214 RecordingFlags,
1215 Data,
1216 &AdOffset,
1217 Length,
1218 &Ad
1219 );
1220 if (Status == EFI_DEVICE_ERROR) {
1221 Status = EFI_SUCCESS;
1222 goto Done;
1223 }
1224
1225 //
1226 // Check if AD is an indirect AD. If so, read Allocation Extent
1227 // Descriptor and its extents (ADs).
1228 //
1229 if (GET_EXTENT_FLAGS (RecordingFlags, Ad) == ExtentIsNextExtent) {
1230 DataBak = Data;
1231 Status = GetAedAdsData (
1232 BlockIo,
1233 DiskIo,
1234 Volume,
1235 ParentIcb,
1236 RecordingFlags,
1237 Ad,
1238 &Data,
1239 &Length
1240 );
1241
1242 if (!DoFreeAed) {
1243 DoFreeAed = TRUE;
1244 } else {
1245 FreePool (DataBak);
1246 }
1247
1248 if (EFI_ERROR (Status)) {
1249 goto Error_Get_Aed;
1250 }
1251
1252 ASSERT (Data != NULL);
1253
1254 AdOffset = 0;
1255 continue;
1256 }
1257
1258 ExtentLength = GET_EXTENT_LENGTH (RecordingFlags, Ad);
1259
1261 RecordingFlags,
1262 Volume,
1263 ParentIcb,
1264 Ad,
1265 &Lsn
1266 );
1267 if (EFI_ERROR (Status)) {
1268 goto Done;
1269 }
1270
1271 switch (ReadFileInfo->Flags) {
1272 case ReadFileGetFileSize:
1273 ReadFileInfo->ReadLength += ExtentLength;
1274 break;
1275 case ReadFileAllocateAndRead:
1276 //
1277 // Increase FileData (if necessary) to read next extent.
1278 //
1279 Status = GrowUpBufferToNextAd (
1280 RecordingFlags,
1281 Ad,
1282 &ReadFileInfo->FileData,
1283 ReadFileInfo->ReadLength
1284 );
1285 if (EFI_ERROR (Status)) {
1286 goto Error_Alloc_Buffer_To_Next_Ad;
1287 }
1288
1289 //
1290 // Read extent's data into FileData.
1291 //
1292 Status = DiskIo->ReadDisk (
1293 DiskIo,
1294 BlockIo->Media->MediaId,
1295 MultU64x32 (Lsn, LogicalBlockSize),
1296 ExtentLength,
1297 (VOID *)((UINT8 *)ReadFileInfo->FileData +
1298 ReadFileInfo->ReadLength)
1299 );
1300 if (EFI_ERROR (Status)) {
1301 goto Error_Read_Disk_Blk;
1302 }
1303
1304 ReadFileInfo->ReadLength += ExtentLength;
1305 break;
1306 case ReadFileSeekAndRead:
1307 //
1308 // Seek file first before reading in its data.
1309 //
1310 if (FinishedSeeking) {
1311 Offset = 0;
1312 goto Skip_File_Seek;
1313 }
1314
1315 if (FilePosition + ExtentLength < ReadFileInfo->FilePosition) {
1316 FilePosition += ExtentLength;
1317 goto Skip_Ad;
1318 }
1319
1320 if (FilePosition + ExtentLength > ReadFileInfo->FilePosition) {
1321 Offset = ReadFileInfo->FilePosition - FilePosition;
1322 } else {
1323 Offset = 0;
1324 }
1325
1326 //
1327 // Done with seeking file. Start reading its data.
1328 //
1329 FinishedSeeking = TRUE;
1330
1331Skip_File_Seek:
1332 //
1333 // Make sure we don't read more data than really wanted.
1334 //
1335 if (ExtentLength - Offset > BytesLeft) {
1336 DataLength = BytesLeft;
1337 } else {
1338 DataLength = ExtentLength - Offset;
1339 }
1340
1341 //
1342 // Read extent's data into FileData.
1343 //
1344 Status = DiskIo->ReadDisk (
1345 DiskIo,
1346 BlockIo->Media->MediaId,
1347 Offset + MultU64x32 (Lsn, LogicalBlockSize),
1348 (UINTN)DataLength,
1349 (VOID *)((UINT8 *)ReadFileInfo->FileData +
1350 DataOffset)
1351 );
1352 if (EFI_ERROR (Status)) {
1353 goto Error_Read_Disk_Blk;
1354 }
1355
1356 //
1357 // Update current file's position.
1358 //
1359 DataOffset += DataLength;
1360 ReadFileInfo->FilePosition += DataLength;
1361
1362 BytesLeft -= DataLength;
1363 if (BytesLeft == 0) {
1364 //
1365 // There is no more file data to read.
1366 //
1367 Status = EFI_SUCCESS;
1368 goto Done;
1369 }
1370
1371 break;
1372 }
1373
1374Skip_Ad:
1375 //
1376 // Point to the next AD (extent).
1377 //
1378 AdOffset += AD_LENGTH (RecordingFlags);
1379 }
1380
1381 break;
1382 case ExtendedAdsSequence:
1383 // FIXME: Not supported. Got no volume with it, yet.
1384 ASSERT (FALSE);
1385 Status = EFI_UNSUPPORTED;
1386 break;
1387
1388 default:
1389 //
1390 // A flag value reserved by the ECMA-167 standard (3rd Edition - June
1391 // 1997); 14.6 ICB Tag; 14.6.8 Flags (RBP 18); was found.
1392 //
1393 Status = EFI_UNSUPPORTED;
1394 break;
1395 }
1396
1397Done:
1398 if (DoFreeAed) {
1399 FreePool (Data);
1400 }
1401
1402 return Status;
1403
1404Error_Read_Disk_Blk:
1405Error_Alloc_Buffer_To_Next_Ad:
1406 if (ReadFileInfo->Flags != ReadFileSeekAndRead) {
1407 FreePool (ReadFileInfo->FileData);
1408 }
1409
1410 if (DoFreeAed) {
1411 FreePool (Data);
1412 }
1413
1414Error_Get_Aed:
1415 return Status;
1416}
1417
1436 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
1437 IN EFI_DISK_IO_PROTOCOL *DiskIo,
1438 IN UDF_VOLUME_INFO *Volume,
1439 IN CHAR16 *FileName,
1440 IN UDF_FILE_INFO *Parent,
1442 OUT UDF_FILE_INFO *File
1443 )
1444{
1445 EFI_STATUS Status;
1446 UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
1447 UDF_READ_DIRECTORY_INFO ReadDirInfo;
1448 BOOLEAN Found;
1449 CHAR16 FoundFileName[UDF_FILENAME_LENGTH];
1450 VOID *CompareFileEntry;
1451
1452 //
1453 // Check if both Parent->FileIdentifierDesc and Icb are NULL.
1454 //
1455 if ((Parent->FileIdentifierDesc == NULL) && (Icb == NULL)) {
1456 return EFI_INVALID_PARAMETER;
1457 }
1458
1459 //
1460 // Check if parent file is really directory.
1461 //
1462 if (FE_ICB_FILE_TYPE (Parent->FileEntry) != UdfFileEntryDirectory) {
1463 return EFI_NOT_FOUND;
1464 }
1465
1466 //
1467 // If FileName is current file or working directory, just duplicate Parent's
1468 // FE/EFE and FID descriptors.
1469 //
1470 if (StrCmp (FileName, L".") == 0) {
1471 if (Parent->FileIdentifierDesc == NULL) {
1472 return EFI_INVALID_PARAMETER;
1473 }
1474
1475 DuplicateFe (BlockIo, Volume, Parent->FileEntry, &File->FileEntry);
1476 if (File->FileEntry == NULL) {
1477 return EFI_OUT_OF_RESOURCES;
1478 }
1479
1480 DuplicateFid (Parent->FileIdentifierDesc, &File->FileIdentifierDesc);
1481 if (File->FileIdentifierDesc == NULL) {
1482 FreePool (File->FileEntry);
1483 return EFI_OUT_OF_RESOURCES;
1484 }
1485
1486 return EFI_SUCCESS;
1487 }
1488
1489 //
1490 // Start directory listing.
1491 //
1492 ZeroMem ((VOID *)&ReadDirInfo, sizeof (UDF_READ_DIRECTORY_INFO));
1493 Found = FALSE;
1494
1495 for ( ; ;) {
1496 Status = ReadDirectoryEntry (
1497 BlockIo,
1498 DiskIo,
1499 Volume,
1500 (Parent->FileIdentifierDesc != NULL) ?
1501 &Parent->FileIdentifierDesc->Icb :
1502 Icb,
1503 Parent->FileEntry,
1504 &ReadDirInfo,
1505 &FileIdentifierDesc
1506 );
1507 if (EFI_ERROR (Status)) {
1508 if (Status == EFI_DEVICE_ERROR) {
1509 Status = EFI_NOT_FOUND;
1510 }
1511
1512 break;
1513 }
1514
1515 //
1516 // After calling function ReadDirectoryEntry(), if 'FileIdentifierDesc' is
1517 // NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the code
1518 // reaches here, 'FileIdentifierDesc' must be not NULL.
1519 //
1520 // The ASSERT here is for addressing a false positive NULL pointer
1521 // dereference issue raised from static analysis.
1522 //
1523 ASSERT (FileIdentifierDesc != NULL);
1524
1525 if (FileIdentifierDesc->FileCharacteristics & PARENT_FILE) {
1526 //
1527 // This FID contains the location (FE/EFE) of the parent directory of this
1528 // directory (Parent), and if FileName is either ".." or "\\", then it's
1529 // the expected FID.
1530 //
1531 if ((StrCmp (FileName, L"..") == 0) || (StrCmp (FileName, L"\\") == 0)) {
1532 Found = TRUE;
1533 break;
1534 }
1535 } else {
1536 Status = GetFileNameFromFid (FileIdentifierDesc, ARRAY_SIZE (FoundFileName), FoundFileName);
1537 if (EFI_ERROR (Status)) {
1538 break;
1539 }
1540
1541 if (StrCmp (FileName, FoundFileName) == 0) {
1542 //
1543 // FID has been found. Prepare to find its respective FE/EFE.
1544 //
1545 Found = TRUE;
1546 break;
1547 }
1548 }
1549
1550 FreePool ((VOID *)FileIdentifierDesc);
1551 }
1552
1553 if (ReadDirInfo.DirectoryData != NULL) {
1554 //
1555 // Free all allocated resources for the directory listing.
1556 //
1557 FreePool (ReadDirInfo.DirectoryData);
1558 }
1559
1560 if (Found) {
1561 Status = EFI_SUCCESS;
1562
1563 File->FileIdentifierDesc = FileIdentifierDesc;
1564
1565 //
1566 // If the requested file is root directory, then the FE/EFE was already
1567 // retrieved in UdfOpenVolume() function, thus no need to find it again.
1568 //
1569 // Otherwise, find FE/EFE from the respective FID.
1570 //
1571 if (StrCmp (FileName, L"\\") != 0) {
1572 Status = FindFileEntry (
1573 BlockIo,
1574 DiskIo,
1575 Volume,
1576 &FileIdentifierDesc->Icb,
1577 &CompareFileEntry
1578 );
1579 if (EFI_ERROR (Status)) {
1580 goto Error_Find_Fe;
1581 }
1582
1583 //
1584 // Make sure that both Parent's FE/EFE and found FE/EFE are not equal.
1585 //
1586 if (CompareMem (
1587 (VOID *)Parent->FileEntry,
1588 (VOID *)CompareFileEntry,
1589 Volume->FileEntrySize
1590 ) != 0)
1591 {
1592 File->FileEntry = CompareFileEntry;
1593 } else {
1594 FreePool ((VOID *)FileIdentifierDesc);
1595 FreePool ((VOID *)CompareFileEntry);
1596 Status = EFI_NOT_FOUND;
1597 }
1598 }
1599 }
1600
1601 return Status;
1602
1603Error_Find_Fe:
1604 FreePool ((VOID *)FileIdentifierDesc);
1605
1606 return Status;
1607}
1608
1625 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
1626 IN EFI_DISK_IO_PROTOCOL *DiskIo,
1627 OUT UDF_VOLUME_INFO *Volume
1628 )
1629{
1630 EFI_STATUS Status;
1631
1632 //
1633 // Read all necessary UDF volume information and keep it private to the driver
1634 //
1635 Status = ReadVolumeFileStructure (
1636 BlockIo,
1637 DiskIo,
1638 Volume
1639 );
1640 if (EFI_ERROR (Status)) {
1641 return Status;
1642 }
1643
1644 //
1645 // Find File Set Descriptor
1646 //
1647 Status = FindFileSetDescriptor (BlockIo, DiskIo, Volume);
1648 if (EFI_ERROR (Status)) {
1649 return Status;
1650 }
1651
1652 return Status;
1653}
1654
1673 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
1674 IN EFI_DISK_IO_PROTOCOL *DiskIo,
1675 IN UDF_VOLUME_INFO *Volume,
1676 OUT UDF_FILE_INFO *File
1677 )
1678{
1679 EFI_STATUS Status;
1680 UDF_FILE_INFO Parent;
1681
1682 Status = FindFileEntry (
1683 BlockIo,
1684 DiskIo,
1685 Volume,
1686 &Volume->FileSetDesc.RootDirectoryIcb,
1687 &File->FileEntry
1688 );
1689 if (EFI_ERROR (Status)) {
1690 return Status;
1691 }
1692
1693 Parent.FileEntry = File->FileEntry;
1694 Parent.FileIdentifierDesc = NULL;
1695
1696 Status = FindFile (
1697 BlockIo,
1698 DiskIo,
1699 Volume,
1700 L"\\",
1701 NULL,
1702 &Parent,
1703 &Volume->FileSetDesc.RootDirectoryIcb,
1704 File
1705 );
1706 if (EFI_ERROR (Status)) {
1707 FreePool (File->FileEntry);
1708 }
1709
1710 return Status;
1711}
1712
1732 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
1733 IN EFI_DISK_IO_PROTOCOL *DiskIo,
1734 IN UDF_VOLUME_INFO *Volume,
1736 OUT VOID **FileEntry
1737 )
1738{
1739 EFI_STATUS Status;
1740 UINT64 Lsn;
1741 UINT32 LogicalBlockSize;
1742 UDF_DESCRIPTOR_TAG *DescriptorTag;
1743 VOID *ReadBuffer;
1744
1745 Status = GetLongAdLsn (Volume, Icb, &Lsn);
1746 if (EFI_ERROR (Status)) {
1747 return Status;
1748 }
1749
1750 LogicalBlockSize = Volume->LogicalVolDesc.LogicalBlockSize;
1751
1752 ReadBuffer = AllocateZeroPool (Volume->FileEntrySize);
1753 if (ReadBuffer == NULL) {
1754 return EFI_OUT_OF_RESOURCES;
1755 }
1756
1757 //
1758 // Read extent.
1759 //
1760 Status = DiskIo->ReadDisk (
1761 DiskIo,
1762 BlockIo->Media->MediaId,
1763 MultU64x32 (Lsn, LogicalBlockSize),
1764 Volume->FileEntrySize,
1765 ReadBuffer
1766 );
1767 if (EFI_ERROR (Status)) {
1768 goto Error_Read_Disk_Blk;
1769 }
1770
1771 DescriptorTag = ReadBuffer;
1772
1773 //
1774 // Check if the read extent contains a valid Tag Identifier for the expected
1775 // FE/EFE.
1776 //
1777 if ((DescriptorTag->TagIdentifier != UdfFileEntry) &&
1778 (DescriptorTag->TagIdentifier != UdfExtendedFileEntry))
1779 {
1780 Status = EFI_VOLUME_CORRUPTED;
1781 goto Error_Invalid_Fe;
1782 }
1783
1784 *FileEntry = ReadBuffer;
1785 return EFI_SUCCESS;
1786
1787Error_Invalid_Fe:
1788Error_Read_Disk_Blk:
1789 FreePool (ReadBuffer);
1790
1791 return Status;
1792}
1793
1816 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
1817 IN EFI_DISK_IO_PROTOCOL *DiskIo,
1818 IN UDF_VOLUME_INFO *Volume,
1819 IN CHAR16 *FilePath,
1820 IN UDF_FILE_INFO *Root,
1821 IN UDF_FILE_INFO *Parent,
1823 OUT UDF_FILE_INFO *File
1824 )
1825{
1826 EFI_STATUS Status;
1827 CHAR16 FileName[UDF_FILENAME_LENGTH];
1828 CHAR16 *FileNamePointer;
1829 UDF_FILE_INFO PreviousFile;
1830 VOID *FileEntry;
1831
1832 Status = EFI_NOT_FOUND;
1833
1834 CopyMem ((VOID *)&PreviousFile, (VOID *)Parent, sizeof (UDF_FILE_INFO));
1835 while (*FilePath != L'\0') {
1836 FileNamePointer = FileName;
1837 while (*FilePath != L'\0' && *FilePath != L'\\') {
1838 if ((((UINTN)FileNamePointer - (UINTN)FileName) / sizeof (CHAR16)) >=
1839 (ARRAY_SIZE (FileName) - 1))
1840 {
1841 return EFI_NOT_FOUND;
1842 }
1843
1844 *FileNamePointer++ = *FilePath++;
1845 }
1846
1847 *FileNamePointer = L'\0';
1848 if (FileName[0] == L'\0') {
1849 //
1850 // Open root directory.
1851 //
1852 if (Root == NULL) {
1853 //
1854 // There is no file found for the root directory yet. So, find only its
1855 // FID by now.
1856 //
1857 // See UdfOpenVolume() function.
1858 //
1859 Status = InternalFindFile (
1860 BlockIo,
1861 DiskIo,
1862 Volume,
1863 L"\\",
1864 &PreviousFile,
1865 Icb,
1866 File
1867 );
1868 } else {
1869 //
1870 // We've already a file pointer (Root) for the root directory. Duplicate
1871 // its FE/EFE and FID descriptors.
1872 //
1873 Status = EFI_SUCCESS;
1874 DuplicateFe (BlockIo, Volume, Root->FileEntry, &File->FileEntry);
1875 if (File->FileEntry == NULL) {
1876 Status = EFI_OUT_OF_RESOURCES;
1877 } else {
1878 //
1879 // File->FileEntry is not NULL.
1880 //
1881 DuplicateFid (Root->FileIdentifierDesc, &File->FileIdentifierDesc);
1882 if (File->FileIdentifierDesc == NULL) {
1883 FreePool (File->FileEntry);
1884 Status = EFI_OUT_OF_RESOURCES;
1885 }
1886 }
1887 }
1888 } else {
1889 //
1890 // No root directory. Find filename from the current directory.
1891 //
1892 Status = InternalFindFile (
1893 BlockIo,
1894 DiskIo,
1895 Volume,
1896 FileName,
1897 &PreviousFile,
1898 Icb,
1899 File
1900 );
1901 }
1902
1903 if (EFI_ERROR (Status)) {
1904 return Status;
1905 }
1906
1907 //
1908 // If the found file is a symlink, then find its respective FE/EFE and
1909 // FID descriptors.
1910 //
1911 if (FE_ICB_FILE_TYPE (File->FileEntry) == UdfFileEntrySymlink) {
1912 FreePool ((VOID *)File->FileIdentifierDesc);
1913
1914 FileEntry = File->FileEntry;
1915
1916 Status = ResolveSymlink (
1917 BlockIo,
1918 DiskIo,
1919 Volume,
1920 &PreviousFile,
1921 FileEntry,
1922 File
1923 );
1924
1925 FreePool (FileEntry);
1926
1927 if (EFI_ERROR (Status)) {
1928 return Status;
1929 }
1930 }
1931
1932 if (CompareMem (
1933 (VOID *)&PreviousFile,
1934 (VOID *)Parent,
1935 sizeof (UDF_FILE_INFO)
1936 ) != 0)
1937 {
1938 CleanupFileInformation (&PreviousFile);
1939 }
1940
1941 CopyMem ((VOID *)&PreviousFile, (VOID *)File, sizeof (UDF_FILE_INFO));
1942 if ((*FilePath != L'\0') && (*FilePath == L'\\')) {
1943 FilePath++;
1944 }
1945 }
1946
1947 return Status;
1948}
1949
1973 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
1974 IN EFI_DISK_IO_PROTOCOL *DiskIo,
1975 IN UDF_VOLUME_INFO *Volume,
1977 IN VOID *FileEntryData,
1978 IN OUT UDF_READ_DIRECTORY_INFO *ReadDirInfo,
1980 )
1981{
1982 EFI_STATUS Status;
1983 UDF_READ_FILE_INFO ReadFileInfo;
1984 UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;
1985
1986 if (ReadDirInfo->DirectoryData == NULL) {
1987 //
1988 // The directory's recorded data has not been read yet. So let's cache it
1989 // into memory and the next calls won't need to read it again.
1990 //
1991 ReadFileInfo.Flags = ReadFileAllocateAndRead;
1992
1993 Status = ReadFile (
1994 BlockIo,
1995 DiskIo,
1996 Volume,
1997 ParentIcb,
1998 FileEntryData,
1999 &ReadFileInfo
2000 );
2001 if (EFI_ERROR (Status)) {
2002 return Status;
2003 }
2004
2005 //
2006 // Fill in ReadDirInfo structure with the read directory's data information.
2007 //
2008 ReadDirInfo->DirectoryData = ReadFileInfo.FileData;
2009 ReadDirInfo->DirectoryLength = ReadFileInfo.ReadLength;
2010 }
2011
2012 do {
2013 if (ReadDirInfo->FidOffset >= ReadDirInfo->DirectoryLength) {
2014 //
2015 // There are no longer FIDs for this directory. By returning
2016 // EFI_DEVICE_ERROR to the callee will indicate end of directory
2017 // listening.
2018 //
2019 return EFI_DEVICE_ERROR;
2020 }
2021
2022 //
2023 // Get FID for this entry.
2024 //
2025 FileIdentifierDesc = GET_FID_FROM_ADS (
2026 ReadDirInfo->DirectoryData,
2027 ReadDirInfo->FidOffset
2028 );
2029 //
2030 // Update FidOffset to point to next FID.
2031 //
2032 ReadDirInfo->FidOffset += GetFidDescriptorLength (FileIdentifierDesc);
2033 } while (FileIdentifierDesc->FileCharacteristics & DELETED_FILE);
2034
2035 DuplicateFid (FileIdentifierDesc, FoundFid);
2036 if (*FoundFid == NULL) {
2037 return EFI_OUT_OF_RESOURCES;
2038 }
2039
2040 return EFI_SUCCESS;
2041}
2042
2065 IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc,
2066 IN UINTN CharMax,
2067 OUT CHAR16 *FileName
2068 )
2069{
2070 UINT8 *OstaCompressed;
2071 UINT8 CompressionId;
2072 UINT8 Length;
2073 UINTN Index;
2074 CHAR16 *FileNameBak;
2075
2076 if (CharMax == 0) {
2077 return EFI_BUFFER_TOO_SMALL;
2078 }
2079
2080 OstaCompressed =
2081 (UINT8 *)(
2082 (UINT8 *)FileIdentifierDesc->Data +
2083 FileIdentifierDesc->LengthOfImplementationUse
2084 );
2085
2086 CompressionId = OstaCompressed[0];
2087 if (!IS_VALID_COMPRESSION_ID (CompressionId)) {
2088 return EFI_VOLUME_CORRUPTED;
2089 }
2090
2091 FileNameBak = FileName;
2092
2093 //
2094 // Decode filename.
2095 //
2096 Length = FileIdentifierDesc->LengthOfFileIdentifier;
2097 if (CompressionId == 16) {
2098 if (((UINTN)Length >> 1) > CharMax) {
2099 return EFI_BUFFER_TOO_SMALL;
2100 }
2101 } else {
2102 if ((Length != 0) && ((UINTN)Length - 1 > CharMax)) {
2103 return EFI_BUFFER_TOO_SMALL;
2104 }
2105 }
2106
2107 for (Index = 1; Index < Length; Index++) {
2108 if (CompressionId == 16) {
2109 *FileName = OstaCompressed[Index++] << 8;
2110 } else {
2111 *FileName = 0;
2112 }
2113
2114 if (Index < Length) {
2115 *FileName |= (CHAR16)(OstaCompressed[Index]);
2116 }
2117
2118 FileName++;
2119 }
2120
2121 Index = ((UINTN)FileName - (UINTN)FileNameBak) / sizeof (CHAR16);
2122 if (Index > CharMax - 1) {
2123 Index = CharMax - 1;
2124 }
2125
2126 FileNameBak[Index] = L'\0';
2127
2128 return EFI_SUCCESS;
2129}
2130
2158 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
2159 IN EFI_DISK_IO_PROTOCOL *DiskIo,
2160 IN UDF_VOLUME_INFO *Volume,
2161 IN UDF_FILE_INFO *Parent,
2162 IN VOID *FileEntryData,
2163 OUT UDF_FILE_INFO *File
2164 )
2165{
2166 EFI_STATUS Status;
2167 UDF_READ_FILE_INFO ReadFileInfo;
2168 UINT8 *Data;
2169 UINT64 Length;
2170 UINT8 *EndData;
2171 UDF_PATH_COMPONENT *PathComp;
2172 UINT8 PathCompLength;
2173 CHAR16 FileName[UDF_FILENAME_LENGTH];
2174 CHAR16 *Char;
2175 UINTN Index;
2176 UINT8 CompressionId;
2177 UDF_FILE_INFO PreviousFile;
2178 BOOLEAN NotParent;
2179 BOOLEAN NotFile;
2180
2181 ZeroMem ((VOID *)File, sizeof (UDF_FILE_INFO));
2182
2183 //
2184 // Symlink files on UDF volumes do not contain so much data other than
2185 // Path Components which resolves to real filenames, so it's OK to read in
2186 // all its data here -- usually the data will be inline with the FE/EFE for
2187 // lower filenames.
2188 //
2189 ReadFileInfo.Flags = ReadFileAllocateAndRead;
2190
2191 Status = ReadFile (
2192 BlockIo,
2193 DiskIo,
2194 Volume,
2195 &Parent->FileIdentifierDesc->Icb,
2196 FileEntryData,
2197 &ReadFileInfo
2198 );
2199 if (EFI_ERROR (Status)) {
2200 return Status;
2201 }
2202
2203 Length = ReadFileInfo.ReadLength;
2204
2205 Data = (UINT8 *)ReadFileInfo.FileData;
2206 EndData = Data + Length;
2207
2208 CopyMem ((VOID *)&PreviousFile, (VOID *)Parent, sizeof (UDF_FILE_INFO));
2209
2210 for ( ; ;) {
2211 PathComp = (UDF_PATH_COMPONENT *)Data;
2212
2213 PathCompLength = PathComp->LengthOfComponentIdentifier;
2214
2215 switch (PathComp->ComponentType) {
2216 case 1:
2217 //
2218 // This Path Component specifies the root directory hierarchy subject to
2219 // agreement between the originator and recipient of the medium. Skip it.
2220 //
2221 // Fall through.
2222 //
2223 case 2:
2224 //
2225 // "\\." of the current directory. Read next Path Component.
2226 //
2227 goto Next_Path_Component;
2228 case 3:
2229 //
2230 // ".." (parent directory). Go to it.
2231 //
2232 CopyMem ((VOID *)FileName, L"..", 6);
2233 break;
2234 case 4:
2235 //
2236 // "." (current file). Duplicate both FE/EFE and FID of this file.
2237 //
2238 DuplicateFe (BlockIo, Volume, PreviousFile.FileEntry, &File->FileEntry);
2239 if (File->FileEntry == NULL) {
2240 Status = EFI_OUT_OF_RESOURCES;
2241 goto Error_Find_File;
2242 }
2243
2244 DuplicateFid (
2245 PreviousFile.FileIdentifierDesc,
2246 &File->FileIdentifierDesc
2247 );
2248 if (File->FileIdentifierDesc == NULL) {
2249 FreePool (File->FileEntry);
2250 Status = EFI_OUT_OF_RESOURCES;
2251 goto Error_Find_File;
2252 }
2253
2254 goto Next_Path_Component;
2255 case 5:
2256 //
2257 // This Path Component identifies an object, either a file or a
2258 // directory or an alias.
2259 //
2260 // Decode it from the compressed data in ComponentIdentifier and find
2261 // respective path.
2262 //
2263 CompressionId = PathComp->ComponentIdentifier[0];
2264 if (!IS_VALID_COMPRESSION_ID (CompressionId)) {
2265 return EFI_VOLUME_CORRUPTED;
2266 }
2267
2268 if ((UINTN)PathComp->ComponentIdentifier + PathCompLength > (UINTN)EndData) {
2269 return EFI_VOLUME_CORRUPTED;
2270 }
2271
2272 Char = FileName;
2273 for (Index = 1; Index < PathCompLength; Index++) {
2274 if (CompressionId == 16) {
2275 *Char = *(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier +
2276 Index) << 8;
2277 Index++;
2278 } else {
2279 if (Index > ARRAY_SIZE (FileName)) {
2280 return EFI_UNSUPPORTED;
2281 }
2282
2283 *Char = 0;
2284 }
2285
2286 if (Index < Length) {
2287 *Char |= (CHAR16)(*(UINT8 *)((UINT8 *)PathComp->ComponentIdentifier + Index));
2288 }
2289
2290 Char++;
2291 }
2292
2293 Index = ((UINTN)Char - (UINTN)FileName) / sizeof (CHAR16);
2294 if (Index > ARRAY_SIZE (FileName) - 1) {
2295 Index = ARRAY_SIZE (FileName) - 1;
2296 }
2297
2298 FileName[Index] = L'\0';
2299 break;
2300 default:
2301 //
2302 // According to the ECMA-167 standard (3rd Edition - June 1997), Section
2303 // 14.16.1.1, all other values are reserved.
2304 //
2305 Status = EFI_VOLUME_CORRUPTED;
2306 goto Error_Find_File;
2307 }
2308
2309 //
2310 // Find file from the read filename in symlink's file data.
2311 //
2312 Status = InternalFindFile (
2313 BlockIo,
2314 DiskIo,
2315 Volume,
2316 FileName,
2317 &PreviousFile,
2318 NULL,
2319 File
2320 );
2321 if (EFI_ERROR (Status)) {
2322 goto Error_Find_File;
2323 }
2324
2325Next_Path_Component:
2326 Data += sizeof (UDF_PATH_COMPONENT) + PathCompLength;
2327 if (Data >= EndData) {
2328 break;
2329 }
2330
2331 //
2332 // Check the content in the file info pointed by File.
2333 //
2334 if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) {
2335 Status = EFI_VOLUME_CORRUPTED;
2336 goto Error_Find_File;
2337 }
2338
2339 NotParent = (CompareMem (
2340 (VOID *)&PreviousFile,
2341 (VOID *)Parent,
2342 sizeof (UDF_FILE_INFO)
2343 ) != 0);
2344 NotFile = (CompareMem (
2345 (VOID *)&PreviousFile,
2346 (VOID *)File,
2347 sizeof (UDF_FILE_INFO)
2348 ) != 0);
2349
2350 if (NotParent && NotFile) {
2351 CleanupFileInformation (&PreviousFile);
2352 }
2353
2354 if (NotFile) {
2355 CopyMem ((VOID *)&PreviousFile, (VOID *)File, sizeof (UDF_FILE_INFO));
2356 }
2357 }
2358
2359 //
2360 // Unmap the symlink file.
2361 //
2362 FreePool (ReadFileInfo.FileData);
2363
2364 //
2365 // Check the content in the resolved file info.
2366 //
2367 if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) {
2368 return EFI_VOLUME_CORRUPTED;
2369 }
2370
2371 return EFI_SUCCESS;
2372
2373Error_Find_File:
2374 if (CompareMem (
2375 (VOID *)&PreviousFile,
2376 (VOID *)Parent,
2377 sizeof (UDF_FILE_INFO)
2378 ) != 0)
2379 {
2380 CleanupFileInformation (&PreviousFile);
2381 }
2382
2383 FreePool (ReadFileInfo.FileData);
2384
2385 return Status;
2386}
2387
2394VOID
2396 IN UDF_FILE_INFO *File
2397 )
2398{
2399 if (File->FileEntry != NULL) {
2400 FreePool (File->FileEntry);
2401 }
2402
2403 if (File->FileIdentifierDesc != NULL) {
2404 FreePool ((VOID *)File->FileIdentifierDesc);
2405 }
2406
2407 ZeroMem ((VOID *)File, sizeof (UDF_FILE_INFO));
2408}
2409
2430 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
2431 IN EFI_DISK_IO_PROTOCOL *DiskIo,
2432 IN UDF_VOLUME_INFO *Volume,
2433 IN UDF_FILE_INFO *File,
2434 OUT UINT64 *Size
2435 )
2436{
2437 EFI_STATUS Status;
2438 UDF_READ_FILE_INFO ReadFileInfo;
2439
2440 ReadFileInfo.Flags = ReadFileGetFileSize;
2441
2442 Status = ReadFile (
2443 BlockIo,
2444 DiskIo,
2445 Volume,
2446 &File->FileIdentifierDesc->Icb,
2447 File->FileEntry,
2448 &ReadFileInfo
2449 );
2450 if (EFI_ERROR (Status)) {
2451 return Status;
2452 }
2453
2454 *Size = ReadFileInfo.ReadLength;
2455
2456 return EFI_SUCCESS;
2457}
2458
2478 IN UDF_FILE_INFO *File,
2479 IN UINT64 FileSize,
2480 IN CHAR16 *FileName,
2481 IN OUT UINTN *BufferSize,
2482 OUT VOID *Buffer
2483 )
2484{
2485 UINTN FileInfoLength;
2487 UDF_FILE_ENTRY *FileEntry;
2488 UDF_EXTENDED_FILE_ENTRY *ExtendedFileEntry;
2489 UDF_DESCRIPTOR_TAG *DescriptorTag;
2490
2491 //
2492 // Calculate the needed size for the EFI_FILE_INFO structure.
2493 //
2494 FileInfoLength = sizeof (EFI_FILE_INFO) + ((FileName != NULL) ?
2495 StrSize (FileName) :
2496 sizeof (CHAR16));
2497 if (*BufferSize < FileInfoLength) {
2498 //
2499 // The given Buffer has no size enough for EFI_FILE_INFO structure.
2500 //
2501 *BufferSize = FileInfoLength;
2502 return EFI_BUFFER_TOO_SMALL;
2503 }
2504
2505 //
2506 // Buffer now contains room enough to store EFI_FILE_INFO structure.
2507 // Now, fill it in with all necessary information about the file.
2508 //
2509 FileInfo = (EFI_FILE_INFO *)Buffer;
2510 FileInfo->Size = FileInfoLength;
2511 FileInfo->Attribute &= ~EFI_FILE_VALID_ATTR;
2512 FileInfo->Attribute |= EFI_FILE_READ_ONLY;
2513
2514 if (IS_FID_DIRECTORY_FILE (File->FileIdentifierDesc)) {
2515 FileInfo->Attribute |= EFI_FILE_DIRECTORY;
2516 } else if (IS_FID_NORMAL_FILE (File->FileIdentifierDesc)) {
2517 FileInfo->Attribute |= EFI_FILE_ARCHIVE;
2518 }
2519
2520 if (IS_FID_HIDDEN_FILE (File->FileIdentifierDesc)) {
2521 FileInfo->Attribute |= EFI_FILE_HIDDEN;
2522 }
2523
2524 DescriptorTag = File->FileEntry;
2525
2526 if (DescriptorTag->TagIdentifier == UdfFileEntry) {
2527 FileEntry = (UDF_FILE_ENTRY *)File->FileEntry;
2528
2529 //
2530 // Check if FE has the system attribute set.
2531 //
2532 if (FileEntry->IcbTag.Flags & (1 << 10)) {
2533 FileInfo->Attribute |= EFI_FILE_SYSTEM;
2534 }
2535
2536 FileInfo->FileSize = FileSize;
2537 FileInfo->PhysicalSize = FileSize;
2538
2539 FileInfo->CreateTime.Year = FileEntry->AccessTime.Year;
2540 FileInfo->CreateTime.Month = FileEntry->AccessTime.Month;
2541 FileInfo->CreateTime.Day = FileEntry->AccessTime.Day;
2542 FileInfo->CreateTime.Hour = FileEntry->AccessTime.Hour;
2543 FileInfo->CreateTime.Minute = FileEntry->AccessTime.Minute;
2544 FileInfo->CreateTime.Second = FileEntry->AccessTime.Second;
2545 FileInfo->CreateTime.Nanosecond =
2546 FileEntry->AccessTime.HundredsOfMicroseconds;
2547
2548 FileInfo->LastAccessTime.Year =
2549 FileEntry->AccessTime.Year;
2550 FileInfo->LastAccessTime.Month =
2551 FileEntry->AccessTime.Month;
2553 FileEntry->AccessTime.Day;
2554 FileInfo->LastAccessTime.Hour =
2555 FileEntry->AccessTime.Hour;
2556 FileInfo->LastAccessTime.Minute =
2557 FileEntry->AccessTime.Minute;
2558 FileInfo->LastAccessTime.Second =
2559 FileEntry->AccessTime.Second;
2560 FileInfo->LastAccessTime.Nanosecond =
2561 FileEntry->AccessTime.HundredsOfMicroseconds;
2562 } else if (DescriptorTag->TagIdentifier == UdfExtendedFileEntry) {
2563 ExtendedFileEntry = (UDF_EXTENDED_FILE_ENTRY *)File->FileEntry;
2564
2565 //
2566 // Check if EFE has the system attribute set.
2567 //
2568 if (ExtendedFileEntry->IcbTag.Flags & (1 << 10)) {
2569 FileInfo->Attribute |= EFI_FILE_SYSTEM;
2570 }
2571
2572 FileInfo->FileSize = FileSize;
2573 FileInfo->PhysicalSize = FileSize;
2574
2575 FileInfo->CreateTime.Year = ExtendedFileEntry->CreationTime.Year;
2576 FileInfo->CreateTime.Month = ExtendedFileEntry->CreationTime.Month;
2577 FileInfo->CreateTime.Day = ExtendedFileEntry->CreationTime.Day;
2578 FileInfo->CreateTime.Hour = ExtendedFileEntry->CreationTime.Hour;
2579 FileInfo->CreateTime.Minute = ExtendedFileEntry->CreationTime.Second;
2580 FileInfo->CreateTime.Second = ExtendedFileEntry->CreationTime.Second;
2581 FileInfo->CreateTime.Nanosecond =
2582 ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;
2583
2584 FileInfo->LastAccessTime.Year =
2585 ExtendedFileEntry->AccessTime.Year;
2586 FileInfo->LastAccessTime.Month =
2587 ExtendedFileEntry->AccessTime.Month;
2589 ExtendedFileEntry->AccessTime.Day;
2590 FileInfo->LastAccessTime.Hour =
2591 ExtendedFileEntry->AccessTime.Hour;
2592 FileInfo->LastAccessTime.Minute =
2593 ExtendedFileEntry->AccessTime.Minute;
2594 FileInfo->LastAccessTime.Second =
2595 ExtendedFileEntry->AccessTime.Second;
2596 FileInfo->LastAccessTime.Nanosecond =
2597 ExtendedFileEntry->AccessTime.HundredsOfMicroseconds;
2598 }
2599
2601 FileInfo->CreateTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;
2603 FileInfo->LastAccessTime.Daylight = EFI_TIME_ADJUST_DAYLIGHT;
2604
2605 CopyMem (
2606 (VOID *)&FileInfo->ModificationTime,
2607 (VOID *)&FileInfo->LastAccessTime,
2608 sizeof (EFI_TIME)
2609 );
2610
2611 if (FileName != NULL) {
2612 StrCpyS (FileInfo->FileName, StrLen (FileName) + 1, FileName);
2613 } else {
2614 FileInfo->FileName[0] = '\0';
2615 }
2616
2617 *BufferSize = FileInfoLength;
2618
2619 return EFI_SUCCESS;
2620}
2621
2644 IN UDF_VOLUME_INFO *Volume,
2645 IN UINTN CharMax,
2646 OUT CHAR16 *String
2647 )
2648{
2649 UDF_FILE_SET_DESCRIPTOR *FileSetDesc;
2650 UINTN Index;
2651 UINT8 *OstaCompressed;
2652 UINT8 CompressionId;
2653 CHAR16 *StringBak;
2654
2655 FileSetDesc = &Volume->FileSetDesc;
2656
2657 OstaCompressed = &FileSetDesc->LogicalVolumeIdentifier[0];
2658
2659 CompressionId = OstaCompressed[0];
2660 if (!IS_VALID_COMPRESSION_ID (CompressionId)) {
2661 return EFI_VOLUME_CORRUPTED;
2662 }
2663
2664 StringBak = String;
2665 for (Index = 1; Index < 128; Index++) {
2666 if (CompressionId == 16) {
2667 if ((Index >> 1) > CharMax) {
2668 return EFI_BUFFER_TOO_SMALL;
2669 }
2670
2671 *String = *(UINT8 *)(OstaCompressed + Index) << 8;
2672 Index++;
2673 } else {
2674 if (Index > CharMax) {
2675 return EFI_BUFFER_TOO_SMALL;
2676 }
2677
2678 *String = 0;
2679 }
2680
2681 if (Index < 128) {
2682 *String |= (CHAR16)(*(UINT8 *)(OstaCompressed + Index));
2683 }
2684
2685 //
2686 // Unlike FID Identifiers, Logical Volume Identifier is stored in a
2687 // NULL-terminated OSTA compressed format, so we must check for the NULL
2688 // character.
2689 //
2690 if (*String == L'\0') {
2691 break;
2692 }
2693
2694 String++;
2695 }
2696
2697 Index = ((UINTN)String - (UINTN)StringBak) / sizeof (CHAR16);
2698 if (Index > CharMax - 1) {
2699 Index = CharMax - 1;
2700 }
2701
2702 StringBak[Index] = L'\0';
2703
2704 return EFI_SUCCESS;
2705}
2706
2733 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
2734 IN EFI_DISK_IO_PROTOCOL *DiskIo,
2735 IN UDF_VOLUME_INFO *Volume,
2736 OUT UINT64 *VolumeSize,
2737 OUT UINT64 *FreeSpaceSize
2738 )
2739{
2740 EFI_STATUS Status;
2741 UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc;
2742 UDF_EXTENT_AD *ExtentAd;
2743 UINT64 Lsn;
2744 UINT32 LogicalBlockSize;
2745 UDF_LOGICAL_VOLUME_INTEGRITY *LogicalVolInt;
2746 UDF_DESCRIPTOR_TAG *DescriptorTag;
2747 UINTN Index;
2748 UINTN Length;
2749 UINT32 LsnsNo;
2750
2751 LogicalVolDesc = &Volume->LogicalVolDesc;
2752
2753 ExtentAd = &LogicalVolDesc->IntegritySequenceExtent;
2754
2755 if ((ExtentAd->ExtentLength == 0) ||
2756 (ExtentAd->ExtentLength < sizeof (UDF_LOGICAL_VOLUME_INTEGRITY)))
2757 {
2758 return EFI_VOLUME_CORRUPTED;
2759 }
2760
2761 LogicalVolInt = AllocatePool (ExtentAd->ExtentLength);
2762 if (LogicalVolInt == NULL) {
2763 return EFI_OUT_OF_RESOURCES;
2764 }
2765
2766 //
2767 // Get location of Logical Volume Integrity Descriptor
2768 //
2769 Lsn = (UINT64)ExtentAd->ExtentLocation - Volume->MainVdsStartLocation;
2770
2771 LogicalBlockSize = LogicalVolDesc->LogicalBlockSize;
2772
2773 //
2774 // Read disk block
2775 //
2776 Status = DiskIo->ReadDisk (
2777 DiskIo,
2778 BlockIo->Media->MediaId,
2779 MultU64x32 (Lsn, LogicalBlockSize),
2780 ExtentAd->ExtentLength,
2781 LogicalVolInt
2782 );
2783 if (EFI_ERROR (Status)) {
2784 goto Out_Free;
2785 }
2786
2787 DescriptorTag = &LogicalVolInt->DescriptorTag;
2788
2789 //
2790 // Check if read block is a Logical Volume Integrity Descriptor
2791 //
2792 if (DescriptorTag->TagIdentifier != UdfLogicalVolumeIntegrityDescriptor) {
2793 Status = EFI_VOLUME_CORRUPTED;
2794 goto Out_Free;
2795 }
2796
2797 if ((LogicalVolInt->NumberOfPartitions > MAX_UINT32 / sizeof (UINT32) / 2) ||
2798 (LogicalVolInt->NumberOfPartitions * sizeof (UINT32) * 2 >
2799 ExtentAd->ExtentLength - sizeof (UDF_LOGICAL_VOLUME_INTEGRITY)))
2800 {
2801 Status = EFI_VOLUME_CORRUPTED;
2802 goto Out_Free;
2803 }
2804
2805 *VolumeSize = 0;
2806 *FreeSpaceSize = 0;
2807
2808 Length = LogicalVolInt->NumberOfPartitions;
2809 for (Index = 0; Index < Length; Index += sizeof (UINT32)) {
2810 LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
2811 //
2812 // Check if size is not specified
2813 //
2814 if (LsnsNo == 0xFFFFFFFFUL) {
2815 continue;
2816 }
2817
2818 //
2819 // Accumulate free space size
2820 //
2821 *FreeSpaceSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
2822 }
2823
2824 Length = LogicalVolInt->NumberOfPartitions * sizeof (UINT32) * 2;
2825 for ( ; Index < Length; Index += sizeof (UINT32)) {
2826 LsnsNo = *(UINT32 *)((UINT8 *)LogicalVolInt->Data + Index);
2827 //
2828 // Check if size is not specified
2829 //
2830 if (LsnsNo == 0xFFFFFFFFUL) {
2831 continue;
2832 }
2833
2834 //
2835 // Accumulate used volume space
2836 //
2837 *VolumeSize += MultU64x32 ((UINT64)LsnsNo, LogicalBlockSize);
2838 }
2839
2840 Status = EFI_SUCCESS;
2841
2842Out_Free:
2843 //
2844 // Free Logical Volume Integrity Descriptor
2845 //
2846 FreePool (LogicalVolInt);
2847
2848 return Status;
2849}
2850
2874 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
2875 IN EFI_DISK_IO_PROTOCOL *DiskIo,
2876 IN UDF_VOLUME_INFO *Volume,
2877 IN UDF_FILE_INFO *File,
2878 IN UINT64 FileSize,
2879 IN OUT UINT64 *FilePosition,
2880 IN OUT VOID *Buffer,
2881 IN OUT UINT64 *BufferSize
2882 )
2883{
2884 EFI_STATUS Status;
2885 UDF_READ_FILE_INFO ReadFileInfo;
2886
2887 ReadFileInfo.Flags = ReadFileSeekAndRead;
2888 ReadFileInfo.FilePosition = *FilePosition;
2889 ReadFileInfo.FileData = Buffer;
2890 ReadFileInfo.FileDataSize = *BufferSize;
2891 ReadFileInfo.FileSize = FileSize;
2892
2893 Status = ReadFile (
2894 BlockIo,
2895 DiskIo,
2896 Volume,
2897 &File->FileIdentifierDesc->Icb,
2898 File->FileEntry,
2899 &ReadFileInfo
2900 );
2901 if (EFI_ERROR (Status)) {
2902 return Status;
2903 }
2904
2905 *BufferSize = ReadFileInfo.FileDataSize;
2906 *FilePosition = ReadFileInfo.FilePosition;
2907
2908 return EFI_SUCCESS;
2909}
2910
2924 IN EFI_HANDLE ControllerHandle
2925 )
2926{
2927 EFI_STATUS Status;
2928 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2929 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
2930 EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode;
2931 EFI_GUID *VendorDefinedGuid;
2932
2933 //
2934 // Open Device Path protocol on ControllerHandle
2935 //
2936 Status = gBS->OpenProtocol (
2937 ControllerHandle,
2938 &gEfiDevicePathProtocolGuid,
2939 (VOID **)&DevicePath,
2940 This->DriverBindingHandle,
2941 ControllerHandle,
2942 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2943 );
2944 if (EFI_ERROR (Status)) {
2945 return EFI_UNSUPPORTED;
2946 }
2947
2948 Status = EFI_UNSUPPORTED;
2949
2950 //
2951 // Get last Device Path node
2952 //
2953 LastDevicePathNode = NULL;
2954 DevicePathNode = DevicePath;
2955 while (!IsDevicePathEnd (DevicePathNode)) {
2956 LastDevicePathNode = DevicePathNode;
2957 DevicePathNode = NextDevicePathNode (DevicePathNode);
2958 }
2959
2960 //
2961 // Check if last Device Path node contains a Vendor-Defined Media Device Path
2962 // of an UDF file system.
2963 //
2964 if ((LastDevicePathNode != NULL) &&
2965 (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH) &&
2966 (DevicePathSubType (LastDevicePathNode) == MEDIA_VENDOR_DP))
2967 {
2968 VendorDefinedGuid = (EFI_GUID *)((UINTN)LastDevicePathNode +
2970 if (CompareGuid (VendorDefinedGuid, &gUdfDevPathGuid)) {
2971 Status = EFI_SUCCESS;
2972 }
2973 }
2974
2975 //
2976 // Close Device Path protocol on ControllerHandle
2977 //
2978 gBS->CloseProtocol (
2979 ControllerHandle,
2980 &gEfiDevicePathProtocolGuid,
2981 This->DriverBindingHandle,
2982 ControllerHandle
2983 );
2984
2985 return Status;
2986}
UINT64 UINTN
INT64 INTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
RETURN_STATUS EFIAPI StrCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:226
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define MEDIA_VENDOR_DP
Media vendor device path subtype.
Definition: DevicePath.h:1093
UINT8 EFIAPI DevicePathType(IN CONST VOID *Node)
UINT8 EFIAPI DevicePathSubType(IN CONST VOID *Node)
BOOLEAN EFIAPI IsDevicePathEnd(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
VOID *EFIAPI ReallocatePool(IN UINTN OldSize, IN UINTN NewSize, IN VOID *OldBuffer OPTIONAL)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_STATUS GetFileNameFromFid(IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc, IN UINTN CharMax, OUT CHAR16 *FileName)
EFI_STATUS ReadUdfVolumeInformation(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, OUT UDF_VOLUME_INFO *Volume)
EFI_STATUS GetFileEntryData(IN VOID *FileEntryData, IN UINTN FileEntrySize, OUT VOID **Data, OUT UINT64 *Length)
UDF_PARTITION_DESCRIPTOR * GetPdFromLongAd(IN UDF_VOLUME_INFO *Volume, IN UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd)
EFI_STATUS GetAllocationDescriptorLsn(IN UDF_FE_RECORDING_FLAGS RecordingFlags, IN UDF_VOLUME_INFO *Volume, IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb, IN VOID *Ad, OUT UINT64 *Lsn)
EFI_STATUS GetLongAdLsn(IN UDF_VOLUME_INFO *Volume, IN UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd, OUT UINT64 *Lsn)
EFI_STATUS GetFileSize(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN UDF_FILE_INFO *File, OUT UINT64 *Size)
EFI_STATUS GetVolumeSize(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, OUT UINT64 *VolumeSize, OUT UINT64 *FreeSpaceSize)
EFI_STATUS StartMainVolumeDescriptorSequence(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint, OUT UDF_VOLUME_INFO *Volume)
EFI_STATUS GetAedAdsOffset(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb, IN UDF_FE_RECORDING_FLAGS RecordingFlags, IN VOID *Ad, OUT UINT64 *Offset, OUT UINT64 *Length)
EFI_STATUS GetAdsInformation(IN VOID *FileEntryData, IN UINTN FileEntrySize, OUT VOID **AdsData, OUT UINT64 *Length)
EFI_STATUS GetAllocationDescriptor(IN UDF_FE_RECORDING_FLAGS RecordingFlags, IN VOID *Data, IN OUT UINT64 *Offset, IN UINT64 Length, OUT VOID **FoundAd)
EFI_STATUS GetAedAdsData(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb, IN UDF_FE_RECORDING_FLAGS RecordingFlags, IN VOID *Ad, OUT VOID **Data, OUT UINT64 *Length)
EFI_STATUS SetFileInfo(IN UDF_FILE_INFO *File, IN UINT64 FileSize, IN CHAR16 *FileName, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
EFI_STATUS ReadDirectoryEntry(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb, IN VOID *FileEntryData, IN OUT UDF_READ_DIRECTORY_INFO *ReadDirInfo, OUT UDF_FILE_IDENTIFIER_DESCRIPTOR **FoundFid)
EFI_STATUS ReadFile(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb, IN VOID *FileEntryData, IN OUT UDF_READ_FILE_INFO *ReadFileInfo)
EFI_STATUS GetShortAdFromAds(IN VOID *Data, IN OUT UINT64 *Offset, IN UINT64 Length, OUT UDF_SHORT_ALLOCATION_DESCRIPTOR **FoundShortAd)
EFI_STATUS SupportUdfFileSystem(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle)
EFI_STATUS GrowUpBufferToNextAd(IN UDF_FE_RECORDING_FLAGS RecordingFlags, IN VOID *Ad, IN OUT VOID **Buffer, IN UINT64 Length)
EFI_STATUS FindFileSetDescriptor(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume)
EFI_STATUS ReadFileData(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN UDF_FILE_INFO *File, IN UINT64 FileSize, IN OUT UINT64 *FilePosition, IN OUT VOID *Buffer, IN OUT UINT64 *BufferSize)
EFI_STATUS FindFile(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN CHAR16 *FilePath, IN UDF_FILE_INFO *Root, IN UDF_FILE_INFO *Parent, IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb, OUT UDF_FILE_INFO *File)
VOID DuplicateFid(IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc, OUT UDF_FILE_IDENTIFIER_DESCRIPTOR **NewFileIdentifierDesc)
EFI_STATUS GetVolumeLabel(IN UDF_VOLUME_INFO *Volume, IN UINTN CharMax, OUT CHAR16 *String)
UINT64 GetFidDescriptorLength(IN UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc)
VOID CleanupFileInformation(IN UDF_FILE_INFO *File)
EFI_STATUS ResolveSymlink(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN UDF_FILE_INFO *Parent, IN VOID *FileEntryData, OUT UDF_FILE_INFO *File)
EFI_STATUS FindFileEntry(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb, OUT VOID **FileEntry)
VOID DuplicateFe(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN UDF_VOLUME_INFO *Volume, IN VOID *FileEntry, OUT VOID **NewFileEntry)
UINT64 GetShortAdLsn(IN UDF_VOLUME_INFO *Volume, IN UDF_PARTITION_DESCRIPTOR *PartitionDesc, IN UDF_SHORT_ALLOCATION_DESCRIPTOR *ShortAd)
EFI_STATUS FindAnchorVolumeDescriptorPointer(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint)
EFI_STATUS FindRootDirectory(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, OUT UDF_FILE_INFO *File)
EFI_STATUS ReadVolumeFileStructure(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, OUT UDF_VOLUME_INFO *Volume)
EFI_STATUS GetLongAdFromAds(IN VOID *Data, IN OUT UINT64 *Offset, IN UINT64 Length, OUT UDF_LONG_ALLOCATION_DESCRIPTOR **FoundLongAd)
EFI_STATUS InternalFindFile(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN CHAR16 *FileName, IN UDF_FILE_INFO *Parent, IN UDF_LONG_ALLOCATION_DESCRIPTOR *Icb, OUT UDF_FILE_INFO *File)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_FILE_INFO * FileInfo(IN EFI_FILE_HANDLE FHand)
VOID EFIAPI Exit(IN EFI_STATUS Status)
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
#define EFI_UNSPECIFIED_TIMEZONE
Definition: UefiSpec.h:58
EFI_TIME ModificationTime
Definition: FileInfo.h:43
UINT64 PhysicalSize
Definition: FileInfo.h:31
EFI_TIME CreateTime
Definition: FileInfo.h:35
UINT64 Size
Definition: FileInfo.h:23
UINT64 Attribute
Definition: FileInfo.h:47
CHAR16 FileName[1]
Definition: FileInfo.h:52
EFI_TIME LastAccessTime
Definition: FileInfo.h:39
UINT64 FileSize
Definition: FileInfo.h:27
Definition: Base.h:213