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
FatEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
FatUnload(IN EFI_HANDLE ImageHandle)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
FatDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
FatDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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 interface.
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
FatDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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 }
526