VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/FatPkg/EnhancedFatDxe/Init.c@ 77662

Last change on this file since 77662 was 77662, checked in by vboxsync, 6 years ago

EFI: First step in UDK2018 merge. Does not build yet.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette