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