Init.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /** @file
  2. Initialization routines.
  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. Allocates volume structure, detects FAT file system, installs protocol,
  9. and initialize cache.
  10. @param Handle - The handle of parent device.
  11. @param DiskIo - The DiskIo of parent device.
  12. @param DiskIo2 - The DiskIo2 of parent device.
  13. @param BlockIo - The BlockIo of parent device.
  14. @retval EFI_SUCCESS - Allocate a new volume successfully.
  15. @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory.
  16. @return Others - Allocating a new volume failed.
  17. **/
  18. EFI_STATUS
  19. FatAllocateVolume (
  20. IN EFI_HANDLE Handle,
  21. IN EFI_DISK_IO_PROTOCOL *DiskIo,
  22. IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
  23. IN EFI_BLOCK_IO_PROTOCOL *BlockIo
  24. )
  25. {
  26. EFI_STATUS Status;
  27. FAT_VOLUME *Volume;
  28. //
  29. // Allocate a volume structure
  30. //
  31. Volume = AllocateZeroPool (sizeof (FAT_VOLUME));
  32. if (Volume == NULL) {
  33. return EFI_OUT_OF_RESOURCES;
  34. }
  35. //
  36. // Initialize the structure
  37. //
  38. Volume->Signature = FAT_VOLUME_SIGNATURE;
  39. Volume->Handle = Handle;
  40. Volume->DiskIo = DiskIo;
  41. Volume->DiskIo2 = DiskIo2;
  42. Volume->BlockIo = BlockIo;
  43. Volume->MediaId = BlockIo->Media->MediaId;
  44. Volume->ReadOnly = BlockIo->Media->ReadOnly;
  45. Volume->VolumeInterface.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
  46. Volume->VolumeInterface.OpenVolume = FatOpenVolume;
  47. InitializeListHead (&Volume->CheckRef);
  48. InitializeListHead (&Volume->DirCacheList);
  49. //
  50. // Initialize Root Directory entry
  51. //
  52. Volume->RootDirEnt.FileString = Volume->RootFileString;
  53. Volume->RootDirEnt.Entry.Attributes = FAT_ATTRIBUTE_DIRECTORY;
  54. //
  55. // Check to see if there's a file system on the volume
  56. //
  57. Status = FatOpenDevice (Volume);
  58. if (EFI_ERROR (Status)) {
  59. goto Done;
  60. }
  61. //
  62. // Initialize cache
  63. //
  64. Status = FatInitializeDiskCache (Volume);
  65. if (EFI_ERROR (Status)) {
  66. goto Done;
  67. }
  68. //
  69. // Install our protocol interfaces on the device's handle
  70. //
  71. Status = gBS->InstallMultipleProtocolInterfaces (
  72. &Volume->Handle,
  73. &gEfiSimpleFileSystemProtocolGuid,
  74. &Volume->VolumeInterface,
  75. NULL
  76. );
  77. if (EFI_ERROR (Status)) {
  78. goto Done;
  79. }
  80. //
  81. // Volume installed
  82. //
  83. DEBUG ((DEBUG_INIT, "Installed Fat filesystem on %p\n", Handle));
  84. Volume->Valid = TRUE;
  85. Done:
  86. if (EFI_ERROR (Status)) {
  87. FatFreeVolume (Volume);
  88. }
  89. return Status;
  90. }
  91. /**
  92. Called by FatDriverBindingStop(), Abandon the volume.
  93. @param Volume - The volume to be abandoned.
  94. @retval EFI_SUCCESS - Abandoned the volume successfully.
  95. @return Others - Can not uninstall the protocol interfaces.
  96. **/
  97. EFI_STATUS
  98. FatAbandonVolume (
  99. IN FAT_VOLUME *Volume
  100. )
  101. {
  102. EFI_STATUS Status;
  103. BOOLEAN LockedByMe;
  104. //
  105. // Uninstall the protocol interface.
  106. //
  107. if (Volume->Handle != NULL) {
  108. Status = gBS->UninstallMultipleProtocolInterfaces (
  109. Volume->Handle,
  110. &gEfiSimpleFileSystemProtocolGuid,
  111. &Volume->VolumeInterface,
  112. NULL
  113. );
  114. if (EFI_ERROR (Status)) {
  115. return Status;
  116. }
  117. }
  118. LockedByMe = FALSE;
  119. //
  120. // Acquire the lock.
  121. // If the caller has already acquired the lock (which
  122. // means we are in the process of some Fat operation),
  123. // we can not acquire again.
  124. //
  125. Status = FatAcquireLockOrFail ();
  126. if (!EFI_ERROR (Status)) {
  127. LockedByMe = TRUE;
  128. }
  129. //
  130. // The volume is still being used. Hence, set error flag for all OFiles still in
  131. // use. In two cases, we could get here. One is EFI_MEDIA_CHANGED, the other is
  132. // EFI_NO_MEDIA.
  133. //
  134. if (Volume->Root != NULL) {
  135. FatSetVolumeError (
  136. Volume->Root,
  137. Volume->BlockIo->Media->MediaPresent ? EFI_MEDIA_CHANGED : EFI_NO_MEDIA
  138. );
  139. }
  140. Volume->Valid = FALSE;
  141. //
  142. // Release the lock.
  143. // If locked by me, this means DriverBindingStop is NOT
  144. // called within an on-going Fat operation, so we should
  145. // take responsibility to cleanup and free the volume.
  146. // Otherwise, the DriverBindingStop is called within an on-going
  147. // Fat operation, we shouldn't check reference, so just let outer
  148. // FatCleanupVolume do the task.
  149. //
  150. if (LockedByMe) {
  151. FatCleanupVolume (Volume, NULL, EFI_SUCCESS, NULL);
  152. FatReleaseLock ();
  153. }
  154. return EFI_SUCCESS;
  155. }
  156. /**
  157. Detects FAT file system on Disk and set relevant fields of Volume.
  158. @param Volume - The volume structure.
  159. @retval EFI_SUCCESS - The Fat File System is detected successfully
  160. @retval EFI_UNSUPPORTED - The volume is not FAT file system.
  161. @retval EFI_VOLUME_CORRUPTED - The volume is corrupted.
  162. **/
  163. EFI_STATUS
  164. FatOpenDevice (
  165. IN OUT FAT_VOLUME *Volume
  166. )
  167. {
  168. EFI_STATUS Status;
  169. UINT32 BlockSize;
  170. UINT32 DirtyMask;
  171. EFI_DISK_IO_PROTOCOL *DiskIo;
  172. FAT_BOOT_SECTOR FatBs;
  173. FAT_VOLUME_TYPE FatType;
  174. UINTN RootDirSectors;
  175. UINTN FatLba;
  176. UINTN RootLba;
  177. UINTN FirstClusterLba;
  178. UINTN Sectors;
  179. UINTN SectorsPerFat;
  180. UINT8 SectorsPerClusterAlignment;
  181. UINT8 BlockAlignment;
  182. //
  183. // Read the FAT_BOOT_SECTOR BPB info
  184. // This is the only part of FAT code that uses parent DiskIo,
  185. // Others use FatDiskIo which utilizes a Cache.
  186. //
  187. DiskIo = Volume->DiskIo;
  188. Status = DiskIo->ReadDisk (DiskIo, Volume->MediaId, 0, sizeof (FatBs), &FatBs);
  189. if (EFI_ERROR (Status)) {
  190. DEBUG ((DEBUG_INIT, "FatOpenDevice: read of part_lba failed %r\n", Status));
  191. return Status;
  192. }
  193. FatType = FatUndefined;
  194. //
  195. // Use LargeSectors if Sectors is 0
  196. //
  197. Sectors = FatBs.FatBsb.Sectors;
  198. if (Sectors == 0) {
  199. Sectors = FatBs.FatBsb.LargeSectors;
  200. }
  201. SectorsPerFat = FatBs.FatBsb.SectorsPerFat;
  202. if (SectorsPerFat == 0) {
  203. SectorsPerFat = FatBs.FatBse.Fat32Bse.LargeSectorsPerFat;
  204. FatType = Fat32;
  205. }
  206. //
  207. // Is boot sector a fat sector?
  208. // (Note that so far we only know if the sector is FAT32 or not, we don't
  209. // know if the sector is Fat16 or Fat12 until later when we can compute
  210. // the volume size)
  211. //
  212. if ((FatBs.FatBsb.ReservedSectors == 0) || (FatBs.FatBsb.NumFats == 0) || (Sectors == 0)) {
  213. return EFI_UNSUPPORTED;
  214. }
  215. if ((FatBs.FatBsb.SectorSize & (FatBs.FatBsb.SectorSize - 1)) != 0) {
  216. return EFI_UNSUPPORTED;
  217. }
  218. BlockAlignment = (UINT8)HighBitSet32 (FatBs.FatBsb.SectorSize);
  219. if ((BlockAlignment > MAX_BLOCK_ALIGNMENT) || (BlockAlignment < MIN_BLOCK_ALIGNMENT)) {
  220. return EFI_UNSUPPORTED;
  221. }
  222. if ((FatBs.FatBsb.SectorsPerCluster & (FatBs.FatBsb.SectorsPerCluster - 1)) != 0) {
  223. return EFI_UNSUPPORTED;
  224. }
  225. SectorsPerClusterAlignment = (UINT8)HighBitSet32 (FatBs.FatBsb.SectorsPerCluster);
  226. if (SectorsPerClusterAlignment > MAX_SECTORS_PER_CLUSTER_ALIGNMENT) {
  227. return EFI_UNSUPPORTED;
  228. }
  229. if ((FatBs.FatBsb.Media <= 0xf7) &&
  230. (FatBs.FatBsb.Media != 0xf0) &&
  231. (FatBs.FatBsb.Media != 0x00) &&
  232. (FatBs.FatBsb.Media != 0x01)
  233. )
  234. {
  235. return EFI_UNSUPPORTED;
  236. }
  237. //
  238. // Initialize fields the volume information for this FatType
  239. //
  240. if (FatType != Fat32) {
  241. if (FatBs.FatBsb.RootEntries == 0) {
  242. return EFI_UNSUPPORTED;
  243. }
  244. //
  245. // Unpack fat12, fat16 info
  246. //
  247. Volume->RootEntries = FatBs.FatBsb.RootEntries;
  248. } else {
  249. //
  250. // If this is fat32, refuse to mount mirror-disabled volumes
  251. //
  252. if (((SectorsPerFat == 0) || (FatBs.FatBse.Fat32Bse.FsVersion != 0)) || (FatBs.FatBse.Fat32Bse.ExtendedFlags & 0x80)) {
  253. return EFI_UNSUPPORTED;
  254. }
  255. //
  256. // Unpack fat32 info
  257. //
  258. Volume->RootCluster = FatBs.FatBse.Fat32Bse.RootDirFirstCluster;
  259. }
  260. Volume->NumFats = FatBs.FatBsb.NumFats;
  261. //
  262. // Compute some fat locations
  263. //
  264. BlockSize = FatBs.FatBsb.SectorSize;
  265. RootDirSectors = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (BlockSize - 1)) / BlockSize;
  266. FatLba = FatBs.FatBsb.ReservedSectors;
  267. RootLba = FatBs.FatBsb.NumFats * SectorsPerFat + FatLba;
  268. FirstClusterLba = RootLba + RootDirSectors;
  269. Volume->FatPos = FatLba * BlockSize;
  270. Volume->FatSize = SectorsPerFat * BlockSize;
  271. Volume->VolumeSize = LShiftU64 (Sectors, BlockAlignment);
  272. Volume->RootPos = LShiftU64 (RootLba, BlockAlignment);
  273. Volume->FirstClusterPos = LShiftU64 (FirstClusterLba, BlockAlignment);
  274. Volume->MaxCluster = (Sectors - FirstClusterLba) >> SectorsPerClusterAlignment;
  275. Volume->ClusterAlignment = (UINT8)(BlockAlignment + SectorsPerClusterAlignment);
  276. Volume->ClusterSize = (UINTN)1 << (Volume->ClusterAlignment);
  277. //
  278. // If this is not a fat32, determine if it's a fat16 or fat12
  279. //
  280. if (FatType != Fat32) {
  281. if (Volume->MaxCluster >= FAT_MAX_FAT16_CLUSTER) {
  282. return EFI_VOLUME_CORRUPTED;
  283. }
  284. FatType = Volume->MaxCluster < FAT_MAX_FAT12_CLUSTER ? Fat12 : Fat16;
  285. //
  286. // fat12 & fat16 fat-entries are 2 bytes
  287. //
  288. Volume->FatEntrySize = sizeof (UINT16);
  289. DirtyMask = FAT16_DIRTY_MASK;
  290. } else {
  291. if (Volume->MaxCluster < FAT_MAX_FAT16_CLUSTER) {
  292. return EFI_VOLUME_CORRUPTED;
  293. }
  294. //
  295. // fat32 fat-entries are 4 bytes
  296. //
  297. Volume->FatEntrySize = sizeof (UINT32);
  298. DirtyMask = FAT32_DIRTY_MASK;
  299. }
  300. //
  301. // Get the DirtyValue and NotDirtyValue
  302. // We should keep the initial value as the NotDirtyValue
  303. // in case the volume is dirty already
  304. //
  305. if (FatType != Fat12) {
  306. Status = FatAccessVolumeDirty (Volume, ReadDisk, &Volume->NotDirtyValue);
  307. if (EFI_ERROR (Status)) {
  308. return Status;
  309. }
  310. Volume->DirtyValue = Volume->NotDirtyValue & DirtyMask;
  311. }
  312. //
  313. // If present, read the fat hint info
  314. //
  315. if (FatType == Fat32) {
  316. Volume->FreeInfoPos = FatBs.FatBse.Fat32Bse.FsInfoSector * BlockSize;
  317. if (FatBs.FatBse.Fat32Bse.FsInfoSector != 0) {
  318. FatDiskIo (Volume, ReadDisk, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector, NULL);
  319. if ((Volume->FatInfoSector.Signature == FAT_INFO_SIGNATURE) &&
  320. (Volume->FatInfoSector.InfoBeginSignature == FAT_INFO_BEGIN_SIGNATURE) &&
  321. (Volume->FatInfoSector.InfoEndSignature == FAT_INFO_END_SIGNATURE) &&
  322. (Volume->FatInfoSector.FreeInfo.ClusterCount <= Volume->MaxCluster)
  323. )
  324. {
  325. Volume->FreeInfoValid = TRUE;
  326. }
  327. }
  328. }
  329. //
  330. // Just make up a FreeInfo.NextCluster for use by allocate cluster
  331. //
  332. if ((FAT_MIN_CLUSTER > Volume->FatInfoSector.FreeInfo.NextCluster) ||
  333. (Volume->FatInfoSector.FreeInfo.NextCluster > Volume->MaxCluster + 1)
  334. )
  335. {
  336. Volume->FatInfoSector.FreeInfo.NextCluster = FAT_MIN_CLUSTER;
  337. }
  338. //
  339. // We are now defining FAT Type
  340. //
  341. Volume->FatType = FatType;
  342. ASSERT (FatType != FatUndefined);
  343. return EFI_SUCCESS;
  344. }