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