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