Home | History | Annotate | Download | only in FvSimpleFileSystemDxe
      1 /** @file
      2   This driver uses the EFI_FIRMWARE_VOLUME2_PROTOCOL to expose files in firmware
      3   volumes via the the EFI_SIMPLE_FILESYSTEM_PROTOCOL and EFI_FILE_PROTOCOL.
      4 
      5   It will expose a single directory, containing one file for each file in the firmware
      6   volume. If a file has a UI section, its contents will be used as a filename.
      7   Otherwise, a string representation of the GUID will be used.
      8   Files of an executable type (That is PEIM, DRIVER, COMBINED_PEIM_DRIVER and APPLICATION)
      9   will have ".efi" added to their filename.
     10 
     11   Its primary intended use is to be able to start EFI applications embedded in FVs
     12   from the UEFI shell. It is entirely read-only.
     13 
     14 Copyright (c) 2014, ARM Limited. All rights reserved.
     15 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
     16 
     17 This program and the accompanying materials
     18 are licensed and made available under the terms and conditions of the BSD License
     19 which accompanies this distribution.  The full text of the license may be found at
     20 http://opensource.org/licenses/bsd-license.php
     21 
     22 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     23 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     24 
     25 **/
     26 
     27 #include "FvSimpleFileSystemInternal.h"
     28 
     29 EFI_UNICODE_COLLATION_PROTOCOL          *mUnicodeCollation = NULL;
     30 
     31 //
     32 // A Guid string is 32 hex characters with 4 hyphens and a NULL-terminated char: 37 characters total
     33 //
     34 #define GUID_STRING_SIZE                (37 * sizeof (CHAR16))
     35 
     36 #define FVFS_VOLUME_LABEL_PREFIX        L"Firmware Volume: "
     37 #define FVFS_VOLUME_LABEL_SIZE          (sizeof (FVFS_VOLUME_LABEL_PREFIX) + GUID_STRING_SIZE - sizeof (CHAR16))
     38 #define FVFS_FALLBACK_VOLUME_LABEL      L"Firmware Volume"
     39 
     40 //
     41 // Template for EFI_SIMPLE_FILE_SYSTEM_PROTOCOL data structure.
     42 //
     43 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mSimpleFsTemplate = {
     44   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
     45   FvSimpleFileSystemOpenVolume
     46 };
     47 
     48 //
     49 // Template for EFI_DRIVER_BINDING_PROTOCOL data structure.
     50 //
     51 EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
     52   FvSimpleFileSystemDriverSupported,
     53   FvSimpleFileSystemDriverStart,
     54   FvSimpleFileSystemDriverStop,
     55   0,
     56   NULL,
     57   NULL
     58 };
     59 
     60 /**
     61   Open the root directory on a volume.
     62 
     63   @param  This     A pointer to the volume to open the root directory.
     64   @param  RootFile A pointer to the location to return the opened file handle for the
     65                    root directory.
     66 
     67   @retval EFI_SUCCESS          The device was opened.
     68   @retval EFI_UNSUPPORTED      This volume does not support the requested file system type.
     69   @retval EFI_NO_MEDIA         The device has no medium.
     70   @retval EFI_DEVICE_ERROR     The device reported an error.
     71   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
     72   @retval EFI_ACCESS_DENIED    The service denied access to the file.
     73   @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
     74   @retval EFI_MEDIA_CHANGED    The device has a different medium in it or the medium is no
     75                                longer supported. Any existing file handles for this volume are
     76                                no longer valid. To access the files on the new medium, the
     77                                volume must be reopened with OpenVolume().
     78 
     79 **/
     80 EFI_STATUS
     81 EFIAPI
     82 FvSimpleFileSystemOpenVolume (
     83   IN     EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
     84      OUT EFI_FILE_PROTOCOL               **RootFile
     85   )
     86 {
     87   EFI_STATUS                      Status;
     88   FV_FILESYSTEM_FILE              *Root;
     89   CHAR16                          *UiSection;
     90   EFI_GUID                        NameGuid;
     91   EFI_FV_FILE_ATTRIBUTES          Attributes;
     92   UINT32                          Authentication;
     93   UINTN                           Key;
     94   EFI_FV_FILETYPE                 FileType;
     95   UINTN                           Size;
     96   FV_FILESYSTEM_INSTANCE          *Instance;
     97   FV_FILESYSTEM_FILE_INFO         *FvFileInfo;
     98   EFI_FIRMWARE_VOLUME2_PROTOCOL   *FvProtocol;
     99   CHAR16                          *Name;
    100   UINTN                           NameLen;
    101   UINTN                           NumChars;
    102   UINTN                           DestMax;
    103 
    104   Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (This);
    105   Status = EFI_SUCCESS;
    106 
    107   if (Instance->Root == NULL) {
    108     //
    109     // Allocate file structure for root file
    110     //
    111     Root = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE));
    112     if (Root == NULL) {
    113       return EFI_OUT_OF_RESOURCES;
    114     }
    115 
    116     Instance->Root  = Root;
    117     Root->Instance  = Instance;
    118     Root->Signature = FVFS_FILE_SIGNATURE;
    119     CopyMem (&Root->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate));
    120     Root->FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO));
    121     if (Root->FvFileInfo == NULL) {
    122         return EFI_OUT_OF_RESOURCES;
    123     }
    124     Root->FvFileInfo->FileInfo.Size      = sizeof (EFI_FILE_INFO);
    125     Root->FvFileInfo->FileInfo.Attribute = EFI_FILE_DIRECTORY | EFI_FILE_READ_ONLY;
    126 
    127     //
    128     // Populate the instance's list of files. We consider anything a file that
    129     // has a UI_SECTION, which we consider to be its filename.
    130     //
    131     FvProtocol = Instance->FvProtocol;
    132     //
    133     // Allocate Key
    134     //
    135     Key = 0;
    136 
    137     do {
    138       FileType = EFI_FV_FILETYPE_ALL;
    139 
    140       Status = FvProtocol->GetNextFile (
    141                              FvProtocol,
    142                              &Key,
    143                              &FileType,
    144                              &NameGuid,
    145                              &Attributes,
    146                              &Size
    147                              );
    148       if (EFI_ERROR (Status)) {
    149         ASSERT (Status == EFI_NOT_FOUND);
    150         break;
    151       }
    152 
    153       //
    154       // Get a file's name: If it has a UI section, use that, otherwise use
    155       // its NameGuid.
    156       //
    157       UiSection = NULL;
    158       Status = FvProtocol->ReadSection (
    159                              FvProtocol,
    160                              &NameGuid,
    161                              EFI_SECTION_USER_INTERFACE,
    162                              0,
    163                              (VOID **)&UiSection,
    164                              &Size,
    165                              &Authentication
    166                              );
    167       if (!EFI_ERROR (Status)) {
    168         Name = UiSection;
    169       } else {
    170         Name = AllocateZeroPool (GUID_STRING_SIZE);
    171         if (Name == NULL) {
    172           return EFI_OUT_OF_RESOURCES;
    173         }
    174         NumChars = UnicodeSPrint (Name, GUID_STRING_SIZE, L"%g", &NameGuid);
    175         ASSERT ((NumChars + 1) * sizeof (CHAR16) == GUID_STRING_SIZE);
    176       }
    177 
    178       //
    179       // Found a file.
    180       // Allocate a file structure and populate it.
    181       //
    182       NameLen = StrSize (Name);
    183       if (FV_FILETYPE_IS_EXECUTABLE (FileType)) {
    184         NameLen += StrSize (L".efi") - sizeof (CHAR16);
    185       }
    186 
    187       FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO) + NameLen - sizeof (CHAR16));
    188       if (FvFileInfo == NULL) {
    189         return EFI_OUT_OF_RESOURCES;
    190       }
    191 
    192       FvFileInfo->Signature = FVFS_FILE_INFO_SIGNATURE;
    193       InitializeListHead (&FvFileInfo->Link);
    194       CopyMem (&FvFileInfo->NameGuid, &NameGuid, sizeof (EFI_GUID));
    195       FvFileInfo->Type = FileType;
    196 
    197       //
    198       // Add ".efi" to filenames of drivers and applications.
    199       //
    200       DestMax = NameLen / sizeof (CHAR16);
    201       Status  = StrnCpyS (&FvFileInfo->FileInfo.FileName[0], DestMax, Name, StrLen (Name));
    202       ASSERT_EFI_ERROR (Status);
    203 
    204       if (FV_FILETYPE_IS_EXECUTABLE (FileType)) {
    205         Status  = StrnCatS (&FvFileInfo->FileInfo.FileName[0], DestMax, L".efi", StrLen (L".efi"));
    206         ASSERT_EFI_ERROR (Status);
    207       }
    208 
    209       FvFileInfo->FileInfo.Size     = sizeof (EFI_FILE_INFO) + NameLen - sizeof (CHAR16);
    210       Status = FvFsGetFileSize (FvProtocol, FvFileInfo);
    211       ASSERT_EFI_ERROR (Status);
    212       FvFileInfo->FileInfo.PhysicalSize = FvFileInfo->FileInfo.FileSize;
    213       FvFileInfo->FileInfo.Attribute    = EFI_FILE_READ_ONLY;
    214 
    215       InsertHeadList (&Instance->FileInfoHead, &FvFileInfo->Link);
    216 
    217       FreePool (Name);
    218 
    219     } while (TRUE);
    220 
    221     if (Status == EFI_NOT_FOUND) {
    222       Status = EFI_SUCCESS;
    223     }
    224   }
    225 
    226   Instance->Root->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance);
    227   *RootFile = &Instance->Root->FileProtocol;
    228   return Status;
    229 }
    230 
    231 /**
    232   Worker function to initialize Unicode Collation support.
    233 
    234   It tries to locate Unicode Collation (2) protocol and matches it with current
    235   platform language code.
    236 
    237   @param  AgentHandle          The handle used to open Unicode Collation (2) protocol.
    238   @param  ProtocolGuid         The pointer to Unicode Collation (2) protocol GUID.
    239   @param  VariableName         The name of the RFC 4646 or ISO 639-2 language variable.
    240   @param  DefaultLanguage      The default language in case the RFC 4646 or ISO 639-2 language is absent.
    241 
    242   @retval EFI_SUCCESS          The Unicode Collation (2) protocol has been successfully located.
    243   @retval Others               The Unicode Collation (2) protocol has not been located.
    244 
    245 **/
    246 EFI_STATUS
    247 InitializeUnicodeCollationSupportWorker (
    248   IN       EFI_HANDLE             AgentHandle,
    249   IN       EFI_GUID               *ProtocolGuid,
    250   IN CONST CHAR16                 *VariableName,
    251   IN CONST CHAR8                  *DefaultLanguage
    252   )
    253 {
    254   EFI_STATUS                      ReturnStatus;
    255   EFI_STATUS                      Status;
    256   UINTN                           NumHandles;
    257   UINTN                           Index;
    258   EFI_HANDLE                      *Handles;
    259   EFI_UNICODE_COLLATION_PROTOCOL  *Uci;
    260   BOOLEAN                         Iso639Language;
    261   CHAR8                           *Language;
    262   CHAR8                           *BestLanguage;
    263 
    264   Status = gBS->LocateHandleBuffer (
    265                   ByProtocol,
    266                   ProtocolGuid,
    267                   NULL,
    268                   &NumHandles,
    269                   &Handles
    270                   );
    271   if (EFI_ERROR (Status)) {
    272     return Status;
    273   }
    274 
    275   Iso639Language = (BOOLEAN) (ProtocolGuid == &gEfiUnicodeCollationProtocolGuid);
    276   GetEfiGlobalVariable2 (VariableName, (VOID**) &Language, NULL);
    277 
    278   ReturnStatus = EFI_UNSUPPORTED;
    279   for (Index = 0; Index < NumHandles; Index++) {
    280     //
    281     // Open Unicode Collation Protocol
    282     //
    283     Status = gBS->OpenProtocol (
    284                     Handles[Index],
    285                     ProtocolGuid,
    286                     (VOID **) &Uci,
    287                     AgentHandle,
    288                     NULL,
    289                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    290                     );
    291     if (EFI_ERROR (Status)) {
    292       continue;
    293     }
    294 
    295     //
    296     // Find the best matching matching language from the supported languages
    297     // of Unicode Collation (2) protocol.
    298     //
    299     BestLanguage = GetBestLanguage (
    300                      Uci->SupportedLanguages,
    301                      Iso639Language,
    302                      (Language == NULL) ? "" : Language,
    303                      DefaultLanguage,
    304                      NULL
    305                      );
    306     if (BestLanguage != NULL) {
    307       FreePool (BestLanguage);
    308       mUnicodeCollation = Uci;
    309       ReturnStatus = EFI_SUCCESS;
    310       break;
    311     }
    312   }
    313 
    314   if (Language != NULL) {
    315     FreePool (Language);
    316   }
    317 
    318   FreePool (Handles);
    319 
    320   return ReturnStatus;
    321 }
    322 
    323 /**
    324   Initialize Unicode Collation support.
    325 
    326   It tries to locate Unicode Collation 2 protocol and matches it with current
    327   platform language code. If for any reason the first attempt fails, it then tries to
    328   use Unicode Collation Protocol.
    329 
    330   @param  AgentHandle          The handle used to open Unicode Collation (2) protocol.
    331 
    332   @retval EFI_SUCCESS          The Unicode Collation (2) protocol has been successfully located.
    333   @retval Others               The Unicode Collation (2) protocol has not been located.
    334 
    335 **/
    336 EFI_STATUS
    337 InitializeUnicodeCollationSupport (
    338   IN EFI_HANDLE    AgentHandle
    339   )
    340 {
    341 
    342   EFI_STATUS       Status;
    343 
    344   Status = EFI_UNSUPPORTED;
    345 
    346   //
    347   // First try to use RFC 4646 Unicode Collation 2 Protocol.
    348   //
    349   Status = InitializeUnicodeCollationSupportWorker (
    350              AgentHandle,
    351              &gEfiUnicodeCollation2ProtocolGuid,
    352              L"PlatformLang",
    353              (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang)
    354              );
    355   //
    356   // If the attempt to use Unicode Collation 2 Protocol fails, then we fall back
    357   // on the ISO 639-2 Unicode Collation Protocol.
    358   //
    359   if (EFI_ERROR (Status)) {
    360     Status = InitializeUnicodeCollationSupportWorker (
    361                AgentHandle,
    362                &gEfiUnicodeCollationProtocolGuid,
    363                L"Lang",
    364                (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang)
    365                );
    366   }
    367 
    368   return Status;
    369 }
    370 
    371 /**
    372   Test to see if this driver supports ControllerHandle.
    373 
    374   @param  DriverBinding       Protocol instance pointer.
    375   @param  ControllerHandle    Handle of device to test
    376   @param  RemainingDevicePath Optional parameter use to pick a specific child
    377                               device to start.
    378 
    379   @retval EFI_SUCCESS         This driver supports this device
    380   @retval EFI_ALREADY_STARTED This driver is already running on this device
    381   @retval other               This driver does not support this device
    382 
    383 **/
    384 EFI_STATUS
    385 EFIAPI
    386 FvSimpleFileSystemDriverSupported (
    387   IN  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding,
    388   IN  EFI_HANDLE                   ControllerHandle,
    389   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    390   )
    391 {
    392   return gBS->OpenProtocol (
    393                 ControllerHandle,
    394                 &gEfiFirmwareVolume2ProtocolGuid,
    395                 NULL,
    396                 gImageHandle,
    397                 ControllerHandle,
    398                 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    399                 );
    400 }
    401 
    402 /**
    403   Start this driver on ControllerHandle by opening a FV protocol and
    404   installing a SimpleFileSystem protocol on ControllerHandle.
    405 
    406   @param  DriverBinding        Protocol instance pointer.
    407   @param  ControllerHandle     Handle of device to bind driver to
    408   @param  RemainingDevicePath  Optional parameter use to pick a specific child
    409                                device to start.
    410 
    411   @retval EFI_SUCCESS          This driver is added to ControllerHandle
    412   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
    413   @retval other                This driver does not support this device
    414 
    415 **/
    416 EFI_STATUS
    417 EFIAPI
    418 FvSimpleFileSystemDriverStart (
    419   IN  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding,
    420   IN  EFI_HANDLE                   ControllerHandle,
    421   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    422   )
    423 {
    424   EFI_STATUS                       Status;
    425   EFI_FIRMWARE_VOLUME2_PROTOCOL    *FvProtocol;
    426   FV_FILESYSTEM_INSTANCE           *Instance;
    427   EFI_DEVICE_PATH_PROTOCOL         *FvDevicePath;
    428   EFI_GUID                         *FvGuid;
    429   UINTN                            NumChars;
    430 
    431   Status = InitializeUnicodeCollationSupport (DriverBinding->DriverBindingHandle);
    432   if (EFI_ERROR (Status)) {
    433     return Status;
    434   }
    435 
    436   //
    437   // Open FV protocol
    438   //
    439   Status = gBS->OpenProtocol (
    440                   ControllerHandle,
    441                   &gEfiFirmwareVolume2ProtocolGuid,
    442                   (VOID **) &FvProtocol,
    443                   gImageHandle,
    444                   ControllerHandle,
    445                   EFI_OPEN_PROTOCOL_BY_DRIVER
    446                   );
    447   if (EFI_ERROR (Status)) {
    448     return Status;
    449   }
    450 
    451   //
    452   // Create an instance
    453   //
    454   Instance = AllocateZeroPool (sizeof (FV_FILESYSTEM_INSTANCE));
    455   if (Instance == NULL) {
    456     return EFI_OUT_OF_RESOURCES;
    457   }
    458 
    459   Instance->Root = NULL;
    460   Instance->FvProtocol = FvProtocol;
    461   Instance->Signature = FVFS_INSTANCE_SIGNATURE;
    462   InitializeListHead (&Instance->FileInfoHead);
    463   InitializeListHead (&Instance->FileHead);
    464   CopyMem (&Instance->SimpleFs, &mSimpleFsTemplate, sizeof (mSimpleFsTemplate));
    465 
    466   Status = gBS->InstallProtocolInterface(
    467                   &ControllerHandle,
    468                   &gEfiSimpleFileSystemProtocolGuid,
    469                   EFI_NATIVE_INTERFACE,
    470                   &Instance->SimpleFs
    471                   );
    472 
    473   //
    474   // Decide on a filesystem volume label, which will include the FV's guid.
    475   // Get the device path to find the FV's GUID
    476   //
    477   Instance->VolumeLabel = NULL;
    478   Status =  gBS->OpenProtocol (
    479                    ControllerHandle,
    480                    &gEfiDevicePathProtocolGuid,
    481                    (VOID **) &FvDevicePath,
    482                    gImageHandle,
    483                    ControllerHandle,
    484                    EFI_OPEN_PROTOCOL_BY_DRIVER
    485                    );
    486   if (!EFI_ERROR (Status)) {
    487     //
    488     // Iterate over device path until we find a firmware volume node
    489     //
    490     while (!IsDevicePathEndType (FvDevicePath)) {
    491       if (DevicePathType (FvDevicePath) == MEDIA_DEVICE_PATH &&
    492           DevicePathSubType (FvDevicePath) == MEDIA_PIWG_FW_VOL_DP) {
    493         //
    494         // Allocate the volume label
    495         //
    496         Instance->VolumeLabel = AllocateZeroPool (FVFS_VOLUME_LABEL_SIZE);
    497         //
    498         // Check the allocation was successful
    499         //
    500         if (Instance->VolumeLabel != NULL) {
    501           //
    502           // Extract the FV's guid
    503           //
    504           FvGuid = &((MEDIA_FW_VOL_DEVICE_PATH *) FvDevicePath)->FvName;
    505           //
    506           // Build the volume label string
    507           //
    508           NumChars = UnicodeSPrint (
    509                        Instance->VolumeLabel,
    510                        FVFS_VOLUME_LABEL_SIZE,
    511                        FVFS_VOLUME_LABEL_PREFIX L"%g",
    512                        FvGuid
    513                        );
    514           ASSERT ((NumChars + 1) * sizeof (CHAR16) == FVFS_VOLUME_LABEL_SIZE);
    515         }
    516         break;
    517       }
    518       FvDevicePath = NextDevicePathNode (FvDevicePath);
    519     }
    520   }
    521   //
    522   // If we didn't decide on a volume label, set a fallback one
    523   //
    524   if (Instance->VolumeLabel == NULL) {
    525     Instance->VolumeLabel = AllocateCopyPool (
    526                               sizeof (FVFS_FALLBACK_VOLUME_LABEL),
    527                               FVFS_FALLBACK_VOLUME_LABEL
    528                               );
    529   }
    530 
    531   return Status;
    532 }
    533 
    534 /**
    535   Stop this driver on ControllerHandle by removing SimpleFileSystem protocol and closing
    536   the FV protocol on ControllerHandle.
    537 
    538   @param  DriverBinding     Protocol instance pointer.
    539   @param  ControllerHandle  Handle of device to stop driver on
    540   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
    541                             children is zero stop the entire bus driver.
    542   @param  ChildHandleBuffer List of Child Handles to Stop.
    543 
    544   @retval EFI_SUCCESS       This driver is removed ControllerHandle
    545   @retval other             This driver was not removed from this device
    546 
    547 **/
    548 EFI_STATUS
    549 EFIAPI
    550 FvSimpleFileSystemDriverStop (
    551   IN  EFI_DRIVER_BINDING_PROTOCOL       *DriverBinding,
    552   IN  EFI_HANDLE                        ControllerHandle,
    553   IN  UINTN                             NumberOfChildren,
    554   IN  EFI_HANDLE                        *ChildHandleBuffer OPTIONAL
    555   )
    556 {
    557   EFI_STATUS                       Status;
    558   FV_FILESYSTEM_INSTANCE           *Instance;
    559   FV_FILESYSTEM_FILE_INFO          *FvFileInfo;
    560   LIST_ENTRY                       *Entry;
    561   LIST_ENTRY                       *DelEntry;
    562   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *SimpleFile;
    563 
    564   Status = gBS->OpenProtocol (
    565                   ControllerHandle,
    566                   &gEfiSimpleFileSystemProtocolGuid,
    567                   (VOID **) &SimpleFile,
    568                   DriverBinding->DriverBindingHandle,
    569                   ControllerHandle,
    570                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    571                   );
    572   if (EFI_ERROR (Status)) {
    573     return Status;
    574   }
    575 
    576   Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (SimpleFile);
    577 
    578   if (IsListEmpty (&Instance->FileHead) == FALSE) {
    579     //
    580     // Not all opened files are closed
    581     //
    582     return EFI_DEVICE_ERROR;
    583   }
    584 
    585   //
    586   // Close and uninstall protocols.
    587   //
    588   Status = gBS->CloseProtocol (
    589                    ControllerHandle,
    590                    &gEfiFirmwareVolume2ProtocolGuid,
    591                    gImageHandle,
    592                    ControllerHandle
    593                    );
    594   ASSERT_EFI_ERROR (Status);
    595 
    596   Status = gBS->UninstallProtocolInterface (
    597                   ControllerHandle,
    598                   &gEfiSimpleFileSystemProtocolGuid,
    599                   &Instance->SimpleFs
    600                   );
    601   ASSERT_EFI_ERROR (Status);
    602 
    603   //
    604   // Free file structures
    605   //
    606   if (!IsListEmpty (&Instance->FileInfoHead)) {
    607     //
    608     // Free the Subtask list.
    609     //
    610     for(Entry = Instance->FileInfoHead.ForwardLink;
    611         Entry != (&Instance->FileInfoHead);
    612        ) {
    613       DelEntry   = Entry;
    614       Entry      = Entry->ForwardLink;
    615       FvFileInfo = FVFS_FILE_INFO_FROM_LINK (DelEntry);
    616 
    617       RemoveEntryList (DelEntry);
    618       FreePool (FvFileInfo);
    619     }
    620   }
    621 
    622   if (Instance->Root != NULL) {
    623     //
    624     // Root->Name is statically allocated, no need to free.
    625     //
    626     if (Instance->Root->FvFileInfo != NULL) {
    627       FreePool (Instance->Root->FvFileInfo);
    628     }
    629     FreePool (Instance->Root);
    630   }
    631 
    632   //
    633   // Free Instance
    634   //
    635   if (Instance->VolumeLabel != NULL) {
    636     FreePool (Instance->VolumeLabel);
    637   }
    638   FreePool (Instance);
    639 
    640   return EFI_SUCCESS;
    641 }
    642 
    643 /**
    644   The user Entry Point for module FvSimpleFileSystem. The user code starts with this function.
    645 
    646   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    647   @param[in] SystemTable    A pointer to the EFI System Table.
    648 
    649   @retval EFI_SUCCESS       The entry point is executed successfully.
    650   @retval other             Some error occurs when executing this entry point.
    651 
    652 **/
    653 EFI_STATUS
    654 EFIAPI
    655 FvSimpleFileSystemEntryPoint (
    656   IN EFI_HANDLE               ImageHandle,
    657   IN EFI_SYSTEM_TABLE         *SystemTable
    658   )
    659 {
    660   EFI_STATUS Status;
    661 
    662   //
    663   // Install driver model protocol(s).
    664   //
    665   Status = EfiLibInstallDriverBindingComponentName2 (
    666              ImageHandle,
    667              SystemTable,
    668              &mDriverBinding,
    669              ImageHandle,
    670              &gFvSimpleFileSystemComponentName,
    671              &gFvSimpleFileSystemComponentName2
    672              );
    673   ASSERT_EFI_ERROR (Status);
    674 
    675   return Status;
    676 }
    677