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