• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
FvSimpleFileSystemOpenVolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL * This,OUT EFI_FILE_PROTOCOL ** RootFile)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
InitializeUnicodeCollationSupportWorker(IN EFI_HANDLE AgentHandle,IN EFI_GUID * ProtocolGuid,IN CONST CHAR16 * VariableName,IN CONST CHAR8 * DefaultLanguage)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
InitializeUnicodeCollationSupport(IN EFI_HANDLE AgentHandle)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
FvSimpleFileSystemDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * DriverBinding,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
FvSimpleFileSystemDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * DriverBinding,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
FvSimpleFileSystemDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * DriverBinding,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)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
FvSimpleFileSystemEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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