]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - FatPkg/EnhancedFatDxe/FileSpace.c
ArmVirtPkg: don't set PcdDebugClearMemoryValue
[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_MIN_CLUSTER || Cluster > Volume->MaxCluster + 1) {\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 (NewCluster < FAT_MIN_CLUSTER || NewCluster > Volume->MaxCluster + 1) {\r
513 Status = EFI_VOLUME_CORRUPTED;\r
514 goto Done;\r
515 }\r
516\r
517 if (LastCluster != 0) {\r
518 FatSetFatEntry (Volume, LastCluster, NewCluster);\r
519 } else {\r
520 OFile->FileCluster = NewCluster;\r
521 OFile->FileCurrentCluster = NewCluster;\r
522 }\r
523\r
524 LastCluster = NewCluster;\r
525 CurSize += 1;\r
526\r
527 //\r
528 // Terminate the cluster list\r
529 //\r
530 // Note that we must do this EVERY time we allocate a cluster, because\r
531 // FatAllocateCluster scans the FAT looking for a free cluster and\r
532 // "LastCluster" is no longer free! Usually, FatAllocateCluster will\r
533 // start looking with the cluster after "LastCluster"; however, when\r
534 // there is only one free cluster left, it will find "LastCluster"\r
535 // a second time. There are other, less predictable scenarios\r
536 // where this could happen, as well.\r
537 //\r
538 FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);\r
539 OFile->FileLastCluster = LastCluster;\r
540 }\r
541 }\r
542\r
543 OFile->FileSize = (UINTN) NewSizeInBytes;\r
544 OFile->Dirty = TRUE;\r
545 return EFI_SUCCESS;\r
546\r
547Done:\r
548 FatShrinkEof (OFile);\r
549 return Status;\r
550}\r
551\r
552/**\r
553\r
554 Seek OFile to requested position, and calculate the number of\r
555 consecutive clusters from the position in the file\r
556\r
557 @param OFile - The open file.\r
558 @param Position - The file's position which will be accessed.\r
559 @param PosLimit - The maximum length current reading/writing may access\r
560\r
561 @retval EFI_SUCCESS - Set the info successfully.\r
562 @retval EFI_VOLUME_CORRUPTED - Cluster chain corrupt.\r
563\r
564**/\r
565EFI_STATUS\r
566FatOFilePosition (\r
567 IN FAT_OFILE *OFile,\r
568 IN UINTN Position,\r
569 IN UINTN PosLimit\r
570 )\r
571{\r
572 FAT_VOLUME *Volume;\r
573 UINTN ClusterSize;\r
574 UINTN Cluster;\r
575 UINTN StartPos;\r
576 UINTN Run;\r
577\r
578 Volume = OFile->Volume;\r
579 ClusterSize = Volume->ClusterSize;\r
580\r
581 ASSERT_VOLUME_LOCKED (Volume);\r
582\r
583 //\r
584 // If this is the fixed root dir, then compute it's position\r
585 // from it's fixed info in the fat bpb\r
586 //\r
587 if (OFile->IsFixedRootDir) {\r
588 OFile->PosDisk = Volume->RootPos + Position;\r
589 Run = OFile->FileSize - Position;\r
590 } else {\r
591 //\r
592 // Run the file's cluster chain to find the current position\r
593 // If possible, run from the current cluster rather than\r
594 // start from beginning\r
595 // Assumption: OFile->Position is always consistent with\r
596 // OFile->FileCurrentCluster.\r
597 // OFile->Position is not modified outside this function;\r
598 // OFile->FileCurrentCluster is modified outside this function\r
599 // to be the same as OFile->FileCluster\r
600 // when OFile->FileCluster is updated, so make a check of this\r
601 // and invalidate the original OFile->Position in this case\r
602 //\r
603 Cluster = OFile->FileCurrentCluster;\r
604 StartPos = OFile->Position;\r
605 if (Position < StartPos || OFile->FileCluster == Cluster) {\r
606 StartPos = 0;\r
607 Cluster = OFile->FileCluster;\r
608 }\r
609\r
610 while (StartPos + ClusterSize <= Position) {\r
611 StartPos += ClusterSize;\r
612 if (Cluster == FAT_CLUSTER_FREE || (Cluster >= FAT_CLUSTER_SPECIAL)) {\r
613 DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatOFilePosition:"" cluster chain corrupt\n"));\r
614 return EFI_VOLUME_CORRUPTED;\r
615 }\r
616\r
617 Cluster = FatGetFatEntry (Volume, Cluster);\r
618 }\r
619\r
620 if (Cluster < FAT_MIN_CLUSTER || Cluster > Volume->MaxCluster + 1) {\r
621 return EFI_VOLUME_CORRUPTED;\r
622 }\r
623\r
624 OFile->PosDisk = Volume->FirstClusterPos +\r
625 LShiftU64 (Cluster - FAT_MIN_CLUSTER, Volume->ClusterAlignment) +\r
626 Position - StartPos;\r
627 OFile->FileCurrentCluster = Cluster;\r
628 OFile->Position = StartPos;\r
629\r
630 //\r
631 // Compute the number of consecutive clusters in the file\r
632 //\r
633 Run = StartPos + ClusterSize - Position;\r
634 if (!FAT_END_OF_FAT_CHAIN (Cluster)) {\r
635 while ((FatGetFatEntry (Volume, Cluster) == Cluster + 1) && Run < PosLimit) {\r
636 Run += ClusterSize;\r
637 Cluster += 1;\r
638 }\r
639 }\r
640 }\r
641\r
642 OFile->PosRem = Run;\r
643 return EFI_SUCCESS;\r
644}\r
645\r
646/**\r
647\r
648 Get the size of directory of the open file.\r
649\r
650 @param Volume - The File System Volume.\r
651 @param Cluster - The Starting cluster.\r
652\r
653 @return The physical size of the file starting at the input cluster, if there is error in the\r
654 cluster chain, the return value is 0.\r
655\r
656**/\r
657UINTN\r
658FatPhysicalDirSize (\r
659 IN FAT_VOLUME *Volume,\r
660 IN UINTN Cluster\r
661 )\r
662{\r
663 UINTN Size;\r
664 ASSERT_VOLUME_LOCKED (Volume);\r
665 //\r
666 // Run the cluster chain for the OFile\r
667 //\r
668 Size = 0;\r
669 //\r
670 // N.B. ".." directories on some media do not contain a starting\r
671 // cluster. In the case of "." or ".." we don't need the size anyway.\r
672 //\r
673 if (Cluster != 0) {\r
674 while (!FAT_END_OF_FAT_CHAIN (Cluster)) {\r
675 if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {\r
676 DEBUG (\r
677 (EFI_D_INIT | EFI_D_ERROR,\r
678 "FATDirSize: cluster chain corrupt\n")\r
679 );\r
680 return 0;\r
681 }\r
682\r
683 Size += Volume->ClusterSize;\r
684 Cluster = FatGetFatEntry (Volume, Cluster);\r
685 }\r
686 }\r
687\r
688 return Size;\r
689}\r
690\r
691/**\r
692\r
693 Get the physical size of a file on the disk.\r
694\r
695 @param Volume - The file system volume.\r
696 @param RealSize - The real size of a file.\r
697\r
698 @return The physical size of a file on the disk.\r
699\r
700**/\r
701UINT64\r
702FatPhysicalFileSize (\r
703 IN FAT_VOLUME *Volume,\r
704 IN UINTN RealSize\r
705 )\r
706{\r
707 UINTN ClusterSizeMask;\r
708 UINT64 PhysicalSize;\r
709 ClusterSizeMask = Volume->ClusterSize - 1;\r
710 PhysicalSize = (RealSize + ClusterSizeMask) & (~((UINT64) ClusterSizeMask));\r
711 return PhysicalSize;\r
712}\r
713\r
714/**\r
715\r
716 Update the free cluster info of FatInfoSector of the volume.\r
717\r
718 @param Volume - FAT file system volume.\r
719\r
720**/\r
721VOID\r
722FatComputeFreeInfo (\r
723 IN FAT_VOLUME *Volume\r
724 )\r
725{\r
726 UINTN Index;\r
727\r
728 //\r
729 // If we don't have valid info, compute it now\r
730 //\r
731 if (!Volume->FreeInfoValid) {\r
732\r
733 Volume->FreeInfoValid = TRUE;\r
734 Volume->FatInfoSector.FreeInfo.ClusterCount = 0;\r
735 for (Index = Volume->MaxCluster + 1; Index >= FAT_MIN_CLUSTER; Index--) {\r
736 if (Volume->DiskError) {\r
737 break;\r
738 }\r
739\r
740 if (FatGetFatEntry (Volume, Index) == FAT_CLUSTER_FREE) {\r
741 Volume->FatInfoSector.FreeInfo.ClusterCount += 1;\r
742 Volume->FatInfoSector.FreeInfo.NextCluster = (UINT32) Index;\r
743 }\r
744 }\r
745\r
746 Volume->FatInfoSector.Signature = FAT_INFO_SIGNATURE;\r
747 Volume->FatInfoSector.InfoBeginSignature = FAT_INFO_BEGIN_SIGNATURE;\r
748 Volume->FatInfoSector.InfoEndSignature = FAT_INFO_END_SIGNATURE;\r
749 }\r
750}\r