Revision: 19297
          http://sourceforge.net/p/edk2/code/19297
Author:   ydong10
Date:     2015-12-16 03:21:44 +0000 (Wed, 16 Dec 2015)
Log Message:
-----------
MdeModulePkg FileExplorerLib: Change file format which has mixed file format.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Eric Dong <[email protected]>
Reviewed-by: Liming Gao <[email protected]>

Modified Paths:
--------------
    trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
    trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorer.h
    trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
    trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorerVfr.vfr
    trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FormGuid.h

Modified: trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
===================================================================
--- trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c      
2015-12-16 03:20:21 UTC (rev 19296)
+++ trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c      
2015-12-16 03:21:44 UTC (rev 19297)
@@ -1,1507 +1,1507 @@
-/** @file
-File explorer related functions.
-
-Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials are licensed and made available 
under
-the terms and conditions of the BSD License that accompanies this distribution.
-The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php.
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-
-#include "FileExplorer.h"
-
-EFI_GUID FileExplorerGuid       = EFI_FILE_EXPLORE_FORMSET_GUID;
-
-///
-/// File system selection menu
-///
-MENU_OPTION      mFsOptionMenu = {
-  MENU_OPTION_SIGNATURE,
-  {NULL},
-  0,
-  FALSE
-};
-
-FILE_EXPLORER_CALLBACK_DATA  gFileExplorerPrivate = {
-  FILE_EXPLORER_CALLBACK_DATA_SIGNATURE,
-  NULL,
-  NULL,
-  {
-    LibExtractConfig,
-    LibRouteConfig,
-    LibCallback
-  },
-  NULL,
-  &mFsOptionMenu,
-  0
-};
-
-HII_VENDOR_DEVICE_PATH  *gHiiVendorDevicePath;
-
-HII_VENDOR_DEVICE_PATH  FeHiiVendorDevicePath = {
-  {
-    {
-      HARDWARE_DEVICE_PATH,
-      HW_VENDOR_DP,
-      {
-        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
-        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
-      }
-    },
-    //
-    // Will be replace with gEfiCallerIdGuid in code.
-    //
-    { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
-  },
-  {
-    END_DEVICE_PATH_TYPE,
-    END_ENTIRE_DEVICE_PATH_SUBTYPE,
-    { 
-      (UINT8) (END_DEVICE_PATH_LENGTH),
-      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
-    }
-  }
-};
-
-VOID                *mLibStartOpCodeHandle = NULL;
-VOID                *mLibEndOpCodeHandle = NULL;
-EFI_IFR_GUID_LABEL  *mLibStartLabel = NULL;
-EFI_IFR_GUID_LABEL  *mLibEndLabel = NULL;
-
-/**
-  This function allows a caller to extract the current configuration for one
-  or more named elements from the target driver.
-
-
-  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param Request         A null-terminated Unicode string in <ConfigRequest> 
format.
-  @param Progress        On return, points to a character in the Request 
string.
-                         Points to the string's null terminator if request was 
successful.
-                         Points to the most recent '&' before the first 
failing name/value
-                         pair (or the beginning of the string if the failure 
is in the
-                         first name/value pair) if the request was not 
successful.
-  @param Results         A null-terminated Unicode string in <ConfigAltResp> 
format which
-                         has all values filled in for the names in the Request 
string.
-                         String to be allocated by the called function.
-
-  @retval  EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
-  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in 
this driver.
-
-**/
-EFI_STATUS
-EFIAPI
-LibExtractConfig (
-  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
-  IN  CONST EFI_STRING                       Request,
-  OUT EFI_STRING                             *Progress,
-  OUT EFI_STRING                             *Results
-  )
-{
-  if (Progress == NULL || Results == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  *Progress = Request;
-  return EFI_NOT_FOUND;
-}
-
-/**
-  This function processes the results of changes in configuration.
-
-
-  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param Configuration   A null-terminated Unicode string in <ConfigResp> 
format.
-  @param Progress        A pointer to a string filled in with the offset of 
the most
-                         recent '&' before the first failing name/value pair 
(or the
-                         beginning of the string if the failure is in the first
-                         name/value pair) or the terminating NULL if all was 
successful.
-
-  @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
-  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in 
this driver.
-
-**/
-EFI_STATUS
-EFIAPI
-LibRouteConfig (
-  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
-  IN  CONST EFI_STRING                       Configuration,
-  OUT EFI_STRING                             *Progress
-  )
-{
-  if (Configuration == NULL || Progress == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  *Progress = Configuration;
-  return EFI_NOT_FOUND;
-}
-
-/**
-  This function processes the results of changes in configuration.
-  When user select a interactive opcode, this callback will be triggered.
-  Based on the Question(QuestionId) that triggers the callback, the 
corresponding
-  actions is performed. It handles:
-
-  1) Process the axtra action or exit file explorer when user select one file .
-  2) update of file content if a dir is selected.
-
-  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param Action          Specifies the type of action taken by the browser.
-  @param QuestionId      A unique value which is sent to the original 
exporting driver
-                         so that it can identify the type of data to expect.
-  @param Type            The type of value for the question.
-  @param Value           A pointer to the data being sent to the original 
exporting driver.
-  @param ActionRequest   On return, points to the action requested by the 
callback function.
-
-  @retval  EFI_SUCCESS           The callback successfully handled the action.
-  @retval  other error           Error occur when parse one directory.
-**/
-EFI_STATUS
-EFIAPI
-LibCallback (
-  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
-  IN  EFI_BROWSER_ACTION                     Action,
-  IN  EFI_QUESTION_ID                        QuestionId,
-  IN  UINT8                                  Type,
-  IN  EFI_IFR_TYPE_VALUE                     *Value,
-  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
-  )
-{
-  EFI_STATUS    Status;
-  BOOLEAN       NeedExit;
-
-  NeedExit = TRUE;
-  
-  if (Action != EFI_BROWSER_ACTION_CHANGING && Action != 
EFI_BROWSER_ACTION_CHANGED) {
-    //
-    // Do nothing for other UEFI Action. Only do call back when data is 
changed.
-    //
-    return EFI_UNSUPPORTED;
-  }
-
-  *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
-
-  if (Action == EFI_BROWSER_ACTION_CHANGED) {
-    if ((Value == NULL) || (ActionRequest == NULL)) {
-      return EFI_INVALID_PARAMETER;
-    }
-    
-    if (QuestionId >= FILE_OPTION_OFFSET) {
-      LibGetDevicePath(QuestionId);
-
-      //
-      // Process the extra action.
-      //
-      if (gFileExplorerPrivate.ChooseHandler != NULL) {
-        NeedExit = gFileExplorerPrivate.ChooseHandler 
(gFileExplorerPrivate.RetDevicePath);
-      }
-
-      if (NeedExit) {
-        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
-      }
-    }
-  } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
-    if (Value == NULL) {
-      return EFI_INVALID_PARAMETER;
-    }
-    
-    if (QuestionId >= FILE_OPTION_OFFSET) {
-      Status = LibUpdateFileExplorer (QuestionId);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Create a menu entry by given menu type.
-
-  @retval NULL           If failed to create the menu.
-  @return the new menu entry.
-
-**/
-MENU_ENTRY *
-LibCreateMenuEntry (
-  VOID
-  )
-{
-  MENU_ENTRY *MenuEntry;
-
-  //
-  // Create new menu entry
-  //
-  MenuEntry = AllocateZeroPool (sizeof (MENU_ENTRY));
-  if (MenuEntry == NULL) {
-    return NULL;
-  }
-
-  MenuEntry->VariableContext = AllocateZeroPool (sizeof (FILE_CONTEXT));
-  if (MenuEntry->VariableContext == NULL) {
-    FreePool (MenuEntry);
-    return NULL;
-  }
-
-  MenuEntry->Signature        = MENU_ENTRY_SIGNATURE;
-  return MenuEntry;
-}
-
-
-/**
-  Get the Menu Entry from the list in Menu Entry List.
-
-  If MenuNumber is great or equal to the number of Menu
-  Entry in the list, then ASSERT.
-
-  @param MenuOption      The Menu Entry List to read the menu entry.
-  @param MenuNumber      The index of Menu Entry.
-
-  @return The Menu Entry.
-
-**/
-MENU_ENTRY *
-LibGetMenuEntry (
-  MENU_OPTION         *MenuOption,
-  UINTN               MenuNumber
-  )
-{
-  MENU_ENTRY      *NewMenuEntry;
-  UINTN           Index;
-  LIST_ENTRY      *List;
-
-  ASSERT (MenuNumber < MenuOption->MenuNumber);
-
-  List = MenuOption->Head.ForwardLink;
-  for (Index = 0; Index < MenuNumber; Index++) {
-    List = List->ForwardLink;
-  }
-
-  NewMenuEntry = CR (List, MENU_ENTRY, Link, MENU_ENTRY_SIGNATURE);
-
-  return NewMenuEntry;
-}
-
-/**
-  Free up all resource allocated for a BM_MENU_ENTRY.
-
-  @param MenuEntry   A pointer to BM_MENU_ENTRY.
-
-**/
-VOID
-LibDestroyMenuEntry (
-  MENU_ENTRY         *MenuEntry
-  )
-{
-  FILE_CONTEXT           *FileContext;
-
-  FileContext = (FILE_CONTEXT *) MenuEntry->VariableContext;
-
-  if (!FileContext->IsRoot) {
-    FreePool (FileContext->DevicePath);
-  } else {
-    if (FileContext->FileHandle != NULL) {
-      FileContext->FileHandle->Close (FileContext->FileHandle);
-    }
-  }
-
-  if (FileContext->FileName != NULL) {
-    FreePool (FileContext->FileName);
-  }
-
-  FreePool (FileContext);
-
-  FreePool (MenuEntry->DisplayString);
-  if (MenuEntry->HelpString != NULL) {
-    FreePool (MenuEntry->HelpString);
-  }
-
-  FreePool (MenuEntry);
-}
-
-
-/**
-  Free resources allocated in Allocate Rountine.
-
-  @param FreeMenu        Menu to be freed
-**/
-VOID
-LibFreeMenu (
-  MENU_OPTION        *FreeMenu
-  )
-{
-  MENU_ENTRY *MenuEntry;
-  while (!IsListEmpty (&FreeMenu->Head)) {
-    MenuEntry = CR (
-                  FreeMenu->Head.ForwardLink,
-                  MENU_ENTRY,
-                  Link,
-                  MENU_ENTRY_SIGNATURE
-                  );
-    RemoveEntryList (&MenuEntry->Link);
-    LibDestroyMenuEntry (MenuEntry);
-  }
-  FreeMenu->MenuNumber = 0;
-}
-
-/**
-
-  Function opens and returns a file handle to the root directory of a volume.
-
-  @param DeviceHandle    A handle for a device
-
-  @return A valid file handle or NULL is returned
-
-**/
-EFI_FILE_HANDLE
-LibOpenRoot (
-  IN EFI_HANDLE                   DeviceHandle
-  )
-{
-  EFI_STATUS                      Status;
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
-  EFI_FILE_HANDLE                 File;
-
-  File = NULL;
-
-  //
-  // File the file system interface to the device
-  //
-  Status = gBS->HandleProtocol (
-                  DeviceHandle,
-                  &gEfiSimpleFileSystemProtocolGuid,
-                  (VOID *) &Volume
-                  );
-
-  //
-  // Open the root directory of the volume
-  //
-  if (!EFI_ERROR (Status)) {
-    Status = Volume->OpenVolume (
-                      Volume,
-                      &File
-                      );
-  }
-  //
-  // Done
-  //
-  return EFI_ERROR (Status) ? NULL : File;
-}
-
-/**
-  This function converts an input device structure to a Unicode string.
-
-  @param DevPath                  A pointer to the device path structure.
-
-  @return A new allocated Unicode string that represents the device path.
-
-**/
-CHAR16 *
-LibDevicePathToStr (
-  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
-  )
-{
-  EFI_STATUS                       Status;
-  CHAR16                           *ToText;
-  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
-
-  if (DevPath == NULL) {
-    return NULL;
-  }
-
-  Status = gBS->LocateProtocol (
-                  &gEfiDevicePathToTextProtocolGuid,
-                  NULL,
-                  (VOID **) &DevPathToText
-                  );
-  ASSERT_EFI_ERROR (Status);
-  ToText = DevPathToText->ConvertDevicePathToText (
-                            DevPath,
-                            FALSE,
-                            TRUE
-                            );
-  ASSERT (ToText != NULL);
-
-  return ToText;
-}
-
-/**
-  Duplicate a string.
-
-  @param Src             The source.
-
-  @return A new string which is duplicated copy of the source.
-  @retval NULL If there is not enough memory.
-
-**/
-CHAR16 *
-LibStrDuplicate (
-  IN CHAR16   *Src
-  )
-{
-  CHAR16  *Dest;
-  UINTN   Size;
-
-  Size  = StrSize (Src);
-  Dest  = AllocateZeroPool (Size);
-  ASSERT (Dest != NULL);
-  if (Dest != NULL) {
-    CopyMem (Dest, Src, Size);
-  }
-
-  return Dest;
-}
-
-/**
-
-  Function gets the file information from an open file descriptor, and stores 
it
-  in a buffer allocated from pool.
-
-  @param FHand           File Handle.
-  @param InfoType        Info type need to get.
-
-  @retval                A pointer to a buffer with file information or NULL 
is returned
-
-**/
-VOID *
-LibFileInfo (
-  IN EFI_FILE_HANDLE      FHand,
-  IN EFI_GUID             *InfoType
-  )
-{
-  EFI_STATUS    Status;
-  EFI_FILE_INFO *Buffer;
-  UINTN         BufferSize;
-
-  Buffer      = NULL;
-  BufferSize  = 0;
-  
-  Status = FHand->GetInfo (
-                    FHand,
-                    InfoType,
-                    &BufferSize,
-                    Buffer
-                    );
-  if (Status == EFI_BUFFER_TOO_SMALL) {
-    Buffer = AllocatePool (BufferSize);
-    ASSERT (Buffer != NULL);
-  }
-
-  Status = FHand->GetInfo (
-                    FHand,
-                    InfoType,
-                    &BufferSize,
-                    Buffer
-                    );
-
-  return Buffer;
-}
-
-/**
-
-  Get file type base on the file name.
-  Just cut the file name, from the ".". eg ".efi"
-
-  @param FileName  File need to be checked.
-
-  @retval the file type string.
-
-**/
-CHAR16*
-LibGetTypeFromName (
-  IN CHAR16   *FileName
-  )
-{
-  UINTN    Index;
-
-  Index = StrLen (FileName) - 1;
-  while ((FileName[Index] != L'.') && (Index != 0)) {
-    Index--;
-  }
-
-  return Index == 0 ? NULL : &FileName[Index];
-}
-
-/**
-  Converts the unicode character of the string from uppercase to lowercase.
-  This is a internal function.
-
-  @param ConfigString  String to be converted
-
-**/
-VOID
-LibToLowerString (
-  IN CHAR16  *String
-  )
-{
-  CHAR16      *TmpStr;
-
-  for (TmpStr = String; *TmpStr != L'\0'; TmpStr++) {
-    if (*TmpStr >= L'A' && *TmpStr <= L'Z') {
-      *TmpStr = (CHAR16) (*TmpStr - L'A' + L'a');
-    }
-  }
-}
-
-/**
-
-  Check whether current FileName point to a valid
-  Efi Image File.
-
-  @param FileName  File need to be checked.
-
-  @retval TRUE  Is Efi Image
-  @retval FALSE Not a valid Efi Image
-
-**/
-BOOLEAN
-LibIsSupportedFileType (
-  IN UINT16  *FileName
-  )
-{
-  CHAR16     *InputFileType;
-  CHAR16     *TmpStr;
-  BOOLEAN    IsSupported;
-
-  if (gFileExplorerPrivate.FileType == NULL) {
-    return TRUE;
-  }
-
-  InputFileType = LibGetTypeFromName (FileName);
-  //
-  // If the file not has *.* style, always return TRUE.
-  //
-  if (InputFileType == NULL) {
-    return TRUE;
-  }
-
-  TmpStr = AllocateCopyPool (StrSize (InputFileType), InputFileType);
-  LibToLowerString(TmpStr);
-
-  IsSupported = (StrStr (gFileExplorerPrivate.FileType, TmpStr) == NULL ? 
FALSE : TRUE);
-
-  FreePool (TmpStr);
-  return IsSupported;
-}
-
-/**
-
-  Append file name to existing file name.
-
-  @param Str1  The existing file name
-  @param Str2  The file name to be appended
-
-  @return Allocate a new string to hold the appended result.
-          Caller is responsible to free the returned string.
-
-**/
-CHAR16 *
-LibAppendFileName (
-  IN  CHAR16  *Str1,
-  IN  CHAR16  *Str2
-  )
-{
-  UINTN   Size1;
-  UINTN   Size2;
-  UINTN   MaxLen;
-  CHAR16  *Str;
-  CHAR16  *TmpStr;
-  CHAR16  *Ptr;
-  CHAR16  *LastSlash;
-
-  Size1 = StrSize (Str1);
-  Size2 = StrSize (Str2);
-  MaxLen = (Size1 + Size2 + sizeof (CHAR16))/ sizeof (CHAR16);
-  Str   = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));
-  ASSERT (Str != NULL);
-
-  TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); 
-  ASSERT (TmpStr != NULL);
-
-  StrCpyS (Str, MaxLen, Str1);
-  if (!((*Str == '\\') && (*(Str + 1) == 0))) {
-    StrCatS (Str, MaxLen, L"\\");
-  }
-
-  StrCatS (Str, MaxLen, Str2);
-
-  Ptr       = Str;
-  LastSlash = Str;
-  while (*Ptr != 0) {
-    if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) 
== L'\\') {
-      //
-      // Convert "\Name\..\" to "\"
-      // DO NOT convert the .. if it is at the end of the string. This will
-      // break the .. behavior in changing directories.
-      //
-
-      //
-      // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of 
two strings 
-      // that overlap.
-      //
-      StrCpyS (TmpStr, MaxLen, Ptr + 3);
-      StrCpyS (LastSlash, MaxLen - (UINTN) (LastSlash - Str), TmpStr);
-      Ptr = LastSlash;
-    } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {
-      //
-      // Convert a "\.\" to a "\"
-      //
-
-      //
-      // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of 
two strings 
-      // that overlap.
-      //
-      StrCpyS (TmpStr, MaxLen, Ptr + 2);
-      StrCpyS (Ptr, MaxLen - (UINTN) (Ptr - Str), TmpStr);
-      Ptr = LastSlash;
-    } else if (*Ptr == '\\') {
-      LastSlash = Ptr;
-    }
-
-    Ptr++;
-  }
-
-  FreePool (TmpStr);
-  
-  return Str;
-}
-
-/**
-  This function build the FsOptionMenu list which records all
-  available file system in the system. They includes all instances
-  of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM.
-
-
-  @retval  EFI_SUCCESS             Success find the file system
-  @retval  EFI_OUT_OF_RESOURCES    Can not create menu entry
-
-**/
-EFI_STATUS
-LibFindFileSystem (
-  VOID
-  )
-{
-  UINTN                        NoSimpleFsHandles;
-  UINTN                        NoLoadFileHandles;
-  EFI_HANDLE                   *SimpleFsHandle;
-  EFI_HANDLE                   *LoadFileHandle;
-  UINT16                       *VolumeLabel;
-  UINTN                        Index;
-  EFI_STATUS                   Status;
-  MENU_ENTRY                   *MenuEntry;
-  FILE_CONTEXT                 *FileContext;
-  UINTN                        OptionNumber;
-  EFI_FILE_SYSTEM_VOLUME_LABEL *Info;
-
-  NoSimpleFsHandles = 0;
-  NoLoadFileHandles = 0;
-  OptionNumber      = 0;
-
-  //
-  // Locate Handles that support Simple File System protocol
-  //
-  Status = gBS->LocateHandleBuffer (
-                  ByProtocol,
-                  &gEfiSimpleFileSystemProtocolGuid,
-                  NULL,
-                  &NoSimpleFsHandles,
-                  &SimpleFsHandle
-                  );
-  if (!EFI_ERROR (Status)) {
-    //
-    // Find all the instances of the File System prototocol
-    //
-    for (Index = 0; Index < NoSimpleFsHandles; Index++) {
-      //
-      // Allocate pool for this load option
-      //
-      MenuEntry = LibCreateMenuEntry ();
-      if (NULL == MenuEntry) {
-        FreePool (SimpleFsHandle);
-        return EFI_OUT_OF_RESOURCES;
-      }
-
-      FileContext = (FILE_CONTEXT *) MenuEntry->VariableContext;
-      FileContext->DeviceHandle = SimpleFsHandle[Index];
-      FileContext->FileHandle = LibOpenRoot (FileContext->DeviceHandle);
-      if (FileContext->FileHandle == NULL) {
-        LibDestroyMenuEntry (MenuEntry);
-        continue;
-      }
-
-      MenuEntry->HelpString = LibDevicePathToStr (DevicePathFromHandle 
(FileContext->DeviceHandle));
-      FileContext->FileName = LibStrDuplicate (L"\\");
-      FileContext->DevicePath = FileDevicePath (FileContext->DeviceHandle, 
FileContext->FileName);
-      FileContext->IsDir = TRUE;
-      FileContext->IsRoot = TRUE;
-
-      //
-      // Get current file system's Volume Label
-      //
-      Info = (EFI_FILE_SYSTEM_VOLUME_LABEL *) LibFileInfo 
(FileContext->FileHandle, &gEfiFileSystemVolumeLabelInfoIdGuid);
-      if (Info == NULL) {
-        VolumeLabel = L"NO FILE SYSTEM INFO";
-      } else {
-        if (Info->VolumeLabel == NULL) {
-          VolumeLabel = L"NULL VOLUME LABEL";
-        } else {
-          VolumeLabel = Info->VolumeLabel;
-          if (*VolumeLabel == 0x0000) {
-            VolumeLabel = L"NO VOLUME LABEL";
-          }
-        }
-      }
-      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);
-      ASSERT (MenuEntry->DisplayString != NULL);
-      UnicodeSPrint (
-        MenuEntry->DisplayString,
-        MAX_CHAR,
-        L"%s, [%s]",
-        VolumeLabel,
-        MenuEntry->HelpString
-        );
-         MenuEntry->DisplayStringToken = HiiSetString (
-                                             gFileExplorerPrivate.FeHiiHandle,
-                                             0,
-                                             MenuEntry->DisplayString,
-                                             NULL
-                                             );
-      FreePool (Info);
-
-      OptionNumber++;
-      InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, 
&MenuEntry->Link);
-    }
-  }
-
-  if (NoSimpleFsHandles != 0) {
-    FreePool (SimpleFsHandle);
-  }
-
-  //
-  // Searching for handles that support Load File protocol
-  //
-  Status = gBS->LocateHandleBuffer (
-                  ByProtocol,
-                  &gEfiLoadFileProtocolGuid,
-                  NULL,
-                  &NoLoadFileHandles,
-                  &LoadFileHandle
-                  );
-
-  if (!EFI_ERROR (Status)) {
-    for (Index = 0; Index < NoLoadFileHandles; Index++) {
-      MenuEntry = LibCreateMenuEntry ();
-      if (NULL == MenuEntry) {
-        FreePool (LoadFileHandle);
-        return EFI_OUT_OF_RESOURCES;
-      }
-
-      FileContext = (FILE_CONTEXT *) MenuEntry->VariableContext;
-      FileContext->DeviceHandle = LoadFileHandle[Index];
-      FileContext->IsRoot = TRUE;
-
-      FileContext->DevicePath = DevicePathFromHandle 
(FileContext->DeviceHandle);
-      FileContext->FileName = LibDevicePathToStr (FileContext->DevicePath);
-
-      MenuEntry->HelpString = LibDevicePathToStr (FileContext->DevicePath);
-      MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);
-      ASSERT (MenuEntry->DisplayString != NULL);
-      UnicodeSPrint (
-        MenuEntry->DisplayString,
-        MAX_CHAR,
-        L"Load File [%s]",
-        MenuEntry->HelpString
-        );
-      MenuEntry->DisplayStringToken = HiiSetString (
-                                           gFileExplorerPrivate.FeHiiHandle,
-                                           0,
-                                           MenuEntry->DisplayString,
-                                           NULL
-                                           );
-
-      OptionNumber++;
-      InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, 
&MenuEntry->Link);
-    }
-  }
-
-  if (NoLoadFileHandles != 0) {
-    FreePool (LoadFileHandle);
-  }
-
-  gFileExplorerPrivate.FsOptionMenu->MenuNumber = OptionNumber;
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Find the file handle from the input menu info.
-  
-  @param  MenuEntry        Input Menu info.
-  @param  RetFileHandle    Return the file handle for the input device path.
-  
-  @retval EFI_SUCESS       Find the file handle success.
-  @retval Other            Find the file handle failure.
-**/
-EFI_STATUS
-LibGetFileHandleFromMenu (
-  IN  MENU_ENTRY                *MenuEntry,  
-  OUT EFI_FILE_HANDLE           *RetFileHandle
-  )
-{
-  EFI_FILE_HANDLE Dir;
-  EFI_FILE_HANDLE NewDir;
-  FILE_CONTEXT    *FileContext;
-  EFI_STATUS      Status;
-
-  FileContext   = (FILE_CONTEXT *) MenuEntry->VariableContext;
-  Dir           = FileContext->FileHandle;
-
-  //
-  // Open current directory to get files from it
-  //
-  Status = Dir->Open (
-                  Dir,
-                  &NewDir,
-                  FileContext->FileName,
-                  EFI_FILE_READ_ONLY,
-                  0
-                  );
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  if (!FileContext->IsRoot) {
-    Dir->Close (Dir);
-  }
-
-  *RetFileHandle = NewDir;
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Find the file handle from the input device path info.
-  
-  @param  RootDirectory    Device path info.
-  @param  RetFileHandle    Return the file handle for the input device path.
-  @param  ParentFileName   Parent file name.
-  @param  DeviceHandle     Driver handle for this partition.
-  
-  @retval EFI_SUCESS       Find the file handle success.
-  @retval Other            Find the file handle failure.
-**/
-EFI_STATUS
-LibGetFileHandleFromDevicePath (
-  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDirectory,  
-  OUT EFI_FILE_HANDLE           *RetFileHandle,
-  OUT UINT16                    **ParentFileName,
-  OUT EFI_HANDLE                *DeviceHandle
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL          *DevicePathNode;
-  EFI_DEVICE_PATH_PROTOCOL          *TempDevicePathNode;
-  EFI_STATUS                        Status;
-  EFI_HANDLE                        Handle;
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;
-  EFI_FILE_HANDLE                   FileHandle;
-  EFI_FILE_HANDLE                   LastHandle;
-  CHAR16                            *TempPath;
-
-  *ParentFileName = NULL;
-
-  //
-  // Attempt to access the file via a file system interface
-  //
-  DevicePathNode = RootDirectory;
-  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, 
&DevicePathNode, &Handle);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  
-  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, 
(VOID**)&Volume);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  
-  //
-  // Open the Volume to get the File System handle
-  //
-  Status = Volume->OpenVolume (Volume, &FileHandle);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  *DeviceHandle = Handle;
-
-  if (IsDevicePathEnd(DevicePathNode)) {
-    *ParentFileName = AllocateCopyPool (StrSize (L"\\"), L"\\");
-    *RetFileHandle = FileHandle;
-    return EFI_SUCCESS;
-  }
-  
-  //
-  // Duplicate the device path to avoid the access to unaligned device path 
node.
-  // Because the device path consists of one or more FILE PATH MEDIA DEVICE 
PATH
-  // nodes, It assures the fields in device path nodes are 2 byte aligned.
-  //
-  TempDevicePathNode = DuplicateDevicePath (DevicePathNode);
-  if (TempDevicePathNode == NULL) {
-
-    //
-    // Setting Status to an EFI_ERROR value will cause the rest of
-    // the file system support below to be skipped.
-    //
-    Status = EFI_OUT_OF_RESOURCES;
-  }
-        
-  //
-  // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
-  // directory information and filename can be seperate. The goal is to inch
-  // our way down each device path node and close the previous node
-  //
-  DevicePathNode = TempDevicePathNode;
-  while (!EFI_ERROR (Status) && !IsDevicePathEnd (DevicePathNode)) {
-    if (DevicePathType (DevicePathNode) != MEDIA_DEVICE_PATH ||
-        DevicePathSubType (DevicePathNode) != MEDIA_FILEPATH_DP) {
-      Status = EFI_UNSUPPORTED;
-      goto Done;
-    }
-
-    LastHandle = FileHandle;
-    FileHandle = NULL;
-
-    Status = LastHandle->Open (
-                          LastHandle,
-                          &FileHandle,
-                          ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName,
-                          EFI_FILE_MODE_READ,
-                          0
-                          );
-    if (*ParentFileName == NULL) {
-      *ParentFileName = AllocateCopyPool (StrSize (((FILEPATH_DEVICE_PATH *) 
DevicePathNode)->PathName), ((FILEPATH_DEVICE_PATH *) 
DevicePathNode)->PathName);
-    } else {
-      TempPath = LibAppendFileName (*ParentFileName, ((FILEPATH_DEVICE_PATH *) 
DevicePathNode)->PathName);
-      FreePool (*ParentFileName);
-      *ParentFileName = TempPath;
-    }
-
-    //
-    // Close the previous node
-    //
-    LastHandle->Close (LastHandle);
-
-    DevicePathNode = NextDevicePathNode (DevicePathNode);
-  }
-
-  if (EFI_ERROR (Status)) {
-    goto Done;
-  }
-
-  *RetFileHandle = FileHandle;
-
-  Status = EFI_SUCCESS;
-
-Done:
-  if (TempDevicePathNode != NULL) {
-    FreePool (TempDevicePathNode);
-  }
-
-  if ((FileHandle != NULL) && (EFI_ERROR (Status))) {
-    FileHandle->Close (FileHandle);
-  }
-
-  return Status;
-}
-
-/**
-  Find files under current directory.
-  
-  All files and sub-directories in current directory
-  will be stored in DirectoryMenu for future use.
-
-  @param FileHandle    Parent file handle. 
-  @param FileName      Parent file name.
-  @param DeviceHandle  Driver handle for this partition.
-
-  @retval EFI_SUCCESS         Get files from current dir successfully.
-  @return Other value if can't get files from current dir.
-
-**/
-EFI_STATUS
-LibFindFiles (
-  IN EFI_FILE_HANDLE           FileHandle,
-  IN UINT16                    *FileName,
-  IN EFI_HANDLE                DeviceHandle
-  )
-{
-  EFI_FILE_INFO   *DirInfo;
-  UINTN           BufferSize;
-  UINTN           DirBufferSize;
-  MENU_ENTRY      *NewMenuEntry;
-  FILE_CONTEXT    *NewFileContext;
-  UINTN           Pass;
-  EFI_STATUS      Status;
-  UINTN           OptionNumber;
-
-  OptionNumber = 0;
-
-  DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;
-  DirInfo       = AllocateZeroPool (DirBufferSize);
-  if (DirInfo == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  //
-  // Get all files in current directory
-  // Pass 1 to get Directories
-  // Pass 2 to get files that are EFI images
-  //
-  for (Pass = 1; Pass <= 2; Pass++) {
-    FileHandle->SetPosition (FileHandle, 0);
-    for (;;) {
-      BufferSize  = DirBufferSize;
-      Status      = FileHandle->Read (FileHandle, &BufferSize, DirInfo);
-      if (EFI_ERROR (Status) || BufferSize == 0) {
-        break;
-      }
-
-      if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) ||
-          ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1)
-          ) {
-        //
-        // Pass 1 is for Directories
-        // Pass 2 is for file names
-        //
-        continue;
-      }
-
-      if (!((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 || 
LibIsSupportedFileType (DirInfo->FileName))) {
-        //
-        // Slip file unless it is a directory entry or a .EFI file
-        //
-        continue;
-      }
-
-      NewMenuEntry = LibCreateMenuEntry ();
-      if (NULL == NewMenuEntry) {
-        return EFI_OUT_OF_RESOURCES;
-      }
-
-      NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
-      NewFileContext->DeviceHandle = DeviceHandle;
-      NewFileContext->FileName = LibAppendFileName (FileName, 
DirInfo->FileName);
-      NewFileContext->FileHandle = FileHandle;
-      NewFileContext->DevicePath = FileDevicePath 
(NewFileContext->DeviceHandle, NewFileContext->FileName);
-      NewMenuEntry->HelpString = NULL;
-      NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & 
EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);
-
-      if (NewFileContext->IsDir) {
-        BufferSize = StrLen (DirInfo->FileName) * 2 + 6;
-        NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);
-        UnicodeSPrint (
-          NewMenuEntry->DisplayString,
-          BufferSize,
-          L"<%s>",
-          DirInfo->FileName
-          );
-      } else {
-        NewMenuEntry->DisplayString = LibStrDuplicate (DirInfo->FileName);
-      }
-      
-      NewMenuEntry->DisplayStringToken = HiiSetString (
-                                           gFileExplorerPrivate.FeHiiHandle,
-                                           0,
-                                           NewMenuEntry->DisplayString,
-                                           NULL
-                                           );
-
-      NewFileContext->IsRoot            = FALSE;
-
-      OptionNumber++;
-      InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, 
&NewMenuEntry->Link);
-    }
-  }
-
-  gFileExplorerPrivate.FsOptionMenu->MenuNumber = OptionNumber;
-
-  FreePool (DirInfo);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Refresh the global UpdateData structure.
-
-**/
-VOID
-LibRefreshUpdateData (
-  VOID
-  )
-{
-  //
-  // Free current updated date
-  //
-  if (mLibStartOpCodeHandle != NULL) {
-    HiiFreeOpCodeHandle (mLibStartOpCodeHandle);
-  }
-  if (mLibEndOpCodeHandle != NULL) {
-    HiiFreeOpCodeHandle (mLibEndOpCodeHandle);
-  }
-
-  //
-  // Create new OpCode Handle
-  //
-  mLibStartOpCodeHandle = HiiAllocateOpCodeHandle ();
-  mLibEndOpCodeHandle = HiiAllocateOpCodeHandle ();
-
-  //
-  // Create Hii Extend Label OpCode as the start opcode
-  //
-  mLibStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
-                                         mLibStartOpCodeHandle,
-                                         &gEfiIfrTianoGuid,
-                                         NULL,
-                                         sizeof (EFI_IFR_GUID_LABEL)
-                                         );
-  mLibStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
-
-  mLibStartLabel->Number = FORM_FILE_EXPLORER_ID;
-
-  //
-  // Create Hii Extend Label OpCode as the start opcode
-  //
-  mLibEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
-                                         mLibEndOpCodeHandle,
-                                         &gEfiIfrTianoGuid,
-                                         NULL,
-                                         sizeof (EFI_IFR_GUID_LABEL)
-                                         );
-  mLibEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
-
-  mLibEndLabel->Number = LABEL_END;
-}
-
-/**
-
-  Update the File Explore page.
-
-**/
-VOID
-LibUpdateFileExplorePage (
-  VOID
-  )
-{
-  UINTN           Index;
-  MENU_ENTRY      *NewMenuEntry;
-  FILE_CONTEXT    *NewFileContext;
-  MENU_OPTION     *MenuOption;
-
-  NewMenuEntry    = NULL;
-  NewFileContext  = NULL;
-
-  LibRefreshUpdateData ();
-  MenuOption = gFileExplorerPrivate.FsOptionMenu;
-
-  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
-    NewMenuEntry    = LibGetMenuEntry (MenuOption, Index);
-    NewFileContext  = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
-
-    if (!NewFileContext->IsDir) {
-      //
-      // Create Text opcode for directory, also create Text opcode for file in 
FileExplorerStateBootFromFile.
-      //
-      HiiCreateActionOpCode (
-        mLibStartOpCodeHandle,
-        (UINT16) (FILE_OPTION_OFFSET + Index),
-        NewMenuEntry->DisplayStringToken,
-        STRING_TOKEN (STR_NULL_STRING),
-        EFI_IFR_FLAG_CALLBACK,
-        0
-        );
-    } else {
-      //
-      // Create Goto opcode for file in FileExplorerStateAddBootOption or 
FileExplorerStateAddDriverOptionState.
-      //
-      HiiCreateGotoOpCode (
-        mLibStartOpCodeHandle,
-        FORM_FILE_EXPLORER_ID,
-        NewMenuEntry->DisplayStringToken,
-        STRING_TOKEN (STR_NULL_STRING),
-        EFI_IFR_FLAG_CALLBACK,
-        (UINT16) (FILE_OPTION_OFFSET + Index)
-        );
-    }
-  }
-
-  HiiUpdateForm (
-    gFileExplorerPrivate.FeHiiHandle,
-    &FileExplorerGuid,
-    FORM_FILE_EXPLORER_ID,
-    mLibStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID
-    mLibEndOpCodeHandle    // LABEL_END
-    );
-}
-
-/**
-  Update the file explower page with the refershed file system.
-
-  @param KeyValue        Key value to identify the type of data to expect.
-
-  @retval  EFI_SUCCESS   Update the file explorer form success.
-  @retval  other errors  Error occur when parse one directory.
-
-**/
-EFI_STATUS
-LibUpdateFileExplorer (
-  IN UINT16                       KeyValue
-  )
-{
-  UINT16          FileOptionMask;
-  MENU_ENTRY      *NewMenuEntry;
-  FILE_CONTEXT    *NewFileContext;
-  EFI_STATUS      Status;
-  EFI_FILE_HANDLE FileHandle;
-
-  Status = EFI_SUCCESS;
-  FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue);
-  NewMenuEntry   = LibGetMenuEntry (gFileExplorerPrivate.FsOptionMenu, 
FileOptionMask);
-  NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
-
-  if (NewFileContext->IsDir) {
-    RemoveEntryList (&NewMenuEntry->Link);
-    LibFreeMenu (gFileExplorerPrivate.FsOptionMenu);
-    LibGetFileHandleFromMenu (NewMenuEntry, &FileHandle);
-    Status = LibFindFiles (FileHandle, NewFileContext->FileName, 
NewFileContext->DeviceHandle);
-    if (!EFI_ERROR (Status)) {
-      LibUpdateFileExplorePage ();
-    } else {
-      LibFreeMenu (gFileExplorerPrivate.FsOptionMenu);
-    }
-    LibDestroyMenuEntry (NewMenuEntry);
-  }
-
-  return Status;
-}
-
-/**
-  Get the device path info saved in the menu structure.
-
-  @param KeyValue        Key value to identify the type of data to expect.
-
-**/
-VOID
-LibGetDevicePath (
-  IN UINT16                       KeyValue
-  )
-{
-  UINT16          FileOptionMask;
-  MENU_ENTRY      *NewMenuEntry;
-  FILE_CONTEXT    *NewFileContext;
-
-  FileOptionMask    = (UINT16) (FILE_OPTION_MASK & KeyValue);
-
-  NewMenuEntry = LibGetMenuEntry (gFileExplorerPrivate.FsOptionMenu, 
FileOptionMask);
-
-  NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
-
-  if (gFileExplorerPrivate.RetDevicePath != NULL) {
-    FreePool (gFileExplorerPrivate.RetDevicePath);
-  }
-  gFileExplorerPrivate.RetDevicePath = DuplicateDevicePath 
(NewFileContext->DevicePath);
-}
-
-/**
-  Choose a file in the specified directory. 
-
-  If user input NULL for the RootDirectory, will choose file in the system.
-
-  If user input *File != NULL, function will return the allocate device path
-  info for the choosed file, caller has to free the memory after use it.
-
-  @param  RootDirectory    Pointer to the root directory.
-  @param  FileType         The file type need to choose.
-  @param  ChooseHandler    Function pointer to the extra task need to do
-                           after choose one file.
-  @param  File             Return the device path for the last time chosed 
file.
-
-  @retval EFI_SUCESS             Choose file success.
-  @retval EFI_INVALID_PARAMETER  Both ChooseHandler and return device path are 
NULL
-                                 One of them must not NULL.
-  @retval Other errors           Choose file failed.
-**/
-EFI_STATUS
-EFIAPI
-ChooseFile (
-  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDirectory,
-  IN  CHAR16                    *FileType,  OPTIONAL
-  IN  CHOOSE_HANDLER            ChooseHandler,  OPTIONAL
-  OUT EFI_DEVICE_PATH_PROTOCOL  **File  OPTIONAL
-  )
-{
-  EFI_FILE_HANDLE                   FileHandle;
-  EFI_STATUS                        Status;
-  UINT16                            *FileName;
-  EFI_HANDLE                        DeviceHandle;
-
-  if ((ChooseHandler == NULL) && (File == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  FileName = NULL;
-
-  gFileExplorerPrivate.RetDevicePath = NULL;
-  gFileExplorerPrivate.ChooseHandler = ChooseHandler;
-  if (FileType != NULL) {
-    gFileExplorerPrivate.FileType = AllocateCopyPool (StrSize (FileType), 
FileType);
-    LibToLowerString(gFileExplorerPrivate.FileType);
-  } else {
-    gFileExplorerPrivate.FileType = NULL;
-  }
-
-  if (RootDirectory == NULL) {
-    Status = LibFindFileSystem();
-  } else {
-    Status = LibGetFileHandleFromDevicePath(RootDirectory, &FileHandle, 
&FileName, &DeviceHandle);
-    if (EFI_ERROR (Status)) {
-      goto Done;
-    }
-
-    Status = LibFindFiles (FileHandle, FileName, DeviceHandle);
-  }
-  if (EFI_ERROR (Status)) {
-    goto Done;
-  }
-
-  LibUpdateFileExplorePage();
-
-  gFileExplorerPrivate.FormBrowser2->SendForm (
-                         gFileExplorerPrivate.FormBrowser2,
-                         &gFileExplorerPrivate.FeHiiHandle,
-                         1,
-                         &FileExplorerGuid,
-                         0,
-                         NULL,
-                         NULL
-                         );
-
-Done:
-  if ((Status == EFI_SUCCESS) && (File != NULL)) {
-    *File  = gFileExplorerPrivate.RetDevicePath;
-  } else if (gFileExplorerPrivate.RetDevicePath != NULL) {
-    FreePool (gFileExplorerPrivate.RetDevicePath);
-  }
-
-  if (gFileExplorerPrivate.FileType != NULL) {
-    FreePool (gFileExplorerPrivate.FileType);
-  }
-
-  LibFreeMenu (gFileExplorerPrivate.FsOptionMenu);
-
-  if (FileName != NULL) {
-    FreePool (FileName);
-  }
-
-  return Status;
-}
-
-/**
-
-  Install Boot Manager Menu driver.
-
-  @param ImageHandle     The image handle.
-  @param SystemTable     The system table.
-
-  @retval  EFI_SUCEESS  Install File explorer library success.
-
-**/
-EFI_STATUS
-EFIAPI
-FileExplorerLibConstructor (
-  IN EFI_HANDLE                            ImageHandle,
-  IN EFI_SYSTEM_TABLE                      *SystemTable
-  )
-{
-  EFI_STATUS                     Status;
-
-  gHiiVendorDevicePath = (HII_VENDOR_DEVICE_PATH*) DuplicateDevicePath 
((EFI_DEVICE_PATH_PROTOCOL*)&FeHiiVendorDevicePath);
-  ASSERT (gHiiVendorDevicePath != NULL);
-  CopyGuid (&gHiiVendorDevicePath->VendorDevicePath.Guid, &gEfiCallerIdGuid);
-
-  //
-  // Install Device Path Protocol and Config Access protocol to driver handle
-  //
-  Status = gBS->InstallMultipleProtocolInterfaces (
-                  &gFileExplorerPrivate.FeDriverHandle,
-                  &gEfiDevicePathProtocolGuid,
-                  gHiiVendorDevicePath,
-                  &gEfiHiiConfigAccessProtocolGuid,
-                  &gFileExplorerPrivate.FeConfigAccess,
-                  NULL
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Post our File Explorer VFR binary to the HII database.
-  //
-  gFileExplorerPrivate.FeHiiHandle = HiiAddPackages (
-                                   &FileExplorerGuid,
-                                   gFileExplorerPrivate.FeDriverHandle,
-                                   FileExplorerVfrBin,
-                                   FileExplorerLibStrings,
-                                   NULL
-                                   );
-  ASSERT (gFileExplorerPrivate.FeHiiHandle != NULL);
-
-  //
-  // Locate Formbrowser2 protocol
-  //
-  Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) 
&gFileExplorerPrivate.FormBrowser2);
-  ASSERT_EFI_ERROR (Status);
-    
-  InitializeListHead (&gFileExplorerPrivate.FsOptionMenu->Head);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Unloads the application and its installed protocol.
-
-  @param[in]  ImageHandle       Handle that identifies the image to be 
unloaded.
-  @param[in]  SystemTable       The system table.
-
-  @retval EFI_SUCCESS           The image has been unloaded.
-**/
-EFI_STATUS
-EFIAPI
-FileExplorerLibDestructor (
-  IN EFI_HANDLE                            ImageHandle,
-  IN EFI_SYSTEM_TABLE                      *SystemTable
-  )
-{
-  EFI_STATUS    Status;
-
-  ASSERT (gHiiVendorDevicePath != NULL);
-
-  Status = gBS->UninstallMultipleProtocolInterfaces (
-                  gFileExplorerPrivate.FeDriverHandle,
-                  &gEfiDevicePathProtocolGuid,
-                  gHiiVendorDevicePath,
-                  &gEfiHiiConfigAccessProtocolGuid,
-                  &gFileExplorerPrivate.FeConfigAccess,
-                  NULL
-                  );
-  ASSERT_EFI_ERROR (Status);
-  
-  HiiRemovePackages (gFileExplorerPrivate.FeHiiHandle);
-
-  FreePool (gHiiVendorDevicePath);
-
-  return EFI_SUCCESS;
-}
-
+/** @file
+File explorer related functions.
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available 
under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "FileExplorer.h"
+
+EFI_GUID FileExplorerGuid       = EFI_FILE_EXPLORE_FORMSET_GUID;
+
+///
+/// File system selection menu
+///
+MENU_OPTION      mFsOptionMenu = {
+  MENU_OPTION_SIGNATURE,
+  {NULL},
+  0,
+  FALSE
+};
+
+FILE_EXPLORER_CALLBACK_DATA  gFileExplorerPrivate = {
+  FILE_EXPLORER_CALLBACK_DATA_SIGNATURE,
+  NULL,
+  NULL,
+  {
+    LibExtractConfig,
+    LibRouteConfig,
+    LibCallback
+  },
+  NULL,
+  &mFsOptionMenu,
+  0
+};
+
+HII_VENDOR_DEVICE_PATH  *gHiiVendorDevicePath;
+
+HII_VENDOR_DEVICE_PATH  FeHiiVendorDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    //
+    // Will be replace with gEfiCallerIdGuid in code.
+    //
+    { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    { 
+      (UINT8) (END_DEVICE_PATH_LENGTH),
+      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+    }
+  }
+};
+
+VOID                *mLibStartOpCodeHandle = NULL;
+VOID                *mLibEndOpCodeHandle = NULL;
+EFI_IFR_GUID_LABEL  *mLibStartLabel = NULL;
+EFI_IFR_GUID_LABEL  *mLibEndLabel = NULL;
+
+/**
+  This function allows a caller to extract the current configuration for one
+  or more named elements from the target driver.
+
+
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param Request         A null-terminated Unicode string in <ConfigRequest> 
format.
+  @param Progress        On return, points to a character in the Request 
string.
+                         Points to the string's null terminator if request was 
successful.
+                         Points to the most recent '&' before the first 
failing name/value
+                         pair (or the beginning of the string if the failure 
is in the
+                         first name/value pair) if the request was not 
successful.
+  @param Results         A null-terminated Unicode string in <ConfigAltResp> 
format which
+                         has all values filled in for the names in the Request 
string.
+                         String to be allocated by the called function.
+
+  @retval  EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
+  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in 
this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+LibExtractConfig (
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN  CONST EFI_STRING                       Request,
+  OUT EFI_STRING                             *Progress,
+  OUT EFI_STRING                             *Results
+  )
+{
+  if (Progress == NULL || Results == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Progress = Request;
+  return EFI_NOT_FOUND;
+}
+
+/**
+  This function processes the results of changes in configuration.
+
+
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param Configuration   A null-terminated Unicode string in <ConfigResp> 
format.
+  @param Progress        A pointer to a string filled in with the offset of 
the most
+                         recent '&' before the first failing name/value pair 
(or the
+                         beginning of the string if the failure is in the first
+                         name/value pair) or the terminating NULL if all was 
successful.
+
+  @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
+  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in 
this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRouteConfig (
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN  CONST EFI_STRING                       Configuration,
+  OUT EFI_STRING                             *Progress
+  )
+{
+  if (Configuration == NULL || Progress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Progress = Configuration;
+  return EFI_NOT_FOUND;
+}
+
+/**
+  This function processes the results of changes in configuration.
+  When user select a interactive opcode, this callback will be triggered.
+  Based on the Question(QuestionId) that triggers the callback, the 
corresponding
+  actions is performed. It handles:
+
+  1) Process the axtra action or exit file explorer when user select one file .
+  2) update of file content if a dir is selected.
+
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param Action          Specifies the type of action taken by the browser.
+  @param QuestionId      A unique value which is sent to the original 
exporting driver
+                         so that it can identify the type of data to expect.
+  @param Type            The type of value for the question.
+  @param Value           A pointer to the data being sent to the original 
exporting driver.
+  @param ActionRequest   On return, points to the action requested by the 
callback function.
+
+  @retval  EFI_SUCCESS           The callback successfully handled the action.
+  @retval  other error           Error occur when parse one directory.
+**/
+EFI_STATUS
+EFIAPI
+LibCallback (
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN  EFI_BROWSER_ACTION                     Action,
+  IN  EFI_QUESTION_ID                        QuestionId,
+  IN  UINT8                                  Type,
+  IN  EFI_IFR_TYPE_VALUE                     *Value,
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  )
+{
+  EFI_STATUS    Status;
+  BOOLEAN       NeedExit;
+
+  NeedExit = TRUE;
+  
+  if (Action != EFI_BROWSER_ACTION_CHANGING && Action != 
EFI_BROWSER_ACTION_CHANGED) {
+    //
+    // Do nothing for other UEFI Action. Only do call back when data is 
changed.
+    //
+    return EFI_UNSUPPORTED;
+  }
+
+  *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+
+  if (Action == EFI_BROWSER_ACTION_CHANGED) {
+    if ((Value == NULL) || (ActionRequest == NULL)) {
+      return EFI_INVALID_PARAMETER;
+    }
+    
+    if (QuestionId >= FILE_OPTION_OFFSET) {
+      LibGetDevicePath(QuestionId);
+
+      //
+      // Process the extra action.
+      //
+      if (gFileExplorerPrivate.ChooseHandler != NULL) {
+        NeedExit = gFileExplorerPrivate.ChooseHandler 
(gFileExplorerPrivate.RetDevicePath);
+      }
+
+      if (NeedExit) {
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+      }
+    }
+  } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
+    if (Value == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+    
+    if (QuestionId >= FILE_OPTION_OFFSET) {
+      Status = LibUpdateFileExplorer (QuestionId);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Create a menu entry by given menu type.
+
+  @retval NULL           If failed to create the menu.
+  @return the new menu entry.
+
+**/
+MENU_ENTRY *
+LibCreateMenuEntry (
+  VOID
+  )
+{
+  MENU_ENTRY *MenuEntry;
+
+  //
+  // Create new menu entry
+  //
+  MenuEntry = AllocateZeroPool (sizeof (MENU_ENTRY));
+  if (MenuEntry == NULL) {
+    return NULL;
+  }
+
+  MenuEntry->VariableContext = AllocateZeroPool (sizeof (FILE_CONTEXT));
+  if (MenuEntry->VariableContext == NULL) {
+    FreePool (MenuEntry);
+    return NULL;
+  }
+
+  MenuEntry->Signature        = MENU_ENTRY_SIGNATURE;
+  return MenuEntry;
+}
+
+
+/**
+  Get the Menu Entry from the list in Menu Entry List.
+
+  If MenuNumber is great or equal to the number of Menu
+  Entry in the list, then ASSERT.
+
+  @param MenuOption      The Menu Entry List to read the menu entry.
+  @param MenuNumber      The index of Menu Entry.
+
+  @return The Menu Entry.
+
+**/
+MENU_ENTRY *
+LibGetMenuEntry (
+  MENU_OPTION         *MenuOption,
+  UINTN               MenuNumber
+  )
+{
+  MENU_ENTRY      *NewMenuEntry;
+  UINTN           Index;
+  LIST_ENTRY      *List;
+
+  ASSERT (MenuNumber < MenuOption->MenuNumber);
+
+  List = MenuOption->Head.ForwardLink;
+  for (Index = 0; Index < MenuNumber; Index++) {
+    List = List->ForwardLink;
+  }
+
+  NewMenuEntry = CR (List, MENU_ENTRY, Link, MENU_ENTRY_SIGNATURE);
+
+  return NewMenuEntry;
+}
+
+/**
+  Free up all resource allocated for a BM_MENU_ENTRY.
+
+  @param MenuEntry   A pointer to BM_MENU_ENTRY.
+
+**/
+VOID
+LibDestroyMenuEntry (
+  MENU_ENTRY         *MenuEntry
+  )
+{
+  FILE_CONTEXT           *FileContext;
+
+  FileContext = (FILE_CONTEXT *) MenuEntry->VariableContext;
+
+  if (!FileContext->IsRoot) {
+    FreePool (FileContext->DevicePath);
+  } else {
+    if (FileContext->FileHandle != NULL) {
+      FileContext->FileHandle->Close (FileContext->FileHandle);
+    }
+  }
+
+  if (FileContext->FileName != NULL) {
+    FreePool (FileContext->FileName);
+  }
+
+  FreePool (FileContext);
+
+  FreePool (MenuEntry->DisplayString);
+  if (MenuEntry->HelpString != NULL) {
+    FreePool (MenuEntry->HelpString);
+  }
+
+  FreePool (MenuEntry);
+}
+
+
+/**
+  Free resources allocated in Allocate Rountine.
+
+  @param FreeMenu        Menu to be freed
+**/
+VOID
+LibFreeMenu (
+  MENU_OPTION        *FreeMenu
+  )
+{
+  MENU_ENTRY *MenuEntry;
+  while (!IsListEmpty (&FreeMenu->Head)) {
+    MenuEntry = CR (
+                  FreeMenu->Head.ForwardLink,
+                  MENU_ENTRY,
+                  Link,
+                  MENU_ENTRY_SIGNATURE
+                  );
+    RemoveEntryList (&MenuEntry->Link);
+    LibDestroyMenuEntry (MenuEntry);
+  }
+  FreeMenu->MenuNumber = 0;
+}
+
+/**
+
+  Function opens and returns a file handle to the root directory of a volume.
+
+  @param DeviceHandle    A handle for a device
+
+  @return A valid file handle or NULL is returned
+
+**/
+EFI_FILE_HANDLE
+LibOpenRoot (
+  IN EFI_HANDLE                   DeviceHandle
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
+  EFI_FILE_HANDLE                 File;
+
+  File = NULL;
+
+  //
+  // File the file system interface to the device
+  //
+  Status = gBS->HandleProtocol (
+                  DeviceHandle,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  (VOID *) &Volume
+                  );
+
+  //
+  // Open the root directory of the volume
+  //
+  if (!EFI_ERROR (Status)) {
+    Status = Volume->OpenVolume (
+                      Volume,
+                      &File
+                      );
+  }
+  //
+  // Done
+  //
+  return EFI_ERROR (Status) ? NULL : File;
+}
+
+/**
+  This function converts an input device structure to a Unicode string.
+
+  @param DevPath                  A pointer to the device path structure.
+
+  @return A new allocated Unicode string that represents the device path.
+
+**/
+CHAR16 *
+LibDevicePathToStr (
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
+  )
+{
+  EFI_STATUS                       Status;
+  CHAR16                           *ToText;
+  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
+
+  if (DevPath == NULL) {
+    return NULL;
+  }
+
+  Status = gBS->LocateProtocol (
+                  &gEfiDevicePathToTextProtocolGuid,
+                  NULL,
+                  (VOID **) &DevPathToText
+                  );
+  ASSERT_EFI_ERROR (Status);
+  ToText = DevPathToText->ConvertDevicePathToText (
+                            DevPath,
+                            FALSE,
+                            TRUE
+                            );
+  ASSERT (ToText != NULL);
+
+  return ToText;
+}
+
+/**
+  Duplicate a string.
+
+  @param Src             The source.
+
+  @return A new string which is duplicated copy of the source.
+  @retval NULL If there is not enough memory.
+
+**/
+CHAR16 *
+LibStrDuplicate (
+  IN CHAR16   *Src
+  )
+{
+  CHAR16  *Dest;
+  UINTN   Size;
+
+  Size  = StrSize (Src);
+  Dest  = AllocateZeroPool (Size);
+  ASSERT (Dest != NULL);
+  if (Dest != NULL) {
+    CopyMem (Dest, Src, Size);
+  }
+
+  return Dest;
+}
+
+/**
+
+  Function gets the file information from an open file descriptor, and stores 
it
+  in a buffer allocated from pool.
+
+  @param FHand           File Handle.
+  @param InfoType        Info type need to get.
+
+  @retval                A pointer to a buffer with file information or NULL 
is returned
+
+**/
+VOID *
+LibFileInfo (
+  IN EFI_FILE_HANDLE      FHand,
+  IN EFI_GUID             *InfoType
+  )
+{
+  EFI_STATUS    Status;
+  EFI_FILE_INFO *Buffer;
+  UINTN         BufferSize;
+
+  Buffer      = NULL;
+  BufferSize  = 0;
+  
+  Status = FHand->GetInfo (
+                    FHand,
+                    InfoType,
+                    &BufferSize,
+                    Buffer
+                    );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Buffer = AllocatePool (BufferSize);
+    ASSERT (Buffer != NULL);
+  }
+
+  Status = FHand->GetInfo (
+                    FHand,
+                    InfoType,
+                    &BufferSize,
+                    Buffer
+                    );
+
+  return Buffer;
+}
+
+/**
+
+  Get file type base on the file name.
+  Just cut the file name, from the ".". eg ".efi"
+
+  @param FileName  File need to be checked.
+
+  @retval the file type string.
+
+**/
+CHAR16*
+LibGetTypeFromName (
+  IN CHAR16   *FileName
+  )
+{
+  UINTN    Index;
+
+  Index = StrLen (FileName) - 1;
+  while ((FileName[Index] != L'.') && (Index != 0)) {
+    Index--;
+  }
+
+  return Index == 0 ? NULL : &FileName[Index];
+}
+
+/**
+  Converts the unicode character of the string from uppercase to lowercase.
+  This is a internal function.
+
+  @param ConfigString  String to be converted
+
+**/
+VOID
+LibToLowerString (
+  IN CHAR16  *String
+  )
+{
+  CHAR16      *TmpStr;
+
+  for (TmpStr = String; *TmpStr != L'\0'; TmpStr++) {
+    if (*TmpStr >= L'A' && *TmpStr <= L'Z') {
+      *TmpStr = (CHAR16) (*TmpStr - L'A' + L'a');
+    }
+  }
+}
+
+/**
+
+  Check whether current FileName point to a valid
+  Efi Image File.
+
+  @param FileName  File need to be checked.
+
+  @retval TRUE  Is Efi Image
+  @retval FALSE Not a valid Efi Image
+
+**/
+BOOLEAN
+LibIsSupportedFileType (
+  IN UINT16  *FileName
+  )
+{
+  CHAR16     *InputFileType;
+  CHAR16     *TmpStr;
+  BOOLEAN    IsSupported;
+
+  if (gFileExplorerPrivate.FileType == NULL) {
+    return TRUE;
+  }
+
+  InputFileType = LibGetTypeFromName (FileName);
+  //
+  // If the file not has *.* style, always return TRUE.
+  //
+  if (InputFileType == NULL) {
+    return TRUE;
+  }
+
+  TmpStr = AllocateCopyPool (StrSize (InputFileType), InputFileType);
+  LibToLowerString(TmpStr);
+
+  IsSupported = (StrStr (gFileExplorerPrivate.FileType, TmpStr) == NULL ? 
FALSE : TRUE);
+
+  FreePool (TmpStr);
+  return IsSupported;
+}
+
+/**
+
+  Append file name to existing file name.
+
+  @param Str1  The existing file name
+  @param Str2  The file name to be appended
+
+  @return Allocate a new string to hold the appended result.
+          Caller is responsible to free the returned string.
+
+**/
+CHAR16 *
+LibAppendFileName (
+  IN  CHAR16  *Str1,
+  IN  CHAR16  *Str2
+  )
+{
+  UINTN   Size1;
+  UINTN   Size2;
+  UINTN   MaxLen;
+  CHAR16  *Str;
+  CHAR16  *TmpStr;
+  CHAR16  *Ptr;
+  CHAR16  *LastSlash;
+
+  Size1 = StrSize (Str1);
+  Size2 = StrSize (Str2);
+  MaxLen = (Size1 + Size2 + sizeof (CHAR16))/ sizeof (CHAR16);
+  Str   = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));
+  ASSERT (Str != NULL);
+
+  TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); 
+  ASSERT (TmpStr != NULL);
+
+  StrCpyS (Str, MaxLen, Str1);
+  if (!((*Str == '\\') && (*(Str + 1) == 0))) {
+    StrCatS (Str, MaxLen, L"\\");
+  }
+
+  StrCatS (Str, MaxLen, Str2);
+
+  Ptr       = Str;
+  LastSlash = Str;
+  while (*Ptr != 0) {
+    if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) 
== L'\\') {
+      //
+      // Convert "\Name\..\" to "\"
+      // DO NOT convert the .. if it is at the end of the string. This will
+      // break the .. behavior in changing directories.
+      //
+
+      //
+      // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of 
two strings 
+      // that overlap.
+      //
+      StrCpyS (TmpStr, MaxLen, Ptr + 3);
+      StrCpyS (LastSlash, MaxLen - (UINTN) (LastSlash - Str), TmpStr);
+      Ptr = LastSlash;
+    } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {
+      //
+      // Convert a "\.\" to a "\"
+      //
+
+      //
+      // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of 
two strings 
+      // that overlap.
+      //
+      StrCpyS (TmpStr, MaxLen, Ptr + 2);
+      StrCpyS (Ptr, MaxLen - (UINTN) (Ptr - Str), TmpStr);
+      Ptr = LastSlash;
+    } else if (*Ptr == '\\') {
+      LastSlash = Ptr;
+    }
+
+    Ptr++;
+  }
+
+  FreePool (TmpStr);
+  
+  return Str;
+}
+
+/**
+  This function build the FsOptionMenu list which records all
+  available file system in the system. They includes all instances
+  of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM.
+
+
+  @retval  EFI_SUCCESS             Success find the file system
+  @retval  EFI_OUT_OF_RESOURCES    Can not create menu entry
+
+**/
+EFI_STATUS
+LibFindFileSystem (
+  VOID
+  )
+{
+  UINTN                        NoSimpleFsHandles;
+  UINTN                        NoLoadFileHandles;
+  EFI_HANDLE                   *SimpleFsHandle;
+  EFI_HANDLE                   *LoadFileHandle;
+  UINT16                       *VolumeLabel;
+  UINTN                        Index;
+  EFI_STATUS                   Status;
+  MENU_ENTRY                   *MenuEntry;
+  FILE_CONTEXT                 *FileContext;
+  UINTN                        OptionNumber;
+  EFI_FILE_SYSTEM_VOLUME_LABEL *Info;
+
+  NoSimpleFsHandles = 0;
+  NoLoadFileHandles = 0;
+  OptionNumber      = 0;
+
+  //
+  // Locate Handles that support Simple File System protocol
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  NULL,
+                  &NoSimpleFsHandles,
+                  &SimpleFsHandle
+                  );
+  if (!EFI_ERROR (Status)) {
+    //
+    // Find all the instances of the File System prototocol
+    //
+    for (Index = 0; Index < NoSimpleFsHandles; Index++) {
+      //
+      // Allocate pool for this load option
+      //
+      MenuEntry = LibCreateMenuEntry ();
+      if (NULL == MenuEntry) {
+        FreePool (SimpleFsHandle);
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      FileContext = (FILE_CONTEXT *) MenuEntry->VariableContext;
+      FileContext->DeviceHandle = SimpleFsHandle[Index];
+      FileContext->FileHandle = LibOpenRoot (FileContext->DeviceHandle);
+      if (FileContext->FileHandle == NULL) {
+        LibDestroyMenuEntry (MenuEntry);
+        continue;
+      }
+
+      MenuEntry->HelpString = LibDevicePathToStr (DevicePathFromHandle 
(FileContext->DeviceHandle));
+      FileContext->FileName = LibStrDuplicate (L"\\");
+      FileContext->DevicePath = FileDevicePath (FileContext->DeviceHandle, 
FileContext->FileName);
+      FileContext->IsDir = TRUE;
+      FileContext->IsRoot = TRUE;
+
+      //
+      // Get current file system's Volume Label
+      //
+      Info = (EFI_FILE_SYSTEM_VOLUME_LABEL *) LibFileInfo 
(FileContext->FileHandle, &gEfiFileSystemVolumeLabelInfoIdGuid);
+      if (Info == NULL) {
+        VolumeLabel = L"NO FILE SYSTEM INFO";
+      } else {
+        if (Info->VolumeLabel == NULL) {
+          VolumeLabel = L"NULL VOLUME LABEL";
+        } else {
+          VolumeLabel = Info->VolumeLabel;
+          if (*VolumeLabel == 0x0000) {
+            VolumeLabel = L"NO VOLUME LABEL";
+          }
+        }
+      }
+      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);
+      ASSERT (MenuEntry->DisplayString != NULL);
+      UnicodeSPrint (
+        MenuEntry->DisplayString,
+        MAX_CHAR,
+        L"%s, [%s]",
+        VolumeLabel,
+        MenuEntry->HelpString
+        );
+         MenuEntry->DisplayStringToken = HiiSetString (
+                                             gFileExplorerPrivate.FeHiiHandle,
+                                             0,
+                                             MenuEntry->DisplayString,
+                                             NULL
+                                             );
+      FreePool (Info);
+
+      OptionNumber++;
+      InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, 
&MenuEntry->Link);
+    }
+  }
+
+  if (NoSimpleFsHandles != 0) {
+    FreePool (SimpleFsHandle);
+  }
+
+  //
+  // Searching for handles that support Load File protocol
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiLoadFileProtocolGuid,
+                  NULL,
+                  &NoLoadFileHandles,
+                  &LoadFileHandle
+                  );
+
+  if (!EFI_ERROR (Status)) {
+    for (Index = 0; Index < NoLoadFileHandles; Index++) {
+      MenuEntry = LibCreateMenuEntry ();
+      if (NULL == MenuEntry) {
+        FreePool (LoadFileHandle);
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      FileContext = (FILE_CONTEXT *) MenuEntry->VariableContext;
+      FileContext->DeviceHandle = LoadFileHandle[Index];
+      FileContext->IsRoot = TRUE;
+
+      FileContext->DevicePath = DevicePathFromHandle 
(FileContext->DeviceHandle);
+      FileContext->FileName = LibDevicePathToStr (FileContext->DevicePath);
+
+      MenuEntry->HelpString = LibDevicePathToStr (FileContext->DevicePath);
+      MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);
+      ASSERT (MenuEntry->DisplayString != NULL);
+      UnicodeSPrint (
+        MenuEntry->DisplayString,
+        MAX_CHAR,
+        L"Load File [%s]",
+        MenuEntry->HelpString
+        );
+      MenuEntry->DisplayStringToken = HiiSetString (
+                                           gFileExplorerPrivate.FeHiiHandle,
+                                           0,
+                                           MenuEntry->DisplayString,
+                                           NULL
+                                           );
+
+      OptionNumber++;
+      InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, 
&MenuEntry->Link);
+    }
+  }
+
+  if (NoLoadFileHandles != 0) {
+    FreePool (LoadFileHandle);
+  }
+
+  gFileExplorerPrivate.FsOptionMenu->MenuNumber = OptionNumber;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Find the file handle from the input menu info.
+  
+  @param  MenuEntry        Input Menu info.
+  @param  RetFileHandle    Return the file handle for the input device path.
+  
+  @retval EFI_SUCESS       Find the file handle success.
+  @retval Other            Find the file handle failure.
+**/
+EFI_STATUS
+LibGetFileHandleFromMenu (
+  IN  MENU_ENTRY                *MenuEntry,  
+  OUT EFI_FILE_HANDLE           *RetFileHandle
+  )
+{
+  EFI_FILE_HANDLE Dir;
+  EFI_FILE_HANDLE NewDir;
+  FILE_CONTEXT    *FileContext;
+  EFI_STATUS      Status;
+
+  FileContext   = (FILE_CONTEXT *) MenuEntry->VariableContext;
+  Dir           = FileContext->FileHandle;
+
+  //
+  // Open current directory to get files from it
+  //
+  Status = Dir->Open (
+                  Dir,
+                  &NewDir,
+                  FileContext->FileName,
+                  EFI_FILE_READ_ONLY,
+                  0
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (!FileContext->IsRoot) {
+    Dir->Close (Dir);
+  }
+
+  *RetFileHandle = NewDir;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Find the file handle from the input device path info.
+  
+  @param  RootDirectory    Device path info.
+  @param  RetFileHandle    Return the file handle for the input device path.
+  @param  ParentFileName   Parent file name.
+  @param  DeviceHandle     Driver handle for this partition.
+  
+  @retval EFI_SUCESS       Find the file handle success.
+  @retval Other            Find the file handle failure.
+**/
+EFI_STATUS
+LibGetFileHandleFromDevicePath (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDirectory,  
+  OUT EFI_FILE_HANDLE           *RetFileHandle,
+  OUT UINT16                    **ParentFileName,
+  OUT EFI_HANDLE                *DeviceHandle
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePathNode;
+  EFI_DEVICE_PATH_PROTOCOL          *TempDevicePathNode;
+  EFI_STATUS                        Status;
+  EFI_HANDLE                        Handle;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;
+  EFI_FILE_HANDLE                   FileHandle;
+  EFI_FILE_HANDLE                   LastHandle;
+  CHAR16                            *TempPath;
+
+  *ParentFileName = NULL;
+
+  //
+  // Attempt to access the file via a file system interface
+  //
+  DevicePathNode = RootDirectory;
+  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, 
&DevicePathNode, &Handle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  
+  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, 
(VOID**)&Volume);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  
+  //
+  // Open the Volume to get the File System handle
+  //
+  Status = Volume->OpenVolume (Volume, &FileHandle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *DeviceHandle = Handle;
+
+  if (IsDevicePathEnd(DevicePathNode)) {
+    *ParentFileName = AllocateCopyPool (StrSize (L"\\"), L"\\");
+    *RetFileHandle = FileHandle;
+    return EFI_SUCCESS;
+  }
+  
+  //
+  // Duplicate the device path to avoid the access to unaligned device path 
node.
+  // Because the device path consists of one or more FILE PATH MEDIA DEVICE 
PATH
+  // nodes, It assures the fields in device path nodes are 2 byte aligned.
+  //
+  TempDevicePathNode = DuplicateDevicePath (DevicePathNode);
+  if (TempDevicePathNode == NULL) {
+
+    //
+    // Setting Status to an EFI_ERROR value will cause the rest of
+    // the file system support below to be skipped.
+    //
+    Status = EFI_OUT_OF_RESOURCES;
+  }
+        
+  //
+  // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
+  // directory information and filename can be seperate. The goal is to inch
+  // our way down each device path node and close the previous node
+  //
+  DevicePathNode = TempDevicePathNode;
+  while (!EFI_ERROR (Status) && !IsDevicePathEnd (DevicePathNode)) {
+    if (DevicePathType (DevicePathNode) != MEDIA_DEVICE_PATH ||
+        DevicePathSubType (DevicePathNode) != MEDIA_FILEPATH_DP) {
+      Status = EFI_UNSUPPORTED;
+      goto Done;
+    }
+
+    LastHandle = FileHandle;
+    FileHandle = NULL;
+
+    Status = LastHandle->Open (
+                          LastHandle,
+                          &FileHandle,
+                          ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName,
+                          EFI_FILE_MODE_READ,
+                          0
+                          );
+    if (*ParentFileName == NULL) {
+      *ParentFileName = AllocateCopyPool (StrSize (((FILEPATH_DEVICE_PATH *) 
DevicePathNode)->PathName), ((FILEPATH_DEVICE_PATH *) 
DevicePathNode)->PathName);
+    } else {
+      TempPath = LibAppendFileName (*ParentFileName, ((FILEPATH_DEVICE_PATH *) 
DevicePathNode)->PathName);
+      FreePool (*ParentFileName);
+      *ParentFileName = TempPath;
+    }
+
+    //
+    // Close the previous node
+    //
+    LastHandle->Close (LastHandle);
+
+    DevicePathNode = NextDevicePathNode (DevicePathNode);
+  }
+
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  *RetFileHandle = FileHandle;
+
+  Status = EFI_SUCCESS;
+
+Done:
+  if (TempDevicePathNode != NULL) {
+    FreePool (TempDevicePathNode);
+  }
+
+  if ((FileHandle != NULL) && (EFI_ERROR (Status))) {
+    FileHandle->Close (FileHandle);
+  }
+
+  return Status;
+}
+
+/**
+  Find files under current directory.
+  
+  All files and sub-directories in current directory
+  will be stored in DirectoryMenu for future use.
+
+  @param FileHandle    Parent file handle. 
+  @param FileName      Parent file name.
+  @param DeviceHandle  Driver handle for this partition.
+
+  @retval EFI_SUCCESS         Get files from current dir successfully.
+  @return Other value if can't get files from current dir.
+
+**/
+EFI_STATUS
+LibFindFiles (
+  IN EFI_FILE_HANDLE           FileHandle,
+  IN UINT16                    *FileName,
+  IN EFI_HANDLE                DeviceHandle
+  )
+{
+  EFI_FILE_INFO   *DirInfo;
+  UINTN           BufferSize;
+  UINTN           DirBufferSize;
+  MENU_ENTRY      *NewMenuEntry;
+  FILE_CONTEXT    *NewFileContext;
+  UINTN           Pass;
+  EFI_STATUS      Status;
+  UINTN           OptionNumber;
+
+  OptionNumber = 0;
+
+  DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;
+  DirInfo       = AllocateZeroPool (DirBufferSize);
+  if (DirInfo == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Get all files in current directory
+  // Pass 1 to get Directories
+  // Pass 2 to get files that are EFI images
+  //
+  for (Pass = 1; Pass <= 2; Pass++) {
+    FileHandle->SetPosition (FileHandle, 0);
+    for (;;) {
+      BufferSize  = DirBufferSize;
+      Status      = FileHandle->Read (FileHandle, &BufferSize, DirInfo);
+      if (EFI_ERROR (Status) || BufferSize == 0) {
+        break;
+      }
+
+      if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) ||
+          ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1)
+          ) {
+        //
+        // Pass 1 is for Directories
+        // Pass 2 is for file names
+        //
+        continue;
+      }
+
+      if (!((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 || 
LibIsSupportedFileType (DirInfo->FileName))) {
+        //
+        // Slip file unless it is a directory entry or a .EFI file
+        //
+        continue;
+      }
+
+      NewMenuEntry = LibCreateMenuEntry ();
+      if (NULL == NewMenuEntry) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
+      NewFileContext->DeviceHandle = DeviceHandle;
+      NewFileContext->FileName = LibAppendFileName (FileName, 
DirInfo->FileName);
+      NewFileContext->FileHandle = FileHandle;
+      NewFileContext->DevicePath = FileDevicePath 
(NewFileContext->DeviceHandle, NewFileContext->FileName);
+      NewMenuEntry->HelpString = NULL;
+      NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & 
EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);
+
+      if (NewFileContext->IsDir) {
+        BufferSize = StrLen (DirInfo->FileName) * 2 + 6;
+        NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);
+        UnicodeSPrint (
+          NewMenuEntry->DisplayString,
+          BufferSize,
+          L"<%s>",
+          DirInfo->FileName
+          );
+      } else {
+        NewMenuEntry->DisplayString = LibStrDuplicate (DirInfo->FileName);
+      }
+      
+      NewMenuEntry->DisplayStringToken = HiiSetString (
+                                           gFileExplorerPrivate.FeHiiHandle,
+                                           0,
+                                           NewMenuEntry->DisplayString,
+                                           NULL
+                                           );
+
+      NewFileContext->IsRoot            = FALSE;
+
+      OptionNumber++;
+      InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, 
&NewMenuEntry->Link);
+    }
+  }
+
+  gFileExplorerPrivate.FsOptionMenu->MenuNumber = OptionNumber;
+
+  FreePool (DirInfo);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Refresh the global UpdateData structure.
+
+**/
+VOID
+LibRefreshUpdateData (
+  VOID
+  )
+{
+  //
+  // Free current updated date
+  //
+  if (mLibStartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mLibStartOpCodeHandle);
+  }
+  if (mLibEndOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mLibEndOpCodeHandle);
+  }
+
+  //
+  // Create new OpCode Handle
+  //
+  mLibStartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  mLibEndOpCodeHandle = HiiAllocateOpCodeHandle ();
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  mLibStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                         mLibStartOpCodeHandle,
+                                         &gEfiIfrTianoGuid,
+                                         NULL,
+                                         sizeof (EFI_IFR_GUID_LABEL)
+                                         );
+  mLibStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+
+  mLibStartLabel->Number = FORM_FILE_EXPLORER_ID;
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  mLibEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                         mLibEndOpCodeHandle,
+                                         &gEfiIfrTianoGuid,
+                                         NULL,
+                                         sizeof (EFI_IFR_GUID_LABEL)
+                                         );
+  mLibEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+
+  mLibEndLabel->Number = LABEL_END;
+}
+
+/**
+
+  Update the File Explore page.
+
+**/
+VOID
+LibUpdateFileExplorePage (
+  VOID
+  )
+{
+  UINTN           Index;
+  MENU_ENTRY      *NewMenuEntry;
+  FILE_CONTEXT    *NewFileContext;
+  MENU_OPTION     *MenuOption;
+
+  NewMenuEntry    = NULL;
+  NewFileContext  = NULL;
+
+  LibRefreshUpdateData ();
+  MenuOption = gFileExplorerPrivate.FsOptionMenu;
+
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
+    NewMenuEntry    = LibGetMenuEntry (MenuOption, Index);
+    NewFileContext  = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
+
+    if (!NewFileContext->IsDir) {
+      //
+      // Create Text opcode for directory, also create Text opcode for file in 
FileExplorerStateBootFromFile.
+      //
+      HiiCreateActionOpCode (
+        mLibStartOpCodeHandle,
+        (UINT16) (FILE_OPTION_OFFSET + Index),
+        NewMenuEntry->DisplayStringToken,
+        STRING_TOKEN (STR_NULL_STRING),
+        EFI_IFR_FLAG_CALLBACK,
+        0
+        );
+    } else {
+      //
+      // Create Goto opcode for file in FileExplorerStateAddBootOption or 
FileExplorerStateAddDriverOptionState.
+      //
+      HiiCreateGotoOpCode (
+        mLibStartOpCodeHandle,
+        FORM_FILE_EXPLORER_ID,
+        NewMenuEntry->DisplayStringToken,
+        STRING_TOKEN (STR_NULL_STRING),
+        EFI_IFR_FLAG_CALLBACK,
+        (UINT16) (FILE_OPTION_OFFSET + Index)
+        );
+    }
+  }
+
+  HiiUpdateForm (
+    gFileExplorerPrivate.FeHiiHandle,
+    &FileExplorerGuid,
+    FORM_FILE_EXPLORER_ID,
+    mLibStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID
+    mLibEndOpCodeHandle    // LABEL_END
+    );
+}
+
+/**
+  Update the file explower page with the refershed file system.
+
+  @param KeyValue        Key value to identify the type of data to expect.
+
+  @retval  EFI_SUCCESS   Update the file explorer form success.
+  @retval  other errors  Error occur when parse one directory.
+
+**/
+EFI_STATUS
+LibUpdateFileExplorer (
+  IN UINT16                       KeyValue
+  )
+{
+  UINT16          FileOptionMask;
+  MENU_ENTRY      *NewMenuEntry;
+  FILE_CONTEXT    *NewFileContext;
+  EFI_STATUS      Status;
+  EFI_FILE_HANDLE FileHandle;
+
+  Status = EFI_SUCCESS;
+  FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue);
+  NewMenuEntry   = LibGetMenuEntry (gFileExplorerPrivate.FsOptionMenu, 
FileOptionMask);
+  NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
+
+  if (NewFileContext->IsDir) {
+    RemoveEntryList (&NewMenuEntry->Link);
+    LibFreeMenu (gFileExplorerPrivate.FsOptionMenu);
+    LibGetFileHandleFromMenu (NewMenuEntry, &FileHandle);
+    Status = LibFindFiles (FileHandle, NewFileContext->FileName, 
NewFileContext->DeviceHandle);
+    if (!EFI_ERROR (Status)) {
+      LibUpdateFileExplorePage ();
+    } else {
+      LibFreeMenu (gFileExplorerPrivate.FsOptionMenu);
+    }
+    LibDestroyMenuEntry (NewMenuEntry);
+  }
+
+  return Status;
+}
+
+/**
+  Get the device path info saved in the menu structure.
+
+  @param KeyValue        Key value to identify the type of data to expect.
+
+**/
+VOID
+LibGetDevicePath (
+  IN UINT16                       KeyValue
+  )
+{
+  UINT16          FileOptionMask;
+  MENU_ENTRY      *NewMenuEntry;
+  FILE_CONTEXT    *NewFileContext;
+
+  FileOptionMask    = (UINT16) (FILE_OPTION_MASK & KeyValue);
+
+  NewMenuEntry = LibGetMenuEntry (gFileExplorerPrivate.FsOptionMenu, 
FileOptionMask);
+
+  NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
+
+  if (gFileExplorerPrivate.RetDevicePath != NULL) {
+    FreePool (gFileExplorerPrivate.RetDevicePath);
+  }
+  gFileExplorerPrivate.RetDevicePath = DuplicateDevicePath 
(NewFileContext->DevicePath);
+}
+
+/**
+  Choose a file in the specified directory. 
+
+  If user input NULL for the RootDirectory, will choose file in the system.
+
+  If user input *File != NULL, function will return the allocate device path
+  info for the choosed file, caller has to free the memory after use it.
+
+  @param  RootDirectory    Pointer to the root directory.
+  @param  FileType         The file type need to choose.
+  @param  ChooseHandler    Function pointer to the extra task need to do
+                           after choose one file.
+  @param  File             Return the device path for the last time chosed 
file.
+
+  @retval EFI_SUCESS             Choose file success.
+  @retval EFI_INVALID_PARAMETER  Both ChooseHandler and return device path are 
NULL
+                                 One of them must not NULL.
+  @retval Other errors           Choose file failed.
+**/
+EFI_STATUS
+EFIAPI
+ChooseFile (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDirectory,
+  IN  CHAR16                    *FileType,  OPTIONAL
+  IN  CHOOSE_HANDLER            ChooseHandler,  OPTIONAL
+  OUT EFI_DEVICE_PATH_PROTOCOL  **File  OPTIONAL
+  )
+{
+  EFI_FILE_HANDLE                   FileHandle;
+  EFI_STATUS                        Status;
+  UINT16                            *FileName;
+  EFI_HANDLE                        DeviceHandle;
+
+  if ((ChooseHandler == NULL) && (File == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FileName = NULL;
+
+  gFileExplorerPrivate.RetDevicePath = NULL;
+  gFileExplorerPrivate.ChooseHandler = ChooseHandler;
+  if (FileType != NULL) {
+    gFileExplorerPrivate.FileType = AllocateCopyPool (StrSize (FileType), 
FileType);
+    LibToLowerString(gFileExplorerPrivate.FileType);
+  } else {
+    gFileExplorerPrivate.FileType = NULL;
+  }
+
+  if (RootDirectory == NULL) {
+    Status = LibFindFileSystem();
+  } else {
+    Status = LibGetFileHandleFromDevicePath(RootDirectory, &FileHandle, 
&FileName, &DeviceHandle);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+
+    Status = LibFindFiles (FileHandle, FileName, DeviceHandle);
+  }
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  LibUpdateFileExplorePage();
+
+  gFileExplorerPrivate.FormBrowser2->SendForm (
+                         gFileExplorerPrivate.FormBrowser2,
+                         &gFileExplorerPrivate.FeHiiHandle,
+                         1,
+                         &FileExplorerGuid,
+                         0,
+                         NULL,
+                         NULL
+                         );
+
+Done:
+  if ((Status == EFI_SUCCESS) && (File != NULL)) {
+    *File  = gFileExplorerPrivate.RetDevicePath;
+  } else if (gFileExplorerPrivate.RetDevicePath != NULL) {
+    FreePool (gFileExplorerPrivate.RetDevicePath);
+  }
+
+  if (gFileExplorerPrivate.FileType != NULL) {
+    FreePool (gFileExplorerPrivate.FileType);
+  }
+
+  LibFreeMenu (gFileExplorerPrivate.FsOptionMenu);
+
+  if (FileName != NULL) {
+    FreePool (FileName);
+  }
+
+  return Status;
+}
+
+/**
+
+  Install Boot Manager Menu driver.
+
+  @param ImageHandle     The image handle.
+  @param SystemTable     The system table.
+
+  @retval  EFI_SUCEESS  Install File explorer library success.
+
+**/
+EFI_STATUS
+EFIAPI
+FileExplorerLibConstructor (
+  IN EFI_HANDLE                            ImageHandle,
+  IN EFI_SYSTEM_TABLE                      *SystemTable
+  )
+{
+  EFI_STATUS                     Status;
+
+  gHiiVendorDevicePath = (HII_VENDOR_DEVICE_PATH*) DuplicateDevicePath 
((EFI_DEVICE_PATH_PROTOCOL*)&FeHiiVendorDevicePath);
+  ASSERT (gHiiVendorDevicePath != NULL);
+  CopyGuid (&gHiiVendorDevicePath->VendorDevicePath.Guid, &gEfiCallerIdGuid);
+
+  //
+  // Install Device Path Protocol and Config Access protocol to driver handle
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &gFileExplorerPrivate.FeDriverHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  gHiiVendorDevicePath,
+                  &gEfiHiiConfigAccessProtocolGuid,
+                  &gFileExplorerPrivate.FeConfigAccess,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Post our File Explorer VFR binary to the HII database.
+  //
+  gFileExplorerPrivate.FeHiiHandle = HiiAddPackages (
+                                   &FileExplorerGuid,
+                                   gFileExplorerPrivate.FeDriverHandle,
+                                   FileExplorerVfrBin,
+                                   FileExplorerLibStrings,
+                                   NULL
+                                   );
+  ASSERT (gFileExplorerPrivate.FeHiiHandle != NULL);
+
+  //
+  // Locate Formbrowser2 protocol
+  //
+  Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) 
&gFileExplorerPrivate.FormBrowser2);
+  ASSERT_EFI_ERROR (Status);
+    
+  InitializeListHead (&gFileExplorerPrivate.FsOptionMenu->Head);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unloads the application and its installed protocol.
+
+  @param[in]  ImageHandle       Handle that identifies the image to be 
unloaded.
+  @param[in]  SystemTable       The system table.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+**/
+EFI_STATUS
+EFIAPI
+FileExplorerLibDestructor (
+  IN EFI_HANDLE                            ImageHandle,
+  IN EFI_SYSTEM_TABLE                      *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+
+  ASSERT (gHiiVendorDevicePath != NULL);
+
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  gFileExplorerPrivate.FeDriverHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  gHiiVendorDevicePath,
+                  &gEfiHiiConfigAccessProtocolGuid,
+                  &gFileExplorerPrivate.FeConfigAccess,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+  
+  HiiRemovePackages (gFileExplorerPrivate.FeHiiHandle);
+
+  FreePool (gHiiVendorDevicePath);
+
+  return EFI_SUCCESS;
+}
+

Modified: trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorer.h
===================================================================
--- trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorer.h      
2015-12-16 03:20:21 UTC (rev 19296)
+++ trunk/edk2/MdeModulePkg/Library/FileExplorerLib/FileExplorer.h      
2015-12-16 03:21:44 UTC (rev 19297)
@@ -1,239 +1,239 @@
-/** @file
-   File explorer lib.
-
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials                          
-are licensed and made available under the terms and conditions of the BSD 
License         
-which accompanies this distribution.  The full text of the license may be 
found at        
-http://opensource.org/licenses/bsd-license.php                                 
           
-                                                                               
           
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,          
           
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.  
           
-**/
-
-#ifndef _FILE_EXPLORER_H_
-#define _FILE_EXPLORER_H_
-
-#include <PiDxe.h>
-#include <Guid/FileSystemVolumeLabelInfo.h>
-#include <Guid/FileInfo.h>
-#include <Guid/MdeModuleHii.h>
-
-#include <Protocol/HiiConfigAccess.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/SimpleFileSystem.h>
-#include <Protocol/DevicePathToText.h>
-#include <Protocol/LoadFile.h>
-#include <Protocol/FormBrowser2.h>
-
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/BaseLib.h>
-#include <Library/UefiLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/FileExplorerLib.h>
-#include <Library/HiiLib.h>
-#include <Library/PrintLib.h>
-
-#include "FormGuid.h"
-
-#define FILE_EXPLORER_CALLBACK_DATA_SIGNATURE     SIGNATURE_32 ('f', 'e', 'c', 
'k')
-
-
-#pragma pack(1)
-
-///
-/// HII specific Vendor Device Path definition.
-///
-typedef struct {
-  VENDOR_DEVICE_PATH             VendorDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL       End;
-} HII_VENDOR_DEVICE_PATH;
-
-typedef struct {
-  EFI_HANDLE                        DeviceHandle;
-  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
-  EFI_FILE_HANDLE                   FileHandle;
-  UINT16                            *FileName;
-
-  BOOLEAN                           IsRoot;
-  BOOLEAN                           IsDir;
-} FILE_CONTEXT;
-
-typedef struct {
-  UINTN           Signature;
-  LIST_ENTRY      Link;
-  UINT16          *DisplayString;
-  UINT16          *HelpString;
-  EFI_STRING_ID   DisplayStringToken;
-  EFI_STRING_ID   HelpStringToken;
-  VOID            *VariableContext;
-} MENU_ENTRY;
-
-typedef struct {
-  UINTN           Signature;
-  LIST_ENTRY      Head;
-  UINTN           MenuNumber;
-  BOOLEAN         Used;
-} MENU_OPTION;
-
-typedef struct {
-  //
-  // Shared callback data.
-  //
-  UINTN                          Signature;
-
-  //
-  // File explorer formset callback data.
-  //
-  EFI_HII_HANDLE                 FeHiiHandle;
-  EFI_HANDLE                     FeDriverHandle;
-  EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess;
-  EFI_FORM_BROWSER2_PROTOCOL     *FormBrowser2;
-  MENU_OPTION                    *FsOptionMenu;
-  CHAR16                         *FileType;
-  CHOOSE_HANDLER                 ChooseHandler;
-  EFI_DEVICE_PATH_PROTOCOL       *RetDevicePath;
-
-} FILE_EXPLORER_CALLBACK_DATA;
-
-#define FILE_EXPLORER_PRIVATE_FROM_THIS(a)  CR (a, 
FILE_EXPLORER_CALLBACK_DATA, FeConfigAccess, 
FILE_EXPLORER_CALLBACK_DATA_SIGNATURE)
-
-#pragma pack()
-
-extern UINT8    FileExplorerVfrBin[];
-
-#define MENU_OPTION_SIGNATURE      SIGNATURE_32 ('m', 'e', 'n', 'u')
-#define MENU_ENTRY_SIGNATURE       SIGNATURE_32 ('e', 'n', 't', 'r')
-
-///
-/// Define the maximum characters that will be accepted.
-///
-#define MAX_CHAR                480
-#define FILE_OPTION_OFFSET      0x8000
-#define FILE_OPTION_MASK        0x7FFF
-
-
-/**
-  This function processes the results of changes in configuration.
-  When user select a interactive opcode, this callback will be triggered.
-  Based on the Question(QuestionId) that triggers the callback, the 
corresponding
-  actions is performed. It handles:
-
-  1) the addition of boot option.
-  2) the addition of driver option.
-  3) exit from file browser
-  4) update of file content if a dir is selected.
-  5) boot the file if a file is selected in "boot from file"
-
-
-  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param Action          Specifies the type of action taken by the browser.
-  @param QuestionId      A unique value which is sent to the original 
exporting driver
-                         so that it can identify the type of data to expect.
-  @param Type            The type of value for the question.
-  @param Value           A pointer to the data being sent to the original 
exporting driver.
-  @param ActionRequest   On return, points to the action requested by the 
callback function.
-
-  @retval  EFI_SUCCESS           The callback successfully handled the action.
-  @retval  EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the 
variable and its data.
-  @retval  EFI_DEVICE_ERROR      The variable could not be saved.
-  @retval  EFI_UNSUPPORTED       The specified Action is not supported by the 
callback.
-
-**/
-EFI_STATUS
-EFIAPI
-LibCallback (
-  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
-  IN  EFI_BROWSER_ACTION                     Action,
-  IN  EFI_QUESTION_ID                        QuestionId,
-  IN  UINT8                                  Type,
-  IN  EFI_IFR_TYPE_VALUE                     *Value,
-  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
-  );
-
-
-/**
-  This function allows a caller to extract the current configuration for one
-  or more named elements from the target driver.
-
-
-  @param This            - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param Request         - A null-terminated Unicode string in <ConfigRequest> 
format.
-  @param Progress        - On return, points to a character in the Request 
string.
-                         Points to the string's null terminator if request was 
successful.
-                         Points to the most recent '&' before the first 
failing name/value
-                         pair (or the beginning of the string if the failure 
is in the
-                         first name/value pair) if the request was not 
successful.
-  @param Results         - A null-terminated Unicode string in <ConfigAltResp> 
format which
-                         has all values filled in for the names in the Request 
string.
-                         String to be allocated by the called function.
-
-  @retval  EFI_SUCCESS            The Results is filled with the requested 
values.
-  @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
-  @retval  EFI_INVALID_PARAMETER  Request is NULL, illegal syntax, or unknown 
name.
-  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in 
this driver.
-
-**/
-EFI_STATUS
-EFIAPI
-LibExtractConfig (
-  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
-  IN  CONST EFI_STRING                       Request,
-  OUT EFI_STRING                             *Progress,
-  OUT EFI_STRING                             *Results
-  );
-
-/**
-  This function processes the results of changes in configuration.
-
-
-  @param This            - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
-  @param Configuration   - A null-terminated Unicode string in <ConfigResp> 
format.
-  @param Progress        - A pointer to a string filled in with the offset of 
the most
-                         recent '&' before the first failing name/value pair 
(or the
-                         beginning of the string if the failure is in the first
-                         name/value pair) or the terminating NULL if all was 
successful.
-
-  @retval  EFI_SUCCESS            The Results is processed successfully.
-  @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
-  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in 
this driver.
-
-**/
-EFI_STATUS
-EFIAPI
-LibRouteConfig (
-  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
-  IN  CONST EFI_STRING                       Configuration,
-  OUT EFI_STRING                             *Progress
-  );
-
-/**
-  Update the file explower page with the refershed file system.
-
-  @param KeyValue        Key value to identify the type of data to expect.
-
-  @retval  EFI_SUCCESS   Update the file explorer form success.
-  @retval  other errors  Error occur when parse one directory.
-
-**/
-EFI_STATUS
-LibUpdateFileExplorer (
-  IN UINT16                       KeyValue
-  );
-  
-  
-/**
-  Get the device path info saved in the menu structure.
-
-  @param KeyValue        Key value to identify the type of data to expect.
-
-**/
-VOID
-LibGetDevicePath (
-  IN UINT16                       KeyValue
-  );
-
-#endif 
+/** @file
+   File explorer lib.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD 
License         
+which accompanies this distribution.  The full text of the license may be 
found at        
+http://opensource.org/licenses/bsd-license.php                                 
           
+                                                                               
           
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,          
           
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.  
           
+**/
+
+#ifndef _FILE_EXPLORER_H_
+#define _FILE_EXPLORER_H_
+
+#include <PiDxe.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+#include <Guid/FileInfo.h>
+#include <Guid/MdeModuleHii.h>
+
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/FormBrowser2.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/FileExplorerLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PrintLib.h>
+
+#include "FormGuid.h"
+
+#define FILE_EXPLORER_CALLBACK_DATA_SIGNATURE     SIGNATURE_32 ('f', 'e', 'c', 
'k')
+
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+  VENDOR_DEVICE_PATH             VendorDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL       End;
+} HII_VENDOR_DEVICE_PATH;
+
+typedef struct {
+  EFI_HANDLE                        DeviceHandle;
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+  EFI_FILE_HANDLE                   FileHandle;
+  UINT16                            *FileName;
+
+  BOOLEAN                           IsRoot;
+  BOOLEAN                           IsDir;
+} FILE_CONTEXT;
+
+typedef struct {
+  UINTN           Signature;
+  LIST_ENTRY      Link;
+  UINT16          *DisplayString;
+  UINT16          *HelpString;
+  EFI_STRING_ID   DisplayStringToken;
+  EFI_STRING_ID   HelpStringToken;
+  VOID            *VariableContext;
+} MENU_ENTRY;
+
+typedef struct {
+  UINTN           Signature;
+  LIST_ENTRY      Head;
+  UINTN           MenuNumber;
+  BOOLEAN         Used;
+} MENU_OPTION;
+
+typedef struct {
+  //
+  // Shared callback data.
+  //
+  UINTN                          Signature;
+
+  //
+  // File explorer formset callback data.
+  //
+  EFI_HII_HANDLE                 FeHiiHandle;
+  EFI_HANDLE                     FeDriverHandle;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess;
+  EFI_FORM_BROWSER2_PROTOCOL     *FormBrowser2;
+  MENU_OPTION                    *FsOptionMenu;
+  CHAR16                         *FileType;
+  CHOOSE_HANDLER                 ChooseHandler;
+  EFI_DEVICE_PATH_PROTOCOL       *RetDevicePath;
+
+} FILE_EXPLORER_CALLBACK_DATA;
+
+#define FILE_EXPLORER_PRIVATE_FROM_THIS(a)  CR (a, 
FILE_EXPLORER_CALLBACK_DATA, FeConfigAccess, 
FILE_EXPLORER_CALLBACK_DATA_SIGNATURE)
+
+#pragma pack()
+
+extern UINT8    FileExplorerVfrBin[];
+
+#define MENU_OPTION_SIGNATURE      SIGNATURE_32 ('m', 'e', 'n', 'u')
+#define MENU_ENTRY_SIGNATURE       SIGNATURE_32 ('e', 'n', 't', 'r')
+
+///
+/// Define the maximum characters that will be accepted.
+///
+#define MAX_CHAR                480
+#define FILE_OPTION_OFFSET      0x8000
+#define FILE_OPTION_MASK        0x7FFF
+
+
+/**
+  This function processes the results of changes in configuration.
+  When user select a interactive opcode, this callback will be triggered.
+  Based on the Question(QuestionId) that triggers the callback, the 
corresponding
+  actions is performed. It handles:
+
+  1) the addition of boot option.
+  2) the addition of driver option.
+  3) exit from file browser
+  4) update of file content if a dir is selected.
+  5) boot the file if a file is selected in "boot from file"
+
+
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param Action          Specifies the type of action taken by the browser.
+  @param QuestionId      A unique value which is sent to the original 
exporting driver
+                         so that it can identify the type of data to expect.
+  @param Type            The type of value for the question.
+  @param Value           A pointer to the data being sent to the original 
exporting driver.
+  @param ActionRequest   On return, points to the action requested by the 
callback function.
+
+  @retval  EFI_SUCCESS           The callback successfully handled the action.
+  @retval  EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the 
variable and its data.
+  @retval  EFI_DEVICE_ERROR      The variable could not be saved.
+  @retval  EFI_UNSUPPORTED       The specified Action is not supported by the 
callback.
+
+**/
+EFI_STATUS
+EFIAPI
+LibCallback (
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN  EFI_BROWSER_ACTION                     Action,
+  IN  EFI_QUESTION_ID                        QuestionId,
+  IN  UINT8                                  Type,
+  IN  EFI_IFR_TYPE_VALUE                     *Value,
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  );
+
+
+/**
+  This function allows a caller to extract the current configuration for one
+  or more named elements from the target driver.
+
+
+  @param This            - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param Request         - A null-terminated Unicode string in <ConfigRequest> 
format.
+  @param Progress        - On return, points to a character in the Request 
string.
+                         Points to the string's null terminator if request was 
successful.
+                         Points to the most recent '&' before the first 
failing name/value
+                         pair (or the beginning of the string if the failure 
is in the
+                         first name/value pair) if the request was not 
successful.
+  @param Results         - A null-terminated Unicode string in <ConfigAltResp> 
format which
+                         has all values filled in for the names in the Request 
string.
+                         String to be allocated by the called function.
+
+  @retval  EFI_SUCCESS            The Results is filled with the requested 
values.
+  @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
+  @retval  EFI_INVALID_PARAMETER  Request is NULL, illegal syntax, or unknown 
name.
+  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in 
this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+LibExtractConfig (
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN  CONST EFI_STRING                       Request,
+  OUT EFI_STRING                             *Progress,
+  OUT EFI_STRING                             *Results
+  );
+
+/**
+  This function processes the results of changes in configuration.
+
+
+  @param This            - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param Configuration   - A null-terminated Unicode string in <ConfigResp> 
format.
+  @param Progress        - A pointer to a string filled in with the offset of 
the most
+                         recent '&' before the first failing name/value pair 
(or the
+                         beginning of the string if the failure is in the first
+                         name/value pair) or the terminating NULL if all was 
successful.
+
+  @retval  EFI_SUCCESS            The Results is processed successfully.
+  @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
+  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in 
this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRouteConfig (
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN  CONST EFI_STRING                       Configuration,

@@ Diff output truncated at 100000 characters. @@

------------------------------------------------------------------------------
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to