]> git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/EnhancedFatDxe/Fat.c
2e6c0896501d3075295b6fb666abb4ac88fabfb2
[mirror_edk2.git] / FatPkg / EnhancedFatDxe / Fat.c
1 /** @file
2 Fat File System driver routines that support EFI driver model.
3
4 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Fat.h"
16
17 EFI_STATUS
18 EFIAPI
19 FatEntryPoint (
20 IN EFI_HANDLE ImageHandle,
21 IN EFI_SYSTEM_TABLE *SystemTable
22 );
23
24 EFI_STATUS
25 EFIAPI
26 FatUnload (
27 IN EFI_HANDLE ImageHandle
28 );
29
30 EFI_STATUS
31 EFIAPI
32 FatDriverBindingSupported (
33 IN EFI_DRIVER_BINDING_PROTOCOL *This,
34 IN EFI_HANDLE Controller,
35 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
36 );
37
38 EFI_STATUS
39 EFIAPI
40 FatDriverBindingStart (
41 IN EFI_DRIVER_BINDING_PROTOCOL *This,
42 IN EFI_HANDLE Controller,
43 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
44 );
45
46 EFI_STATUS
47 EFIAPI
48 FatDriverBindingStop (
49 IN EFI_DRIVER_BINDING_PROTOCOL *This,
50 IN EFI_HANDLE Controller,
51 IN UINTN NumberOfChildren,
52 IN EFI_HANDLE *ChildHandleBuffer
53 );
54
55 //
56 // DriverBinding protocol instance
57 //
58 EFI_DRIVER_BINDING_PROTOCOL gFatDriverBinding = {
59 FatDriverBindingSupported,
60 FatDriverBindingStart,
61 FatDriverBindingStop,
62 0xa,
63 NULL,
64 NULL
65 };
66
67 /**
68
69 Register Driver Binding protocol for this driver.
70
71 @param ImageHandle - Handle for the image of this driver.
72 @param SystemTable - Pointer to the EFI System Table.
73
74 @retval EFI_SUCCESS - Driver loaded.
75 @return other - Driver not loaded.
76
77 **/
78 EFI_STATUS
79 EFIAPI
80 FatEntryPoint (
81 IN EFI_HANDLE ImageHandle,
82 IN EFI_SYSTEM_TABLE *SystemTable
83 )
84 {
85 EFI_STATUS Status;
86
87 //
88 // Initialize the EFI Driver Library
89 //
90 Status = EfiLibInstallDriverBindingComponentName2 (
91 ImageHandle,
92 SystemTable,
93 &gFatDriverBinding,
94 ImageHandle,
95 &gFatComponentName,
96 &gFatComponentName2
97 );
98 ASSERT_EFI_ERROR (Status);
99
100 return Status;
101 }
102
103 /**
104
105 Unload function for this image. Uninstall DriverBinding protocol.
106
107 @param ImageHandle - Handle for the image of this driver.
108
109 @retval EFI_SUCCESS - Driver unloaded successfully.
110 @return other - Driver can not unloaded.
111
112 **/
113 EFI_STATUS
114 EFIAPI
115 FatUnload (
116 IN EFI_HANDLE ImageHandle
117 )
118 {
119 EFI_STATUS Status;
120 EFI_HANDLE *DeviceHandleBuffer;
121 UINTN DeviceHandleCount;
122 UINTN Index;
123 VOID *ComponentName;
124 VOID *ComponentName2;
125
126 Status = gBS->LocateHandleBuffer (
127 AllHandles,
128 NULL,
129 NULL,
130 &DeviceHandleCount,
131 &DeviceHandleBuffer
132 );
133 if (EFI_ERROR (Status)) {
134 return Status;
135 }
136
137 for (Index = 0; Index < DeviceHandleCount; Index++) {
138 Status = EfiTestManagedDevice (DeviceHandleBuffer[Index], ImageHandle, &gEfiDiskIoProtocolGuid);
139 if (!EFI_ERROR (Status)) {
140 Status = gBS->DisconnectController (
141 DeviceHandleBuffer[Index],
142 ImageHandle,
143 NULL
144 );
145 if (EFI_ERROR (Status)) {
146 break;
147 }
148 }
149 }
150
151 if (Index == DeviceHandleCount) {
152 //
153 // Driver is stopped successfully.
154 //
155 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentNameProtocolGuid, &ComponentName);
156 if (EFI_ERROR (Status)) {
157 ComponentName = NULL;
158 }
159
160 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentName2ProtocolGuid, &ComponentName2);
161 if (EFI_ERROR (Status)) {
162 ComponentName2 = NULL;
163 }
164
165 if (ComponentName == NULL) {
166 if (ComponentName2 == NULL) {
167 Status = gBS->UninstallMultipleProtocolInterfaces (
168 ImageHandle,
169 &gEfiDriverBindingProtocolGuid, &gFatDriverBinding,
170 NULL
171 );
172 } else {
173 Status = gBS->UninstallMultipleProtocolInterfaces (
174 ImageHandle,
175 &gEfiDriverBindingProtocolGuid, &gFatDriverBinding,
176 &gEfiComponentName2ProtocolGuid, ComponentName2,
177 NULL
178 );
179 }
180 } else {
181 if (ComponentName2 == NULL) {
182 Status = gBS->UninstallMultipleProtocolInterfaces (
183 ImageHandle,
184 &gEfiDriverBindingProtocolGuid, &gFatDriverBinding,
185 &gEfiComponentNameProtocolGuid, ComponentName,
186 NULL
187 );
188 } else {
189 Status = gBS->UninstallMultipleProtocolInterfaces (
190 ImageHandle,
191 &gEfiDriverBindingProtocolGuid, &gFatDriverBinding,
192 &gEfiComponentNameProtocolGuid, ComponentName,
193 &gEfiComponentName2ProtocolGuid, ComponentName2,
194 NULL
195 );
196 }
197 }
198 }
199
200 if (DeviceHandleBuffer != NULL) {
201 FreePool (DeviceHandleBuffer);
202 }
203
204 return Status;
205 }
206
207 /**
208
209 Test to see if this driver can add a file system to ControllerHandle.
210 ControllerHandle must support both Disk IO and Block IO protocols.
211
212 @param This - Protocol instance pointer.
213 @param ControllerHandle - Handle of device to test.
214 @param RemainingDevicePath - Not used.
215
216 @retval EFI_SUCCESS - This driver supports this device.
217 @retval EFI_ALREADY_STARTED - This driver is already running on this device.
218 @return other - This driver does not support this device.
219
220 **/
221 EFI_STATUS
222 EFIAPI
223 FatDriverBindingSupported (
224 IN EFI_DRIVER_BINDING_PROTOCOL *This,
225 IN EFI_HANDLE ControllerHandle,
226 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
227 )
228 {
229 EFI_STATUS Status;
230 EFI_DISK_IO_PROTOCOL *DiskIo;
231
232 //
233 // Open the IO Abstraction(s) needed to perform the supported test
234 //
235 Status = gBS->OpenProtocol (
236 ControllerHandle,
237 &gEfiDiskIoProtocolGuid,
238 (VOID **) &DiskIo,
239 This->DriverBindingHandle,
240 ControllerHandle,
241 EFI_OPEN_PROTOCOL_BY_DRIVER
242 );
243
244 if (EFI_ERROR (Status)) {
245 return Status;
246 }
247 //
248 // Close the I/O Abstraction(s) used to perform the supported test
249 //
250 gBS->CloseProtocol (
251 ControllerHandle,
252 &gEfiDiskIoProtocolGuid,
253 This->DriverBindingHandle,
254 ControllerHandle
255 );
256
257 //
258 // Open the IO Abstraction(s) needed to perform the supported test
259 //
260 Status = gBS->OpenProtocol (
261 ControllerHandle,
262 &gEfiBlockIoProtocolGuid,
263 NULL,
264 This->DriverBindingHandle,
265 ControllerHandle,
266 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
267 );
268
269 return Status;
270 }
271
272 /**
273
274 Start this driver on ControllerHandle by opening a Block IO and Disk IO
275 protocol, reading Device Path. Add a Simple File System protocol to
276 ControllerHandle if the media contains a valid file system.
277
278 @param This - Protocol instance pointer.
279 @param ControllerHandle - Handle of device to bind driver to.
280 @param RemainingDevicePath - Not used.
281
282 @retval EFI_SUCCESS - This driver is added to DeviceHandle.
283 @retval EFI_ALREADY_STARTED - This driver is already running on DeviceHandle.
284 @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory.
285 @return other - This driver does not support this device.
286
287 **/
288 EFI_STATUS
289 EFIAPI
290 FatDriverBindingStart (
291 IN EFI_DRIVER_BINDING_PROTOCOL *This,
292 IN EFI_HANDLE ControllerHandle,
293 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
294 )
295 {
296 EFI_STATUS Status;
297 EFI_BLOCK_IO_PROTOCOL *BlockIo;
298 EFI_DISK_IO_PROTOCOL *DiskIo;
299 EFI_DISK_IO2_PROTOCOL *DiskIo2;
300 BOOLEAN LockedByMe;
301
302 LockedByMe = FALSE;
303 //
304 // Acquire the lock.
305 // If caller has already acquired the lock, cannot lock it again.
306 //
307 Status = FatAcquireLockOrFail ();
308 if (!EFI_ERROR (Status)) {
309 LockedByMe = TRUE;
310 }
311
312 Status = InitializeUnicodeCollationSupport (This->DriverBindingHandle);
313 if (EFI_ERROR (Status)) {
314 goto Exit;
315 }
316 //
317 // Open our required BlockIo and DiskIo
318 //
319 Status = gBS->OpenProtocol (
320 ControllerHandle,
321 &gEfiBlockIoProtocolGuid,
322 (VOID **) &BlockIo,
323 This->DriverBindingHandle,
324 ControllerHandle,
325 EFI_OPEN_PROTOCOL_GET_PROTOCOL
326 );
327 if (EFI_ERROR (Status)) {
328 goto Exit;
329 }
330
331 Status = gBS->OpenProtocol (
332 ControllerHandle,
333 &gEfiDiskIoProtocolGuid,
334 (VOID **) &DiskIo,
335 This->DriverBindingHandle,
336 ControllerHandle,
337 EFI_OPEN_PROTOCOL_BY_DRIVER
338 );
339 if (EFI_ERROR (Status)) {
340 goto Exit;
341 }
342
343 Status = gBS->OpenProtocol (
344 ControllerHandle,
345 &gEfiDiskIo2ProtocolGuid,
346 (VOID **) &DiskIo2,
347 This->DriverBindingHandle,
348 ControllerHandle,
349 EFI_OPEN_PROTOCOL_BY_DRIVER
350 );
351 if (EFI_ERROR (Status)) {
352 DiskIo2 = NULL;
353 }
354
355 //
356 // Allocate Volume structure. In FatAllocateVolume(), Resources
357 // are allocated with protocol installed and cached initialized
358 //
359 Status = FatAllocateVolume (ControllerHandle, DiskIo, DiskIo2, BlockIo);
360
361 //
362 // When the media changes on a device it will Reinstall the BlockIo interaface.
363 // This will cause a call to our Stop(), and a subsequent reentrant call to our
364 // Start() successfully. We should leave the device open when this happen.
365 //
366 if (EFI_ERROR (Status)) {
367 Status = gBS->OpenProtocol (
368 ControllerHandle,
369 &gEfiSimpleFileSystemProtocolGuid,
370 NULL,
371 This->DriverBindingHandle,
372 ControllerHandle,
373 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
374 );
375 if (EFI_ERROR (Status)) {
376 gBS->CloseProtocol (
377 ControllerHandle,
378 &gEfiDiskIoProtocolGuid,
379 This->DriverBindingHandle,
380 ControllerHandle
381 );
382 gBS->CloseProtocol (
383 ControllerHandle,
384 &gEfiDiskIo2ProtocolGuid,
385 This->DriverBindingHandle,
386 ControllerHandle
387 );
388 }
389 }
390
391 Exit:
392 //
393 // Unlock if locked by myself.
394 //
395 if (LockedByMe) {
396 FatReleaseLock ();
397 }
398 return Status;
399 }
400
401 /**
402
403 Stop this driver on ControllerHandle.
404
405 @param This - Protocol instance pointer.
406 @param ControllerHandle - Handle of device to stop driver on.
407 @param NumberOfChildren - Not used.
408 @param ChildHandleBuffer - Not used.
409
410 @retval EFI_SUCCESS - This driver is removed DeviceHandle.
411 @return other - This driver was not removed from this device.
412
413 **/
414 EFI_STATUS
415 EFIAPI
416 FatDriverBindingStop (
417 IN EFI_DRIVER_BINDING_PROTOCOL *This,
418 IN EFI_HANDLE ControllerHandle,
419 IN UINTN NumberOfChildren,
420 IN EFI_HANDLE *ChildHandleBuffer
421 )
422 {
423 EFI_STATUS Status;
424 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
425 FAT_VOLUME *Volume;
426 EFI_DISK_IO2_PROTOCOL *DiskIo2;
427
428 DiskIo2 = NULL;
429 //
430 // Get our context back
431 //
432 Status = gBS->OpenProtocol (
433 ControllerHandle,
434 &gEfiSimpleFileSystemProtocolGuid,
435 (VOID **) &FileSystem,
436 This->DriverBindingHandle,
437 ControllerHandle,
438 EFI_OPEN_PROTOCOL_GET_PROTOCOL
439 );
440
441 if (!EFI_ERROR (Status)) {
442 Volume = VOLUME_FROM_VOL_INTERFACE (FileSystem);
443 DiskIo2 = Volume->DiskIo2;
444 Status = FatAbandonVolume (Volume);
445 }
446
447 if (!EFI_ERROR (Status)) {
448 if (DiskIo2 != NULL) {
449 Status = gBS->CloseProtocol (
450 ControllerHandle,
451 &gEfiDiskIo2ProtocolGuid,
452 This->DriverBindingHandle,
453 ControllerHandle
454 );
455 ASSERT_EFI_ERROR (Status);
456 }
457 Status = gBS->CloseProtocol (
458 ControllerHandle,
459 &gEfiDiskIoProtocolGuid,
460 This->DriverBindingHandle,
461 ControllerHandle
462 );
463 ASSERT_EFI_ERROR (Status);
464 }
465
466 return Status;
467 }