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 - 2016, 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 = NULL;
227   if (!IsListEmpty (&Instance->FileInfoHead)) {
228     Instance->Root->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance);
229   }
230 
231   *RootFile = &Instance->Root->FileProtocol;
232   return Status;
233 }
234 
235 /**
236   Worker function to initialize Unicode Collation support.
237 
238   It tries to locate Unicode Collation (2) protocol and matches it with current
239   platform language code.
240 
241   @param  AgentHandle          The handle used to open Unicode Collation (2) protocol.
242   @param  ProtocolGuid         The pointer to Unicode Collation (2) protocol GUID.
243   @param  VariableName         The name of the RFC 4646 or ISO 639-2 language variable.
244   @param  DefaultLanguage      The default language in case the RFC 4646 or ISO 639-2 language is absent.
245 
246   @retval EFI_SUCCESS          The Unicode Collation (2) protocol has been successfully located.
247   @retval Others               The Unicode Collation (2) protocol has not been located.
248 
249 **/
250 EFI_STATUS
InitializeUnicodeCollationSupportWorker(IN EFI_HANDLE AgentHandle,IN EFI_GUID * ProtocolGuid,IN CONST CHAR16 * VariableName,IN CONST CHAR8 * DefaultLanguage)251 InitializeUnicodeCollationSupportWorker (
252   IN       EFI_HANDLE             AgentHandle,
253   IN       EFI_GUID               *ProtocolGuid,
254   IN CONST CHAR16                 *VariableName,
255   IN CONST CHAR8                  *DefaultLanguage
256   )
257 {
258   EFI_STATUS                      ReturnStatus;
259   EFI_STATUS                      Status;
260   UINTN                           NumHandles;
261   UINTN                           Index;
262   EFI_HANDLE                      *Handles;
263   EFI_UNICODE_COLLATION_PROTOCOL  *Uci;
264   BOOLEAN                         Iso639Language;
265   CHAR8                           *Language;
266   CHAR8                           *BestLanguage;
267 
268   Status = gBS->LocateHandleBuffer (
269                   ByProtocol,
270                   ProtocolGuid,
271                   NULL,
272                   &NumHandles,
273                   &Handles
274                   );
275   if (EFI_ERROR (Status)) {
276     return Status;
277   }
278 
279   Iso639Language = (BOOLEAN) (ProtocolGuid == &gEfiUnicodeCollationProtocolGuid);
280   GetEfiGlobalVariable2 (VariableName, (VOID**) &Language, NULL);
281 
282   ReturnStatus = EFI_UNSUPPORTED;
283   for (Index = 0; Index < NumHandles; Index++) {
284     //
285     // Open Unicode Collation Protocol
286     //
287     Status = gBS->OpenProtocol (
288                     Handles[Index],
289                     ProtocolGuid,
290                     (VOID **) &Uci,
291                     AgentHandle,
292                     NULL,
293                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
294                     );
295     if (EFI_ERROR (Status)) {
296       continue;
297     }
298 
299     //
300     // Find the best matching matching language from the supported languages
301     // of Unicode Collation (2) protocol.
302     //
303     BestLanguage = GetBestLanguage (
304                      Uci->SupportedLanguages,
305                      Iso639Language,
306                      (Language == NULL) ? "" : Language,
307                      DefaultLanguage,
308                      NULL
309                      );
310     if (BestLanguage != NULL) {
311       FreePool (BestLanguage);
312       mUnicodeCollation = Uci;
313       ReturnStatus = EFI_SUCCESS;
314       break;
315     }
316   }
317 
318   if (Language != NULL) {
319     FreePool (Language);
320   }
321 
322   FreePool (Handles);
323 
324   return ReturnStatus;
325 }
326 
327 /**
328   Initialize Unicode Collation support.
329 
330   It tries to locate Unicode Collation 2 protocol and matches it with current
331   platform language code. If for any reason the first attempt fails, it then tries to
332   use Unicode Collation Protocol.
333 
334   @param  AgentHandle          The handle used to open Unicode Collation (2) protocol.
335 
336   @retval EFI_SUCCESS          The Unicode Collation (2) protocol has been successfully located.
337   @retval Others               The Unicode Collation (2) protocol has not been located.
338 
339 **/
340 EFI_STATUS
InitializeUnicodeCollationSupport(IN EFI_HANDLE AgentHandle)341 InitializeUnicodeCollationSupport (
342   IN EFI_HANDLE    AgentHandle
343   )
344 {
345 
346   EFI_STATUS       Status;
347 
348   Status = EFI_UNSUPPORTED;
349 
350   //
351   // First try to use RFC 4646 Unicode Collation 2 Protocol.
352   //
353   Status = InitializeUnicodeCollationSupportWorker (
354              AgentHandle,
355              &gEfiUnicodeCollation2ProtocolGuid,
356              L"PlatformLang",
357              (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang)
358              );
359   //
360   // If the attempt to use Unicode Collation 2 Protocol fails, then we fall back
361   // on the ISO 639-2 Unicode Collation Protocol.
362   //
363   if (EFI_ERROR (Status)) {
364     Status = InitializeUnicodeCollationSupportWorker (
365                AgentHandle,
366                &gEfiUnicodeCollationProtocolGuid,
367                L"Lang",
368                (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang)
369                );
370   }
371 
372   return Status;
373 }
374 
375 /**
376   Test to see if this driver supports ControllerHandle.
377 
378   @param  DriverBinding       Protocol instance pointer.
379   @param  ControllerHandle    Handle of device to test
380   @param  RemainingDevicePath Optional parameter use to pick a specific child
381                               device to start.
382 
383   @retval EFI_SUCCESS         This driver supports this device
384   @retval EFI_ALREADY_STARTED This driver is already running on this device
385   @retval other               This driver does not support this device
386 
387 **/
388 EFI_STATUS
389 EFIAPI
FvSimpleFileSystemDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * DriverBinding,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)390 FvSimpleFileSystemDriverSupported (
391   IN  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding,
392   IN  EFI_HANDLE                   ControllerHandle,
393   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
394   )
395 {
396   return gBS->OpenProtocol (
397                 ControllerHandle,
398                 &gEfiFirmwareVolume2ProtocolGuid,
399                 NULL,
400                 gImageHandle,
401                 ControllerHandle,
402                 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
403                 );
404 }
405 
406 /**
407   Start this driver on ControllerHandle by opening a FV protocol and
408   installing a SimpleFileSystem protocol on ControllerHandle.
409 
410   @param  DriverBinding        Protocol instance pointer.
411   @param  ControllerHandle     Handle of device to bind driver to
412   @param  RemainingDevicePath  Optional parameter use to pick a specific child
413                                device to start.
414 
415   @retval EFI_SUCCESS          This driver is added to ControllerHandle
416   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
417   @retval other                This driver does not support this device
418 
419 **/
420 EFI_STATUS
421 EFIAPI
FvSimpleFileSystemDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * DriverBinding,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)422 FvSimpleFileSystemDriverStart (
423   IN  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding,
424   IN  EFI_HANDLE                   ControllerHandle,
425   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
426   )
427 {
428   EFI_STATUS                       Status;
429   EFI_FIRMWARE_VOLUME2_PROTOCOL    *FvProtocol;
430   FV_FILESYSTEM_INSTANCE           *Instance;
431   EFI_DEVICE_PATH_PROTOCOL         *FvDevicePath;
432   EFI_GUID                         *FvGuid;
433   UINTN                            NumChars;
434 
435   Status = InitializeUnicodeCollationSupport (DriverBinding->DriverBindingHandle);
436   if (EFI_ERROR (Status)) {
437     return Status;
438   }
439 
440   //
441   // Open FV protocol
442   //
443   Status = gBS->OpenProtocol (
444                   ControllerHandle,
445                   &gEfiFirmwareVolume2ProtocolGuid,
446                   (VOID **) &FvProtocol,
447                   gImageHandle,
448                   ControllerHandle,
449                   EFI_OPEN_PROTOCOL_BY_DRIVER
450                   );
451   if (EFI_ERROR (Status)) {
452     return Status;
453   }
454 
455   //
456   // Create an instance
457   //
458   Instance = AllocateZeroPool (sizeof (FV_FILESYSTEM_INSTANCE));
459   ASSERT (Instance != NULL);
460 
461   Instance->Root = NULL;
462   Instance->FvProtocol = FvProtocol;
463   Instance->Signature = FVFS_INSTANCE_SIGNATURE;
464   InitializeListHead (&Instance->FileInfoHead);
465   InitializeListHead (&Instance->FileHead);
466   CopyMem (&Instance->SimpleFs, &mSimpleFsTemplate, sizeof (mSimpleFsTemplate));
467 
468   Status = gBS->InstallProtocolInterface(
469                   &ControllerHandle,
470                   &gEfiSimpleFileSystemProtocolGuid,
471                   EFI_NATIVE_INTERFACE,
472                   &Instance->SimpleFs
473                   );
474   ASSERT_EFI_ERROR (Status);
475 
476   //
477   // Decide on a filesystem volume label, which will include the FV's guid.
478   // Get the device path to find the FV's GUID
479   //
480   Instance->VolumeLabel = NULL;
481   Status =  gBS->OpenProtocol (
482                    ControllerHandle,
483                    &gEfiDevicePathProtocolGuid,
484                    (VOID **) &FvDevicePath,
485                    gImageHandle,
486                    ControllerHandle,
487                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
488                    );
489   if (!EFI_ERROR (Status)) {
490     //
491     // Iterate over device path until we find a firmware volume node
492     //
493     while (!IsDevicePathEndType (FvDevicePath)) {
494       if (DevicePathType (FvDevicePath) == MEDIA_DEVICE_PATH &&
495           DevicePathSubType (FvDevicePath) == MEDIA_PIWG_FW_VOL_DP) {
496         //
497         // Allocate the volume label
498         //
499         Instance->VolumeLabel = AllocateZeroPool (FVFS_VOLUME_LABEL_SIZE);
500         //
501         // Check the allocation was successful
502         //
503         if (Instance->VolumeLabel != NULL) {
504           //
505           // Extract the FV's guid
506           //
507           FvGuid = &((MEDIA_FW_VOL_DEVICE_PATH *) FvDevicePath)->FvName;
508           //
509           // Build the volume label string
510           //
511           NumChars = UnicodeSPrint (
512                        Instance->VolumeLabel,
513                        FVFS_VOLUME_LABEL_SIZE,
514                        FVFS_VOLUME_LABEL_PREFIX L"%g",
515                        FvGuid
516                        );
517           ASSERT ((NumChars + 1) * sizeof (CHAR16) == FVFS_VOLUME_LABEL_SIZE);
518         }
519         break;
520       }
521       FvDevicePath = NextDevicePathNode (FvDevicePath);
522     }
523   }
524   //
525   // If we didn't decide on a volume label, set a fallback one
526   //
527   if (Instance->VolumeLabel == NULL) {
528     Instance->VolumeLabel = AllocateCopyPool (
529                               sizeof (FVFS_FALLBACK_VOLUME_LABEL),
530                               FVFS_FALLBACK_VOLUME_LABEL
531                               );
532   }
533 
534   return EFI_SUCCESS;
535 }
536 
537 /**
538   Stop this driver on ControllerHandle by removing SimpleFileSystem protocol and closing
539   the FV protocol on ControllerHandle.
540 
541   @param  DriverBinding     Protocol instance pointer.
542   @param  ControllerHandle  Handle of device to stop driver on
543   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
544                             children is zero stop the entire bus driver.
545   @param  ChildHandleBuffer List of Child Handles to Stop.
546 
547   @retval EFI_SUCCESS       This driver is removed ControllerHandle
548   @retval other             This driver was not removed from this device
549 
550 **/
551 EFI_STATUS
552 EFIAPI
FvSimpleFileSystemDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * DriverBinding,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)553 FvSimpleFileSystemDriverStop (
554   IN  EFI_DRIVER_BINDING_PROTOCOL       *DriverBinding,
555   IN  EFI_HANDLE                        ControllerHandle,
556   IN  UINTN                             NumberOfChildren,
557   IN  EFI_HANDLE                        *ChildHandleBuffer OPTIONAL
558   )
559 {
560   EFI_STATUS                       Status;
561   FV_FILESYSTEM_INSTANCE           *Instance;
562   FV_FILESYSTEM_FILE_INFO          *FvFileInfo;
563   LIST_ENTRY                       *Entry;
564   LIST_ENTRY                       *DelEntry;
565   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *SimpleFile;
566 
567   Status = gBS->OpenProtocol (
568                   ControllerHandle,
569                   &gEfiSimpleFileSystemProtocolGuid,
570                   (VOID **) &SimpleFile,
571                   DriverBinding->DriverBindingHandle,
572                   ControllerHandle,
573                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
574                   );
575   if (EFI_ERROR (Status)) {
576     return Status;
577   }
578 
579   Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (SimpleFile);
580 
581   if (IsListEmpty (&Instance->FileHead) == FALSE) {
582     //
583     // Not all opened files are closed
584     //
585     return EFI_DEVICE_ERROR;
586   }
587 
588   //
589   // Close and uninstall protocols.
590   //
591   Status = gBS->CloseProtocol (
592                    ControllerHandle,
593                    &gEfiFirmwareVolume2ProtocolGuid,
594                    gImageHandle,
595                    ControllerHandle
596                    );
597   ASSERT_EFI_ERROR (Status);
598 
599   Status = gBS->UninstallProtocolInterface (
600                   ControllerHandle,
601                   &gEfiSimpleFileSystemProtocolGuid,
602                   &Instance->SimpleFs
603                   );
604   ASSERT_EFI_ERROR (Status);
605 
606   //
607   // Free file structures
608   //
609   if (!IsListEmpty (&Instance->FileInfoHead)) {
610     //
611     // Free the Subtask list.
612     //
613     for(Entry = Instance->FileInfoHead.ForwardLink;
614         Entry != (&Instance->FileInfoHead);
615        ) {
616       DelEntry   = Entry;
617       Entry      = Entry->ForwardLink;
618       FvFileInfo = FVFS_FILE_INFO_FROM_LINK (DelEntry);
619 
620       RemoveEntryList (DelEntry);
621       FreePool (FvFileInfo);
622     }
623   }
624 
625   if (Instance->Root != NULL) {
626     //
627     // Root->Name is statically allocated, no need to free.
628     //
629     if (Instance->Root->FvFileInfo != NULL) {
630       FreePool (Instance->Root->FvFileInfo);
631     }
632     FreePool (Instance->Root);
633   }
634 
635   //
636   // Free Instance
637   //
638   if (Instance->VolumeLabel != NULL) {
639     FreePool (Instance->VolumeLabel);
640   }
641   FreePool (Instance);
642 
643   return EFI_SUCCESS;
644 }
645 
646 /**
647   The user Entry Point for module FvSimpleFileSystem. The user code starts with this function.
648 
649   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
650   @param[in] SystemTable    A pointer to the EFI System Table.
651 
652   @retval EFI_SUCCESS       The entry point is executed successfully.
653   @retval other             Some error occurs when executing this entry point.
654 
655 **/
656 EFI_STATUS
657 EFIAPI
FvSimpleFileSystemEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)658 FvSimpleFileSystemEntryPoint (
659   IN EFI_HANDLE               ImageHandle,
660   IN EFI_SYSTEM_TABLE         *SystemTable
661   )
662 {
663   EFI_STATUS Status;
664 
665   //
666   // Install driver model protocol(s).
667   //
668   Status = EfiLibInstallDriverBindingComponentName2 (
669              ImageHandle,
670              SystemTable,
671              &mDriverBinding,
672              ImageHandle,
673              &gFvSimpleFileSystemComponentName,
674              &gFvSimpleFileSystemComponentName2
675              );
676   ASSERT_EFI_ERROR (Status);
677 
678   return Status;
679 }
680