FileSpace.c 19 KB

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