You need to clarify in the function header comment for ChooseFile API if the 
caller needs to free the returned DevicePath (File parameter).

Also, ChooseFile API may fail to de-allocate memory upon some failure 
conditions.

Reviewed-by: Jaben Carsey <jaben.car...@intel.com>

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Eric
> Dong
> Sent: Tuesday, October 27, 2015 7:35 PM
> To: edk2-devel@lists.01.org
> Cc: Gao, Liming <liming....@intel.com>
> Subject: [edk2] [Patch] MdeModulePkg FileExplorerLib: Create file explorer
> library.
> 
> This library support select one file from the specified directory or from
> system root directory.
> 
> Cc: Liming Gao <liming....@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Eric Dong <eric.d...@intel.com>
> ---
>  MdeModulePkg/Include/Library/FileExplorerLib.h     |   57 +
>  .../Library/FileExplorerLib/FileExplorer.c         | 1507
> ++++++++++++++++++++
>  .../Library/FileExplorerLib/FileExplorer.h         |  240 ++++
>  .../Library/FileExplorerLib/FileExplorerLib.inf    |   58 +
>  .../Library/FileExplorerLib/FileExplorerString.uni |  Bin 0 -> 1852 bytes
>  .../Library/FileExplorerLib/FileExplorerVfr.vfr    |   32 +
>  MdeModulePkg/Library/FileExplorerLib/FormGuid.h    |   27 +
>  MdeModulePkg/MdeModulePkg.dec                      |    4 +
>  8 files changed, 1925 insertions(+)
>  create mode 100644 MdeModulePkg/Include/Library/FileExplorerLib.h
>  create mode 100644 MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
>  create mode 100644 MdeModulePkg/Library/FileExplorerLib/FileExplorer.h
>  create mode 100644
> MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
>  create mode 100644
> MdeModulePkg/Library/FileExplorerLib/FileExplorerString.uni
>  create mode 100644
> MdeModulePkg/Library/FileExplorerLib/FileExplorerVfr.vfr
>  create mode 100644 MdeModulePkg/Library/FileExplorerLib/FormGuid.h
> 
> diff --git a/MdeModulePkg/Include/Library/FileExplorerLib.h
> b/MdeModulePkg/Include/Library/FileExplorerLib.h
> new file mode 100644
> index 0000000..7e0d5a2
> --- /dev/null
> +++ b/MdeModulePkg/Include/Library/FileExplorerLib.h
> @@ -0,0 +1,57 @@
> +/** @file
> +
> +  This library class defines a set of interfaces for how to do file explorer.
> +
> +Copyright (c) 2007 - 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.
> +
> +**/
> +
> +#ifndef __FILE_EXPLORER_LIB_H__
> +#define __FILE_EXPLORER_LIB_H__
> +
> +/**
> +  Prototype for precessing the find file.
> +
> +  @param[in] FilePath     The device path of the find file.
> +
> +  @retval    TRUE         Need exit file explorer after do the extra task.
> +  @retval    FALSE        Not need to exit file explorer after do the extra 
> task.
> +
> +**/
> +typedef
> +BOOLEAN
> +(EFIAPI *EXTRA_ACTION)(
> +  IN EFI_DEVICE_PATH_PROTOCOL  *FilePath
> +  );
> +
> +/**
> +  Choose a file in the specified directory.
> +
> +  If user input NULL for the RootDirectory, will choose file in the system.
> +
> +  @param  RootDirectory    Pointer to the root directory.
> +  @param  FileType         The file type need to choose.
> +  @param  ExtraAction      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 the file success.
> +  @retval Other errors     Choose the file failed.
> +**/
> +EFI_STATUS
> +EFIAPI
> +ChooseFile (
> +  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDirectory,
> +  IN  CHAR16                    *FileType,
> +  IN  EXTRA_ACTION              ExtraAction,
> +  OUT EFI_DEVICE_PATH_PROTOCOL  **File
> +  );
> +
> +#endif
> diff --git a/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
> b/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
> new file mode 100644
> index 0000000..c862a2d
> --- /dev/null
> +++ b/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
> @@ -0,0 +1,1507 @@
> +/** @file
> +  File explorer related functions.
> +
> +  Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
> +  This software and associated documentation (if any) is furnished
> +  under a license and may only be used or copied in accordance
> +  with the terms of the license. Except as permitted by such
> +  license, no part of this software or documentation may be
> +  reproduced, stored in a retrieval system, or transmitted in any
> +  form or by any means without the express written consent of
> +  Intel Corporation.
> +
> +**/
> +
> +#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
> +};
> +
> +FILE_EXPLORER_CALLBACK_DATA  *gPrivatePtr;
> +
> +HII_VENDOR_DEVICE_PATH  FeHiiVendorDevicePath = {
> +  {
> +    {
> +      HARDWARE_DEVICE_PATH,
> +      HW_VENDOR_DP,
> +      {
> +        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
> +        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
> +      }
> +    },
> +    //
> +    // {91DB4238-B0C8-472e-BBFF-F3A6541010FF}
> +    //
> +    { 0x91db4238, 0xb0c8, 0x472e, { 0xbb, 0xff, 0xf3, 0xa6, 0x54, 0x10, 0x10,
> 0xff } }
> +  },
> +  {
> +    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 (gPrivatePtr->ExtraAction != NULL) {
> +        NeedExit = gPrivatePtr->ExtraAction (gPrivatePtr->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;
> +
> +  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 (gPrivatePtr->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;
> +  CHAR16  *Str;
> +  CHAR16  *TmpStr;
> +  CHAR16  *Ptr;
> +  CHAR16  *LastSlash;
> +
> +  Size1 = StrSize (Str1);
> +  Size2 = StrSize (Str2);
> +  Str   = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));
> +  ASSERT (Str != NULL);
> +
> +  TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));
> +  ASSERT (TmpStr != NULL);
> +
> +  StrCat (Str, Str1);
> +  if (!((*Str == '\\') && (*(Str + 1) == 0))) {
> +    StrCat (Str, L"\\");
> +  }
> +
> +  StrCat (Str, 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 StrCpy in BaseLib does not handle copy of
> two strings
> +      // that overlap.
> +      //
> +      StrCpy (TmpStr, Ptr + 3);
> +      StrCpy (LastSlash, TmpStr);
> +      Ptr = LastSlash;
> +    } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {
> +      //
> +      // Convert a "\.\" to a "\"
> +      //
> +
> +      //
> +      // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of
> two strings
> +      // that overlap.
> +      //
> +      StrCpy (TmpStr, Ptr + 2);
> +      StrCpy (Ptr, 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 (
> +                                             gPrivatePtr->FeHiiHandle,
> +                                             0,
> +                                             MenuEntry->DisplayString,
> +                                             NULL
> +                                             );
> +      FreePool (Info);
> +
> +      OptionNumber++;
> +      InsertTailList (&gPrivatePtr->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 (
> +                                           gPrivatePtr->FeHiiHandle,
> +                                           0,
> +                                           MenuEntry->DisplayString,
> +                                           NULL
> +                                           );
> +
> +      OptionNumber++;
> +      InsertTailList (&gPrivatePtr->FsOptionMenu->Head, &MenuEntry->Link);
> +    }
> +  }
> +
> +  if (NoLoadFileHandles != 0) {
> +    FreePool (LoadFileHandle);
> +  }
> +
> +  gPrivatePtr->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 (
> +                                           gPrivatePtr->FeHiiHandle,
> +                                           0,
> +                                           NewMenuEntry->DisplayString,
> +                                           NULL
> +                                           );
> +
> +      NewFileContext->IsRoot            = FALSE;
> +
> +      OptionNumber++;
> +      InsertTailList (&gPrivatePtr->FsOptionMenu->Head, &NewMenuEntry-
> >Link);
> +    }
> +  }
> +
> +  gPrivatePtr->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 = gPrivatePtr->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 (
> +    gPrivatePtr->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 (gPrivatePtr->FsOptionMenu,
> FileOptionMask);
> +  NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
> +
> +  if (NewFileContext->IsDir) {
> +    RemoveEntryList (&NewMenuEntry->Link);
> +    LibFreeMenu (gPrivatePtr->FsOptionMenu);
> +    LibGetFileHandleFromMenu (NewMenuEntry, &FileHandle);
> +    Status = LibFindFiles (FileHandle, NewFileContext->FileName,
> NewFileContext->DeviceHandle);
> +    if (!EFI_ERROR (Status)) {
> +      LibUpdateFileExplorePage ();
> +    } else {
> +      LibFreeMenu (gPrivatePtr->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 (gPrivatePtr->FsOptionMenu,
> FileOptionMask);
> +
> +  NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;
> +
> +  if (gPrivatePtr->RetDevicePath != NULL) {
> +    FreePool (gPrivatePtr->RetDevicePath);
> +  }
> +  gPrivatePtr->RetDevicePath = DuplicateDevicePath (NewFileContext-
> >DevicePath);
> +}
> +
> +/**
> +  Choose a file in the specified directory.
> +
> +  If user input NULL for the RootDirectory, will choose file in the system.
> +
> +  @param  RootDirectory    Pointer to the root directory.
> +  @param  FileType         The file type need to choose.
> +  @param  ExtraAction      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 the file success.
> +  @retval Other errors     Choose the file failed.
> +**/
> +EFI_STATUS
> +EFIAPI
> +ChooseFile (
> +  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDirectory,
> +  IN  CHAR16                    *FileType,
> +  IN  EXTRA_ACTION              ExtraAction,
> +  OUT EFI_DEVICE_PATH_PROTOCOL  **File
> +  )
> +{
> +  EFI_FILE_HANDLE                   FileHandle;
> +  EFI_STATUS                        Status;
> +  UINT16                            *FileName;
> +  EFI_HANDLE                        DeviceHandle;
> +
> +  gPrivatePtr->ExtraAction = ExtraAction;
> +  gPrivatePtr->FileType = AllocateCopyPool (StrSize (FileType), FileType);
> +  LibToLowerString(gPrivatePtr->FileType);
> +
> +  if (RootDirectory == NULL) {
> +    Status = LibFindFileSystem();
> +  } else {
> +    Status = LibGetFileHandleFromDevicePath(RootDirectory, &FileHandle,
> &FileName, &DeviceHandle);
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    Status = LibFindFiles (FileHandle, FileName, DeviceHandle);
> +  }
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  LibUpdateFileExplorePage();
> +
> +  gPrivatePtr->FormBrowser2->SendForm (
> +                         gPrivatePtr->FormBrowser2,
> +                         &gPrivatePtr->FeHiiHandle,
> +                         1,
> +                         &FileExplorerGuid,
> +                         0,
> +                         NULL,
> +                         NULL
> +                         );
> +
> +  *File  = gPrivatePtr->RetDevicePath;
> +
> +  gPrivatePtr->RetDevicePath = NULL;
> +  FreePool (gPrivatePtr->FileType);
> +  LibFreeMenu (gPrivatePtr->FsOptionMenu);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +
> +  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;
> +  EFI_HANDLE                     DriverHandle;
> +  EFI_DEVICE_PATH_PROTOCOL       *DevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL       *TmpDevicePath;
> +  EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
> +
> +  DevicePath = DuplicateDevicePath
> ((EFI_DEVICE_PATH_PROTOCOL*)&FeHiiVendorDevicePath);
> +  ASSERT (DevicePath != NULL);
> +  TmpDevicePath = DevicePath;
> +
> +  Status = gBS->LocateDevicePath (&gEfiHiiConfigAccessProtocolGuid,
> &TmpDevicePath, &DriverHandle);
> +  if (EFI_ERROR (Status)) {
> +    InitializeListHead (&gFileExplorerPrivate.FsOptionMenu->Head);
> +    gFileExplorerPrivate.ReferenceCount++;
> +
> +    //
> +    // Install Device Path Protocol and Config Access protocol to driver 
> handle
> +    //
> +    Status = gBS->InstallMultipleProtocolInterfaces (
> +                    &gFileExplorerPrivate.FeDriverHandle,
> +                    &gEfiDevicePathProtocolGuid,
> +                    &FeHiiVendorDevicePath,
> +                    &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);
> +
> +    gPrivatePtr = &gFileExplorerPrivate;
> +  } else {
> +    Status = gBS->HandleProtocol (DriverHandle,
> &gEfiHiiConfigAccessProtocolGuid, &ConfigAccess);
> +    ASSERT_EFI_ERROR (Status);
> +    gPrivatePtr = FILE_EXPLORER_PRIVATE_FROM_THIS (ConfigAccess);
> +    gPrivatePtr->ReferenceCount++;
> +  }
> +
> +  FreePool (DevicePath);
> +  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;
> +  EFI_HANDLE                     DriverHandle;
> +  EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
> +  EFI_DEVICE_PATH_PROTOCOL       *DevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL       *TmpDevicePath;
> +
> +  DevicePath = DuplicateDevicePath
> ((EFI_DEVICE_PATH_PROTOCOL*)&FeHiiVendorDevicePath);
> +  ASSERT (DevicePath != NULL);
> +  TmpDevicePath = DevicePath;
> +
> +  Status = gBS->LocateDevicePath (&gEfiHiiConfigAccessProtocolGuid,
> &TmpDevicePath, &DriverHandle);
> +  ASSERT_EFI_ERROR (Status);
> +  Status = gBS->HandleProtocol (DriverHandle,
> &gEfiHiiConfigAccessProtocolGuid, &ConfigAccess);
> +  ASSERT_EFI_ERROR (Status);
> +  gPrivatePtr = FILE_EXPLORER_PRIVATE_FROM_THIS (ConfigAccess);
> +
> +  if (gPrivatePtr->ReferenceCount == 1) {
> +    LibFreeMenu (gPrivatePtr->FsOptionMenu);
> +
> +    Status = gBS->UninstallMultipleProtocolInterfaces (
> +                    gPrivatePtr->FeDriverHandle,
> +                    &gEfiDevicePathProtocolGuid,
> +                    &FeHiiVendorDevicePath,
> +                    &gEfiHiiConfigAccessProtocolGuid,
> +                    &gPrivatePtr->FeConfigAccess,
> +                    NULL
> +                    );
> +    ASSERT_EFI_ERROR (Status);
> +
> +    HiiRemovePackages (gPrivatePtr->FeHiiHandle);
> +  }
> +
> +  gPrivatePtr->ReferenceCount--;
> +
> +  FreePool (DevicePath);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Library/FileExplorerLib/FileExplorer.h
> b/MdeModulePkg/Library/FileExplorerLib/FileExplorer.h
> new file mode 100644
> index 0000000..875fc77
> --- /dev/null
> +++ b/MdeModulePkg/Library/FileExplorerLib/FileExplorer.h
> @@ -0,0 +1,240 @@
> +/** @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;
> +  UINTN                          ReferenceCount;
> +  CHAR16                         *FileType;
> +  EXTRA_ACTION                   ExtraAction;
> +  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
> diff --git a/MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
> b/MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
> new file mode 100644
> index 0000000..bb4d813
> --- /dev/null
> +++ b/MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
> @@ -0,0 +1,58 @@
> +## @file
> +#  library defines a set of interfaces for how to do file explorer.
> +#
> +#  Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
> +#  This software and associated documentation (if any) is furnished
> +#  under a license and may only be used or copied in accordance
> +#  with the terms of the license. Except as permitted by such
> +#  license, no part of this software or documentation may be
> +#  reproduced, stored in a retrieval system, or transmitted in any
> +#  form or by any means without the express written consent of
> +#  Intel Corporation.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = FileExplorerLib
> +  FILE_GUID                      = 4FC9C630-0F90-4053-8F13-264CBD22FC58
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = FileExplorerLib|DXE_DRIVER 
> UEFI_APPLICATION
> +  CONSTRUCTOR                    = FileExplorerLibConstructor
> +  DESTRUCTOR                     = FileExplorerLibDestructor
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
> +#
> +
> +[Sources]
> +  FileExplorer.h
> +  FileExplorerVfr.vfr
> +  FileExplorerString.uni
> +  FileExplorer.c
> +  FormGuid.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  DevicePathLib
> +  BaseLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  BaseMemoryLib
> +  DebugLib
> +
> +[Guids]
> +  gEfiFileSystemVolumeLabelInfoIdGuid           ## CONSUMES ## GUID
> (Indicate the information type is volume)
> +  gEfiIfrTianoGuid                              ## CONSUMES ## GUID 
> (Extended IFR Guid
> Opcode)
> +
> +[Protocols]
> +  gEfiSimpleFileSystemProtocolGuid              ## PROTOCOL CONSUMES
> +  gEfiLoadFileProtocolGuid                      ## PROTOCOL CONSUMES
> +  gEfiHiiConfigAccessProtocolGuid               ## PROTOCOL CONSUMES
> +  gEfiFormBrowser2ProtocolGuid                  ## PROTOCOL CONSUMES
> diff --git a/MdeModulePkg/Library/FileExplorerLib/FileExplorerString.uni
> b/MdeModulePkg/Library/FileExplorerLib/FileExplorerString.uni
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..4315a368b80f2b78afb2
> e4e0b93017b379068488
> GIT binary patch
> literal 1852
> zcmc(g-EPxB5QXO&iFdG?n}TQy72E;hM-
> 8e}prWb7U6dwq8YyusJ0awWd5gk#W|C%&
> z5`?%x*4pdcnK@_9%-TQiPE6NhuFT$8ZeyF+&>q?YU(Z-
> g=X$@gxmDN|HsWo7wY&<(
> zoH1iovz{}nc)sH~V<)qZ)^oc#9tHEl`ph!BcE5@Huk5&imtwysPH8L09@(wOJS4^
> =
> zVw~DjuIJ2-)^E@3g*{<@4vr8f%oU*`hVDH_729KW-
> m)(X<rT4&Lxo?>sO%f}0hTYx
> z=Zn2=aO}Wk>^av&&WXDux_mRwa^TMziy3Ukj;v_XPAdzWVk?$gPMIBInXe<
> PJjcMu
> zv9GY!+pV)oHCnKvib(k$L#j$;)g<LJWp~BC@}KzZ#`hO)CvH)_KF^XE!B<sQ+&-7~
> z2h5|2DTgKYbGT)G7pnBH$Woe0q3uqSpDJ-?-
> <@%Zm$2khuKg8PvBdAjS=Xr12P?&I
> z##9d!pel;0qNrOA`|1|i|EWG31*KbxuDX}t%wQ>QVk-_c$coxjGI}h|(~vIfc^B5?
> zCi@|p$v4=@N_y9<rb=w8Qs9*`i4!=z_YcJsL6uj}MYN25jf%}+EPYfx)on;El#5P*
> z>ab+KK~^WI3!<~sy`gK$;BU^J>^EccB|1q~URmq@t%W+`JVH}_b@Vk7%YsvX
> &37rY
> z1Nuk%>H(dP1NYtSmy^wrwK>o7Yp>P)0fKzPQ_NbtrC+=&>)_M1PhehfbwSq3I
> V&HW
> zQSjP*-*Q=iG=hCI198z1^6m)#y1ENF)gVRQmvfseFVMKl_-
> dETKa=^H>(ODa<Ga5z
> f+=ZN0E%c8+PkaGNDj27w`fpma=>z=>_c8hf(BBml
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/MdeModulePkg/Library/FileExplorerLib/FileExplorerVfr.vfr
> b/MdeModulePkg/Library/FileExplorerLib/FileExplorerVfr.vfr
> new file mode 100644
> index 0000000..ee9755f
> --- /dev/null
> +++ b/MdeModulePkg/Library/FileExplorerLib/FileExplorerVfr.vfr
> @@ -0,0 +1,32 @@
> +///** @file
> +//
> +//    File Explorer Formset
> +//
> +//  Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
> +//  This software and associated documentation (if any) is furnished
> +//  under a license and may only be used or copied in accordance
> +//  with the terms of the license. Except as permitted by such
> +//  license, no part of this software or documentation may be
> +//  reproduced, stored in a retrieval system, or transmitted in any
> +//  form or by any means without the express written consent of
> +//  Intel Corporation.
> +
> +
> +//**/
> +
> +#include "FormGuid.h"
> +
> +formset
> +  guid = EFI_FILE_EXPLORE_FORMSET_GUID,
> +  title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE),
> +  help = STRING_TOKEN(STR_NULL_STRING),
> +  classguid = EFI_FILE_EXPLORE_FORMSET_GUID,
> +
> +  form formid = FORM_FILE_EXPLORER_ID,
> +       title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);
> +
> +       label FORM_FILE_EXPLORER_ID;
> +       label LABEL_END;
> +  endform;
> +
> +endformset;
> \ No newline at end of file
> diff --git a/MdeModulePkg/Library/FileExplorerLib/FormGuid.h
> b/MdeModulePkg/Library/FileExplorerLib/FormGuid.h
> new file mode 100644
> index 0000000..d842012
> --- /dev/null
> +++ b/MdeModulePkg/Library/FileExplorerLib/FormGuid.h
> @@ -0,0 +1,27 @@
> +/** @file
> +  Formset guids, form id and VarStore data structure for Boot Maintenance
> Manager.
> +
> +  Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
> +  This software and associated documentation (if any) is furnished
> +  under a license and may only be used or copied in accordance
> +  with the terms of the license. Except as permitted by such
> +  license, no part of this software or documentation may be
> +  reproduced, stored in a retrieval system, or transmitted in any
> +  form or by any means without the express written consent of
> +  Intel Corporation.
> +
> +**/
> +#ifndef _FILE_EXPLORER_FORM_GUID_H_
> +#define _FILE_EXPLORER_FORM_GUID_H_
> +
> +
> +#define EFI_FILE_EXPLORE_FORMSET_GUID \
> +  { \
> +  0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c,
> 0x5b} \
> +  }
> +
> +#define FORM_FILE_EXPLORER_ID                0x1000
> +#define LABEL_END                            0xffff
> +
> +#endif
> +
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec
> index 3dfcd6a..d45e49a 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -128,10 +128,14 @@
>    VarCheckLib|Include/Library/VarCheckLib.h
> 
>    ## @libraryclass  Provides services to get variable error flag and do 
> platform
> variable cleanup.
>    #
>    PlatformVarCleanupLib|Include/Library/PlatformVarCleanupLib.h
> +
> +  ## @libraryclass  Provides services to get do the file explorer.
> +  #
> +  FileExplorerLib|Include/Library/FileExplorerLib.h
> 
>  [Guids]
>    ## MdeModule package token space guid
>    # Include/Guid/MdeModulePkgTokenSpace.h
>    gEfiMdeModulePkgTokenSpaceGuid       = { 0xA1AFF049, 0xFDEB, 0x442a, {
> 0xB3, 0x20, 0x13, 0xAB, 0x4C, 0xB7, 0x2B, 0xBC }}
> --
> 1.9.5.msysgit.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to