Init.c 12 KB

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