TianoCore EDK2 master
Loading...
Searching...
No Matches
DirectoryManage.c
Go to the documentation of this file.
1
9#include "Fat.h"
10
27 IN FAT_OFILE *Parent,
28 IN IO_MODE IoMode,
29 IN UINTN EntryPos,
30 IN OUT VOID *Entry
31 )
32{
33 UINTN Position;
34 UINTN BufferSize;
35
36 Position = EntryPos * sizeof (FAT_DIRECTORY_ENTRY);
37 if (Position >= Parent->FileSize) {
38 //
39 // End of directory
40 //
41 ASSERT (IoMode == ReadData);
42 ((FAT_DIRECTORY_ENTRY *)Entry)->FileName[0] = EMPTY_ENTRY_MARK;
43 ((FAT_DIRECTORY_ENTRY *)Entry)->Attributes = 0;
44 return EFI_SUCCESS;
45 }
46
47 BufferSize = sizeof (FAT_DIRECTORY_ENTRY);
48 return FatAccessOFile (Parent, IoMode, Position, &BufferSize, Entry, NULL);
49}
50
64 IN FAT_OFILE *OFile,
65 IN FAT_DIRENT *DirEnt
66 )
67{
68 EFI_STATUS Status;
69 FAT_DIRECTORY_LFN LfnEntry;
70 UINTN EntryPos;
71 CHAR16 *LfnBufferPointer;
72 CHAR16 LfnBuffer[MAX_LFN_ENTRIES * LFN_CHAR_TOTAL + 1];
73 UINT8 EntryCount;
74 UINT8 LfnOrdinal;
75
76 EntryPos = DirEnt->EntryPos;
77 EntryCount = DirEnt->EntryCount;
78 //
79 // Write directory entry
80 //
81 Status = FatAccessEntry (OFile, WriteData, EntryPos, &DirEnt->Entry);
82 if (EFI_ERROR (Status)) {
83 return Status;
84 }
85
86 if (--EntryCount > 0) {
87 //
88 // Write LFN directory entry
89 //
90 SetMem (LfnBuffer, sizeof (CHAR16) * LFN_CHAR_TOTAL * EntryCount, 0xff);
91 Status = StrCpyS (
92 LfnBuffer,
93 ARRAY_SIZE (LfnBuffer),
94 DirEnt->FileString
95 );
96 if (EFI_ERROR (Status)) {
97 return Status;
98 }
99
100 LfnBufferPointer = LfnBuffer;
101 LfnEntry.Attributes = FAT_ATTRIBUTE_LFN;
102 LfnEntry.Type = 0;
103 LfnEntry.MustBeZero = 0;
104 LfnEntry.Checksum = FatCheckSum (DirEnt->Entry.FileName);
105 for (LfnOrdinal = 1; LfnOrdinal <= EntryCount; LfnOrdinal++) {
106 LfnEntry.Ordinal = LfnOrdinal;
107 if (LfnOrdinal == EntryCount) {
108 LfnEntry.Ordinal |= FAT_LFN_LAST;
109 }
110
111 CopyMem (LfnEntry.Name1, LfnBufferPointer, sizeof (CHAR16) * LFN_CHAR1_LEN);
112 LfnBufferPointer += LFN_CHAR1_LEN;
113 CopyMem (LfnEntry.Name2, LfnBufferPointer, sizeof (CHAR16) * LFN_CHAR2_LEN);
114 LfnBufferPointer += LFN_CHAR2_LEN;
115 CopyMem (LfnEntry.Name3, LfnBufferPointer, sizeof (CHAR16) * LFN_CHAR3_LEN);
116 LfnBufferPointer += LFN_CHAR3_LEN;
117 EntryPos--;
118 if (DirEnt->Invalid) {
119 LfnEntry.Ordinal = DELETE_ENTRY_MARK;
120 }
121
122 Status = FatAccessEntry (OFile, WriteData, EntryPos, &LfnEntry);
123 if (EFI_ERROR (Status)) {
124 return Status;
125 }
126 }
127 }
128
129 return EFI_SUCCESS;
130}
131
142BOOLEAN
144 IN FAT_DIRENT *DirEnt
145 )
146{
147 CHAR16 *FileString;
148
149 FileString = DirEnt->FileString;
150 if ((StrCmp (FileString, L".") == 0) || (StrCmp (FileString, L"..") == 0)) {
151 return TRUE;
152 }
153
154 return FALSE;
155}
156
164STATIC
165VOID
167 IN FAT_OFILE *OFile
168 )
169{
170 UINTN Cluster;
171 FAT_DIRENT *DirEnt;
172
173 DirEnt = OFile->DirEnt;
174 Cluster = OFile->FileCluster;
175 DirEnt->Entry.FileClusterHigh = (UINT16)(Cluster >> 16);
176 DirEnt->Entry.FileCluster = (UINT16)Cluster;
177}
178
186VOID
188 IN FAT_OFILE *OFile
189 )
190{
191 ASSERT (OFile->ODir == NULL);
192 OFile->DirEnt->Entry.FileSize = (UINT32)OFile->FileSize;
193 FatSetDirEntCluster (OFile);
194}
195
204VOID
206 IN FAT_DIRENT *DirEnt1,
207 IN FAT_DIRENT *DirEnt2
208 )
209{
210 UINT8 *Entry1;
211 UINT8 *Entry2;
212
213 Entry1 = (UINT8 *)&DirEnt1->Entry;
214 Entry2 = (UINT8 *)&DirEnt2->Entry;
215 CopyMem (
216 Entry1 + FAT_ENTRY_INFO_OFFSET,
217 Entry2 + FAT_ENTRY_INFO_OFFSET,
218 sizeof (FAT_DIRECTORY_ENTRY) - FAT_ENTRY_INFO_OFFSET
219 );
220}
221
230STATIC
231VOID
233 IN FAT_OFILE *Parent,
234 IN FAT_DIRENT *DirEnt
235 )
236{
237 CHAR16 LfnBuffer[MAX_LFN_ENTRIES * LFN_CHAR_TOTAL + 1];
238 CHAR16 *LfnBufferPointer;
239 CHAR8 *File8Dot3Name;
240 UINTN EntryPos;
241 UINT8 LfnOrdinal;
242 UINT8 LfnChecksum;
243 FAT_DIRECTORY_LFN LfnEntry;
244 EFI_STATUS Status;
245
246 EntryPos = DirEnt->EntryPos;
247 File8Dot3Name = DirEnt->Entry.FileName;
248 LfnBufferPointer = LfnBuffer;
249 //
250 // Computes checksum for LFN
251 //
252 LfnChecksum = FatCheckSum (File8Dot3Name);
253 LfnOrdinal = 1;
254 do {
255 if (EntryPos == 0) {
256 LfnBufferPointer = LfnBuffer;
257 break;
258 }
259
260 EntryPos--;
261 Status = FatAccessEntry (Parent, ReadData, EntryPos, &LfnEntry);
262 if (EFI_ERROR (Status) ||
263 (LfnEntry.Attributes != FAT_ATTRIBUTE_LFN) ||
264 (LfnEntry.MustBeZero != 0) ||
265 (LfnEntry.Checksum != LfnChecksum) ||
266 ((LfnEntry.Ordinal & (~FAT_LFN_LAST)) != LfnOrdinal) ||
267 (LfnOrdinal > MAX_LFN_ENTRIES)
268 )
269 {
270 //
271 // The directory entry does not have a long file name or
272 // some error occurs when loading long file name for a directory entry,
273 // and then we load the long name from short name
274 //
275 LfnBufferPointer = LfnBuffer;
276 break;
277 }
278
279 CopyMem (LfnBufferPointer, LfnEntry.Name1, sizeof (CHAR16) * LFN_CHAR1_LEN);
280 LfnBufferPointer += LFN_CHAR1_LEN;
281 CopyMem (LfnBufferPointer, LfnEntry.Name2, sizeof (CHAR16) * LFN_CHAR2_LEN);
282 LfnBufferPointer += LFN_CHAR2_LEN;
283 CopyMem (LfnBufferPointer, LfnEntry.Name3, sizeof (CHAR16) * LFN_CHAR3_LEN);
284 LfnBufferPointer += LFN_CHAR3_LEN;
285 LfnOrdinal++;
286 } while ((LfnEntry.Ordinal & FAT_LFN_LAST) == 0);
287
288 DirEnt->EntryCount = LfnOrdinal;
289 //
290 // Terminate current Lfnbuffer
291 //
292 *LfnBufferPointer = 0;
293 if (LfnBufferPointer == LfnBuffer) {
294 //
295 // Fail to get the long file name from long file name entry,
296 // get the file name from short name
297 //
299 DirEnt,
300 LfnBuffer,
301 ARRAY_SIZE (LfnBuffer)
302 );
303 }
304
305 DirEnt->FileString = AllocateCopyPool (StrSize (LfnBuffer), LfnBuffer);
306}
307
316STATIC
317VOID
319 IN FAT_ODIR *ODir,
320 IN FAT_DIRENT *DirEnt
321 )
322{
323 if (DirEnt->Link.BackLink == NULL) {
324 DirEnt->Link.BackLink = &ODir->ChildList;
325 }
326
327 InsertTailList (DirEnt->Link.BackLink, &DirEnt->Link);
328 FatInsertToHashTable (ODir, DirEnt);
329}
330
343STATIC
346 IN FAT_OFILE *OFile,
347 OUT FAT_DIRENT **PtrDirEnt
348 )
349{
350 EFI_STATUS Status;
351 FAT_DIRENT *DirEnt;
352 FAT_ODIR *ODir;
354
355 ODir = OFile->ODir;
356 //
357 // Make sure the parent's directory has been opened
358 //
359 ASSERT (ODir != NULL);
360 //
361 // Assert we have not reached the end of directory
362 //
363 ASSERT (!ODir->EndOfDir);
364 DirEnt = NULL;
365
366 for ( ; ;) {
367 //
368 // Read the next directory entry until we find a valid directory entry (excluding lfn entry)
369 //
370 Status = FatAccessEntry (OFile, ReadData, ODir->CurrentEndPos, &Entry);
371 if (EFI_ERROR (Status)) {
372 return Status;
373 }
374
375 if (((UINT8)Entry.FileName[0] != DELETE_ENTRY_MARK) && ((Entry.Attributes & FAT_ATTRIBUTE_VOLUME_ID) == 0)) {
376 //
377 // We get a valid directory entry, then handle it
378 //
379 break;
380 }
381
382 ODir->CurrentEndPos++;
383 }
384
385 if (Entry.FileName[0] != EMPTY_ENTRY_MARK) {
386 //
387 // Although FAT spec states this field is always 0 for FAT12 & FAT16, some applications
388 // might use it for some special usage, it is safer to zero it in memory for FAT12 & FAT16.
389 //
390 if (OFile->Volume->FatType != Fat32) {
391 Entry.FileClusterHigh = 0;
392 }
393
394 //
395 // This is a valid directory entry
396 //
397 DirEnt = AllocateZeroPool (sizeof (FAT_DIRENT));
398 if (DirEnt == NULL) {
399 return EFI_OUT_OF_RESOURCES;
400 }
401
402 DirEnt->Signature = FAT_DIRENT_SIGNATURE;
403 //
404 // Remember the directory's entry position on disk
405 //
406 DirEnt->EntryPos = (UINT16)ODir->CurrentEndPos;
407 CopyMem (&DirEnt->Entry, &Entry, sizeof (FAT_DIRECTORY_ENTRY));
408 FatLoadLongNameEntry (OFile, DirEnt);
409 if (DirEnt->FileString == NULL) {
410 Status = EFI_OUT_OF_RESOURCES;
411 goto Done;
412 }
413
414 //
415 // Add this directory entry to directory
416 //
417 FatAddDirEnt (ODir, DirEnt);
418 //
419 // Point to next directory entry
420 //
421 ODir->CurrentEndPos++;
422 } else {
423 ODir->EndOfDir = TRUE;
424 }
425
426 *PtrDirEnt = DirEnt;
427 return EFI_SUCCESS;
428
429Done:
430 FatFreeDirEnt (DirEnt);
431 return Status;
432}
433
449 IN FAT_VOLUME *Volume,
450 IN FAT_DIRENT *DirEnt,
451 IN OUT UINTN *BufferSize,
452 OUT VOID *Buffer
453 )
454{
455 UINTN Size;
456 UINTN NameSize;
457 UINTN ResultSize;
458 UINTN Cluster;
459 EFI_STATUS Status;
460 EFI_FILE_INFO *Info;
461 FAT_DIRECTORY_ENTRY *Entry;
462 FAT_DATE_TIME FatLastAccess;
463
464 ASSERT_VOLUME_LOCKED (Volume);
465
467 NameSize = StrSize (DirEnt->FileString);
468 ResultSize = Size + NameSize;
469
470 Status = EFI_BUFFER_TOO_SMALL;
471 if (*BufferSize >= ResultSize) {
472 Status = EFI_SUCCESS;
473 Entry = &DirEnt->Entry;
474 Info = Buffer;
475 Info->Size = ResultSize;
476 if ((Entry->Attributes & FAT_ATTRIBUTE_DIRECTORY) != 0) {
477 Cluster = (Entry->FileClusterHigh << 16) | Entry->FileCluster;
478 Info->PhysicalSize = FatPhysicalDirSize (Volume, Cluster);
479 Info->FileSize = Info->PhysicalSize;
480 } else {
481 Info->FileSize = Entry->FileSize;
482 Info->PhysicalSize = FatPhysicalFileSize (Volume, Entry->FileSize);
483 }
484
485 ZeroMem (&FatLastAccess.Time, sizeof (FatLastAccess.Time));
486 CopyMem (&FatLastAccess.Date, &Entry->FileLastAccess, sizeof (FatLastAccess.Date));
487 FatFatTimeToEfiTime (&FatLastAccess, &Info->LastAccessTime);
488 FatFatTimeToEfiTime (&Entry->FileCreateTime, &Info->CreateTime);
489 FatFatTimeToEfiTime (&Entry->FileModificationTime, &Info->ModificationTime);
490 Info->Attribute = Entry->Attributes & EFI_FILE_VALID_ATTR;
491 CopyMem ((CHAR8 *)Buffer + Size, DirEnt->FileString, NameSize);
492 }
493
494 *BufferSize = ResultSize;
495 return Status;
496}
497
510STATIC
513 IN FAT_OFILE *OFile,
514 IN CHAR16 *FileNameString,
515 OUT FAT_DIRENT **PtrDirEnt
516 )
517{
518 BOOLEAN PossibleShortName;
519 CHAR8 File8Dot3Name[FAT_NAME_LEN];
520 FAT_ODIR *ODir;
521 FAT_DIRENT *DirEnt;
522 EFI_STATUS Status;
523
524 ODir = OFile->ODir;
525 ASSERT (ODir != NULL);
526 //
527 // Check if the file name is a valid short name
528 //
529 PossibleShortName = FatCheckIs8Dot3Name (FileNameString, File8Dot3Name);
530 //
531 // Search the hash table first
532 //
533 DirEnt = *FatLongNameHashSearch (ODir, FileNameString);
534 if ((DirEnt == NULL) && PossibleShortName) {
535 DirEnt = *FatShortNameHashSearch (ODir, File8Dot3Name);
536 }
537
538 if (DirEnt == NULL) {
539 //
540 // We fail to get the directory entry from hash table; we then
541 // search the rest directory
542 //
543 while (!ODir->EndOfDir) {
544 Status = FatLoadNextDirEnt (OFile, &DirEnt);
545 if (EFI_ERROR (Status)) {
546 return Status;
547 }
548
549 if (DirEnt != NULL) {
550 if (FatStriCmp (FileNameString, DirEnt->FileString) == 0) {
551 break;
552 }
553
554 if (PossibleShortName && (CompareMem (File8Dot3Name, DirEnt->Entry.FileName, FAT_NAME_LEN) == 0)) {
555 break;
556 }
557 }
558 }
559 }
560
561 *PtrDirEnt = DirEnt;
562 return EFI_SUCCESS;
563}
564
572VOID
574 IN FAT_OFILE *OFile
575 )
576{
577 FAT_ODIR *ODir;
578
579 ODir = OFile->ODir;
580 ASSERT (ODir != NULL);
581 ODir->CurrentCursor = &(ODir->ChildList);
582 ODir->CurrentPos = 0;
583}
584
598 IN FAT_OFILE *OFile,
599 OUT FAT_DIRENT **PtrDirEnt
600 )
601{
602 EFI_STATUS Status;
603 FAT_DIRENT *DirEnt;
604 FAT_ODIR *ODir;
605
606 ODir = OFile->ODir;
607 ASSERT (ODir != NULL);
608 if (ODir->CurrentCursor->ForwardLink == &ODir->ChildList) {
609 //
610 // End of directory, we will try one more time
611 //
612 if (!ODir->EndOfDir) {
613 //
614 // Read directory from disk
615 //
616 Status = FatLoadNextDirEnt (OFile, &DirEnt);
617 if (EFI_ERROR (Status)) {
618 return Status;
619 }
620 }
621 }
622
623 if (ODir->CurrentCursor->ForwardLink == &ODir->ChildList) {
624 //
625 // End of directory, return NULL
626 //
627 DirEnt = NULL;
628 ODir->CurrentPos = ODir->CurrentEndPos;
629 } else {
630 ODir->CurrentCursor = ODir->CurrentCursor->ForwardLink;
631 DirEnt = DIRENT_FROM_LINK (ODir->CurrentCursor);
632 ODir->CurrentPos = DirEnt->EntryPos + 1;
633 }
634
635 *PtrDirEnt = DirEnt;
636 return EFI_SUCCESS;
637}
638
647STATIC
648VOID
650 IN FAT_OFILE *OFile,
651 IN FAT_DIRENT *DirEnt
652 )
653{
654 CHAR16 *FileString;
655 CHAR8 *File8Dot3Name;
656
657 //
658 // Get new entry count and set the 8.3 name
659 //
660 DirEnt->EntryCount = 1;
661 FileString = DirEnt->FileString;
662 File8Dot3Name = DirEnt->Entry.FileName;
663 SetMem (File8Dot3Name, FAT_NAME_LEN, ' ');
664 if (StrCmp (FileString, L".") == 0) {
665 //
666 // "." entry
667 //
668 File8Dot3Name[0] = '.';
669 FatCloneDirEnt (DirEnt, OFile->DirEnt);
670 } else if (StrCmp (FileString, L"..") == 0) {
671 //
672 // ".." entry
673 //
674 File8Dot3Name[0] = '.';
675 File8Dot3Name[1] = '.';
676 FatCloneDirEnt (DirEnt, OFile->Parent->DirEnt);
677 } else {
678 //
679 // Normal name
680 //
681 if (FatCheckIs8Dot3Name (FileString, File8Dot3Name)) {
682 //
683 // This file name is a valid 8.3 file name, we need to further check its case flag
684 //
685 FatSetCaseFlag (DirEnt);
686 } else {
687 //
688 // The file name is not a valid 8.3 name we need to generate an 8.3 name for it
689 //
690 FatCreate8Dot3Name (OFile, DirEnt);
691 DirEnt->EntryCount = (UINT8)(LFN_ENTRY_NUMBER (StrLen (FileString)) + DirEnt->EntryCount);
692 }
693 }
694}
695
706STATIC
709 IN FAT_OFILE *OFile
710 )
711{
712 return FatExpandOFile (OFile, OFile->FileSize + OFile->Volume->ClusterSize);
713}
714
726STATIC
729 IN FAT_OFILE *Root,
730 OUT FAT_DIRENT *DirEnt
731 )
732{
733 EFI_STATUS Status;
734 UINTN EntryPos;
735 FAT_DIRECTORY_ENTRY *Entry;
736
737 EntryPos = 0;
738 Entry = &DirEnt->Entry;
739 DirEnt->Invalid = TRUE;
740 do {
741 Status = FatAccessEntry (Root, ReadData, EntryPos, Entry);
742 if (EFI_ERROR (Status)) {
743 return Status;
744 }
745
746 if (((UINT8)Entry->FileName[0] != DELETE_ENTRY_MARK) && (((Entry->Attributes) & (~FAT_ATTRIBUTE_ARCHIVE)) == FAT_ATTRIBUTE_VOLUME_ID)) {
747 DirEnt->EntryPos = (UINT16)EntryPos;
748 DirEnt->EntryCount = 1;
749 DirEnt->Invalid = FALSE;
750 break;
751 }
752
753 EntryPos++;
754 } while (Entry->FileName[0] != EMPTY_ENTRY_MARK);
755
756 return EFI_SUCCESS;
757}
758
774STATIC
777 IN FAT_OFILE *OFile,
778 IN FAT_DIRENT *DirEnt
779 )
780{
781 EFI_STATUS Status;
782 FAT_ODIR *ODir;
783 LIST_ENTRY *CurrentEntry;
784 FAT_DIRENT *CurrentDirEnt;
785 UINT32 CurrentPos;
786 UINT32 LabelPos;
787 UINT32 NewEntryPos;
788 UINT16 EntryCount;
789 FAT_DIRENT LabelDirEnt;
790
791 LabelPos = 0;
792 if (OFile->Parent == NULL) {
793 Status = FatSeekVolumeId (OFile, &LabelDirEnt);
794 if (EFI_ERROR (Status)) {
795 return Status;
796 }
797
798 if (!LabelDirEnt.Invalid) {
799 LabelPos = LabelDirEnt.EntryPos;
800 }
801 }
802
803 EntryCount = DirEnt->EntryCount;
804 NewEntryPos = EntryCount;
805 CurrentPos = 0;
806 ODir = OFile->ODir;
807 for (CurrentEntry = ODir->ChildList.ForwardLink;
808 CurrentEntry != &ODir->ChildList;
809 CurrentEntry = CurrentEntry->ForwardLink
810 )
811 {
812 CurrentDirEnt = DIRENT_FROM_LINK (CurrentEntry);
813 if (NewEntryPos + CurrentDirEnt->EntryCount <= CurrentDirEnt->EntryPos) {
814 if ((LabelPos > NewEntryPos) || (LabelPos <= CurrentPos)) {
815 //
816 // first fit succeeded
817 //
818 goto Done;
819 }
820 }
821
822 CurrentPos = CurrentDirEnt->EntryPos;
823 NewEntryPos = CurrentPos + EntryCount;
824 }
825
826 if (NewEntryPos >= ODir->CurrentEndPos) {
827 return EFI_VOLUME_FULL;
828 }
829
830Done:
831 DirEnt->EntryPos = (UINT16)NewEntryPos;
832 DirEnt->Link.BackLink = CurrentEntry;
833 return EFI_SUCCESS;
834}
835
848STATIC
851 IN FAT_OFILE *OFile,
852 IN FAT_DIRENT *DirEnt
853 )
854{
855 EFI_STATUS Status;
856 FAT_ODIR *ODir;
857 FAT_DIRENT *TempDirEnt;
858 UINT32 NewEndPos;
859
860 ODir = OFile->ODir;
861 ASSERT (ODir != NULL);
862 //
863 // Make sure the whole directory has been loaded
864 //
865 while (!ODir->EndOfDir) {
866 Status = FatLoadNextDirEnt (OFile, &TempDirEnt);
867 if (EFI_ERROR (Status)) {
868 return Status;
869 }
870 }
871
872 //
873 // We will append this entry to the end of directory
874 //
875 FatGetCurrentFatTime (&DirEnt->Entry.FileCreateTime);
876 CopyMem (&DirEnt->Entry.FileModificationTime, &DirEnt->Entry.FileCreateTime, sizeof (FAT_DATE_TIME));
877 CopyMem (&DirEnt->Entry.FileLastAccess, &DirEnt->Entry.FileCreateTime.Date, sizeof (FAT_DATE));
878 NewEndPos = ODir->CurrentEndPos + DirEnt->EntryCount;
879 if (NewEndPos * sizeof (FAT_DIRECTORY_ENTRY) > OFile->FileSize) {
880 if (NewEndPos >= (OFile->IsFixedRootDir ? OFile->Volume->RootEntries : FAT_MAX_DIRENTRY_COUNT)) {
881 //
882 // We try to use fist fit algorithm to insert this directory entry
883 //
884 return FatFirstFitInsertDirEnt (OFile, DirEnt);
885 }
886
887 //
888 // We should allocate a new cluster for this directory
889 //
890 Status = FatExpandODir (OFile);
891 if (EFI_ERROR (Status)) {
892 return Status;
893 }
894 }
895
896 //
897 // We append our directory entry at the end of directory file
898 //
899 ODir->CurrentEndPos = NewEndPos;
900 DirEnt->EntryPos = (UINT16)(ODir->CurrentEndPos - 1);
901 return EFI_SUCCESS;
902}
903
917 IN FAT_VOLUME *Volume,
918 IN CHAR16 *Name
919 )
920{
921 EFI_STATUS Status;
922 FAT_DIRENT LabelDirEnt;
923
924 *Name = 0;
925 Status = FatSeekVolumeId (Volume->Root, &LabelDirEnt);
926 if (!EFI_ERROR (Status)) {
927 if (!LabelDirEnt.Invalid) {
928 FatNameToStr (LabelDirEnt.Entry.FileName, FAT_NAME_LEN, FALSE, Name);
929 }
930 }
931
932 return Status;
933}
934
949 IN FAT_VOLUME *Volume,
950 IN CHAR16 *Name
951 )
952{
953 EFI_STATUS Status;
954 FAT_DIRENT LabelDirEnt;
955 FAT_OFILE *Root;
956
957 Root = Volume->Root;
958 Status = FatSeekVolumeId (Volume->Root, &LabelDirEnt);
959 if (EFI_ERROR (Status)) {
960 return Status;
961 }
962
963 if (LabelDirEnt.Invalid) {
964 //
965 // If there is not the relevant directory entry, create a new one
966 //
967 ZeroMem (&LabelDirEnt, sizeof (FAT_DIRENT));
968 LabelDirEnt.EntryCount = 1;
969 Status = FatNewEntryPos (Root, &LabelDirEnt);
970 if (EFI_ERROR (Status)) {
971 return Status;
972 }
973
974 LabelDirEnt.Entry.Attributes = FAT_ATTRIBUTE_VOLUME_ID;
975 }
976
977 SetMem (LabelDirEnt.Entry.FileName, FAT_NAME_LEN, ' ');
978 if (FatStrToFat (Name, FAT_NAME_LEN, LabelDirEnt.Entry.FileName)) {
979 return EFI_UNSUPPORTED;
980 }
981
982 FatGetCurrentFatTime (&LabelDirEnt.Entry.FileModificationTime);
983 return FatStoreDirEnt (Root, &LabelDirEnt);
984}
985
998 IN FAT_OFILE *OFile
999 )
1000{
1001 EFI_STATUS Status;
1002 FAT_DIRENT *DirEnt;
1003
1004 Status = FatExpandODir (OFile);
1005 if (EFI_ERROR (Status)) {
1006 return Status;
1007 }
1008
1009 FatSetDirEntCluster (OFile);
1010 //
1011 // Create "."
1012 //
1013 Status = FatCreateDirEnt (OFile, L".", FAT_ATTRIBUTE_DIRECTORY, &DirEnt);
1014 if (EFI_ERROR (Status)) {
1015 return Status;
1016 }
1017
1018 //
1019 // Create ".."
1020 //
1021 Status = FatCreateDirEnt (OFile, L"..", FAT_ATTRIBUTE_DIRECTORY, &DirEnt);
1022 return Status;
1023}
1024
1041 IN FAT_OFILE *OFile,
1042 IN CHAR16 *FileName,
1043 IN UINT8 Attributes,
1044 OUT FAT_DIRENT **PtrDirEnt
1045 )
1046{
1047 FAT_DIRENT *DirEnt;
1048 FAT_ODIR *ODir;
1049 EFI_STATUS Status;
1050
1051 ASSERT (OFile != NULL);
1052 ODir = OFile->ODir;
1053 ASSERT (ODir != NULL);
1054 DirEnt = AllocateZeroPool (sizeof (FAT_DIRENT));
1055 if (DirEnt == NULL) {
1056 return EFI_OUT_OF_RESOURCES;
1057 }
1058
1059 DirEnt->Signature = FAT_DIRENT_SIGNATURE;
1060 DirEnt->FileString = AllocateCopyPool (StrSize (FileName), FileName);
1061 if (DirEnt->FileString == NULL) {
1062 Status = EFI_OUT_OF_RESOURCES;
1063 goto Done;
1064 }
1065
1066 //
1067 // Determine how many directory entries we need
1068 //
1069 FatSetEntryCount (OFile, DirEnt);
1070 //
1071 // Determine the file's directory entry position
1072 //
1073 Status = FatNewEntryPos (OFile, DirEnt);
1074 if (EFI_ERROR (Status)) {
1075 goto Done;
1076 }
1077
1078 FatAddDirEnt (ODir, DirEnt);
1079 DirEnt->Entry.Attributes = Attributes;
1080 *PtrDirEnt = DirEnt;
1081 DEBUG ((DEBUG_INFO, "FSOpen: Created new directory entry '%S'\n", DirEnt->FileString));
1082 return FatStoreDirEnt (OFile, DirEnt);
1083
1084Done:
1085 FatFreeDirEnt (DirEnt);
1086 return Status;
1087}
1088
1102 IN FAT_OFILE *OFile,
1103 IN FAT_DIRENT *DirEnt
1104 )
1105{
1106 FAT_ODIR *ODir;
1107
1108 ODir = OFile->ODir;
1109 if (ODir->CurrentCursor == &DirEnt->Link) {
1110 //
1111 // Move the directory cursor to its previous directory entry
1112 //
1113 ODir->CurrentCursor = ODir->CurrentCursor->BackLink;
1114 }
1115
1116 //
1117 // Remove from directory entry list
1118 //
1119 RemoveEntryList (&DirEnt->Link);
1120 //
1121 // Remove from hash table
1122 //
1123 FatDeleteFromHashTable (ODir, DirEnt);
1124 DirEnt->Entry.FileName[0] = DELETE_ENTRY_MARK;
1125 DirEnt->Invalid = TRUE;
1126 return FatStoreDirEnt (OFile, DirEnt);
1127}
1128
1143 IN FAT_OFILE *Parent,
1144 IN FAT_DIRENT *DirEnt
1145 )
1146{
1147 FAT_OFILE *OFile;
1148 FAT_VOLUME *Volume;
1149
1150 if (DirEnt->OFile == NULL) {
1151 //
1152 // Open the directory entry
1153 //
1154 OFile = AllocateZeroPool (sizeof (FAT_OFILE));
1155 if (OFile == NULL) {
1156 return EFI_OUT_OF_RESOURCES;
1157 }
1158
1159 OFile->Signature = FAT_OFILE_SIGNATURE;
1160 InitializeListHead (&OFile->Opens);
1161 InitializeListHead (&OFile->ChildHead);
1162 OFile->Parent = Parent;
1163 OFile->DirEnt = DirEnt;
1164 if (Parent != NULL) {
1165 //
1166 // The newly created OFile is not root
1167 //
1168 Volume = Parent->Volume;
1169 OFile->FullPathLen = Parent->FullPathLen + 1 + StrLen (DirEnt->FileString);
1170 OFile->FileCluster = ((DirEnt->Entry.FileClusterHigh) << 16) | (DirEnt->Entry.FileCluster);
1171 InsertTailList (&Parent->ChildHead, &OFile->ChildLink);
1172 } else {
1173 //
1174 // The newly created OFile is root
1175 //
1176 Volume = VOLUME_FROM_ROOT_DIRENT (DirEnt);
1177 Volume->Root = OFile;
1178 OFile->FileCluster = Volume->RootCluster;
1179 if (Volume->FatType != Fat32) {
1180 OFile->IsFixedRootDir = TRUE;
1181 }
1182 }
1183
1184 OFile->FileCurrentCluster = OFile->FileCluster;
1185 OFile->Volume = Volume;
1186 InsertHeadList (&Volume->CheckRef, &OFile->CheckLink);
1187
1188 OFile->FileSize = DirEnt->Entry.FileSize;
1189 if ((DirEnt->Entry.Attributes & FAT_ATTRIBUTE_DIRECTORY) != 0) {
1190 if (OFile->IsFixedRootDir) {
1191 OFile->FileSize = Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY);
1192 } else {
1193 OFile->FileSize = FatPhysicalDirSize (Volume, OFile->FileCluster);
1194 }
1195
1196 FatRequestODir (OFile);
1197 if (OFile->ODir == NULL) {
1198 return EFI_OUT_OF_RESOURCES;
1199 }
1200 }
1201
1202 DirEnt->OFile = OFile;
1203 }
1204
1205 return EFI_SUCCESS;
1206}
1207
1215VOID
1217 IN FAT_DIRENT *DirEnt
1218 )
1219{
1220 FAT_OFILE *OFile;
1221 FAT_VOLUME *Volume;
1222
1223 OFile = DirEnt->OFile;
1224 ASSERT (OFile != NULL);
1225 Volume = OFile->Volume;
1226
1227 if (OFile->ODir != NULL) {
1228 FatDiscardODir (OFile);
1229 }
1230
1231 if (OFile->Parent == NULL) {
1232 Volume->Root = NULL;
1233 } else {
1234 RemoveEntryList (&OFile->ChildLink);
1235 }
1236
1237 FreePool (OFile);
1238 DirEnt->OFile = NULL;
1239 if (DirEnt->Invalid == TRUE) {
1240 //
1241 // Free directory entry itself
1242 //
1243 FatFreeDirEnt (DirEnt);
1244 }
1245}
1246
1269 IN OUT FAT_OFILE **PtrOFile,
1270 IN CHAR16 *FileName,
1271 IN UINT8 Attributes,
1272 OUT CHAR16 *NewFileName
1273 )
1274{
1275 EFI_STATUS Status;
1276 FAT_VOLUME *Volume;
1277 CHAR16 ComponentName[EFI_PATH_STRING_LENGTH];
1278 UINTN FileNameLen;
1279 BOOLEAN DirIntended;
1280 CHAR16 *Next;
1281 FAT_OFILE *OFile;
1282 FAT_DIRENT *DirEnt;
1283
1284 DirEnt = NULL;
1285
1286 FileNameLen = StrLen (FileName);
1287 if (FileNameLen == 0) {
1288 return EFI_INVALID_PARAMETER;
1289 }
1290
1291 OFile = *PtrOFile;
1292 Volume = OFile->Volume;
1293
1294 DirIntended = FALSE;
1295 if (FileName[FileNameLen - 1] == PATH_NAME_SEPARATOR) {
1296 DirIntended = TRUE;
1297 }
1298
1299 //
1300 // If name starts with path name separator, then move to root OFile
1301 //
1302 if (*FileName == PATH_NAME_SEPARATOR) {
1303 OFile = Volume->Root;
1304 FileName++;
1305 FileNameLen--;
1306 }
1307
1308 //
1309 // Per FAT Spec the file name should meet the following criteria:
1310 // C1. Length (FileLongName) <= 255
1311 // C2. Length (X:FileFullPath<NUL>) <= 260
1312 // Here we check C2 first.
1313 //
1314 if (2 + OFile->FullPathLen + 1 + FileNameLen + 1 > EFI_PATH_STRING_LENGTH) {
1315 //
1316 // Full path length can not surpass 256
1317 //
1318 return EFI_INVALID_PARAMETER;
1319 }
1320
1321 //
1322 // Start at current location
1323 //
1324 Next = FileName;
1325 for ( ; ;) {
1326 //
1327 // Get the next component name
1328 //
1329 FileName = Next;
1330 Next = FatGetNextNameComponent (FileName, ComponentName);
1331
1332 //
1333 // If end of the file name, we're done
1334 //
1335 if (ComponentName[0] == 0) {
1336 if (DirIntended && (OFile->ODir == NULL)) {
1337 return EFI_NOT_FOUND;
1338 }
1339
1340 NewFileName[0] = 0;
1341 break;
1342 }
1343
1344 //
1345 // If "dot", then current
1346 //
1347 if (StrCmp (ComponentName, L".") == 0) {
1348 continue;
1349 }
1350
1351 //
1352 // If "dot dot", then parent
1353 //
1354 if (StrCmp (ComponentName, L"..") == 0) {
1355 if (OFile->Parent == NULL) {
1356 return EFI_INVALID_PARAMETER;
1357 }
1358
1359 OFile = OFile->Parent;
1360 continue;
1361 }
1362
1363 if (!FatFileNameIsValid (ComponentName, NewFileName)) {
1364 return EFI_INVALID_PARAMETER;
1365 }
1366
1367 //
1368 // We have a component name, try to open it
1369 //
1370 if (OFile->ODir == NULL) {
1371 //
1372 // This file isn't a directory, can't open it
1373 //
1374 return EFI_NOT_FOUND;
1375 }
1376
1377 //
1378 // Search the compName in the directory
1379 //
1380 Status = FatSearchODir (OFile, NewFileName, &DirEnt);
1381 if (EFI_ERROR (Status)) {
1382 return Status;
1383 }
1384
1385 if (DirEnt == NULL) {
1386 //
1387 // component name is not found in the directory
1388 //
1389 if (*Next != 0) {
1390 return EFI_NOT_FOUND;
1391 }
1392
1393 if (DirIntended && ((Attributes & FAT_ATTRIBUTE_DIRECTORY) == 0)) {
1394 return EFI_INVALID_PARAMETER;
1395 }
1396
1397 //
1398 // It's the last component name - return with the open
1399 // path and the remaining name
1400 //
1401 break;
1402 }
1403
1404 Status = FatOpenDirEnt (OFile, DirEnt);
1405 if (EFI_ERROR (Status)) {
1406 return Status;
1407 }
1408
1409 OFile = DirEnt->OFile;
1410 }
1411
1412 *PtrOFile = OFile;
1413 return EFI_SUCCESS;
1414}
UINT64 UINTN
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
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
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)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID FatRequestODir(IN FAT_OFILE *OFile)
VOID FatDiscardODir(IN FAT_OFILE *OFile)
EFI_STATUS FatRemoveDirEnt(IN FAT_OFILE *OFile, IN FAT_DIRENT *DirEnt)
EFI_STATUS FatStoreDirEnt(IN FAT_OFILE *OFile, IN FAT_DIRENT *DirEnt)
EFI_STATUS FatGetDirEntInfo(IN FAT_VOLUME *Volume, IN FAT_DIRENT *DirEnt, IN OUT UINTN *BufferSize, OUT VOID *Buffer)
EFI_STATUS FatCreateDirEnt(IN FAT_OFILE *OFile, IN CHAR16 *FileName, IN UINT8 Attributes, OUT FAT_DIRENT **PtrDirEnt)
BOOLEAN FatIsDotDirEnt(IN FAT_DIRENT *DirEnt)
EFI_STATUS FatOpenDirEnt(IN FAT_OFILE *Parent, IN FAT_DIRENT *DirEnt)
EFI_STATUS FatLocateOFile(IN OUT FAT_OFILE **PtrOFile, IN CHAR16 *FileName, IN UINT8 Attributes, OUT CHAR16 *NewFileName)
STATIC EFI_STATUS FatExpandODir(IN FAT_OFILE *OFile)
EFI_STATUS FatSetVolumeEntry(IN FAT_VOLUME *Volume, IN CHAR16 *Name)
EFI_STATUS FatCreateDotDirEnts(IN FAT_OFILE *OFile)
STATIC EFI_STATUS FatSearchODir(IN FAT_OFILE *OFile, IN CHAR16 *FileNameString, OUT FAT_DIRENT **PtrDirEnt)
EFI_STATUS FatGetNextDirEnt(IN FAT_OFILE *OFile, OUT FAT_DIRENT **PtrDirEnt)
EFI_STATUS FatGetVolumeEntry(IN FAT_VOLUME *Volume, IN CHAR16 *Name)
STATIC EFI_STATUS FatAccessEntry(IN FAT_OFILE *Parent, IN IO_MODE IoMode, IN UINTN EntryPos, IN OUT VOID *Entry)
STATIC EFI_STATUS FatLoadNextDirEnt(IN FAT_OFILE *OFile, OUT FAT_DIRENT **PtrDirEnt)
STATIC VOID FatLoadLongNameEntry(IN FAT_OFILE *Parent, IN FAT_DIRENT *DirEnt)
STATIC VOID FatSetEntryCount(IN FAT_OFILE *OFile, IN FAT_DIRENT *DirEnt)
VOID FatCloneDirEnt(IN FAT_DIRENT *DirEnt1, IN FAT_DIRENT *DirEnt2)
STATIC EFI_STATUS FatSeekVolumeId(IN FAT_OFILE *Root, OUT FAT_DIRENT *DirEnt)
VOID FatUpdateDirEntClusterSizeInfo(IN FAT_OFILE *OFile)
STATIC EFI_STATUS FatFirstFitInsertDirEnt(IN FAT_OFILE *OFile, IN FAT_DIRENT *DirEnt)
STATIC EFI_STATUS FatNewEntryPos(IN FAT_OFILE *OFile, IN FAT_DIRENT *DirEnt)
VOID FatResetODirCursor(IN FAT_OFILE *OFile)
STATIC VOID FatAddDirEnt(IN FAT_ODIR *ODir, IN FAT_DIRENT *DirEnt)
VOID FatCloseDirEnt(IN FAT_DIRENT *DirEnt)
STATIC VOID FatSetDirEntCluster(IN FAT_OFILE *OFile)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
FAT_DIRENT ** FatShortNameHashSearch(IN FAT_ODIR *ODir, IN CHAR8 *ShortNameString)
Definition: Hash.c:103
BOOLEAN FatFileNameIsValid(IN CHAR16 *InputFileName, OUT CHAR16 *OutputFileName)
Definition: FileName.c:444
VOID FatFatTimeToEfiTime(IN FAT_DATE_TIME *FTime, OUT EFI_TIME *ETime)
Definition: Misc.c:519
BOOLEAN FatStrToFat(IN CHAR16 *String, IN UINTN FatSize, OUT CHAR8 *Fat)
UINTN FatPhysicalDirSize(IN FAT_VOLUME *Volume, IN UINTN Cluster)
Definition: FileSpace.c:654
VOID FatInsertToHashTable(IN FAT_ODIR *ODir, IN FAT_DIRENT *DirEnt)
Definition: Hash.c:132
VOID FatNameToStr(IN CHAR8 *FatName, IN UINTN Len, IN UINTN LowerCase, IN CHAR16 *Str)
EFI_STATUS FatExpandOFile(IN FAT_OFILE *OFile, IN UINT64 ExpandedSize)
Definition: ReadWrite.c:537
VOID FatGetFileNameViaCaseFlag(IN FAT_DIRENT *DirEnt, IN OUT CHAR16 *FileString, IN UINTN FileStringMax)
Definition: FileName.c:348
VOID FatSetCaseFlag(IN FAT_DIRENT *DirEnt)
Definition: FileName.c:293
INTN FatStriCmp(IN CHAR16 *Str1, IN CHAR16 *Str2)
UINT64 FatPhysicalFileSize(IN FAT_VOLUME *Volume, IN UINTN RealSize)
Definition: FileSpace.c:699
VOID FatCreate8Dot3Name(IN FAT_OFILE *Parent, IN FAT_DIRENT *DirEnt)
Definition: FileName.c:169
EFI_STATUS FatAccessOFile(IN FAT_OFILE *OFile, IN IO_MODE IoMode, IN UINTN Position, IN UINTN *DataBufferSize, IN UINT8 *UserBuffer, IN FAT_TASK *Task)
UINT8 FatCheckSum(IN CHAR8 *ShortNameString)
Definition: FileName.c:382
VOID FatFreeDirEnt(IN FAT_DIRENT *DirEnt)
Definition: Misc.c:441
VOID FatDeleteFromHashTable(IN FAT_ODIR *ODir, IN FAT_DIRENT *DirEnt)
Definition: Hash.c:165
VOID FatGetCurrentFatTime(OUT FAT_DATE_TIME *FatTime)
Definition: Misc.c:543
CHAR16 * FatGetNextNameComponent(IN CHAR16 *Path, OUT CHAR16 *Name)
Definition: FileName.c:410
BOOLEAN FatCheckIs8Dot3Name(IN CHAR16 *FileName, OUT CHAR8 *File8Dot3Name)
Definition: FileName.c:25
FAT_DIRENT ** FatLongNameHashSearch(IN FAT_ODIR *ODir, IN CHAR16 *LongNameString)
Definition: Hash.c:72
#define SIZE_OF_EFI_FILE_INFO
Definition: FileInfo.h:62
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#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 OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
Definition: Fat.h:204
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
EFI_TIME LastAccessTime
Definition: FileInfo.h:39
UINT64 FileSize
Definition: FileInfo.h:27