TianoCore EDK2 master
Loading...
Searching...
No Matches
Init.c
Go to the documentation of this file.
1
9#include "Fat.h"
10
28 IN EFI_HANDLE Handle,
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 if ((BlockIo == NULL) || (BlockIo->Media == NULL)) {
66 DEBUG ((DEBUG_ERROR, "%a BlockIo or BlockIo is NULL!\n", __func__));
67 Status = EFI_INVALID_PARAMETER;
68 goto Done;
69 }
70
71 //
72 // Check to see if the underlying block device's BlockSize meets what the FAT spec requires
73 //
74 if ((BlockIo->Media->BlockSize != 512) &&
75 (BlockIo->Media->BlockSize != SIZE_1KB) &&
76 (BlockIo->Media->BlockSize != SIZE_2KB) &&
77 (BlockIo->Media->BlockSize != SIZE_4KB))
78 {
79 Status = EFI_UNSUPPORTED;
80 DEBUG ((
81 DEBUG_ERROR,
82 "%a invalid BlockIo BlockSize %u for FAT filesystem on MediaId %u. Must be 512B, 1KB, 2KB, or 4KB\n",
83 __func__,
84 BlockIo->Media->BlockSize,
85 BlockIo->Media->MediaId
86 ));
87 goto Done;
88 }
89
90 //
91 // Check to see if there's a file system on the volume
92 //
93 Status = FatOpenDevice (Volume);
94 if (EFI_ERROR (Status)) {
95 goto Done;
96 }
97
98 //
99 // Initialize cache
100 //
101 Status = FatInitializeDiskCache (Volume);
102 if (EFI_ERROR (Status)) {
103 goto Done;
104 }
105
106 //
107 // Install our protocol interfaces on the device's handle
108 //
109 Status = gBS->InstallMultipleProtocolInterfaces (
110 &Volume->Handle,
111 &gEfiSimpleFileSystemProtocolGuid,
112 &Volume->VolumeInterface,
113 NULL
114 );
115 if (EFI_ERROR (Status)) {
116 goto Done;
117 }
118
119 //
120 // Volume installed
121 //
122 DEBUG ((DEBUG_INIT, "Installed Fat filesystem on %p\n", Handle));
123 Volume->Valid = TRUE;
124
125Done:
126 if (EFI_ERROR (Status)) {
127 FatFreeVolume (Volume);
128 }
129
130 return Status;
131}
132
145 IN FAT_VOLUME *Volume
146 )
147{
148 EFI_STATUS Status;
149 BOOLEAN LockedByMe;
150
151 //
152 // Uninstall the protocol interface.
153 //
154 if (Volume->Handle != NULL) {
155 Status = gBS->UninstallMultipleProtocolInterfaces (
156 Volume->Handle,
157 &gEfiSimpleFileSystemProtocolGuid,
158 &Volume->VolumeInterface,
159 NULL
160 );
161 if (EFI_ERROR (Status)) {
162 return Status;
163 }
164 }
165
166 LockedByMe = FALSE;
167
168 //
169 // Acquire the lock.
170 // If the caller has already acquired the lock (which
171 // means we are in the process of some Fat operation),
172 // we can not acquire again.
173 //
174 Status = FatAcquireLockOrFail ();
175 if (!EFI_ERROR (Status)) {
176 LockedByMe = TRUE;
177 }
178
179 //
180 // The volume is still being used. Hence, set error flag for all OFiles still in
181 // use. In two cases, we could get here. One is EFI_MEDIA_CHANGED, the other is
182 // EFI_NO_MEDIA.
183 //
184 if (Volume->Root != NULL) {
186 Volume->Root,
187 Volume->BlockIo->Media->MediaPresent ? EFI_MEDIA_CHANGED : EFI_NO_MEDIA
188 );
189 }
190
191 Volume->Valid = FALSE;
192
193 //
194 // Release the lock.
195 // If locked by me, this means DriverBindingStop is NOT
196 // called within an on-going Fat operation, so we should
197 // take responsibility to cleanup and free the volume.
198 // Otherwise, the DriverBindingStop is called within an on-going
199 // Fat operation, we shouldn't check reference, so just let outer
200 // FatCleanupVolume do the task.
201 //
202 if (LockedByMe) {
205 }
206
207 return EFI_SUCCESS;
208}
209
223 IN OUT FAT_VOLUME *Volume
224 )
225{
226 EFI_STATUS Status;
227 UINT32 BlockSize;
228 UINT32 DirtyMask;
229 EFI_DISK_IO_PROTOCOL *DiskIo;
230 FAT_BOOT_SECTOR FatBs;
231 FAT_VOLUME_TYPE FatType;
232 UINTN RootDirSectors;
233 UINTN FatLba;
234 UINTN RootLba;
235 UINTN FirstClusterLba;
236 UINTN Sectors;
237 UINTN SectorsPerFat;
238 UINT8 SectorsPerClusterAlignment;
239 UINT8 BlockAlignment;
240
241 //
242 // Read the FAT_BOOT_SECTOR BPB info
243 // This is the only part of FAT code that uses parent DiskIo,
244 // Others use FatDiskIo which utilizes a Cache.
245 //
246 DiskIo = Volume->DiskIo;
247 Status = DiskIo->ReadDisk (DiskIo, Volume->MediaId, 0, sizeof (FatBs), &FatBs);
248
249 if (EFI_ERROR (Status)) {
250 DEBUG ((DEBUG_VERBOSE, "%a: read of part_lba failed %r\n", __func__, Status));
251 return Status;
252 }
253
254 FatType = FatUndefined;
255
256 //
257 // Use LargeSectors if Sectors is 0
258 //
259 Sectors = FatBs.FatBsb.Sectors;
260 if (Sectors == 0) {
261 Sectors = FatBs.FatBsb.LargeSectors;
262 }
263
264 SectorsPerFat = FatBs.FatBsb.SectorsPerFat;
265 if (SectorsPerFat == 0) {
266 SectorsPerFat = FatBs.FatBse.Fat32Bse.LargeSectorsPerFat;
267 FatType = Fat32;
268 }
269
270 //
271 // Is boot sector a fat sector?
272 // (Note that so far we only know if the sector is FAT32 or not, we don't
273 // know if the sector is Fat16 or Fat12 until later when we can compute
274 // the volume size)
275 //
276 if ((FatBs.FatBsb.ReservedSectors == 0) || (FatBs.FatBsb.NumFats == 0) || (Sectors == 0)) {
277 return EFI_UNSUPPORTED;
278 }
279
280 if ((FatBs.FatBsb.SectorSize & (FatBs.FatBsb.SectorSize - 1)) != 0) {
281 return EFI_UNSUPPORTED;
282 }
283
284 BlockAlignment = (UINT8)HighBitSet32 (FatBs.FatBsb.SectorSize);
285 if ((BlockAlignment > MAX_BLOCK_ALIGNMENT) || (BlockAlignment < MIN_BLOCK_ALIGNMENT)) {
286 return EFI_UNSUPPORTED;
287 }
288
289 if ((FatBs.FatBsb.SectorsPerCluster & (FatBs.FatBsb.SectorsPerCluster - 1)) != 0) {
290 return EFI_UNSUPPORTED;
291 }
292
293 SectorsPerClusterAlignment = (UINT8)HighBitSet32 (FatBs.FatBsb.SectorsPerCluster);
294 if (SectorsPerClusterAlignment > MAX_SECTORS_PER_CLUSTER_ALIGNMENT) {
295 return EFI_UNSUPPORTED;
296 }
297
298 if ((FatBs.FatBsb.Media <= 0xf7) &&
299 (FatBs.FatBsb.Media != 0xf0) &&
300 (FatBs.FatBsb.Media != 0x00) &&
301 (FatBs.FatBsb.Media != 0x01)
302 )
303 {
304 return EFI_UNSUPPORTED;
305 }
306
307 //
308 // Initialize fields the volume information for this FatType
309 //
310 if (FatType != Fat32) {
311 if (FatBs.FatBsb.RootEntries == 0) {
312 return EFI_UNSUPPORTED;
313 }
314
315 //
316 // Unpack fat12, fat16 info
317 //
318 Volume->RootEntries = FatBs.FatBsb.RootEntries;
319 } else {
320 //
321 // If this is fat32, refuse to mount mirror-disabled volumes
322 //
323 if (((SectorsPerFat == 0) || (FatBs.FatBse.Fat32Bse.FsVersion != 0)) || (FatBs.FatBse.Fat32Bse.ExtendedFlags & 0x80)) {
324 return EFI_UNSUPPORTED;
325 }
326
327 //
328 // Unpack fat32 info
329 //
330 Volume->RootCluster = FatBs.FatBse.Fat32Bse.RootDirFirstCluster;
331 }
332
333 Volume->NumFats = FatBs.FatBsb.NumFats;
334 //
335 // Compute some fat locations
336 //
337 BlockSize = FatBs.FatBsb.SectorSize;
338 RootDirSectors = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (BlockSize - 1)) / BlockSize;
339
340 FatLba = FatBs.FatBsb.ReservedSectors;
341 RootLba = FatBs.FatBsb.NumFats * SectorsPerFat + FatLba;
342 FirstClusterLba = RootLba + RootDirSectors;
343
344 Volume->FatPos = FatLba * BlockSize;
345 Volume->FatSize = SectorsPerFat * BlockSize;
346
347 Volume->VolumeSize = LShiftU64 (Sectors, BlockAlignment);
348 Volume->RootPos = LShiftU64 (RootLba, BlockAlignment);
349 Volume->FirstClusterPos = LShiftU64 (FirstClusterLba, BlockAlignment);
350 Volume->MaxCluster = (Sectors - FirstClusterLba) >> SectorsPerClusterAlignment;
351 Volume->ClusterAlignment = (UINT8)(BlockAlignment + SectorsPerClusterAlignment);
352 Volume->ClusterSize = (UINTN)1 << (Volume->ClusterAlignment);
353
354 //
355 // If this is not a fat32, determine if it's a fat16 or fat12
356 //
357 if (FatType != Fat32) {
358 if (Volume->MaxCluster >= FAT_MAX_FAT16_CLUSTER) {
359 return EFI_VOLUME_CORRUPTED;
360 }
361
362 FatType = Volume->MaxCluster < FAT_MAX_FAT12_CLUSTER ? Fat12 : Fat16;
363 //
364 // fat12 & fat16 fat-entries are 2 bytes
365 //
366 Volume->FatEntrySize = sizeof (UINT16);
367 DirtyMask = FAT16_DIRTY_MASK;
368 } else {
369 if (Volume->MaxCluster < FAT_MAX_FAT16_CLUSTER) {
370 return EFI_VOLUME_CORRUPTED;
371 }
372
373 //
374 // fat32 fat-entries are 4 bytes
375 //
376 Volume->FatEntrySize = sizeof (UINT32);
377 DirtyMask = FAT32_DIRTY_MASK;
378 }
379
380 //
381 // Get the DirtyValue and NotDirtyValue
382 // We should keep the initial value as the NotDirtyValue
383 // in case the volume is dirty already
384 //
385 if (FatType != Fat12) {
386 Status = FatAccessVolumeDirty (Volume, ReadDisk, &Volume->NotDirtyValue);
387 if (EFI_ERROR (Status)) {
388 return Status;
389 }
390
391 Volume->DirtyValue = Volume->NotDirtyValue & DirtyMask;
392 }
393
394 //
395 // If present, read the fat hint info
396 //
397 if (FatType == Fat32) {
398 Volume->FreeInfoPos = FatBs.FatBse.Fat32Bse.FsInfoSector * BlockSize;
399 if (FatBs.FatBse.Fat32Bse.FsInfoSector != 0) {
400 FatDiskIo (Volume, ReadDisk, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector, NULL);
401 if ((Volume->FatInfoSector.Signature == FAT_INFO_SIGNATURE) &&
402 (Volume->FatInfoSector.InfoBeginSignature == FAT_INFO_BEGIN_SIGNATURE) &&
403 (Volume->FatInfoSector.InfoEndSignature == FAT_INFO_END_SIGNATURE) &&
404 (Volume->FatInfoSector.FreeInfo.ClusterCount <= Volume->MaxCluster)
405 )
406 {
407 Volume->FreeInfoValid = TRUE;
408 }
409 }
410 }
411
412 //
413 // Just make up a FreeInfo.NextCluster for use by allocate cluster
414 //
415 if ((FAT_MIN_CLUSTER > Volume->FatInfoSector.FreeInfo.NextCluster) ||
416 (Volume->FatInfoSector.FreeInfo.NextCluster > Volume->MaxCluster + 1)
417 )
418 {
419 Volume->FatInfoSector.FreeInfo.NextCluster = FAT_MIN_CLUSTER;
420 }
421
422 //
423 // We are now defining FAT Type
424 //
425 Volume->FatType = FatType;
426 ASSERT (FatType != FatUndefined);
427
428 return EFI_SUCCESS;
429}
UINT64 UINTN
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
INTN EFIAPI HighBitSet32(IN UINT32 Operand)
Definition: HighBitSet32.c:27
EFI_STATUS FatInitializeDiskCache(IN FAT_VOLUME *Volume)
Definition: DiskCache.c:649
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID FatFreeVolume(IN FAT_VOLUME *Volume)
Definition: Misc.c:460
EFI_STATUS FatAcquireLockOrFail(VOID)
Definition: Misc.c:413
EFI_STATUS EFIAPI FatOpenVolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, OUT EFI_FILE_PROTOCOL **File)
Definition: OpenVolume.c:25
EFI_STATUS FatDiskIo(IN FAT_VOLUME *Volume, IN IO_MODE IoMode, IN UINT64 Offset, IN UINTN BufferSize, IN OUT VOID *Buffer, IN FAT_TASK *Task)
Definition: Misc.c:315
VOID FatSetVolumeError(IN FAT_OFILE *OFile, IN EFI_STATUS Status)
Definition: Flush.c:459
EFI_STATUS FatAccessVolumeDirty(IN FAT_VOLUME *Volume, IN IO_MODE IoMode, IN VOID *DirtyValue)
Definition: Misc.c:230
VOID FatReleaseLock(VOID)
Definition: Misc.c:426
EFI_STATUS FatCleanupVolume(IN FAT_VOLUME *Volume, IN FAT_OFILE *OFile, IN EFI_STATUS EfiStatus, IN FAT_TASK *Task)
Definition: Flush.c:382
EFI_STATUS FatOpenDevice(IN OUT FAT_VOLUME *Volume)
Definition: Init.c:222
EFI_STATUS FatAllocateVolume(IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN EFI_BLOCK_IO_PROTOCOL *BlockIo)
Definition: Init.c:27
EFI_STATUS FatAbandonVolume(IN FAT_VOLUME *Volume)
Definition: Init.c:144
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS