Home | History | Annotate | Download | only in EnhancedFatDxe
      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 }
    532