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