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