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