]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Library / FileExplorerLib / FileExplorer.c
index 9f75d6ede544080eec8fc8a8ad602ab6d56b8519..27f12fcbf986e24698373a35a67eda9762021718 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
 File explorer related functions.\r
 \r
-Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials are licensed and made available under\r
-the terms and conditions of the BSD License that accompanies this distribution.\r
-The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php.\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -61,7 +55,7 @@ HII_VENDOR_DEVICE_PATH  FeHiiVendorDevicePath = {
   {\r
     END_DEVICE_PATH_TYPE,\r
     END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
-    { \r
+    {\r
       (UINT8) (END_DEVICE_PATH_LENGTH),\r
       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
     }\r
@@ -72,6 +66,25 @@ VOID                *mLibStartOpCodeHandle = NULL;
 VOID                *mLibEndOpCodeHandle = NULL;\r
 EFI_IFR_GUID_LABEL  *mLibStartLabel = NULL;\r
 EFI_IFR_GUID_LABEL  *mLibEndLabel = NULL;\r
+UINT16              mQuestionIdUpdate;\r
+CHAR16  mNewFileName[MAX_FILE_NAME_LEN];\r
+CHAR16  mNewFolderName[MAX_FOLDER_NAME_LEN];\r
+UINTN  mNewFileQuestionId    = NEW_FILE_QUESTION_ID_BASE;\r
+UINTN  mNewFolderQuestionId  = NEW_FOLDER_QUESTION_ID_BASE;\r
+\r
+/**\r
+  Create a new file or folder in current directory.\r
+\r
+  @param FileName              Point to the fileNmae or folder.\r
+  @param CreateFile            CreateFile== TRUE  means create a new file.\r
+                               CreateFile== FALSE means create a new Folder.\r
+\r
+**/\r
+EFI_STATUS\r
+LibCreateNewFile (\r
+  IN CHAR16     *FileName,\r
+  IN BOOLEAN    CreateFile\r
+  );\r
 \r
 /**\r
   This function allows a caller to extract the current configuration for one\r
@@ -174,9 +187,13 @@ LibCallback (
 {\r
   EFI_STATUS    Status;\r
   BOOLEAN       NeedExit;\r
+  CHAR16        *NewFileName;\r
+  CHAR16        *NewFolderName;\r
 \r
   NeedExit = TRUE;\r
-  \r
+  NewFileName   = NULL;\r
+  NewFolderName = NULL;\r
+\r
   if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {\r
     //\r
     // Do nothing for other UEFI Action. Only do call back when data is changed.\r
@@ -188,7 +205,55 @@ LibCallback (
     if ((Value == NULL) || (ActionRequest == NULL)) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
-    \r
+\r
+    if (QuestionId == KEY_VALUE_CREATE_FILE_AND_EXIT) {\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+      if (!IsZeroBuffer (mNewFileName, sizeof (mNewFileName))) {\r
+        Status = LibCreateNewFile (mNewFileName,TRUE);\r
+        ZeroMem (mNewFileName,sizeof (mNewFileName));\r
+      }\r
+    }\r
+\r
+    if (QuestionId == KEY_VALUE_NO_CREATE_FILE_AND_EXIT) {\r
+      ZeroMem (mNewFileName,sizeof (mNewFileName));\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+    }\r
+\r
+    if (QuestionId == KEY_VALUE_CREATE_FOLDER_AND_EXIT) {\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+      if (!IsZeroBuffer (mNewFolderName, sizeof (mNewFolderName))) {\r
+        Status = LibCreateNewFile (mNewFolderName, FALSE);\r
+        ZeroMem (mNewFolderName,sizeof (mNewFolderName));\r
+      }\r
+    }\r
+\r
+    if (QuestionId == KEY_VALUE_NO_CREATE_FOLDER_AND_EXIT) {\r
+      ZeroMem (mNewFolderName,sizeof (mNewFolderName));\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+    }\r
+\r
+    if (QuestionId == NEW_FILE_NAME_ID) {\r
+      NewFileName = HiiGetString (gFileExplorerPrivate.FeHiiHandle, Value->string, NULL);\r
+      if (NewFileName != NULL) {\r
+        StrCpyS (mNewFileName, MAX_FILE_NAME_LEN, NewFileName);\r
+        FreePool (NewFileName);\r
+        NewFileName = NULL;\r
+      } else {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+\r
+    if (QuestionId == NEW_FOLDER_NAME_ID) {\r
+      NewFolderName = HiiGetString (gFileExplorerPrivate.FeHiiHandle, Value->string, NULL);\r
+      if (NewFolderName != NULL) {\r
+        StrCpyS (mNewFolderName, MAX_FOLDER_NAME_LEN, NewFolderName);\r
+        FreePool (NewFolderName);\r
+        NewFolderName = NULL;\r
+      } else {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+\r
     if (QuestionId >= FILE_OPTION_OFFSET) {\r
       LibGetDevicePath(QuestionId);\r
 \r
@@ -207,8 +272,8 @@ LibCallback (
     if (Value == NULL) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
-    \r
     if (QuestionId >= FILE_OPTION_OFFSET) {\r
+      LibGetDevicePath(QuestionId);\r
       Status = LibUpdateFileExplorer (QuestionId);\r
       if (EFI_ERROR (Status)) {\r
         return Status;\r
@@ -483,7 +548,7 @@ LibFileInfo (
 \r
   Buffer      = NULL;\r
   BufferSize  = 0;\r
-  \r
+\r
   Status = FHand->GetInfo (\r
                     FHand,\r
                     InfoType,\r
@@ -620,11 +685,19 @@ LibAppendFileName (
 \r
   Size1 = StrSize (Str1);\r
   Size2 = StrSize (Str2);\r
+\r
+  //\r
+  // Check overflow\r
+  //\r
+  if (((MAX_UINTN - Size1) < Size2) || ((MAX_UINTN - Size1 - Size2) < sizeof(CHAR16))) {\r
+    return NULL;\r
+  }\r
+\r
   MaxLen = (Size1 + Size2 + sizeof (CHAR16))/ sizeof (CHAR16);\r
   Str   = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));\r
   ASSERT (Str != NULL);\r
 \r
-  TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); \r
+  TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));\r
   ASSERT (TmpStr != NULL);\r
 \r
   StrCpyS (Str, MaxLen, Str1);\r
@@ -645,11 +718,11 @@ LibAppendFileName (
       //\r
 \r
       //\r
-      // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings \r
+      // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings\r
       // that overlap.\r
       //\r
       StrCpyS (TmpStr, MaxLen, Ptr + 3);\r
-      StrCpyS (LastSlash, MaxLen - (UINTN) (LastSlash - Str), TmpStr);\r
+      StrCpyS (LastSlash, MaxLen - ((UINTN) LastSlash - (UINTN) Str) / sizeof (CHAR16), TmpStr);\r
       Ptr = LastSlash;\r
     } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
       //\r
@@ -657,11 +730,11 @@ LibAppendFileName (
       //\r
 \r
       //\r
-      // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings \r
+      // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings\r
       // that overlap.\r
       //\r
       StrCpyS (TmpStr, MaxLen, Ptr + 2);\r
-      StrCpyS (Ptr, MaxLen - (UINTN) (Ptr - Str), TmpStr);\r
+      StrCpyS (Ptr, MaxLen - ((UINTN) Ptr - (UINTN) Str) / sizeof (CHAR16), TmpStr);\r
       Ptr = LastSlash;\r
     } else if (*Ptr == '\\') {\r
       LastSlash = Ptr;\r
@@ -671,7 +744,7 @@ LibAppendFileName (
   }\r
 \r
   FreePool (TmpStr);\r
-  \r
+\r
   return Str;\r
 }\r
 \r
@@ -691,9 +764,7 @@ LibFindFileSystem (
   )\r
 {\r
   UINTN                        NoSimpleFsHandles;\r
-  UINTN                        NoLoadFileHandles;\r
   EFI_HANDLE                   *SimpleFsHandle;\r
-  EFI_HANDLE                   *LoadFileHandle;\r
   UINT16                       *VolumeLabel;\r
   UINTN                        Index;\r
   EFI_STATUS                   Status;\r
@@ -703,7 +774,6 @@ LibFindFileSystem (
   EFI_FILE_SYSTEM_VOLUME_LABEL *Info;\r
 \r
   NoSimpleFsHandles = 0;\r
-  NoLoadFileHandles = 0;\r
   OptionNumber      = 0;\r
 \r
   //\r
@@ -769,13 +839,15 @@ LibFindFileSystem (
         VolumeLabel,\r
         MenuEntry->HelpString\r
         );\r
-         MenuEntry->DisplayStringToken = HiiSetString (\r
+      MenuEntry->DisplayStringToken = HiiSetString (\r
                                              gFileExplorerPrivate.FeHiiHandle,\r
                                              0,\r
                                              MenuEntry->DisplayString,\r
                                              NULL\r
                                              );\r
-      FreePool (Info);\r
+\r
+      if (Info != NULL)\r
+        FreePool (Info);\r
 \r
       OptionNumber++;\r
       InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, &MenuEntry->Link);\r
@@ -786,57 +858,6 @@ LibFindFileSystem (
     FreePool (SimpleFsHandle);\r
   }\r
 \r
-  //\r
-  // Searching for handles that support Load File protocol\r
-  //\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiLoadFileProtocolGuid,\r
-                  NULL,\r
-                  &NoLoadFileHandles,\r
-                  &LoadFileHandle\r
-                  );\r
-\r
-  if (!EFI_ERROR (Status)) {\r
-    for (Index = 0; Index < NoLoadFileHandles; Index++) {\r
-      MenuEntry = LibCreateMenuEntry ();\r
-      if (NULL == MenuEntry) {\r
-        FreePool (LoadFileHandle);\r
-        return EFI_OUT_OF_RESOURCES;\r
-      }\r
-\r
-      FileContext = (FILE_CONTEXT *) MenuEntry->VariableContext;\r
-      FileContext->DeviceHandle = LoadFileHandle[Index];\r
-      FileContext->IsRoot = TRUE;\r
-\r
-      FileContext->DevicePath = DevicePathFromHandle (FileContext->DeviceHandle);\r
-      FileContext->FileName = LibDevicePathToStr (FileContext->DevicePath);\r
-\r
-      MenuEntry->HelpString = LibDevicePathToStr (FileContext->DevicePath);\r
-      MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
-      ASSERT (MenuEntry->DisplayString != NULL);\r
-      UnicodeSPrint (\r
-        MenuEntry->DisplayString,\r
-        MAX_CHAR,\r
-        L"Load File [%s]",\r
-        MenuEntry->HelpString\r
-        );\r
-      MenuEntry->DisplayStringToken = HiiSetString (\r
-                                           gFileExplorerPrivate.FeHiiHandle,\r
-                                           0,\r
-                                           MenuEntry->DisplayString,\r
-                                           NULL\r
-                                           );\r
-\r
-      OptionNumber++;\r
-      InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, &MenuEntry->Link);\r
-    }\r
-  }\r
-\r
-  if (NoLoadFileHandles != 0) {\r
-    FreePool (LoadFileHandle);\r
-  }\r
-\r
   gFileExplorerPrivate.FsOptionMenu->MenuNumber = OptionNumber;\r
 \r
   return EFI_SUCCESS;\r
@@ -844,16 +865,16 @@ LibFindFileSystem (
 \r
 /**\r
   Find the file handle from the input menu info.\r
-  \r
+\r
   @param  MenuEntry        Input Menu info.\r
   @param  RetFileHandle    Return the file handle for the input device path.\r
-  \r
+\r
   @retval EFI_SUCESS       Find the file handle success.\r
   @retval Other            Find the file handle failure.\r
 **/\r
 EFI_STATUS\r
 LibGetFileHandleFromMenu (\r
-  IN  MENU_ENTRY                *MenuEntry,  \r
+  IN  MENU_ENTRY                *MenuEntry,\r
   OUT EFI_FILE_HANDLE           *RetFileHandle\r
   )\r
 {\r
@@ -890,18 +911,18 @@ LibGetFileHandleFromMenu (
 \r
 /**\r
   Find the file handle from the input device path info.\r
-  \r
+\r
   @param  RootDirectory    Device path info.\r
   @param  RetFileHandle    Return the file handle for the input device path.\r
   @param  ParentFileName   Parent file name.\r
   @param  DeviceHandle     Driver handle for this partition.\r
-  \r
+\r
   @retval EFI_SUCESS       Find the file handle success.\r
   @retval Other            Find the file handle failure.\r
 **/\r
 EFI_STATUS\r
 LibGetFileHandleFromDevicePath (\r
-  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDirectory,  \r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDirectory,\r
   OUT EFI_FILE_HANDLE           *RetFileHandle,\r
   OUT UINT16                    **ParentFileName,\r
   OUT EFI_HANDLE                *DeviceHandle\r
@@ -926,12 +947,12 @@ LibGetFileHandleFromDevicePath (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  \r
+\r
   Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&Volume);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  \r
+\r
   //\r
   // Open the Volume to get the File System handle\r
   //\r
@@ -947,7 +968,7 @@ LibGetFileHandleFromDevicePath (
     *RetFileHandle = FileHandle;\r
     return EFI_SUCCESS;\r
   }\r
-  \r
+\r
   //\r
   // Duplicate the device path to avoid the access to unaligned device path node.\r
   // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH\r
@@ -961,8 +982,9 @@ LibGetFileHandleFromDevicePath (
     // the file system support below to be skipped.\r
     //\r
     Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
   }\r
-        \r
+\r
   //\r
   // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the\r
   // directory information and filename can be seperate. The goal is to inch\r
@@ -990,6 +1012,11 @@ LibGetFileHandleFromDevicePath (
       *ParentFileName = AllocateCopyPool (StrSize (((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName), ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName);\r
     } else {\r
       TempPath = LibAppendFileName (*ParentFileName, ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName);\r
+      if (TempPath == NULL) {\r
+        LastHandle->Close (LastHandle);\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
+      }\r
       FreePool (*ParentFileName);\r
       *ParentFileName = TempPath;\r
     }\r
@@ -1022,13 +1049,79 @@ Done:
   return Status;\r
 }\r
 \r
+/**\r
+  Create a new file or folder in current directory.\r
+\r
+  @param FileName              Point to the fileNmae or folder name.\r
+  @param CreateFile            CreateFile== TRUE  means create a new file.\r
+                               CreateFile== FALSE means create a new Folder.\r
+\r
+**/\r
+EFI_STATUS\r
+LibCreateNewFile (\r
+  IN CHAR16     *FileName,\r
+  IN BOOLEAN    CreateFile\r
+  )\r
+{\r
+  EFI_FILE_HANDLE      FileHandle;\r
+  EFI_FILE_HANDLE      NewHandle;\r
+  EFI_HANDLE           DeviceHandle;\r
+  EFI_STATUS           Status;\r
+  CHAR16               *ParentName;\r
+  CHAR16               *FullFileName;\r
+\r
+  NewHandle = NULL;\r
+  FullFileName = NULL;\r
+\r
+  LibGetFileHandleFromDevicePath(gFileExplorerPrivate.RetDevicePath, &FileHandle, &ParentName, &DeviceHandle);\r
+  FullFileName = LibAppendFileName (ParentName, FileName);\r
+  if (FullFileName == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  if (CreateFile) {\r
+    Status = FileHandle->Open(\r
+                          FileHandle,\r
+                          &NewHandle,\r
+                          FullFileName,\r
+                          EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,\r
+                          0\r
+                          );\r
+    if (EFI_ERROR (Status)) {\r
+      FileHandle->Close (FileHandle);\r
+      return Status;\r
+    }\r
+  } else {\r
+    Status = FileHandle->Open(\r
+                          FileHandle,\r
+                          &NewHandle,\r
+                          FullFileName,\r
+                          EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,\r
+                          EFI_FILE_DIRECTORY\r
+                          );\r
+    if (EFI_ERROR (Status)) {\r
+      FileHandle->Close (FileHandle);\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  FileHandle->Close (FileHandle);\r
+\r
+  //\r
+  // Return the DevicePath of the new created file or folder.\r
+  //\r
+  gFileExplorerPrivate.RetDevicePath = FileDevicePath (DeviceHandle, FullFileName);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
 /**\r
   Find files under current directory.\r
-  \r
+\r
   All files and sub-directories in current directory\r
   will be stored in DirectoryMenu for future use.\r
 \r
-  @param FileHandle    Parent file handle. \r
+  @param FileHandle    Parent file handle.\r
   @param FileName      Parent file name.\r
   @param DeviceHandle  Driver handle for this partition.\r
 \r
@@ -1065,12 +1158,14 @@ LibFindFiles (
   // Pass 1 to get Directories\r
   // Pass 2 to get files that are EFI images\r
   //\r
+  Status = EFI_SUCCESS;\r
   for (Pass = 1; Pass <= 2; Pass++) {\r
     FileHandle->SetPosition (FileHandle, 0);\r
     for (;;) {\r
       BufferSize  = DirBufferSize;\r
       Status      = FileHandle->Read (FileHandle, &BufferSize, DirInfo);\r
       if (EFI_ERROR (Status) || BufferSize == 0) {\r
+        Status = EFI_SUCCESS;\r
         break;\r
       }\r
 \r
@@ -1093,12 +1188,18 @@ LibFindFiles (
 \r
       NewMenuEntry = LibCreateMenuEntry ();\r
       if (NULL == NewMenuEntry) {\r
-        return EFI_OUT_OF_RESOURCES;\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
       }\r
 \r
       NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
       NewFileContext->DeviceHandle = DeviceHandle;\r
       NewFileContext->FileName = LibAppendFileName (FileName, DirInfo->FileName);\r
+      if  (NewFileContext->FileName == NULL) {\r
+        LibDestroyMenuEntry (NewMenuEntry);\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
+      }\r
       NewFileContext->FileHandle = FileHandle;\r
       NewFileContext->DevicePath = FileDevicePath (NewFileContext->DeviceHandle, NewFileContext->FileName);\r
       NewMenuEntry->HelpString = NULL;\r
@@ -1116,7 +1217,7 @@ LibFindFiles (
       } else {\r
         NewMenuEntry->DisplayString = LibStrDuplicate (DirInfo->FileName);\r
       }\r
-      \r
+\r
       NewMenuEntry->DisplayStringToken = HiiSetString (\r
                                            gFileExplorerPrivate.FeHiiHandle,\r
                                            0,\r
@@ -1133,9 +1234,11 @@ LibFindFiles (
 \r
   gFileExplorerPrivate.FsOptionMenu->MenuNumber = OptionNumber;\r
 \r
+Done:\r
+\r
   FreePool (DirInfo);\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -1204,24 +1307,54 @@ LibUpdateFileExplorePage (
   MENU_ENTRY      *NewMenuEntry;\r
   FILE_CONTEXT    *NewFileContext;\r
   MENU_OPTION     *MenuOption;\r
+  BOOLEAN         CreateNewFile;\r
 \r
   NewMenuEntry    = NULL;\r
   NewFileContext  = NULL;\r
+  CreateNewFile   = FALSE;\r
 \r
   LibRefreshUpdateData ();\r
   MenuOption = gFileExplorerPrivate.FsOptionMenu;\r
 \r
+  mQuestionIdUpdate += QUESTION_ID_UPDATE_STEP;\r
+\r
   for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
     NewMenuEntry    = LibGetMenuEntry (MenuOption, Index);\r
     NewFileContext  = (FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
 \r
+    if (!NewFileContext->IsRoot && !CreateNewFile) {\r
+      HiiCreateGotoOpCode (\r
+        mLibStartOpCodeHandle,\r
+        FORM_ADD_NEW_FILE_ID,\r
+        STRING_TOKEN (STR_NEW_FILE),\r
+        STRING_TOKEN (STR_NEW_FILE_HELP),\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        (UINT16) (mNewFileQuestionId++)\r
+        );\r
+      HiiCreateGotoOpCode (\r
+        mLibStartOpCodeHandle,\r
+        FORM_ADD_NEW_FOLDER_ID,\r
+        STRING_TOKEN (STR_NEW_FOLDER),\r
+        STRING_TOKEN (STR_NEW_FOLDER_HELP),\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        (UINT16) (mNewFolderQuestionId++)\r
+        );\r
+      HiiCreateTextOpCode(\r
+        mLibStartOpCodeHandle,\r
+        STRING_TOKEN (STR_NULL_STRING),\r
+        STRING_TOKEN (STR_NULL_STRING),\r
+        0\r
+        );\r
+      CreateNewFile = TRUE;\r
+    }\r
+\r
     if (!NewFileContext->IsDir) {\r
       //\r
       // Create Text opcode for directory, also create Text opcode for file in FileExplorerStateBootFromFile.\r
       //\r
       HiiCreateActionOpCode (\r
         mLibStartOpCodeHandle,\r
-        (UINT16) (FILE_OPTION_OFFSET + Index),\r
+        (UINT16) (FILE_OPTION_OFFSET + Index + mQuestionIdUpdate),\r
         NewMenuEntry->DisplayStringToken,\r
         STRING_TOKEN (STR_NULL_STRING),\r
         EFI_IFR_FLAG_CALLBACK,\r
@@ -1237,7 +1370,7 @@ LibUpdateFileExplorePage (
         NewMenuEntry->DisplayStringToken,\r
         STRING_TOKEN (STR_NULL_STRING),\r
         EFI_IFR_FLAG_CALLBACK,\r
-        (UINT16) (FILE_OPTION_OFFSET + Index)\r
+        (UINT16) (FILE_OPTION_OFFSET + Index + mQuestionIdUpdate)\r
         );\r
     }\r
   }\r
@@ -1272,7 +1405,7 @@ LibUpdateFileExplorer (
   EFI_FILE_HANDLE FileHandle;\r
 \r
   Status = EFI_SUCCESS;\r
-  FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue);\r
+  FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue) - mQuestionIdUpdate;\r
   NewMenuEntry   = LibGetMenuEntry (gFileExplorerPrivate.FsOptionMenu, FileOptionMask);\r
   NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
 \r
@@ -1307,7 +1440,7 @@ LibGetDevicePath (
   MENU_ENTRY      *NewMenuEntry;\r
   FILE_CONTEXT    *NewFileContext;\r
 \r
-  FileOptionMask    = (UINT16) (FILE_OPTION_MASK & KeyValue);\r
+  FileOptionMask    = (UINT16) (FILE_OPTION_MASK & KeyValue) - mQuestionIdUpdate;\r
 \r
   NewMenuEntry = LibGetMenuEntry (gFileExplorerPrivate.FsOptionMenu, FileOptionMask);\r
 \r
@@ -1320,7 +1453,7 @@ LibGetDevicePath (
 }\r
 \r
 /**\r
-  Choose a file in the specified directory. \r
+  Choose a file in the specified directory.\r
 \r
   If user input NULL for the RootDirectory, will choose file in the system.\r
 \r
@@ -1356,6 +1489,7 @@ ChooseFile (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  mQuestionIdUpdate = 0;\r
   FileName = NULL;\r
 \r
   gFileExplorerPrivate.RetDevicePath = NULL;\r
@@ -1472,7 +1606,7 @@ FileExplorerLibConstructor (
   //\r
   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFileExplorerPrivate.FormBrowser2);\r
   ASSERT_EFI_ERROR (Status);\r
-    \r
+\r
   InitializeListHead (&gFileExplorerPrivate.FsOptionMenu->Head);\r
 \r
   return EFI_SUCCESS;\r
@@ -1507,7 +1641,7 @@ FileExplorerLibDestructor (
                     NULL\r
                     );\r
     ASSERT_EFI_ERROR (Status);\r
-    \r
+\r
     HiiRemovePackages (gFileExplorerPrivate.FeHiiHandle);\r
   }\r
 \r