]> git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/EnhancedFatDxe/FileSpace.c
1. Correct File header to ## @file 2. Remove unnecessary .common] postfix on section.
[mirror_edk2.git] / FatPkg / EnhancedFatDxe / FileSpace.c
1 /*++
2
3 Copyright (c) 2005, Intel Corporation
4 All rights reserved. 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 FileSpace.c
16
17 Abstract:
18
19 Routines dealing with disk spaces and FAT table entries
20
21 Revision History
22
23 --*/
24
25 #include "Fat.h"
26
27
28 STATIC
29 VOID *
30 FatLoadFatEntry (
31 IN FAT_VOLUME *Volume,
32 IN UINTN Index
33 )
34 /*++
35
36 Routine Description:
37
38 Get the FAT entry of the volume, which is identified with the Index.
39
40 Arguments:
41
42 Volume - FAT file system volume.
43 Index - The index of the FAT entry of the volume.
44
45 Returns:
46
47 The buffer of the FAT entry
48
49 --*/
50 {
51 UINTN Pos;
52 EFI_STATUS Status;
53
54 if (Index > (Volume->MaxCluster + 1)) {
55 Volume->FatEntryBuffer = (UINT32) -1;
56 return &Volume->FatEntryBuffer;
57 }
58 //
59 // Compute buffer position needed
60 //
61 switch (Volume->FatType) {
62 case FAT12:
63 Pos = FAT_POS_FAT12 (Index);
64 break;
65
66 case FAT16:
67 Pos = FAT_POS_FAT16 (Index);
68 break;
69
70 default:
71 Pos = FAT_POS_FAT32 (Index);
72 }
73 //
74 // Set the position and read the buffer
75 //
76 Volume->FatEntryPos = Volume->FatPos + Pos;
77 Status = FatDiskIo (
78 Volume,
79 READ_FAT,
80 Volume->FatEntryPos,
81 Volume->FatEntrySize,
82 &Volume->FatEntryBuffer
83 );
84 if (EFI_ERROR (Status)) {
85 Volume->FatEntryBuffer = (UINT32) -1;
86 }
87
88 return &Volume->FatEntryBuffer;
89 }
90
91 STATIC
92 UINTN
93 FatGetFatEntry (
94 IN FAT_VOLUME *Volume,
95 IN UINTN Index
96 )
97 /*++
98
99 Routine Description:
100
101 Get the FAT entry value of the volume, which is identified with the Index.
102
103 Arguments:
104
105 Volume - FAT file system volume.
106 Index - The index of the FAT entry of the volume.
107
108 Returns:
109
110 The value of the FAT entry.
111
112 --*/
113 {
114 VOID *Pos;
115 UINT8 *E12;
116 UINT16 *E16;
117 UINT32 *E32;
118 UINTN Accum;
119
120 Pos = FatLoadFatEntry (Volume, Index);
121
122 if (Index > (Volume->MaxCluster + 1)) {
123 return (UINTN) -1;
124 }
125
126 switch (Volume->FatType) {
127 case FAT12:
128 E12 = Pos;
129 Accum = E12[0] | (E12[1] << 8);
130 Accum = FAT_ODD_CLUSTER_FAT12 (Index) ? (Accum >> 4) : (Accum & FAT_CLUSTER_MASK_FAT12);
131 Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT12) ? FAT_CLUSTER_SPECIAL_EXT : 0);
132 break;
133
134 case FAT16:
135 E16 = Pos;
136 Accum = *E16;
137 Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT16) ? FAT_CLUSTER_SPECIAL_EXT : 0);
138 break;
139
140 default:
141 E32 = Pos;
142 Accum = *E32 & FAT_CLUSTER_MASK_FAT32;
143 Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT32) ? FAT_CLUSTER_SPECIAL_EXT : 0);
144 }
145
146 return Accum;
147 }
148
149 STATIC
150 EFI_STATUS
151 FatSetFatEntry (
152 IN FAT_VOLUME *Volume,
153 IN UINTN Index,
154 IN UINTN Value
155 )
156 /*++
157
158 Routine Description:
159
160 Set the FAT entry value of the volume, which is identified with the Index.
161
162 Arguments:
163
164 Volume - FAT file system volume.
165 Index - The index of the FAT entry of the volume.
166 Value - The new value of the FAT entry.
167
168 Returns:
169
170 EFI_SUCCESS - Set the new FAT entry value sucessfully.
171 EFI_VOLUME_CORRUPTED - The FAT type of the volume is error.
172 other - An error occurred when operation the FAT entries.
173
174 --*/
175 {
176 VOID *Pos;
177 UINT8 *E12;
178 UINT16 *E16;
179 UINT32 *E32;
180 UINTN Accum;
181 EFI_STATUS Status;
182 UINTN OriginalVal;
183
184 if (Index < FAT_MIN_CLUSTER) {
185 return EFI_VOLUME_CORRUPTED;
186 }
187
188 OriginalVal = FatGetFatEntry (Volume, Index);
189 if (Value == FAT_CLUSTER_FREE && OriginalVal != FAT_CLUSTER_FREE) {
190 Volume->FatInfoSector.FreeInfo.ClusterCount += 1;
191 if (Index < Volume->FatInfoSector.FreeInfo.NextCluster) {
192 Volume->FatInfoSector.FreeInfo.NextCluster = (UINT32) Index;
193 }
194 } else if (Value != FAT_CLUSTER_FREE && OriginalVal == FAT_CLUSTER_FREE) {
195 if (Volume->FatInfoSector.FreeInfo.ClusterCount != 0) {
196 Volume->FatInfoSector.FreeInfo.ClusterCount -= 1;
197 }
198 }
199 //
200 // Make sure the entry is in memory
201 //
202 Pos = FatLoadFatEntry (Volume, Index);
203
204 //
205 // Update the value
206 //
207 switch (Volume->FatType) {
208 case FAT12:
209 E12 = Pos;
210 Accum = E12[0] | (E12[1] << 8);
211 Value = Value & FAT_CLUSTER_MASK_FAT12;
212
213 if (FAT_ODD_CLUSTER_FAT12 (Index)) {
214 Accum = (Value << 4) | (Accum & 0xF);
215 } else {
216 Accum = Value | (Accum & FAT_CLUSTER_UNMASK_FAT12);
217 }
218
219 E12[0] = (UINT8) (Accum & 0xFF);
220 E12[1] = (UINT8) (Accum >> 8);
221 break;
222
223 case FAT16:
224 E16 = Pos;
225 *E16 = (UINT16) Value;
226 break;
227
228 default:
229 E32 = Pos;
230 *E32 = (*E32 & FAT_CLUSTER_UNMASK_FAT32) | (UINT32) (Value & FAT_CLUSTER_MASK_FAT32);
231 }
232 //
233 // If the volume's dirty bit is not set, set it now
234 //
235 if (!Volume->FatDirty && Volume->FatType != FAT12) {
236 Volume->FatDirty = TRUE;
237 FatAccessVolumeDirty (Volume, WRITE_FAT, &Volume->DirtyValue);
238 }
239 //
240 // Write the updated fat entry value to the volume
241 // The fat is the first fat, and other fat will be in sync
242 // when the FAT cache flush back.
243 //
244 Status = FatDiskIo (
245 Volume,
246 WRITE_FAT,
247 Volume->FatEntryPos,
248 Volume->FatEntrySize,
249 &Volume->FatEntryBuffer
250 );
251 return Status;
252 }
253
254 STATIC
255 EFI_STATUS
256 FatFreeClusters (
257 IN FAT_VOLUME *Volume,
258 IN UINTN Cluster
259 )
260 /*++
261
262 Routine Description:
263
264 Free the cluster clain.
265
266 Arguments:
267
268 Volume - FAT file system volume.
269 Cluster - The first cluster of cluster chain.
270
271 Returns:
272
273 EFI_SUCCESS - The cluster chain is freed successfully.
274 EFI_VOLUME_CORRUPTED - There are errors in the file's clusters.
275
276 --*/
277 {
278 UINTN LastCluster;
279
280 while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
281 if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
282
283 DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatShrinkEof: cluster chain corrupt\n"));
284 return EFI_VOLUME_CORRUPTED;
285 }
286
287 LastCluster = Cluster;
288 Cluster = FatGetFatEntry (Volume, Cluster);
289 FatSetFatEntry (Volume, LastCluster, FAT_CLUSTER_FREE);
290 }
291
292 return EFI_SUCCESS;
293 }
294
295 STATIC
296 UINTN
297 FatAllocateCluster (
298 IN FAT_VOLUME *Volume
299 )
300 /*++
301
302 Routine Description:
303
304 Allocate a free cluster and return the cluster index.
305
306 Arguments:
307
308 Volume - FAT file system volume.
309
310 Returns:
311
312 The index of the free cluster
313
314 --*/
315 {
316 UINTN Cluster;
317
318 //
319 // Start looking at FatFreePos for the next unallocated cluster
320 //
321 if (Volume->DiskError) {
322 return (UINTN) FAT_CLUSTER_LAST;
323 }
324
325 for (;;) {
326 //
327 // If the end of the list, return no available cluster
328 //
329 if (Volume->FatInfoSector.FreeInfo.NextCluster > (Volume->MaxCluster + 1)) {
330 if (Volume->FreeInfoValid && 0 < (INT32) (Volume->FatInfoSector.FreeInfo.ClusterCount)) {
331 Volume->FreeInfoValid = FALSE;
332 }
333
334 FatComputeFreeInfo (Volume);
335 if (Volume->FatInfoSector.FreeInfo.NextCluster > (Volume->MaxCluster + 1)) {
336 return (UINTN) FAT_CLUSTER_LAST;
337 }
338 }
339
340 Cluster = FatGetFatEntry (Volume, Volume->FatInfoSector.FreeInfo.NextCluster);
341 if (Cluster == FAT_CLUSTER_FREE) {
342 break;
343 }
344 //
345 // Try the next cluster
346 //
347 Volume->FatInfoSector.FreeInfo.NextCluster += 1;
348 }
349
350 Cluster = Volume->FatInfoSector.FreeInfo.NextCluster;
351 Volume->FatInfoSector.FreeInfo.NextCluster += 1;
352 return Cluster;
353 }
354
355 STATIC
356 UINTN
357 FatSizeToClusters (
358 IN FAT_VOLUME *Volume,
359 IN UINTN Size
360 )
361 /*++
362
363 Routine Description:
364
365 Count the number of clusters given a size
366
367 Arguments:
368
369 Volume - The file system volume.
370 Size - The size in bytes.
371
372 Returns:
373
374 The number of the clusters.
375
376 --*/
377 {
378 UINTN Clusters;
379
380 Clusters = Size >> Volume->ClusterAlignment;
381 if ((Size & (Volume->ClusterSize - 1)) > 0) {
382 Clusters += 1;
383 }
384
385 return Clusters;
386 }
387
388 EFI_STATUS
389 FatShrinkEof (
390 IN FAT_OFILE *OFile
391 )
392 /*++
393
394 Routine Description:
395
396 Shrink the end of the open file base on the file size.
397
398 Arguments:
399
400 OFile - The open file.
401
402 Returns:
403
404 EFI_SUCCESS - Shrinked sucessfully.
405 EFI_VOLUME_CORRUPTED - There are errors in the file's clusters.
406
407 --*/
408 {
409 FAT_VOLUME *Volume;
410 UINTN NewSize;
411 UINTN CurSize;
412 UINTN Cluster;
413 UINTN LastCluster;
414
415 Volume = OFile->Volume;
416 ASSERT_VOLUME_LOCKED (Volume);
417
418 NewSize = FatSizeToClusters (Volume, OFile->FileSize);
419
420 //
421 // Find the address of the last cluster
422 //
423 Cluster = OFile->FileCluster;
424 LastCluster = FAT_CLUSTER_FREE;
425
426 if (NewSize != 0) {
427
428 for (CurSize = 0; CurSize < NewSize; CurSize++) {
429 if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
430
431 DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatShrinkEof: cluster chain corrupt\n"));
432 return EFI_VOLUME_CORRUPTED;
433 }
434
435 LastCluster = Cluster;
436 Cluster = FatGetFatEntry (Volume, Cluster);
437 }
438
439 FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
440
441 } else {
442 //
443 // Check to see if the file is already completely truncated
444 //
445 if (Cluster == FAT_CLUSTER_FREE) {
446 return EFI_SUCCESS;
447 }
448 //
449 // The file is being completely truncated.
450 //
451 OFile->FileCluster = FAT_CLUSTER_FREE;
452 }
453 //
454 // Set CurrentCluster == FileCluster
455 // to force a recalculation of Position related stuffs
456 //
457 OFile->FileCurrentCluster = OFile->FileCluster;
458 OFile->FileLastCluster = LastCluster;
459 OFile->Dirty = TRUE;
460 //
461 // Free the remaining cluster chain
462 //
463 return FatFreeClusters (Volume, Cluster);
464 }
465
466 EFI_STATUS
467 FatGrowEof (
468 IN FAT_OFILE *OFile,
469 IN UINT64 NewSizeInBytes
470 )
471 /*++
472
473 Routine Description:
474
475 Grow the end of the open file base on the NewSizeInBytes.
476
477 Arguments:
478
479 OFile - The open file.
480 NewSizeInBytes - The new size in bytes of the open file.
481
482 Returns:
483
484 EFI_SUCCESS - The file is grown sucessfully.
485 EFI_UNSUPPORTED - The file size is larger than 4GB.
486 EFI_VOLUME_CORRUPTED - There are errors in the files' clusters.
487 EFI_VOLUME_FULL - The volume is full and can not grow the file.
488
489 --*/
490 {
491 FAT_VOLUME *Volume;
492 EFI_STATUS Status;
493 UINTN Cluster;
494 UINTN CurSize;
495 UINTN NewSize;
496 UINTN LastCluster;
497 UINTN NewCluster;
498 UINTN ClusterCount;
499
500 //
501 // For FAT file system, the max file is 4GB.
502 //
503 if (NewSizeInBytes > 0x0FFFFFFFFL) {
504 return EFI_UNSUPPORTED;
505 }
506
507 Volume = OFile->Volume;
508 ASSERT_VOLUME_LOCKED (Volume);
509 //
510 // If the file is already large enough, do nothing
511 //
512 CurSize = FatSizeToClusters (Volume, OFile->FileSize);
513 NewSize = FatSizeToClusters (Volume, (UINTN) NewSizeInBytes);
514
515 if (CurSize < NewSize) {
516 //
517 // If we haven't found the files last cluster do it now
518 //
519 if ((OFile->FileCluster != 0) && (OFile->FileLastCluster == 0)) {
520 Cluster = OFile->FileCluster;
521 ClusterCount = 0;
522
523 while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
524 if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
525
526 DEBUG (
527 (EFI_D_INIT | EFI_D_ERROR,
528 "FatGrowEof: cluster chain corrupt\n")
529 );
530 Status = EFI_VOLUME_CORRUPTED;
531 goto Done;
532 }
533
534 ClusterCount++;
535 OFile->FileLastCluster = Cluster;
536 Cluster = FatGetFatEntry (Volume, Cluster);
537 }
538
539 if (ClusterCount != CurSize) {
540 DEBUG (
541 (EFI_D_INIT | EFI_D_ERROR,
542 "FatGrowEof: cluster chain size does not match file size\n")
543 );
544 Status = EFI_VOLUME_CORRUPTED;
545 goto Done;
546 }
547
548 }
549 //
550 // Loop until we've allocated enough space
551 //
552 LastCluster = OFile->FileLastCluster;
553
554 while (CurSize < NewSize) {
555 NewCluster = FatAllocateCluster (Volume);
556 if (FAT_END_OF_FAT_CHAIN (NewCluster)) {
557 if (LastCluster != FAT_CLUSTER_FREE) {
558 FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
559 OFile->FileLastCluster = LastCluster;
560 }
561
562 Status = EFI_VOLUME_FULL;
563 goto Done;
564 }
565
566 if (LastCluster != 0) {
567 FatSetFatEntry (Volume, LastCluster, NewCluster);
568 } else {
569 OFile->FileCluster = NewCluster;
570 OFile->FileCurrentCluster = NewCluster;
571 }
572
573 LastCluster = NewCluster;
574 CurSize += 1;
575 }
576 //
577 // Terminate the cluster list
578 //
579 FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
580 OFile->FileLastCluster = LastCluster;
581 }
582
583 OFile->FileSize = (UINTN) NewSizeInBytes;
584 OFile->Dirty = TRUE;
585 return EFI_SUCCESS;
586
587 Done:
588 FatShrinkEof (OFile);
589 return Status;
590 }
591
592 EFI_STATUS
593 FatOFilePosition (
594 IN FAT_OFILE *OFile,
595 IN UINTN Position,
596 IN UINTN PosLimit
597 )
598 /*++
599
600 Routine Description:
601
602 Seek OFile to requested position, and calculate the number of
603 consecutive clusters from the position in the file
604
605 Arguments:
606
607 OFile - The open file.
608 Position - The file's position which will be accessed.
609 PosLimit - The maximum length current reading/writing may access
610
611 Returns:
612
613 EFI_SUCCESS - Set the info successfully.
614 EFI_VOLUME_CORRUPTED - Cluster chain corrupt.
615
616 --*/
617 {
618 FAT_VOLUME *Volume;
619 UINTN ClusterSize;
620 UINTN Cluster;
621 UINTN StartPos;
622 UINTN Run;
623
624 Volume = OFile->Volume;
625 ClusterSize = Volume->ClusterSize;
626
627 ASSERT_VOLUME_LOCKED (Volume);
628
629 //
630 // If this is the fixed root dir, then compute it's position
631 // from it's fixed info in the fat bpb
632 //
633 if (OFile->IsFixedRootDir) {
634 OFile->PosDisk = Volume->RootPos + Position;
635 Run = OFile->FileSize - Position;
636 } else {
637 //
638 // Run the file's cluster chain to find the current position
639 // If possible, run from the current cluster rather than
640 // start from beginning
641 // Assumption: OFile->Position is always consistent with
642 // OFile->FileCurrentCluster.
643 // OFile->Position is not modified outside this function;
644 // OFile->FileCurrentCluster is modified outside this function
645 // to be the same as OFile->FileCluster
646 // when OFile->FileCluster is updated, so make a check of this
647 // and invalidate the original OFile->Position in this case
648 //
649 Cluster = OFile->FileCurrentCluster;
650 StartPos = OFile->Position;
651 if (Position < StartPos || OFile->FileCluster == Cluster) {
652 StartPos = 0;
653 Cluster = OFile->FileCluster;
654 }
655
656 while (StartPos + ClusterSize <= Position) {
657 StartPos += ClusterSize;
658 if (Cluster == FAT_CLUSTER_FREE || (Cluster >= FAT_CLUSTER_SPECIAL)) {
659 DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatOFilePosition:"" cluster chain corrupt\n"));
660 return EFI_VOLUME_CORRUPTED;
661 }
662
663 Cluster = FatGetFatEntry (Volume, Cluster);
664 }
665
666 if (Cluster < FAT_MIN_CLUSTER) {
667 return EFI_VOLUME_CORRUPTED;
668 }
669
670 OFile->PosDisk = Volume->FirstClusterPos +
671 LShiftU64 (Cluster - FAT_MIN_CLUSTER, Volume->ClusterAlignment) +
672 Position - StartPos;
673 OFile->FileCurrentCluster = Cluster;
674 OFile->Position = StartPos;
675
676 //
677 // Compute the number of consecutive clusters in the file
678 //
679 Run = StartPos + ClusterSize - Position;
680 if (!FAT_END_OF_FAT_CHAIN (Cluster)) {
681 while ((FatGetFatEntry (Volume, Cluster) == Cluster + 1) && Run < PosLimit) {
682 Run += ClusterSize;
683 Cluster += 1;
684 }
685 }
686 }
687
688 OFile->PosRem = Run;
689 return EFI_SUCCESS;
690 }
691
692 UINTN
693 FatPhysicalDirSize (
694 IN FAT_VOLUME *Volume,
695 IN UINTN Cluster
696 )
697 /*++
698
699 Routine Description:
700
701 Get the size of directory of the open file
702
703 Arguments:
704
705 Volume - The File System Volume.
706 Cluster - The Starting cluster.
707
708 Returns:
709
710 The physical size of the file starting at the input cluster, if there is error in the
711 cluster chain, the return value is 0.
712
713 --*/
714 {
715 UINTN Size;
716 ASSERT_VOLUME_LOCKED (Volume);
717 //
718 // Run the cluster chain for the OFile
719 //
720 Size = 0;
721 //
722 // N.B. ".." directories on some media do not contain a starting
723 // cluster. In the case of "." or ".." we don't need the size anyway.
724 //
725 if (Cluster != 0) {
726 while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
727 if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
728 DEBUG (
729 (EFI_D_INIT | EFI_D_ERROR,
730 "FATDirSize: cluster chain corrupt\n")
731 );
732 return 0;
733 }
734
735 Size += Volume->ClusterSize;
736 Cluster = FatGetFatEntry (Volume, Cluster);
737 }
738 }
739
740 return Size;
741 }
742
743 UINT64
744 FatPhysicalFileSize (
745 IN FAT_VOLUME *Volume,
746 IN UINTN RealSize
747 )
748 /*++
749
750 Routine Description:
751
752 Get the physical size of a file on the disk.
753
754 Arguments:
755
756 Volume - The file system volume.
757 RealSize - The real size of a file.
758
759 Returns:
760
761 The physical size of a file on the disk.
762
763 --*/
764 {
765 UINTN ClusterSizeMask;
766 UINT64 PhysicalSize;
767 ClusterSizeMask = Volume->ClusterSize - 1;
768 PhysicalSize = (RealSize + ClusterSizeMask) & (~((UINT64) ClusterSizeMask));
769 return PhysicalSize;
770 }
771
772 VOID
773 FatComputeFreeInfo (
774 IN FAT_VOLUME *Volume
775 )
776 /*++
777
778 Routine Description:
779
780 Update the free cluster info of FatInfoSector of the volume.
781
782 Arguments:
783
784 Volume - FAT file system volume.
785
786 Returns:
787
788 None.
789
790 --*/
791 {
792 UINTN Index;
793
794 //
795 // If we don't have valid info, compute it now
796 //
797 if (!Volume->FreeInfoValid) {
798
799 Volume->FreeInfoValid = TRUE;
800 Volume->FatInfoSector.FreeInfo.ClusterCount = 0;
801 for (Index = Volume->MaxCluster + 1; Index >= FAT_MIN_CLUSTER; Index--) {
802 if (Volume->DiskError) {
803 break;
804 }
805
806 if (FatGetFatEntry (Volume, Index) == FAT_CLUSTER_FREE) {
807 Volume->FatInfoSector.FreeInfo.ClusterCount += 1;
808 Volume->FatInfoSector.FreeInfo.NextCluster = (UINT32) Index;
809 }
810 }
811
812 Volume->FatInfoSector.Signature = FAT_INFO_SIGNATURE;
813 Volume->FatInfoSector.InfoBeginSignature = FAT_INFO_BEGIN_SIGNATURE;
814 Volume->FatInfoSector.InfoEndSignature = FAT_INFO_END_SIGNATURE;
815 }
816 }