]> git.proxmox.com Git - mirror_edk2.git/blame - FatPkg/EnhancedFatDxe/FileSpace.c
FatPkg: Refine casting expression result to bigger size
[mirror_edk2.git] / FatPkg / EnhancedFatDxe / FileSpace.c
CommitLineData
cae7420b
DB
1/** @file\r
2 Routines dealing with disk spaces and FAT table entries.\r
b9ec9330 3\r
149d6335 4Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>\r
6163cc98 5This program and the accompanying materials are licensed and made available\r
b9ec9330
QH
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
b9ec9330 14\r
cae7420b 15**/\r
b9ec9330 16\r
cae7420b 17#include "Fat.h"\r
b9ec9330 18\r
b9ec9330 19\r
cae7420b 20/**\r
b9ec9330 21\r
cae7420b 22 Get the FAT entry of the volume, which is identified with the Index.\r
b9ec9330 23\r
cae7420b
DB
24 @param Volume - FAT file system volume.\r
25 @param Index - The index of the FAT entry of the volume.\r
b9ec9330 26\r
cae7420b 27 @return The buffer of the FAT entry\r
b9ec9330 28\r
cae7420b 29**/\r
b9ec9330
QH
30STATIC\r
31VOID *\r
32FatLoadFatEntry (\r
33 IN FAT_VOLUME *Volume,\r
34 IN UINTN Index\r
35 )\r
b9ec9330
QH
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
c1680e88 48 case Fat12:\r
b9ec9330
QH
49 Pos = FAT_POS_FAT12 (Index);\r
50 break;\r
51\r
c1680e88 52 case Fat16:\r
b9ec9330
QH
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
c1680e88 65 ReadFat,\r
b9ec9330
QH
66 Volume->FatEntryPos,\r
67 Volume->FatEntrySize,\r
149d6335
RN
68 &Volume->FatEntryBuffer,\r
69 NULL\r
b9ec9330
QH
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
cae7420b
DB
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
b9ec9330
QH
88STATIC\r
89UINTN\r
90FatGetFatEntry (\r
91 IN FAT_VOLUME *Volume,\r
92 IN UINTN Index\r
93 )\r
b9ec9330
QH
94{\r
95 VOID *Pos;\r
c1680e88
DB
96 UINT8 *En12;\r
97 UINT16 *En16;\r
98 UINT32 *En32;\r
b9ec9330
QH
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
c1680e88
DB
108 case Fat12:\r
109 En12 = Pos;\r
110 Accum = En12[0] | (En12[1] << 8);\r
b9ec9330
QH
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
c1680e88
DB
115 case Fat16:\r
116 En16 = Pos;\r
117 Accum = *En16;\r
b9ec9330
QH
118 Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT16) ? FAT_CLUSTER_SPECIAL_EXT : 0);\r
119 break;\r
120\r
121 default:\r
c1680e88
DB
122 En32 = Pos;\r
123 Accum = *En32 & FAT_CLUSTER_MASK_FAT32;\r
b9ec9330
QH
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
cae7420b
DB
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
b9ec9330
QH
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
b9ec9330
QH
150{\r
151 VOID *Pos;\r
c1680e88
DB
152 UINT8 *En12;\r
153 UINT16 *En16;\r
154 UINT32 *En32;\r
b9ec9330
QH
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
c1680e88
DB
183 case Fat12:\r
184 En12 = Pos;\r
185 Accum = En12[0] | (En12[1] << 8);\r
b9ec9330
QH
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
c1680e88
DB
194 En12[0] = (UINT8) (Accum & 0xFF);\r
195 En12[1] = (UINT8) (Accum >> 8);\r
b9ec9330
QH
196 break;\r
197\r
c1680e88
DB
198 case Fat16:\r
199 En16 = Pos;\r
200 *En16 = (UINT16) Value;\r
b9ec9330
QH
201 break;\r
202\r
203 default:\r
c1680e88
DB
204 En32 = Pos;\r
205 *En32 = (*En32 & FAT_CLUSTER_UNMASK_FAT32) | (UINT32) (Value & FAT_CLUSTER_MASK_FAT32);\r
b9ec9330
QH
206 }\r
207 //\r
208 // If the volume's dirty bit is not set, set it now\r
209 //\r
c1680e88 210 if (!Volume->FatDirty && Volume->FatType != Fat12) {\r
b9ec9330 211 Volume->FatDirty = TRUE;\r
c1680e88 212 FatAccessVolumeDirty (Volume, WriteFat, &Volume->DirtyValue);\r
b9ec9330
QH
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
c1680e88 221 WriteFat,\r
b9ec9330
QH
222 Volume->FatEntryPos,\r
223 Volume->FatEntrySize,\r
149d6335
RN
224 &Volume->FatEntryBuffer,\r
225 NULL\r
b9ec9330
QH
226 );\r
227 return Status;\r
228}\r
229\r
cae7420b
DB
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
b9ec9330
QH
241STATIC\r
242EFI_STATUS\r
243FatFreeClusters (\r
244 IN FAT_VOLUME *Volume,\r
245 IN UINTN Cluster\r
246 )\r
b9ec9330
QH
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
cae7420b 265/**\r
b9ec9330
QH
266\r
267 Allocate a free cluster and return the cluster index.\r
268\r
cae7420b 269 @param Volume - FAT file system volume.\r
b9ec9330 270\r
cae7420b 271 @return The index of the free cluster\r
b9ec9330 272\r
cae7420b
DB
273**/\r
274STATIC\r
275UINTN\r
276FatAllocateCluster (\r
277 IN FAT_VOLUME *Volume\r
278 )\r
b9ec9330
QH
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
cae7420b
DB
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
b9ec9330
QH
329STATIC\r
330UINTN\r
331FatSizeToClusters (\r
332 IN FAT_VOLUME *Volume,\r
333 IN UINTN Size\r
334 )\r
b9ec9330
QH
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
cae7420b 346/**\r
b9ec9330
QH
347\r
348 Shrink the end of the open file base on the file size.\r
349\r
cae7420b 350 @param OFile - The open file.\r
b9ec9330 351\r
cae7420b
DB
352 @retval EFI_SUCCESS - Shrinked sucessfully.\r
353 @retval EFI_VOLUME_CORRUPTED - There are errors in the file's clusters.\r
b9ec9330 354\r
cae7420b
DB
355**/\r
356EFI_STATUS\r
357FatShrinkEof (\r
358 IN FAT_OFILE *OFile\r
359 )\r
b9ec9330
QH
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
cae7420b 418/**\r
b9ec9330
QH
419\r
420 Grow the end of the open file base on the NewSizeInBytes.\r
421\r
cae7420b
DB
422 @param OFile - The open file.\r
423 @param NewSizeInBytes - The new size in bytes of the open file.\r
b9ec9330 424\r
cae7420b
DB
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
b9ec9330 429\r
cae7420b
DB
430**/\r
431EFI_STATUS\r
432FatGrowEof (\r
433 IN FAT_OFILE *OFile,\r
434 IN UINT64 NewSizeInBytes\r
435 )\r
b9ec9330
QH
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
cae7420b 538/**\r
b9ec9330
QH
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
cae7420b
DB
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
b9ec9330 546\r
cae7420b
DB
547 @retval EFI_SUCCESS - Set the info successfully.\r
548 @retval EFI_VOLUME_CORRUPTED - Cluster chain corrupt.\r
b9ec9330 549\r
cae7420b
DB
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
b9ec9330
QH
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
cae7420b 632/**\r
b9ec9330 633\r
cae7420b 634 Get the size of directory of the open file.\r
b9ec9330 635\r
cae7420b
DB
636 @param Volume - The File System Volume.\r
637 @param Cluster - The Starting cluster.\r
b9ec9330 638\r
cae7420b 639 @return The physical size of the file starting at the input cluster, if there is error in the\r
b9ec9330
QH
640 cluster chain, the return value is 0.\r
641\r
cae7420b
DB
642**/\r
643UINTN\r
644FatPhysicalDirSize (\r
645 IN FAT_VOLUME *Volume,\r
646 IN UINTN Cluster\r
647 )\r
b9ec9330
QH
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
cae7420b
DB
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
b9ec9330
QH
687UINT64\r
688FatPhysicalFileSize (\r
689 IN FAT_VOLUME *Volume,\r
690 IN UINTN RealSize\r
691 )\r
b9ec9330
QH
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
cae7420b 700/**\r
b9ec9330
QH
701\r
702 Update the free cluster info of FatInfoSector of the volume.\r
703\r
cae7420b 704 @param Volume - FAT file system volume.\r
b9ec9330 705\r
cae7420b
DB
706**/\r
707VOID\r
708FatComputeFreeInfo (\r
709 IN FAT_VOLUME *Volume\r
710 )\r
b9ec9330
QH
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