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