]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellLib/UefiShellLib.c
ShellPkg: remove potential memory leak with new apps on old shell
[mirror_edk2.git] / ShellPkg / Library / UefiShellLib / UefiShellLib.c
index 85a5d44f081495b553c64206f7fd31ab65d9948b..9b58786756bfb0ab63a45baaa1ca630d9eab8a55 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Provides interface to shell functionality for shell commands and applications.\r
 \r
-  Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -486,6 +486,8 @@ ShellOpenFileByDevicePath(
   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
   EFI_FILE_PROTOCOL               *Handle1;\r
   EFI_FILE_PROTOCOL               *Handle2;\r
+  CHAR16                          *FnafPathName;\r
+  UINTN                           PathLen;\r
 \r
   if (FilePath == NULL || FileHandle == NULL || DeviceHandle == NULL) {\r
     return (EFI_INVALID_PARAMETER);\r
@@ -551,13 +553,36 @@ ShellOpenFileByDevicePath(
     Handle2  = Handle1;\r
     Handle1 = NULL;\r
 \r
+    //\r
+    // File Name Alignment Fix (FNAF)\r
+    // Handle2->Open may be incapable of handling a unaligned CHAR16 data.\r
+    // The structure pointed to by FilePath may be not CHAR16 aligned.\r
+    // This code copies the potentially unaligned PathName data from the\r
+    // FilePath structure to the aligned FnafPathName for use in the\r
+    // calls to Handl2->Open.\r
+    //\r
+\r
+    //\r
+    // Determine length of PathName, in bytes.\r
+    //\r
+    PathLen = DevicePathNodeLength (*FilePath) - SIZE_OF_FILEPATH_DEVICE_PATH;\r
+\r
+    //\r
+    // Allocate memory for the aligned copy of the string Extra allocation is to allow for forced alignment\r
+    // Copy bytes from possibly unaligned location to aligned location\r
+    //\r
+    FnafPathName = AllocateCopyPool(PathLen, (UINT8 *)((FILEPATH_DEVICE_PATH*)*FilePath)->PathName);\r
+    if (FnafPathName == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
     //\r
     // Try to test opening an existing file\r
     //\r
     Status = Handle2->Open (\r
                           Handle2,\r
                           &Handle1,\r
-                          ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
+                          FnafPathName,\r
                           OpenMode &~EFI_FILE_MODE_CREATE,\r
                           0\r
                          );\r
@@ -569,11 +594,17 @@ ShellOpenFileByDevicePath(
       Status = Handle2->Open (\r
                             Handle2,\r
                             &Handle1,\r
-                            ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
+                            FnafPathName,\r
                             OpenMode,\r
                             Attributes\r
                            );\r
     }\r
+\r
+    //\r
+    // Free the alignment buffer\r
+    //\r
+    FreePool(FnafPathName);\r
+\r
     //\r
     // Close the last node\r
     //\r
@@ -1567,6 +1598,7 @@ ShellCloseFileMetaArg (
       FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info);\r
       FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node);\r
     }\r
+    SHELL_FREE_NON_NULL(*ListHead);\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -2606,10 +2638,12 @@ InternalPrintTo (
     return (gEfiShellProtocol->WriteFile(gEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));\r
   }\r
   if (mEfiShellInterface          != NULL) {\r
+    if (mEfiShellInterface->RedirArgc == 0) { \r
     //\r
     // Divide in half for old shell.  Must be string length not size.\r
-    //\r
-    Size /= 2;\r
+      // \r
+      Size /=2;  // Divide in half only when no redirection.\r
+    }\r
     return (mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut,          &Size, (VOID*)String));\r
   }\r
   ASSERT(FALSE);\r
@@ -3023,9 +3057,35 @@ ShellIsFileInPath(
   return (Status);\r
 }\r
 \r
+/**\r
+  Function return the number converted from a hex representation of a number.\r
+\r
+  Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid\r
+  result.  Use ShellConvertStringToUint64 instead.\r
+\r
+  @param[in] String   String representation of a number.\r
+\r
+  @return             The unsigned integer result of the conversion.\r
+  @retval (UINTN)(-1) An error occured.\r
+**/\r
+UINTN\r
+EFIAPI\r
+ShellHexStrToUintn(\r
+  IN CONST CHAR16 *String\r
+  )\r
+{\r
+  UINT64        RetVal;\r
+\r
+  if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, TRUE, TRUE))) {\r
+    return ((UINTN)RetVal);\r
+  }\r
+  \r
+  return ((UINTN)(-1));\r
+}\r
+\r
 /**\r
   Function to determine whether a string is decimal or hex representation of a number\r
-  and return the number converted from the string.\r
+  and return the number converted from the string.  Spaces are always skipped.\r
 \r
   @param[in] String   String representation of a number\r
 \r
@@ -3140,11 +3200,13 @@ StrnCatGrow (
   //\r
   if (CurrentSize != NULL) {\r
     NewSize = *CurrentSize;\r
-    while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {\r
-      NewSize += 2 * Count * sizeof(CHAR16);\r
+    if (NewSize < DestinationStartSize + (Count * sizeof(CHAR16))) {\r
+      while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {\r
+        NewSize += 2 * Count * sizeof(CHAR16);\r
+      }\r
+      *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
+      *CurrentSize = NewSize;\r
     }\r
-    *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
-    *CurrentSize = NewSize;\r
   } else {\r
     *Destination = AllocateZeroPool((Count+1)*sizeof(CHAR16));\r
   }\r
@@ -3235,6 +3297,10 @@ ShellPromptForResponse (
       //\r
       *Resp = ShellPromptResponseMax;\r
       while (*Resp == ShellPromptResponseMax) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
         Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
         ASSERT_EFI_ERROR(Status);\r
@@ -3263,6 +3329,10 @@ ShellPromptForResponse (
       //\r
       *Resp = ShellPromptResponseMax;\r
       while (*Resp == ShellPromptResponseMax) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
         Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
         ASSERT_EFI_ERROR(Status);\r
@@ -3297,6 +3367,10 @@ ShellPromptForResponse (
       //\r
       *Resp = ShellPromptResponseMax;\r
       while (*Resp == ShellPromptResponseMax) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
         if (Type == ShellPromptResponseTypeEnterContinue) {\r
           Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
@@ -3324,6 +3398,10 @@ ShellPromptForResponse (
       //\r
       *Resp = ShellPromptResponseMax;\r
       while (*Resp == ShellPromptResponseMax) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
         Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
         ASSERT_EFI_ERROR(Status);\r
@@ -3345,6 +3423,10 @@ ShellPromptForResponse (
         ShellPrintEx(-1, -1, L"%s", Prompt);\r
       }\r
       while(1) {\r
+        if (ShellGetExecutionBreakFlag()) {\r
+          Status = EFI_ABORTED;\r
+          break;\r
+        }\r
         gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
         Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
         ASSERT_EFI_ERROR(Status);\r
@@ -3358,6 +3440,7 @@ ShellPromptForResponse (
       break;\r
     //\r
     // This is the location to add new prompt types.\r
+    // If your new type loops remember to add ExecutionBreak support.\r
     //\r
     default:\r
       ASSERT(FALSE);\r
@@ -4024,3 +4107,108 @@ ShellFileHandleReadLine(
 \r
   return (Status);\r
 }\r
+\r
+/**\r
+  Function to print help file / man page content in the spec from the UEFI Shell protocol GetHelpText function.\r
+\r
+  @param[in] CommandToGetHelpOn  Pointer to a string containing the command name of help file to be printed.\r
+  @param[in] SectionToGetHelpOn  Pointer to the section specifier(s).\r
+  @param[in] PrintCommandText    If TRUE, prints the command followed by the help content, otherwise prints \r
+                                 the help content only.\r
+  @retval EFI_DEVICE_ERROR       The help data format was incorrect.\r
+  @retval EFI_NOT_FOUND          The help data could not be found.\r
+  @retval EFI_SUCCESS            The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPrintHelp (\r
+  IN CONST CHAR16     *CommandToGetHelpOn,\r
+  IN CONST CHAR16     *SectionToGetHelpOn,\r
+  IN BOOLEAN          PrintCommandText\r
+  )\r
+{\r
+       EFI_STATUS          Status;\r
+       CHAR16              *OutText;\r
+         \r
+       OutText = NULL;\r
+       \r
+  //\r
+  // Get the string to print based\r
+  //\r
+       Status = gEfiShellProtocol->GetHelpText (CommandToGetHelpOn, SectionToGetHelpOn, &OutText);\r
+  \r
+  //\r
+  // make sure we got a valid string\r
+  //\r
+  if (EFI_ERROR(Status)){\r
+    return Status;\r
+       } \r
+  if (OutText == NULL || StrLen(OutText) == 0) {\r
+    return EFI_NOT_FOUND;  \r
+       }\r
+  \r
+  //\r
+  // Chop off trailing stuff we dont need\r
+  //\r
+  while (OutText[StrLen(OutText)-1] == L'\r' || OutText[StrLen(OutText)-1] == L'\n' || OutText[StrLen(OutText)-1] == L' ') {\r
+    OutText[StrLen(OutText)-1] = CHAR_NULL;\r
+  }\r
+  \r
+  //\r
+  // Print this out to the console\r
+  //\r
+  if (PrintCommandText) {\r
+    ShellPrintEx(-1, -1, L"%H%-14s%N- %s\r\n", CommandToGetHelpOn, OutText);\r
+  } else {\r
+    ShellPrintEx(-1, -1, L"%N%s\r\n", OutText);\r
+  }\r
+  \r
+  SHELL_FREE_NON_NULL(OutText);\r
+\r
+       return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Function to delete a file by name\r
+  \r
+  @param[in]       FileName       Pointer to file name to delete.\r
+  \r
+  @retval EFI_SUCCESS             the file was deleted sucessfully\r
+  @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not\r
+                                  deleted\r
+  @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.\r
+  @retval EFI_NOT_FOUND           The specified file could not be found on the\r
+                                  device or the file system could not be found\r
+                                  on the device.\r
+  @retval EFI_NO_MEDIA            The device has no medium.\r
+  @retval EFI_MEDIA_CHANGED       The device has a different medium in it or the\r
+                                  medium is no longer supported.\r
+  @retval EFI_DEVICE_ERROR        The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED    The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED     The file or medium is write protected.\r
+  @retval EFI_ACCESS_DENIED       The file was opened read only.\r
+  @retval EFI_OUT_OF_RESOURCES    Not enough resources were available to open the\r
+                                  file.\r
+  @retval other                   The file failed to open\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellDeleteFileByName(\r
+  IN CONST CHAR16               *FileName\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  SHELL_FILE_HANDLE         FileHandle;\r
+  \r
+  Status = ShellFileExists(FileName);\r
+  \r
+  if (Status == EFI_SUCCESS){\r
+    Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0x0);\r
+    if (Status == EFI_SUCCESS){\r
+      Status = ShellDeleteFile(&FileHandle);\r
+    }\r
+  } \r
+\r
+  return(Status);\r
+  \r
+}\r