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