]> git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/EnhancedFatDxe/DirectoryManage.c
FatPkg/EnhancedFatDxe: Make the variable name follow rule
[mirror_edk2.git] / FatPkg / EnhancedFatDxe / DirectoryManage.c
1 /*++
2
3 Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12
13 Module Name:
14
15 DirectoryManage.c
16
17 Abstract:
18
19 Functions for performing directory entry io
20
21 Revision History
22
23 --*/
24
25 #include "Fat.h"
26
27 STATIC
28 EFI_STATUS
29 FatAccessEntry (
30 IN FAT_OFILE *Parent,
31 IN IO_MODE IoMode,
32 IN UINTN EntryPos,
33 IN OUT VOID *Entry
34 )
35 /*++
36
37 Routine Description:
38
39 Get a directory entry from disk for the Ofile.
40
41 Arguments:
42
43 Parent - The parent of the OFile which need to update.
44 IoMode - Indicate whether to read directory entry or write directroy entry.
45 EntryPos - The position of the directory entry to be accessed.
46 Entry - The directory entry read or written.
47
48 Returns:
49
50 EFI_SUCCESS - Access the directory entry sucessfully.
51 other - An error occurred when reading the directory entry.
52
53 --*/
54 {
55 UINTN Position;
56 UINTN BufferSize;
57
58 Position = EntryPos * sizeof (FAT_DIRECTORY_ENTRY);
59 if (Position >= Parent->FileSize) {
60 //
61 // End of directory
62 //
63 ASSERT (IoMode == ReadData);
64 ((FAT_DIRECTORY_ENTRY *) Entry)->FileName[0] = EMPTY_ENTRY_MARK;
65 ((FAT_DIRECTORY_ENTRY *) Entry)->Attributes = 0;
66 return EFI_SUCCESS;
67 }
68
69 BufferSize = sizeof (FAT_DIRECTORY_ENTRY);
70 return FatAccessOFile (Parent, IoMode, Position, &BufferSize, Entry, NULL);
71 }
72
73 EFI_STATUS
74 FatStoreDirEnt (
75 IN FAT_OFILE *OFile,
76 IN FAT_DIRENT *DirEnt
77 )
78 /*++
79
80 Routine Description:
81
82 Save the directory entry to disk.
83
84 Arguments:
85
86 OFile - The parent OFile which needs to update.
87 DirEnt - The directory entry to be saved.
88
89 Returns:
90
91 EFI_SUCCESS - Store the directory entry successfully.
92 other - An error occurred when writing the directory entry.
93
94 --*/
95 {
96 EFI_STATUS Status;
97 FAT_DIRECTORY_LFN LfnEntry;
98 UINTN EntryPos;
99 CHAR16 *LfnBufferPointer;
100 CHAR16 LfnBuffer[MAX_LFN_ENTRIES * LFN_CHAR_TOTAL + 1];
101 UINT8 EntryCount;
102 UINT8 LfnOrdinal;
103
104 EntryPos = DirEnt->EntryPos;
105 EntryCount = DirEnt->EntryCount;
106 //
107 // Write directory entry
108 //
109 Status = FatAccessEntry (OFile, WriteData, EntryPos, &DirEnt->Entry);
110 if (EFI_ERROR (Status)) {
111 return Status;
112 }
113
114 if (--EntryCount > 0) {
115 //
116 // Write LFN directory entry
117 //
118 SetMem (LfnBuffer, sizeof (CHAR16) * LFN_CHAR_TOTAL * EntryCount, 0xff);
119 Status = StrCpyS (
120 LfnBuffer,
121 ARRAY_SIZE (LfnBuffer),
122 DirEnt->FileString
123 );
124 if (EFI_ERROR (Status)) {
125 return Status;
126 }
127
128 LfnBufferPointer = LfnBuffer;
129 LfnEntry.Attributes = FAT_ATTRIBUTE_LFN;
130 LfnEntry.Type = 0;
131 LfnEntry.MustBeZero = 0;
132 LfnEntry.Checksum = FatCheckSum (DirEnt->Entry.FileName);
133 for (LfnOrdinal = 1; LfnOrdinal <= EntryCount; LfnOrdinal++) {
134 LfnEntry.Ordinal = LfnOrdinal;
135 if (LfnOrdinal == EntryCount) {
136 LfnEntry.Ordinal |= FAT_LFN_LAST;
137 }
138
139 CopyMem (LfnEntry.Name1, LfnBufferPointer, sizeof (CHAR16) * LFN_CHAR1_LEN);
140 LfnBufferPointer += LFN_CHAR1_LEN;
141 CopyMem (LfnEntry.Name2, LfnBufferPointer, sizeof (CHAR16) * LFN_CHAR2_LEN);
142 LfnBufferPointer += LFN_CHAR2_LEN;
143 CopyMem (LfnEntry.Name3, LfnBufferPointer, sizeof (CHAR16) * LFN_CHAR3_LEN);
144 LfnBufferPointer += LFN_CHAR3_LEN;
145 EntryPos--;
146 if (DirEnt->Invalid) {
147 LfnEntry.Ordinal = DELETE_ENTRY_MARK;
148 }
149
150 Status = FatAccessEntry (OFile, WriteData, EntryPos, &LfnEntry);
151 if (EFI_ERROR (Status)) {
152 return Status;
153 }
154 }
155 }
156
157 return EFI_SUCCESS;
158 }
159
160 BOOLEAN
161 FatIsDotDirEnt (
162 IN FAT_DIRENT *DirEnt
163 )
164 /*++
165
166 Routine Description:
167
168 Determine whether the directory entry is "." or ".." entry.
169
170 Arguments:
171
172 DirEnt - The corresponding directory entry.
173
174 Returns:
175
176 TRUE - The directory entry is "." or ".." directory entry
177 FALSE - The directory entry is not "." or ".." directory entry
178
179 --*/
180 {
181 CHAR16 *FileString;
182 FileString = DirEnt->FileString;
183 if (StrCmp (FileString, L".") == 0 || StrCmp (FileString, L"..") == 0) {
184 return TRUE;
185 }
186
187 return FALSE;
188 }
189
190 STATIC
191 VOID
192 FatSetDirEntCluster (
193 IN FAT_OFILE *OFile
194 )
195 /*++
196
197 Routine Description:
198
199 Set the OFile's cluster info in its directory entry.
200
201 Arguments:
202
203 OFile - The corresponding OFile.
204
205 Returns:
206
207 None.
208
209 --*/
210 {
211 UINTN Cluster;
212 FAT_DIRENT *DirEnt;
213
214 DirEnt = OFile->DirEnt;
215 Cluster = OFile->FileCluster;
216 DirEnt->Entry.FileClusterHigh = (UINT16) (Cluster >> 16);
217 DirEnt->Entry.FileCluster = (UINT16) Cluster;
218 }
219
220 VOID
221 FatUpdateDirEntClusterSizeInfo (
222 IN FAT_OFILE *OFile
223 )
224 /*++
225
226 Routine Description:
227
228 Set the OFile's cluster and size info in its directory entry.
229
230 Arguments:
231
232 OFile - The corresponding OFile.
233
234 Returns:
235
236 None.
237
238 --*/
239 {
240 ASSERT (OFile->ODir == NULL);
241 OFile->DirEnt->Entry.FileSize = (UINT32) OFile->FileSize;
242 FatSetDirEntCluster (OFile);
243 }
244
245 VOID
246 FatCloneDirEnt (
247 IN FAT_DIRENT *DirEnt1,
248 IN FAT_DIRENT *DirEnt2
249 )
250 /*++
251
252 Routine Description:
253
254 Copy all the information of DirEnt2 to DirEnt1 except for 8.3 name.
255
256 Arguments:
257
258 DirEnt1 - The destination directory entry.
259 DirEnt2 - The source directory entry.
260
261 Returns:
262
263 None.
264
265 --*/
266 {
267 UINT8 *Entry1;
268 UINT8 *Entry2;
269 Entry1 = (UINT8 *) &DirEnt1->Entry;
270 Entry2 = (UINT8 *) &DirEnt2->Entry;
271 CopyMem (
272 Entry1 + FAT_ENTRY_INFO_OFFSET,
273 Entry2 + FAT_ENTRY_INFO_OFFSET,
274 sizeof (FAT_DIRECTORY_ENTRY) - FAT_ENTRY_INFO_OFFSET
275 );
276 }
277
278 STATIC
279 VOID
280 FatLoadLongNameEntry (
281 IN FAT_OFILE *Parent,
282 IN FAT_DIRENT *DirEnt
283 )
284 /*++
285
286 Routine Description:
287
288 Get the LFN for the directory entry.
289
290 Arguments:
291
292 Parent - The parent directory.
293 DirEnt - The directory entry to get LFN.
294
295 Returns:
296
297 None.
298
299 --*/
300 {
301 CHAR16 LfnBuffer[MAX_LFN_ENTRIES * LFN_CHAR_TOTAL + 1];
302 CHAR16 *LfnBufferPointer;
303 CHAR8 *File8Dot3Name;
304 UINTN EntryPos;
305 UINT8 LfnOrdinal;
306 UINT8 LfnChecksum;
307 FAT_DIRECTORY_LFN LfnEntry;
308 EFI_STATUS Status;
309
310 EntryPos = DirEnt->EntryPos;
311 File8Dot3Name = DirEnt->Entry.FileName;
312 LfnBufferPointer = LfnBuffer;
313 //
314 // Computes checksum for LFN
315 //
316 LfnChecksum = FatCheckSum (File8Dot3Name);
317 LfnOrdinal = 1;
318 do {
319 if (EntryPos == 0) {
320 LfnBufferPointer = LfnBuffer;
321 break;
322 }
323
324 EntryPos--;
325 Status = FatAccessEntry (Parent, ReadData, EntryPos, &LfnEntry);
326 if (EFI_ERROR (Status) ||
327 LfnEntry.Attributes != FAT_ATTRIBUTE_LFN ||
328 LfnEntry.MustBeZero != 0 ||
329 LfnEntry.Checksum != LfnChecksum ||
330 (LfnEntry.Ordinal & (~FAT_LFN_LAST)) != LfnOrdinal ||
331 LfnOrdinal > MAX_LFN_ENTRIES
332 ) {
333 //
334 // The directory entry does not have a long file name or
335 // some error occurs when loading long file name for a directory entry,
336 // and then we load the long name from short name
337 //
338 LfnBufferPointer = LfnBuffer;
339 break;
340 }
341
342 CopyMem (LfnBufferPointer, LfnEntry.Name1, sizeof (CHAR16) * LFN_CHAR1_LEN);
343 LfnBufferPointer += LFN_CHAR1_LEN;
344 CopyMem (LfnBufferPointer, LfnEntry.Name2, sizeof (CHAR16) * LFN_CHAR2_LEN);
345 LfnBufferPointer += LFN_CHAR2_LEN;
346 CopyMem (LfnBufferPointer, LfnEntry.Name3, sizeof (CHAR16) * LFN_CHAR3_LEN);
347 LfnBufferPointer += LFN_CHAR3_LEN;
348 LfnOrdinal++;
349 } while ((LfnEntry.Ordinal & FAT_LFN_LAST) == 0);
350 DirEnt->EntryCount = LfnOrdinal;
351 //
352 // Terminate current Lfnbuffer
353 //
354 *LfnBufferPointer = 0;
355 if (LfnBufferPointer == LfnBuffer) {
356 //
357 // Fail to get the long file name from long file name entry,
358 // get the file name from short name
359 //
360 FatGetFileNameViaCaseFlag (
361 DirEnt,
362 LfnBuffer,
363 ARRAY_SIZE (LfnBuffer)
364 );
365 }
366
367 DirEnt->FileString = AllocateCopyPool (StrSize (LfnBuffer), LfnBuffer);
368 }
369
370 STATIC
371 VOID
372 FatAddDirEnt (
373 IN FAT_ODIR *ODir,
374 IN FAT_DIRENT *DirEnt
375 )
376 /*++
377
378 Routine Description:
379
380 Add this directory entry node to the list of directory entries and hash table.
381
382 Arguments:
383
384 ODir - The parent OFile which needs to be updated.
385 DirEnt - The directory entry to be added.
386
387 Returns:
388
389 None.
390
391 --*/
392 {
393 if (DirEnt->Link.BackLink == NULL) {
394 DirEnt->Link.BackLink = &ODir->ChildList;
395 }
396 InsertTailList (DirEnt->Link.BackLink, &DirEnt->Link);
397 FatInsertToHashTable (ODir, DirEnt);
398 }
399
400 STATIC
401 EFI_STATUS
402 FatLoadNextDirEnt (
403 IN FAT_OFILE *OFile,
404 OUT FAT_DIRENT **PtrDirEnt
405 )
406 /*++
407
408 Routine Description:
409
410 Load from disk the next directory entry at current end of directory position
411
412 Arguments:
413
414 OFile - The parent OFile.
415 PtrDirEnt - The directory entry that is loaded.
416
417 Returns:
418
419 EFI_SUCCESS - Load the directory entry successfully.
420 EFI_OUT_OF_RESOURCES - Out of resource.
421 other - An error occurred when reading the directory entries.
422
423 --*/
424 {
425 EFI_STATUS Status;
426 FAT_DIRENT *DirEnt;
427 FAT_ODIR *ODir;
428 FAT_DIRECTORY_ENTRY Entry;
429
430 ODir = OFile->ODir;
431 //
432 // Make sure the parent's directory has been opened
433 //
434 ASSERT (ODir != NULL);
435 //
436 // Assert we have not reached the end of directory
437 //
438 ASSERT (!ODir->EndOfDir);
439 DirEnt = NULL;
440
441 for (;;) {
442 //
443 // Read the next directory entry until we find a valid directory entry (excluding lfn entry)
444 //
445 Status = FatAccessEntry (OFile, ReadData, ODir->CurrentEndPos, &Entry);
446 if (EFI_ERROR (Status)) {
447 return Status;
448 }
449
450 if (((UINT8) Entry.FileName[0] != DELETE_ENTRY_MARK) && (Entry.Attributes & FAT_ATTRIBUTE_VOLUME_ID) == 0) {
451 //
452 // We get a valid directory entry, then handle it
453 //
454 break;
455 }
456
457 ODir->CurrentEndPos++;
458 }
459
460 if (Entry.FileName[0] != EMPTY_ENTRY_MARK) {
461 //
462 // Although FAT spec states this field is always 0 for FAT12 & FAT16, some applications
463 // might use it for some special usage, it is safer to zero it in memory for FAT12 & FAT16.
464 //
465 if (OFile->Volume->FatType != Fat32) {
466 Entry.FileClusterHigh = 0;
467 }
468
469 //
470 // This is a valid directory entry
471 //
472 DirEnt = AllocateZeroPool (sizeof (FAT_DIRENT));
473 if (DirEnt == NULL) {
474 return EFI_OUT_OF_RESOURCES;
475 }
476
477 DirEnt->Signature = FAT_DIRENT_SIGNATURE;
478 //
479 // Remember the directory's entry position on disk
480 //
481 DirEnt->EntryPos = (UINT16) ODir->CurrentEndPos;
482 CopyMem (&DirEnt->Entry, &Entry, sizeof (FAT_DIRECTORY_ENTRY));
483 FatLoadLongNameEntry (OFile, DirEnt);
484 if (DirEnt->FileString == NULL) {
485 Status = EFI_OUT_OF_RESOURCES;
486 goto Done;
487 }
488 //
489 // Add this directory entry to directory
490 //
491 FatAddDirEnt (ODir, DirEnt);
492 //
493 // Point to next directory entry
494 //
495 ODir->CurrentEndPos++;
496 } else {
497 ODir->EndOfDir = TRUE;
498 }
499
500 *PtrDirEnt = DirEnt;
501 return EFI_SUCCESS;
502
503 Done:
504 FatFreeDirEnt (DirEnt);
505 return Status;
506 }
507
508 EFI_STATUS
509 FatGetDirEntInfo (
510 IN FAT_VOLUME *Volume,
511 IN FAT_DIRENT *DirEnt,
512 IN OUT UINTN *BufferSize,
513 OUT VOID *Buffer
514 )
515 /*++
516
517 Routine Description:
518
519 Get the directory entry's info into Buffer.
520
521 Arguments:
522
523 Volume - FAT file system volume.
524 DirEnt - The corresponding directory entry.
525 BufferSize - Size of Buffer.
526 Buffer - Buffer containing file info.
527
528 Returns:
529
530 EFI_SUCCESS - Get the file info successfully.
531 EFI_BUFFER_TOO_SMALL - The buffer is too small.
532
533 --*/
534 {
535 UINTN Size;
536 UINTN NameSize;
537 UINTN ResultSize;
538 UINTN Cluster;
539 EFI_STATUS Status;
540 EFI_FILE_INFO *Info;
541 FAT_DIRECTORY_ENTRY *Entry;
542 FAT_DATE_TIME FatLastAccess;
543
544 ASSERT_VOLUME_LOCKED (Volume);
545
546 Size = SIZE_OF_EFI_FILE_INFO;
547 NameSize = StrSize (DirEnt->FileString);
548 ResultSize = Size + NameSize;
549
550 Status = EFI_BUFFER_TOO_SMALL;
551 if (*BufferSize >= ResultSize) {
552 Status = EFI_SUCCESS;
553 Entry = &DirEnt->Entry;
554 Info = Buffer;
555 Info->Size = ResultSize;
556 if ((Entry->Attributes & FAT_ATTRIBUTE_DIRECTORY) != 0) {
557 Cluster = (Entry->FileClusterHigh << 16) | Entry->FileCluster;
558 Info->PhysicalSize = FatPhysicalDirSize (Volume, Cluster);
559 Info->FileSize = Info->PhysicalSize;
560 } else {
561 Info->FileSize = Entry->FileSize;
562 Info->PhysicalSize = FatPhysicalFileSize (Volume, Entry->FileSize);
563 }
564
565 ZeroMem (&FatLastAccess.Time, sizeof (FatLastAccess.Time));
566 CopyMem (&FatLastAccess.Date, &Entry->FileLastAccess, sizeof (FatLastAccess.Date));
567 FatFatTimeToEfiTime (&FatLastAccess, &Info->LastAccessTime);
568 FatFatTimeToEfiTime (&Entry->FileCreateTime, &Info->CreateTime);
569 FatFatTimeToEfiTime (&Entry->FileModificationTime, &Info->ModificationTime);
570 Info->Attribute = Entry->Attributes & EFI_FILE_VALID_ATTR;
571 CopyMem ((CHAR8 *) Buffer + Size, DirEnt->FileString, NameSize);
572 }
573
574 *BufferSize = ResultSize;
575 return Status;
576 }
577
578 STATIC
579 EFI_STATUS
580 FatSearchODir (
581 IN FAT_OFILE *OFile,
582 IN CHAR16 *FileNameString,
583 OUT FAT_DIRENT **PtrDirEnt
584 )
585 /*++
586
587 Routine Description:
588
589 Search the directory for the directory entry whose filename is FileNameString.
590
591 Arguments:
592
593 OFile - The parent OFile whose directory is to be searched.
594 FileNameString - The filename to be searched.
595 PtrDirEnt - pointer to the directory entry if found.
596
597 Returns:
598
599 EFI_SUCCESS - Find the directory entry or not found.
600 other - An error occurred when reading the directory entries.
601
602 --*/
603 {
604 BOOLEAN PossibleShortName;
605 CHAR8 File8Dot3Name[FAT_NAME_LEN];
606 FAT_ODIR *ODir;
607 FAT_DIRENT *DirEnt;
608 EFI_STATUS Status;
609
610 ODir = OFile->ODir;
611 ASSERT (ODir != NULL);
612 //
613 // Check if the file name is a valid short name
614 //
615 PossibleShortName = FatCheckIs8Dot3Name (FileNameString, File8Dot3Name);
616 //
617 // Search the hash table first
618 //
619 DirEnt = *FatLongNameHashSearch (ODir, FileNameString);
620 if (DirEnt == NULL && PossibleShortName) {
621 DirEnt = *FatShortNameHashSearch (ODir, File8Dot3Name);
622 }
623 if (DirEnt == NULL) {
624 //
625 // We fail to get the directory entry from hash table; we then
626 // search the rest directory
627 //
628 while (!ODir->EndOfDir) {
629 Status = FatLoadNextDirEnt (OFile, &DirEnt);
630 if (EFI_ERROR (Status)) {
631 return Status;
632 }
633
634 if (DirEnt != NULL) {
635 if (FatStriCmp (FileNameString, DirEnt->FileString) == 0) {
636 break;
637 }
638
639 if (PossibleShortName && CompareMem (File8Dot3Name, DirEnt->Entry.FileName, FAT_NAME_LEN) == 0) {
640 break;
641 }
642 }
643 }
644 }
645
646 *PtrDirEnt = DirEnt;
647 return EFI_SUCCESS;
648 }
649
650 VOID
651 FatResetODirCursor (
652 IN FAT_OFILE *OFile
653 )
654 /*++
655
656 Routine Description:
657
658 Set the OFile's current directory cursor to the list head.
659
660 Arguments:
661
662 OFile - The directory OFile whose directory cursor is reset.
663
664 Returns:
665
666 None.
667
668 --*/
669 {
670 FAT_ODIR *ODir;
671
672 ODir = OFile->ODir;
673 ASSERT (ODir != NULL);
674 ODir->CurrentCursor = &(ODir->ChildList);
675 ODir->CurrentPos = 0;
676 }
677
678 EFI_STATUS
679 FatGetNextDirEnt (
680 IN FAT_OFILE *OFile,
681 OUT FAT_DIRENT **PtrDirEnt
682 )
683 /*++
684
685 Routine Description:
686
687 Set the directory's cursor to the next and get the next directory entry.
688
689 Arguments:
690
691 OFile - The parent OFile.
692 PtrDirEnt - The next directory entry.
693
694 Returns:
695
696 EFI_SUCCESS - We get the next directory entry successfully.
697 other - An error occurred when get next directory entry.
698
699 --*/
700 {
701 EFI_STATUS Status;
702 FAT_DIRENT *DirEnt;
703 FAT_ODIR *ODir;
704
705 ODir = OFile->ODir;
706 ASSERT (ODir != NULL);
707 if (ODir->CurrentCursor->ForwardLink == &ODir->ChildList) {
708 //
709 // End of directory, we will try one more time
710 //
711 if (!ODir->EndOfDir) {
712 //
713 // Read directory from disk
714 //
715 Status = FatLoadNextDirEnt (OFile, &DirEnt);
716 if (EFI_ERROR (Status)) {
717 return Status;
718 }
719 }
720 }
721
722 if (ODir->CurrentCursor->ForwardLink == &ODir->ChildList) {
723 //
724 // End of directory, return NULL
725 //
726 DirEnt = NULL;
727 ODir->CurrentPos = ODir->CurrentEndPos;
728 } else {
729 ODir->CurrentCursor = ODir->CurrentCursor->ForwardLink;
730 DirEnt = DIRENT_FROM_LINK (ODir->CurrentCursor);
731 ODir->CurrentPos = DirEnt->EntryPos + 1;
732 }
733
734 *PtrDirEnt = DirEnt;
735 return EFI_SUCCESS;
736 }
737
738 STATIC
739 VOID
740 FatSetEntryCount (
741 IN FAT_OFILE *OFile,
742 IN FAT_DIRENT *DirEnt
743 )
744 /*++
745
746 Routine Description:
747
748 Set the directory entry count according to the filename.
749
750 Arguments:
751
752 OFile - The corresponding OFile.
753 DirEnt - The directory entry to be set.
754
755 Returns:
756
757 None.
758
759 --*/
760 {
761 CHAR16 *FileString;
762 CHAR8 *File8Dot3Name;
763
764 //
765 // Get new entry count and set the 8.3 name
766 //
767 DirEnt->EntryCount = 1;
768 FileString = DirEnt->FileString;
769 File8Dot3Name = DirEnt->Entry.FileName;
770 SetMem (File8Dot3Name, FAT_NAME_LEN, ' ');
771 if (StrCmp (FileString, L".") == 0) {
772 //
773 // "." entry
774 //
775 File8Dot3Name[0] = '.';
776 FatCloneDirEnt (DirEnt, OFile->DirEnt);
777 } else if (StrCmp (FileString, L"..") == 0) {
778 //
779 // ".." entry
780 //
781 File8Dot3Name[0] = '.';
782 File8Dot3Name[1] = '.';
783 FatCloneDirEnt (DirEnt, OFile->Parent->DirEnt);
784 } else {
785 //
786 // Normal name
787 //
788 if (FatCheckIs8Dot3Name (FileString, File8Dot3Name)) {
789 //
790 // This file name is a valid 8.3 file name, we need to further check its case flag
791 //
792 FatSetCaseFlag (DirEnt);
793 } else {
794 //
795 // The file name is not a valid 8.3 name we need to generate an 8.3 name for it
796 //
797 FatCreate8Dot3Name (OFile, DirEnt);
798 DirEnt->EntryCount = (UINT8)(LFN_ENTRY_NUMBER (StrLen (FileString)) + DirEnt->EntryCount);
799 }
800 }
801 }
802
803 STATIC
804 EFI_STATUS
805 FatExpandODir (
806 IN FAT_OFILE *OFile
807 )
808 /*++
809
810 Routine Description:
811
812 Append a zero cluster to the current OFile.
813
814 Arguments:
815
816 OFile - The directory OFile which needs to be updated.
817
818 Returns:
819
820 EFI_SUCCESS - Append a zero cluster to the OFile successfully.
821 other - An error occurred when appending the zero cluster.
822
823 --*/
824 {
825 return FatExpandOFile (OFile, OFile->FileSize + OFile->Volume->ClusterSize);
826 }
827
828 STATIC
829 EFI_STATUS
830 FatSeekVolumeId (
831 IN FAT_OFILE *Root,
832 OUT FAT_DIRENT *DirEnt
833 )
834 /*++
835
836 Routine Description:
837
838 Search the Root OFile for the possible volume label.
839
840 Arguments:
841
842 Root - The Root OFile.
843 DirEnt - The returned directory entry of volume label.
844
845 Returns:
846
847 EFI_SUCCESS - The search process is completed successfully.
848 other - An error occurred when searching volume label.
849
850 --*/
851 {
852 EFI_STATUS Status;
853 UINTN EntryPos;
854 FAT_DIRECTORY_ENTRY *Entry;
855
856 EntryPos = 0;
857 Entry = &DirEnt->Entry;
858 DirEnt->Invalid = TRUE;
859 do {
860 Status = FatAccessEntry (Root, ReadData, EntryPos, Entry);
861 if (EFI_ERROR (Status)) {
862 return Status;
863 }
864
865 if (((UINT8) Entry->FileName[0] != DELETE_ENTRY_MARK) && (((Entry->Attributes) & (~FAT_ATTRIBUTE_ARCHIVE)) == FAT_ATTRIBUTE_VOLUME_ID)) {
866 DirEnt->EntryPos = (UINT16) EntryPos;
867 DirEnt->EntryCount = 1;
868 DirEnt->Invalid = FALSE;
869 break;
870 }
871
872 EntryPos++;
873 } while (Entry->FileName[0] != EMPTY_ENTRY_MARK);
874 return EFI_SUCCESS;
875 }
876
877 STATIC
878 EFI_STATUS
879 FatFirstFitInsertDirEnt (
880 IN FAT_OFILE *OFile,
881 IN FAT_DIRENT *DirEnt
882 )
883 /*++
884
885 Routine Description:
886
887 Use First Fit Algorithm to insert directory entry.
888 Only this function will erase "E5" entries in a directory.
889 In view of safest recovery, this function will only be triggered
890 when maximum directory entry number has reached.
891
892 Arguments:
893
894 OFile - The corresponding OFile.
895 DirEnt - The directory entry to be inserted.
896
897 Returns:
898
899 EFI_SUCCESS - The directory entry has been successfully inserted.
900 EFI_VOLUME_FULL - The directory can not hold more directory entries.
901 Others - Some error occurred when inserting new directory entries.
902
903 --*/
904 {
905 EFI_STATUS Status;
906 FAT_ODIR *ODir;
907 LIST_ENTRY *CurrentEntry;
908 FAT_DIRENT *CurrentDirEnt;
909 UINT32 CurrentPos;
910 UINT32 LabelPos;
911 UINT32 NewEntryPos;
912 UINT16 EntryCount;
913 FAT_DIRENT LabelDirEnt;
914
915 LabelPos = 0;
916 if (OFile->Parent == NULL) {
917 Status = FatSeekVolumeId (OFile, &LabelDirEnt);
918 if (EFI_ERROR (Status)) {
919 return Status;
920 }
921
922 if (!LabelDirEnt.Invalid) {
923 LabelPos = LabelDirEnt.EntryPos;
924 }
925 }
926
927 EntryCount = DirEnt->EntryCount;
928 NewEntryPos = EntryCount;
929 CurrentPos = 0;
930 ODir = OFile->ODir;
931 for (CurrentEntry = ODir->ChildList.ForwardLink;
932 CurrentEntry != &ODir->ChildList;
933 CurrentEntry = CurrentEntry->ForwardLink
934 ) {
935 CurrentDirEnt = DIRENT_FROM_LINK (CurrentEntry);
936 if (NewEntryPos + CurrentDirEnt->EntryCount <= CurrentDirEnt->EntryPos) {
937 if (LabelPos > NewEntryPos || LabelPos <= CurrentPos) {
938 //
939 // first fit succeeded
940 //
941 goto Done;
942 }
943 }
944
945 CurrentPos = CurrentDirEnt->EntryPos;
946 NewEntryPos = CurrentPos + EntryCount;
947 }
948
949 if (NewEntryPos >= ODir->CurrentEndPos) {
950 return EFI_VOLUME_FULL;
951 }
952
953 Done:
954 DirEnt->EntryPos = (UINT16) NewEntryPos;
955 DirEnt->Link.BackLink = CurrentEntry;
956 return EFI_SUCCESS;
957 }
958
959 STATIC
960 EFI_STATUS
961 FatNewEntryPos (
962 IN FAT_OFILE *OFile,
963 IN FAT_DIRENT *DirEnt
964 )
965 /*++
966
967 Routine Description:
968
969 Find the new directory entry position for the directory entry.
970
971 Arguments:
972
973 OFile - The corresponding OFile.
974 DirEnt - The directory entry whose new position is to be set.
975
976 Returns:
977
978 EFI_SUCCESS - The new directory entry position is successfully found.
979 EFI_VOLUME_FULL - The directory has reach its maximum capacity.
980 other - An error occurred when reading the directory entry.
981
982 --*/
983 {
984 EFI_STATUS Status;
985 FAT_ODIR *ODir;
986 FAT_DIRENT *TempDirEnt;
987 UINT32 NewEndPos;
988
989 ODir = OFile->ODir;
990 ASSERT (ODir != NULL);
991 //
992 // Make sure the whole directory has been loaded
993 //
994 while (!ODir->EndOfDir) {
995 Status = FatLoadNextDirEnt (OFile, &TempDirEnt);
996 if (EFI_ERROR (Status)) {
997 return Status;
998 }
999 }
1000 //
1001 // We will append this entry to the end of directory
1002 //
1003 FatGetCurrentFatTime (&DirEnt->Entry.FileCreateTime);
1004 CopyMem (&DirEnt->Entry.FileModificationTime, &DirEnt->Entry.FileCreateTime, sizeof (FAT_DATE_TIME));
1005 CopyMem (&DirEnt->Entry.FileLastAccess, &DirEnt->Entry.FileCreateTime.Date, sizeof (FAT_DATE));
1006 NewEndPos = ODir->CurrentEndPos + DirEnt->EntryCount;
1007 if (NewEndPos * sizeof (FAT_DIRECTORY_ENTRY) > OFile->FileSize) {
1008 if (NewEndPos >= (OFile->IsFixedRootDir ? OFile->Volume->RootEntries : FAT_MAX_DIRENTRY_COUNT)) {
1009 //
1010 // We try to use fist fit algorithm to insert this directory entry
1011 //
1012 return FatFirstFitInsertDirEnt (OFile, DirEnt);
1013 }
1014 //
1015 // We should allocate a new cluster for this directory
1016 //
1017 Status = FatExpandODir (OFile);
1018 if (EFI_ERROR (Status)) {
1019 return Status;
1020 }
1021 }
1022 //
1023 // We append our directory entry at the end of directory file
1024 //
1025 ODir->CurrentEndPos = NewEndPos;
1026 DirEnt->EntryPos = (UINT16) (ODir->CurrentEndPos - 1);
1027 return EFI_SUCCESS;
1028 }
1029
1030 EFI_STATUS
1031 FatGetVolumeEntry (
1032 IN FAT_VOLUME *Volume,
1033 IN CHAR16 *Name
1034 )
1035 /*++
1036
1037 Routine Description:
1038
1039 Get the directory entry for the volume.
1040
1041 Arguments:
1042
1043 Volume - FAT file system volume.
1044 Name - The file name of the volume.
1045
1046 Returns:
1047
1048 EFI_SUCCESS - Update the volume with the directory entry sucessfully.
1049 others - An error occurred when getting volume label.
1050
1051 --*/
1052 {
1053 EFI_STATUS Status;
1054 FAT_DIRENT LabelDirEnt;
1055
1056 *Name = 0;
1057 Status = FatSeekVolumeId (Volume->Root, &LabelDirEnt);
1058 if (!EFI_ERROR (Status)) {
1059 if (!LabelDirEnt.Invalid) {
1060 FatNameToStr (LabelDirEnt.Entry.FileName, FAT_NAME_LEN, FALSE, Name);
1061 }
1062 }
1063
1064 return Status;
1065 }
1066
1067 EFI_STATUS
1068 FatSetVolumeEntry (
1069 IN FAT_VOLUME *Volume,
1070 IN CHAR16 *Name
1071 )
1072 /*++
1073
1074 Routine Description:
1075
1076 Set the relevant directory entry into disk for the volume.
1077
1078 Arguments:
1079
1080 Volume - FAT file system volume.
1081 Name - The new file name of the volume.
1082
1083 Returns:
1084
1085 EFI_SUCCESS - Update the Volume sucessfully.
1086 EFI_UNSUPPORTED - The input label is not a valid volume label.
1087 other - An error occurred when setting volume label.
1088
1089 --*/
1090 {
1091 EFI_STATUS Status;
1092 FAT_DIRENT LabelDirEnt;
1093 FAT_OFILE *Root;
1094
1095 Root = Volume->Root;
1096 Status = FatSeekVolumeId (Volume->Root, &LabelDirEnt);
1097 if (EFI_ERROR (Status)) {
1098 return Status;
1099 }
1100
1101 if (LabelDirEnt.Invalid) {
1102 //
1103 // If there is not the relevant directory entry, create a new one
1104 //
1105 ZeroMem (&LabelDirEnt, sizeof (FAT_DIRENT));
1106 LabelDirEnt.EntryCount = 1;
1107 Status = FatNewEntryPos (Root, &LabelDirEnt);
1108 if (EFI_ERROR (Status)) {
1109 return Status;
1110 }
1111
1112 LabelDirEnt.Entry.Attributes = FAT_ATTRIBUTE_VOLUME_ID;
1113 }
1114
1115 SetMem (LabelDirEnt.Entry.FileName, FAT_NAME_LEN, ' ');
1116 if (FatStrToFat (Name, FAT_NAME_LEN, LabelDirEnt.Entry.FileName)) {
1117 return EFI_UNSUPPORTED;
1118 }
1119
1120 FatGetCurrentFatTime (&LabelDirEnt.Entry.FileModificationTime);
1121 return FatStoreDirEnt (Root, &LabelDirEnt);
1122 }
1123
1124 EFI_STATUS
1125 FatCreateDotDirEnts (
1126 IN FAT_OFILE *OFile
1127 )
1128 /*++
1129
1130 Routine Description:
1131
1132 Create "." and ".." directory entries in the newly-created parent OFile.
1133
1134 Arguments:
1135
1136 OFile - The parent OFile.
1137
1138 Returns:
1139
1140 EFI_SUCCESS - The dot directory entries are successfully created.
1141 other - An error occurred when creating the directory entry.
1142
1143 --*/
1144 {
1145 EFI_STATUS Status;
1146 FAT_DIRENT *DirEnt;
1147
1148 Status = FatExpandODir (OFile);
1149 if (EFI_ERROR (Status)) {
1150 return Status;
1151 }
1152
1153 FatSetDirEntCluster (OFile);
1154 //
1155 // Create "."
1156 //
1157 Status = FatCreateDirEnt (OFile, L".", FAT_ATTRIBUTE_DIRECTORY, &DirEnt);
1158 if (EFI_ERROR (Status)) {
1159 return Status;
1160 }
1161 //
1162 // Create ".."
1163 //
1164 Status = FatCreateDirEnt (OFile, L"..", FAT_ATTRIBUTE_DIRECTORY, &DirEnt);
1165 return Status;
1166 }
1167
1168 EFI_STATUS
1169 FatCreateDirEnt (
1170 IN FAT_OFILE *OFile,
1171 IN CHAR16 *FileName,
1172 IN UINT8 Attributes,
1173 OUT FAT_DIRENT **PtrDirEnt
1174 )
1175 /*++
1176
1177 Routine Description:
1178
1179 Create a directory entry in the parent OFile.
1180
1181 Arguments:
1182
1183 OFile - The parent OFile.
1184 FileName - The filename of the newly-created directory entry.
1185 Attributes - The attribute of the newly-created directory entry.
1186 PtrDirEnt - The pointer to the newly-created directory entry.
1187
1188 Returns:
1189
1190 EFI_SUCCESS - The directory entry is successfully created.
1191 EFI_OUT_OF_RESOURCES - Not enough memory to create the directory entry.
1192 other - An error occurred when creating the directory entry.
1193
1194 --*/
1195 {
1196 FAT_DIRENT *DirEnt;
1197 FAT_ODIR *ODir;
1198 EFI_STATUS Status;
1199
1200 ASSERT (OFile != NULL);
1201 ODir = OFile->ODir;
1202 ASSERT (ODir != NULL);
1203 DirEnt = AllocateZeroPool (sizeof (FAT_DIRENT));
1204 if (DirEnt == NULL) {
1205 return EFI_OUT_OF_RESOURCES;
1206 }
1207
1208 DirEnt->Signature = FAT_DIRENT_SIGNATURE;
1209 DirEnt->FileString = AllocateCopyPool (StrSize (FileName), FileName);
1210 if (DirEnt->FileString == NULL) {
1211 Status = EFI_OUT_OF_RESOURCES;
1212 goto Done;
1213 }
1214 //
1215 // Determine how many directory entries we need
1216 //
1217 FatSetEntryCount (OFile, DirEnt);
1218 //
1219 // Determine the file's directory entry position
1220 //
1221 Status = FatNewEntryPos (OFile, DirEnt);
1222 if (EFI_ERROR (Status)) {
1223 goto Done;
1224 }
1225
1226 FatAddDirEnt (ODir, DirEnt);
1227 DirEnt->Entry.Attributes = Attributes;
1228 *PtrDirEnt = DirEnt;
1229 DEBUG ((EFI_D_INFO, "FSOpen: Created new directory entry '%S'\n", DirEnt->FileString));
1230 return FatStoreDirEnt (OFile, DirEnt);
1231
1232 Done:
1233 FatFreeDirEnt (DirEnt);
1234 return Status;
1235 }
1236
1237 EFI_STATUS
1238 FatRemoveDirEnt (
1239 IN FAT_OFILE *OFile,
1240 IN FAT_DIRENT *DirEnt
1241 )
1242 /*++
1243
1244 Routine Description:
1245
1246 Remove this directory entry node from the list of directory entries and hash table.
1247
1248 Arguments:
1249
1250 OFile - The parent OFile.
1251 DirEnt - The directory entry to be removed.
1252
1253 Returns:
1254
1255 EFI_SUCCESS - The directory entry is successfully removed.
1256 other - An error occurred when removing the directory entry.
1257
1258 --*/
1259 {
1260 FAT_ODIR *ODir;
1261
1262 ODir = OFile->ODir;
1263 if (ODir->CurrentCursor == &DirEnt->Link) {
1264 //
1265 // Move the directory cursor to its previous directory entry
1266 //
1267 ODir->CurrentCursor = ODir->CurrentCursor->BackLink;
1268 }
1269 //
1270 // Remove from directory entry list
1271 //
1272 RemoveEntryList (&DirEnt->Link);
1273 //
1274 // Remove from hash table
1275 //
1276 FatDeleteFromHashTable (ODir, DirEnt);
1277 DirEnt->Entry.FileName[0] = DELETE_ENTRY_MARK;
1278 DirEnt->Invalid = TRUE;
1279 return FatStoreDirEnt (OFile, DirEnt);
1280 }
1281
1282 EFI_STATUS
1283 FatOpenDirEnt (
1284 IN FAT_OFILE *Parent,
1285 IN FAT_DIRENT *DirEnt
1286 )
1287 /*++
1288
1289 Routine Description:
1290
1291 Open the directory entry to get the OFile.
1292
1293 Arguments:
1294
1295 OFile - The parent OFile.
1296 DirEnt - The directory entry to be opened.
1297
1298 Returns:
1299
1300 EFI_SUCCESS - The directory entry is successfully opened.
1301 EFI_OUT_OF_RESOURCES - not enough memory to allocate a new OFile.
1302 other - An error occurred when opening the directory entry.
1303
1304 --*/
1305 {
1306 FAT_OFILE *OFile;
1307 FAT_VOLUME *Volume;
1308
1309 if (DirEnt->OFile == NULL) {
1310 //
1311 // Open the directory entry
1312 //
1313 OFile = AllocateZeroPool (sizeof (FAT_OFILE));
1314 if (OFile == NULL) {
1315 return EFI_OUT_OF_RESOURCES;
1316 }
1317
1318 OFile->Signature = FAT_OFILE_SIGNATURE;
1319 InitializeListHead (&OFile->Opens);
1320 InitializeListHead (&OFile->ChildHead);
1321 OFile->Parent = Parent;
1322 OFile->DirEnt = DirEnt;
1323 if (Parent != NULL) {
1324 //
1325 // The newly created OFile is not root
1326 //
1327 Volume = Parent->Volume;
1328 OFile->FullPathLen = Parent->FullPathLen + 1 + StrLen (DirEnt->FileString);
1329 OFile->FileCluster = ((DirEnt->Entry.FileClusterHigh) << 16) | (DirEnt->Entry.FileCluster);
1330 InsertTailList (&Parent->ChildHead, &OFile->ChildLink);
1331 } else {
1332 //
1333 // The newly created OFile is root
1334 //
1335 Volume = VOLUME_FROM_ROOT_DIRENT (DirEnt);
1336 Volume->Root = OFile;
1337 OFile->FileCluster = Volume->RootCluster;
1338 if (Volume->FatType != Fat32) {
1339 OFile->IsFixedRootDir = TRUE;
1340 }
1341 }
1342
1343 OFile->FileCurrentCluster = OFile->FileCluster;
1344 OFile->Volume = Volume;
1345 InsertHeadList (&Volume->CheckRef, &OFile->CheckLink);
1346
1347 OFile->FileSize = DirEnt->Entry.FileSize;
1348 if ((DirEnt->Entry.Attributes & FAT_ATTRIBUTE_DIRECTORY) != 0) {
1349 if (OFile->IsFixedRootDir) {
1350 OFile->FileSize = Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY);
1351 } else {
1352 OFile->FileSize = FatPhysicalDirSize (Volume, OFile->FileCluster);
1353 }
1354
1355 FatRequestODir (OFile);
1356 if (OFile->ODir == NULL) {
1357 return EFI_OUT_OF_RESOURCES;
1358 }
1359 }
1360
1361 DirEnt->OFile = OFile;
1362 }
1363
1364 return EFI_SUCCESS;
1365 }
1366
1367 VOID
1368 FatCloseDirEnt (
1369 IN FAT_DIRENT *DirEnt
1370 )
1371 /*++
1372
1373 Routine Description:
1374
1375 Close the directory entry and free the OFile.
1376
1377 Arguments:
1378
1379 DirEnt - The directory entry to be closed.
1380
1381 Returns:
1382
1383 EFI_SUCCESS - The directory entry is successfully opened.
1384 Other - An error occurred when opening the directory entry.
1385
1386 --*/
1387 {
1388 FAT_OFILE *OFile;
1389 FAT_VOLUME *Volume;
1390
1391 OFile = DirEnt->OFile;
1392 ASSERT (OFile != NULL);
1393 Volume = OFile->Volume;
1394
1395 if (OFile->ODir != NULL) {
1396 FatDiscardODir (OFile);
1397 }
1398
1399 if (OFile->Parent == NULL) {
1400 Volume->Root = NULL;
1401 } else {
1402 RemoveEntryList (&OFile->ChildLink);
1403 }
1404
1405 FreePool (OFile);
1406 DirEnt->OFile = NULL;
1407 if (DirEnt->Invalid == TRUE) {
1408 //
1409 // Free directory entry itself
1410 //
1411 FatFreeDirEnt (DirEnt);
1412 }
1413 }
1414
1415 EFI_STATUS
1416 FatLocateOFile (
1417 IN OUT FAT_OFILE **PtrOFile,
1418 IN CHAR16 *FileName,
1419 IN UINT8 Attributes,
1420 OUT CHAR16 *NewFileName
1421 )
1422 /*++
1423
1424 Routine Description:
1425
1426 Traverse filename and open all OFiles that can be opened.
1427 Update filename pointer to the component that can't be opened.
1428 If more than one name component remains, returns an error;
1429 otherwise, return the remaining name component so that the caller might choose to create it.
1430
1431 Arguments:
1432 PtrOFile - As input, the reference OFile; as output, the located OFile.
1433 FileName - The file name relevant to the OFile.
1434 Attributes - The attribute of the destination OFile.
1435 NewFileName - The remaining file name.
1436
1437 Returns:
1438
1439 EFI_NOT_FOUND - The file name can't be opened and there is more than one
1440 components within the name left (this means the name can
1441 not be created either).
1442 EFI_INVALID_PARAMETER - The parameter is not valid.
1443 EFI_SUCCESS - Open the file successfully.
1444 other - An error occured when locating the OFile.
1445
1446 --*/
1447 {
1448 EFI_STATUS Status;
1449 FAT_VOLUME *Volume;
1450 CHAR16 ComponentName[EFI_PATH_STRING_LENGTH];
1451 UINTN FileNameLen;
1452 BOOLEAN DirIntended;
1453 CHAR16 *Next;
1454 FAT_OFILE *OFile;
1455 FAT_DIRENT *DirEnt;
1456
1457 DirEnt = NULL;
1458
1459 FileNameLen = StrLen (FileName);
1460 if (FileNameLen == 0) {
1461 return EFI_INVALID_PARAMETER;
1462 }
1463
1464 OFile = *PtrOFile;
1465 Volume = OFile->Volume;
1466
1467 DirIntended = FALSE;
1468 if (FileName[FileNameLen - 1] == PATH_NAME_SEPARATOR) {
1469 DirIntended = TRUE;
1470 }
1471 //
1472 // If name starts with path name separator, then move to root OFile
1473 //
1474 if (*FileName == PATH_NAME_SEPARATOR) {
1475 OFile = Volume->Root;
1476 FileName++;
1477 FileNameLen--;
1478 }
1479 //
1480 // Per FAT Spec the file name should meet the following criteria:
1481 // C1. Length (FileLongName) <= 255
1482 // C2. Length (X:FileFullPath<NUL>) <= 260
1483 // Here we check C2 first.
1484 //
1485 if (2 + OFile->FullPathLen + 1 + FileNameLen + 1 > EFI_PATH_STRING_LENGTH) {
1486 //
1487 // Full path length can not surpass 256
1488 //
1489 return EFI_INVALID_PARAMETER;
1490 }
1491 //
1492 // Start at current location
1493 //
1494 Next = FileName;
1495 for (;;) {
1496 //
1497 // Get the next component name
1498 //
1499 FileName = Next;
1500 Next = FatGetNextNameComponent (FileName, ComponentName);
1501
1502 //
1503 // If end of the file name, we're done
1504 //
1505 if (ComponentName[0] == 0) {
1506 if (DirIntended && OFile->ODir == NULL) {
1507 return EFI_NOT_FOUND;
1508 }
1509
1510 NewFileName[0] = 0;
1511 break;
1512 }
1513 //
1514 // If "dot", then current
1515 //
1516 if (StrCmp (ComponentName, L".") == 0) {
1517 continue;
1518 }
1519 //
1520 // If "dot dot", then parent
1521 //
1522 if (StrCmp (ComponentName, L"..") == 0) {
1523 if (OFile->Parent == NULL) {
1524 return EFI_INVALID_PARAMETER;
1525 }
1526 OFile = OFile->Parent;
1527 continue;
1528 }
1529
1530 if (!FatFileNameIsValid (ComponentName, NewFileName)) {
1531 return EFI_INVALID_PARAMETER;
1532 }
1533 //
1534 // We have a component name, try to open it
1535 //
1536 if (OFile->ODir == NULL) {
1537 //
1538 // This file isn't a directory, can't open it
1539 //
1540 return EFI_NOT_FOUND;
1541 }
1542 //
1543 // Search the compName in the directory
1544 //
1545 Status = FatSearchODir (OFile, NewFileName, &DirEnt);
1546 if (EFI_ERROR (Status)) {
1547 return Status;
1548 }
1549
1550 if (DirEnt == NULL) {
1551 //
1552 // component name is not found in the directory
1553 //
1554 if (*Next != 0) {
1555 return EFI_NOT_FOUND;
1556 }
1557
1558 if (DirIntended && (Attributes & FAT_ATTRIBUTE_DIRECTORY) == 0) {
1559 return EFI_INVALID_PARAMETER;
1560 }
1561 //
1562 // It's the last component name - return with the open
1563 // path and the remaining name
1564 //
1565 break;
1566 }
1567
1568 Status = FatOpenDirEnt (OFile, DirEnt);
1569 if (EFI_ERROR (Status)) {
1570 return Status;
1571 }
1572
1573 OFile = DirEnt->OFile;
1574 }
1575
1576 *PtrOFile = OFile;
1577 return EFI_SUCCESS;
1578 }
1579