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