]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/ShellProtocol.c
ShellPkg/Shell - Fix ASSERT() when FvSimpleFileSystemDxe is used
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellProtocol.c
index 72d42d7222810641b32d0a43e58c40590c1d475a..def3bd35c208e6a7a669a744e55db1cd338231ee 100644 (file)
@@ -449,38 +449,37 @@ EfiShellGetFilePathFromDevicePath(
           ; FilePath = (FILEPATH_DEVICE_PATH*)NextDevicePathNode (&FilePath->Header)\r
          ){\r
         //\r
-        // all the rest should be file path nodes\r
+        // If any node is not a file path node, then the conversion can not be completed\r
         //\r
         if ((DevicePathType(&FilePath->Header) != MEDIA_DEVICE_PATH) ||\r
             (DevicePathSubType(&FilePath->Header) != MEDIA_FILEPATH_DP)) {\r
           FreePool(PathForReturn);\r
-          PathForReturn = NULL;\r
-          ASSERT(FALSE);\r
-        } else {\r
-          //\r
-          // append the path part onto the filepath.\r
-          //\r
-          ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
-\r
-          AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
-          ASSERT (AlignedNode != NULL);\r
-\r
-          // File Path Device Path Nodes 'can optionally add a "\" separator to\r
-          //  the beginning and/or the end of the Path Name string.'\r
-          // (UEFI Spec 2.4 section 9.3.6.4).\r
-          // If necessary, add a "\", but otherwise don't\r
-          // (This is specified in the above section, and also implied by the\r
-          //  UEFI Shell spec section 3.7)\r
-          if ((PathSize != 0)                        &&\r
-              (PathForReturn != NULL)                &&\r
-              (PathForReturn[PathSize - 1] != L'\\') &&\r
-              (AlignedNode->PathName[0]    != L'\\')) {\r
-            PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);\r
-          }\r
+          return NULL;\r
+        }\r
 \r
-          PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
-          FreePool(AlignedNode);\r
+        //\r
+        // append the path part onto the filepath.\r
+        //\r
+        ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
+\r
+        AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
+        ASSERT (AlignedNode != NULL);\r
+\r
+        // File Path Device Path Nodes 'can optionally add a "\" separator to\r
+        //  the beginning and/or the end of the Path Name string.'\r
+        // (UEFI Spec 2.4 section 9.3.6.4).\r
+        // If necessary, add a "\", but otherwise don't\r
+        // (This is specified in the above section, and also implied by the\r
+        //  UEFI Shell spec section 3.7)\r
+        if ((PathSize != 0)                        &&\r
+            (PathForReturn != NULL)                &&\r
+            (PathForReturn[PathSize - 1] != L'\\') &&\r
+            (AlignedNode->PathName[0]    != L'\\')) {\r
+          PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);\r
         }\r
+\r
+        PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
+        FreePool(AlignedNode);\r
       } // for loop of remaining nodes\r
     }\r
     if (PathForReturn != NULL) {\r
@@ -532,17 +531,18 @@ EfiShellGetDevicePathFromFilePath(
     if (Cwd == NULL) {\r
       return (NULL);\r
     }\r
-    Size = StrSize(Cwd) + StrSize(Path) - sizeof(CHAR16);\r
+    Size = StrSize(Cwd) + StrSize(Path);\r
     NewPath = AllocateZeroPool(Size);\r
     if (NewPath == NULL) {\r
       return (NULL);\r
     }\r
-    StrnCpy(NewPath, Cwd, Size/sizeof(CHAR16)-1);\r
+    StrCpyS(NewPath, Size/sizeof(CHAR16), Cwd);\r
+    StrCatS(NewPath, Size/sizeof(CHAR16), L"\\");\r
     if (*Path == L'\\') {\r
       Path++;\r
       while (PathRemoveLastItem(NewPath)) ;\r
     }\r
-    StrnCat(NewPath, Path, Size/sizeof(CHAR16) - 1 - StrLen(NewPath));\r
+    StrCatS(NewPath, Size/sizeof(CHAR16), Path);\r
     DevicePathForReturn = EfiShellGetDevicePathFromFilePath(NewPath);\r
     FreePool(NewPath);\r
     return (DevicePathForReturn);\r
@@ -1500,7 +1500,7 @@ InternalShellExecuteDevicePath(
     ShellParamsProtocol.StdIn   = ShellInfoObject.NewShellParametersProtocol->StdIn;\r
     ShellParamsProtocol.StdOut  = ShellInfoObject.NewShellParametersProtocol->StdOut;\r
     ShellParamsProtocol.StdErr  = ShellInfoObject.NewShellParametersProtocol->StdErr;\r
-    Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, NULL, NULL);\r
+    Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, Efi_Application, NULL, NULL);\r
     ASSERT_EFI_ERROR(Status);\r
     //\r
     // Replace Argv[0] with the full path of the binary we're executing:\r
@@ -1630,40 +1630,62 @@ EfiShellExecute(
   CHAR16                    *Temp;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   UINTN                     Size;\r
+  EFI_STATUS                CalleeStatusCode;\r
 \r
+  CalleeStatusCode = EFI_SUCCESS;\r
+  \r
   if ((PcdGet8(PcdShellSupportLevel) < 1)) {\r
     return (EFI_UNSUPPORTED);\r
   }\r
 \r
-  DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
+  if (Environment != NULL) {\r
+    // If Environment isn't null, load a new image of the shell with its own\r
+    // environment\r
+    DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
\r
+    DEBUG_CODE_BEGIN();\r
+    Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
+    FreePool(Temp);\r
+    Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);\r
+    FreePool(Temp);\r
+    Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);\r
+    FreePool(Temp);\r
+    DEBUG_CODE_END();\r
+\r
+    Temp = NULL;\r
+    Size = 0;\r
+    ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));\r
+    StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);\r
+    StrnCatGrow(&Temp, &Size, CommandLine, 0);\r
 \r
-  DEBUG_CODE_BEGIN();\r
-  Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
-  FreePool(Temp);\r
-  Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);\r
-  FreePool(Temp);\r
-  Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);\r
-  FreePool(Temp);\r
-  DEBUG_CODE_END();\r
+    Status = InternalShellExecuteDevicePath(\r
+      ParentImageHandle,\r
+      DevPath,\r
+      Temp,\r
+      (CONST CHAR16**)Environment,\r
+      StatusCode);\r
 \r
-  Temp = NULL;\r
-  Size = 0;\r
-  ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));\r
-  StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);\r
-  StrnCatGrow(&Temp, &Size, CommandLine, 0);\r
+    //\r
+    // de-allocate and return\r
+    //\r
+    FreePool(DevPath);\r
+    FreePool(Temp);\r
+  } else {\r
+    // If Environment is NULL, we are free to use and mutate the current shell\r
+    // environment. This is much faster as uses much less memory.\r
+\r
+    if (CommandLine == NULL) {\r
+      CommandLine = L"";\r
+    }\r
 \r
-  Status = InternalShellExecuteDevicePath(\r
-    ParentImageHandle,\r
-    DevPath,\r
-    Temp,\r
-    (CONST CHAR16**)Environment,\r
-    StatusCode);\r
+    Status = RunShellCommand (CommandLine, &CalleeStatusCode);\r
+\r
+    // Pass up the command's exit code if the caller wants it\r
+    if (StatusCode != NULL) {\r
+      *StatusCode = (EFI_STATUS) CalleeStatusCode;\r
+    }\r
+  }\r
 \r
-  //\r
-  // de-allocate and return\r
-  //\r
-  FreePool(DevPath);\r
-  FreePool(Temp);\r
   return(Status);\r
 }\r
 \r
@@ -2220,7 +2242,7 @@ ShellSearchHandle(
 \r
   CurrentFilePattern = AllocateZeroPool((NextFilePatternStart-FilePattern+1)*sizeof(CHAR16));\r
   ASSERT(CurrentFilePattern != NULL);\r
-  StrnCpy(CurrentFilePattern, FilePattern, NextFilePatternStart-FilePattern);\r
+  StrnCpyS(CurrentFilePattern, NextFilePatternStart-FilePattern+1, FilePattern, NextFilePatternStart-FilePattern);\r
 \r
   if (CurrentFilePattern[0]   == CHAR_NULL\r
     &&NextFilePatternStart[0] == CHAR_NULL\r
@@ -2284,8 +2306,8 @@ ShellSearchHandle(
             if (NewFullName == NULL) {\r
               Status = EFI_OUT_OF_RESOURCES;\r
             } else {\r
-              StrnCpy(NewFullName, MapName, Size/sizeof(CHAR16)-1);\r
-              StrnCat(NewFullName, ShellInfoNode->FullName+1, (Size/sizeof(CHAR16))-StrLen(NewFullName)-1);\r
+              StrCpyS(NewFullName, Size/sizeof(CHAR16), MapName);\r
+              StrCatS(NewFullName, Size/sizeof(CHAR16), ShellInfoNode->FullName+1);\r
               FreePool((VOID*)ShellInfoNode->FullName);\r
               ShellInfoNode->FullName = NewFullName;\r
             }\r
@@ -2495,6 +2517,7 @@ EfiShellOpenFileList(
     CurDir = EfiShellGetCurDir(NULL);\r
     ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));\r
     StrnCatGrow(&Path2, &Path2Size, CurDir, 0);\r
+    StrnCatGrow(&Path2, &Path2Size, L"\\", 0);\r
     if (*Path == L'\\') {\r
       Path++;\r
       while (PathRemoveLastItem(Path2)) ;\r
@@ -2615,7 +2638,10 @@ EfiShellGetEnvEx(
       ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link)\r
      ){\r
       ASSERT(Node->Key != NULL);\r
-      StrnCpy(CurrentWriteLocation, Node->Key,  (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)) - 1);\r
+      StrCpyS( CurrentWriteLocation, \r
+                (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)), \r
+                Node->Key\r
+                );\r
       CurrentWriteLocation += StrLen(CurrentWriteLocation) + 1;\r
     }\r
 \r
@@ -2793,6 +2819,8 @@ EfiShellSetEnv(
   FileSystemMapping is not NULL, it returns the current directory associated with the\r
   FileSystemMapping. In both cases, the returned name includes the file system\r
   mapping (i.e. fs0:\current-dir).\r
+  \r
+  Note that the current directory string should exclude the tailing backslash character.\r
 \r
   @param FileSystemMapping      A pointer to the file system mapping. If NULL,\r
                                 then the current working directory is returned.\r
@@ -2849,6 +2877,8 @@ EfiShellGetCurDir(
   If the current working directory or the current working file system is changed then the\r
   %cwd% environment variable will be updated\r
 \r
+  Note that the current directory string should exclude the tailing backslash character.\r
+\r
   @param FileSystem             A pointer to the file system's mapped name. If NULL, then the current working\r
                                 directory is changed.\r
   @param Dir                    Points to the NULL-terminated directory on the device specified by FileSystem.\r
@@ -2936,9 +2966,11 @@ EfiShellSetCurDir(
       ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
       MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0);\r
     }\r
-    if ((MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] != L'\\') || (MapListItem->CurrentDirectoryPath == NULL)) {\r
+    if ((MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') || (MapListItem->CurrentDirectoryPath == NULL)) {\r
       ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
-      MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);\r
+      if (MapListItem->CurrentDirectoryPath != NULL) {\r
+        MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;\r
+      }\r
     }\r
   } else {\r
     //\r
@@ -2970,9 +3002,9 @@ EfiShellSetCurDir(
       MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);\r
       ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
       MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0);\r
-      if (MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] != L'\\') {\r
+      if (MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') {\r
         ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
-        MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);\r
+        MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;\r
       }\r
     }\r
   }\r
@@ -3046,7 +3078,11 @@ EfiShellGetHelpText(
       FixCommand = AllocateZeroPool(StrSize(Command) - 4 * sizeof (CHAR16));\r
       ASSERT(FixCommand != NULL);\r
 \r
-      StrnCpy(FixCommand, Command, StrLen(Command)-4);\r
+      StrnCpyS( FixCommand, \r
+                (StrSize(Command) - 4 * sizeof (CHAR16))/sizeof(CHAR16), \r
+                Command, \r
+                StrLen(Command)-4\r
+                );\r
       Status = ProcessManFile(FixCommand, FixCommand, Sections, NULL, HelpText);\r
       FreePool(FixCommand);\r
       return Status;\r
@@ -3214,6 +3250,7 @@ EfiShellGetAlias(
   UINT32      Attribs;\r
   EFI_STATUS  Status;\r
   CHAR16      *AliasLower;\r
+  CHAR16      *AliasVal;\r
 \r
   // Convert to lowercase to make aliases case-insensitive\r
   if (Alias != NULL) {\r
@@ -3222,7 +3259,8 @@ EfiShellGetAlias(
     ToLower (AliasLower);\r
 \r
     if (Volatile == NULL) {\r
-      return (AddBufferToFreeList(GetVariable(AliasLower, &gShellAliasGuid)));\r
+      GetVariable2 (AliasLower, &gShellAliasGuid, (VOID **)&AliasVal, NULL);\r
+      return (AddBufferToFreeList(AliasVal));\r
     }\r
     RetSize = 0;\r
     RetVal = NULL;\r