]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/ShellProtocol.c
fix for word wrapping.
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellProtocol.c
index 0f799786ee3fb28aa571a8d1a564d8c0b9154de7..8b2e89041b8c62d59529392b70bc9d8bf0901580 100644 (file)
@@ -2,7 +2,7 @@
   Member functions of EFI_SHELL_PROTOCOL and functions for creation,\r
   manipulation, and initialization of EFI_SHELL_PROTOCOL.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2011, 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
@@ -37,6 +37,36 @@ EfiShellClose (
   return (FileHandleClose(ConvertShellHandleToEfiFileProtocol(FileHandle)));\r
 }\r
 \r
+/**\r
+  Internal worker to determine whether there is a BlockIo somewhere\r
+  upon the device path specified.\r
+\r
+  @param[in] DevicePath    The device path to test.\r
+\r
+  @retval TRUE      gEfiBlockIoProtocolGuid was installed on a handle with this device path\r
+  @retval FALSE     gEfiBlockIoProtocolGuid was not found.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalShellProtocolIsBlockIoPresent(\r
+  IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathCopy;\r
+  EFI_STATUS                Status;\r
+  EFI_HANDLE                Handle;\r
+\r
+  Handle = NULL;\r
+\r
+  DevicePathCopy = (EFI_DEVICE_PATH_PROTOCOL*)DevicePath;\r
+  Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, &DevicePathCopy, &Handle);\r
+\r
+  if ((Handle != NULL) && (!EFI_ERROR(Status))) {\r
+    return (TRUE);\r
+  }\r
+  return (FALSE);\r
+}\r
+\r
 /**\r
   Internal worker to determine whether there is a file system somewhere\r
   upon the device path specified.\r
@@ -176,7 +206,8 @@ EfiShellSetMap(
   // make sure this is a valid to add device path\r
   //\r
   ///@todo add BlockIo to this test...\r
-  if (!InternalShellProtocolIsSimpleFileSystemPresent(DevicePath)) {\r
+  if (!InternalShellProtocolIsSimpleFileSystemPresent(DevicePath)\r
+    && !InternalShellProtocolIsBlockIoPresent(DevicePath)) {\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
 \r
@@ -496,10 +527,9 @@ EfiShellGetDevicePathFromFilePath(
     NewPath = AllocateZeroPool(Size);\r
     ASSERT(NewPath != NULL);\r
     StrCpy(NewPath, Cwd);\r
-    if ((Path[0] == (CHAR16)L'\\') &&\r
-        (NewPath[StrLen(NewPath)-1] == (CHAR16)L'\\')\r
-       ) {\r
-      ((CHAR16*)NewPath)[StrLen(NewPath)-1] = CHAR_NULL;\r
+    if (*Path == L'\\') {\r
+      Path++;\r
+      while (ChopLastSlash(NewPath)) ;\r
     }\r
     StrCat(NewPath, Path);\r
     DevicePathForReturn = EfiShellGetDevicePathFromFilePath(NewPath);\r
@@ -555,7 +585,11 @@ EfiShellGetDevicePathFromFilePath(
   //\r
   // build the full device path\r
   //\r
-  DevicePathForReturn = FileDevicePath(Handle, Path+StrLen(MapName)+1);\r
+  if (*(Path+StrLen(MapName)+1) == CHAR_NULL) {\r
+    DevicePathForReturn = FileDevicePath(Handle, L"\\");\r
+  } else {\r
+    DevicePathForReturn = FileDevicePath(Handle, Path+StrLen(MapName)+1);\r
+  }\r
 \r
   FreePool(MapName);\r
   if (DevicePathCopyForFree != NULL) {\r
@@ -621,6 +655,11 @@ EfiShellGetDeviceName(
   CHAR8                             *Lang;\r
   CHAR8                             *TempChar;\r
 \r
+  UINTN                             ParentControllerCount;\r
+  EFI_HANDLE                        *ParentControllerBuffer;\r
+  UINTN                             ParentDriverCount;\r
+  EFI_HANDLE                        *ParentDriverBuffer;\r
+\r
   if (BestDeviceName == NULL ||\r
       DeviceHandle   == NULL\r
      ){\r
@@ -673,7 +712,7 @@ EfiShellGetDeviceName(
         continue;\r
       }\r
       if (Language == NULL) {\r
-        Lang = AllocatePool(AsciiStrSize(CompName2->SupportedLanguages));\r
+        Lang = AllocateZeroPool(AsciiStrSize(CompName2->SupportedLanguages));\r
         if (Lang == NULL) {\r
           return (EFI_OUT_OF_RESOURCES);\r
         }\r
@@ -683,7 +722,7 @@ EfiShellGetDeviceName(
           *TempChar = CHAR_NULL;\r
         }\r
       } else {\r
-        Lang = AllocatePool(AsciiStrSize(Language));\r
+        Lang = AllocateZeroPool(AsciiStrSize(Language));\r
         if (Lang == NULL) {\r
           return (EFI_OUT_OF_RESOURCES);\r
         }\r
@@ -699,14 +738,80 @@ EfiShellGetDeviceName(
     if (HandleList != NULL) {\r
       FreePool(HandleList);\r
     }\r
+\r
+    //\r
+    // Now check the parent controller using this as the child.\r
+    //\r
+    if (DeviceNameToReturn == NULL){\r
+      PARSE_HANDLE_DATABASE_PARENTS(DeviceHandle, &ParentControllerCount, &ParentControllerBuffer);\r
+      for (LoopVar = 0 ; LoopVar < ParentControllerCount ; LoopVar++) {\r
+        PARSE_HANDLE_DATABASE_UEFI_DRIVERS(ParentControllerBuffer[LoopVar], &ParentDriverCount, &ParentDriverBuffer);\r
+        for (HandleCount = 0 ; HandleCount < ParentDriverCount ; HandleCount++) {\r
+          //\r
+          // try using that driver's component name with controller and our driver as the child.\r
+          //\r
+          Status = gBS->OpenProtocol(\r
+            ParentDriverBuffer[HandleCount],\r
+            &gEfiComponentName2ProtocolGuid,\r
+            (VOID**)&CompName2,\r
+            gImageHandle,\r
+            NULL,\r
+            EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+          if (EFI_ERROR(Status)) {\r
+            Status = gBS->OpenProtocol(\r
+              ParentDriverBuffer[HandleCount],\r
+              &gEfiComponentNameProtocolGuid,\r
+              (VOID**)&CompName2,\r
+              gImageHandle,\r
+              NULL,\r
+              EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+          }\r
+\r
+          if (EFI_ERROR(Status)) {\r
+            continue;\r
+          }\r
+          if (Language == NULL) {\r
+            Lang = AllocateZeroPool(AsciiStrSize(CompName2->SupportedLanguages));\r
+            if (Lang == NULL) {\r
+              return (EFI_OUT_OF_RESOURCES);\r
+            }\r
+            AsciiStrCpy(Lang, CompName2->SupportedLanguages);\r
+            TempChar = AsciiStrStr(Lang, ";");\r
+            if (TempChar != NULL){\r
+              *TempChar = CHAR_NULL;\r
+            }\r
+          } else {\r
+            Lang = AllocateZeroPool(AsciiStrSize(Language));\r
+            if (Lang == NULL) {\r
+              return (EFI_OUT_OF_RESOURCES);\r
+            }\r
+            AsciiStrCpy(Lang, Language);\r
+          }\r
+          Status = CompName2->GetControllerName(CompName2, ParentControllerBuffer[LoopVar], DeviceHandle, Lang, &DeviceNameToReturn);\r
+          FreePool(Lang);\r
+          Lang = NULL;\r
+          if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) {\r
+            break;\r
+          }\r
+\r
+\r
+\r
+        }\r
+        SHELL_FREE_NON_NULL(ParentDriverBuffer);\r
+        if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) {\r
+          break;\r
+        }\r
+      }\r
+      SHELL_FREE_NON_NULL(ParentControllerBuffer);\r
+    }\r
+    //\r
+    // dont return on fail since we will try device path if that bit is on\r
+    //\r
     if (DeviceNameToReturn != NULL){\r
       ASSERT(BestDeviceName != NULL);\r
       StrnCatGrow(BestDeviceName, NULL, DeviceNameToReturn, 0);\r
       return (EFI_SUCCESS);\r
     }\r
-    //\r
-    // dont return on fail since we will try device path if that bit is on\r
-    //\r
   }\r
   if ((Flags & EFI_DEVICE_NAME_USE_DEVICE_PATH) != 0) {\r
     Status = gBS->LocateProtocol(\r
@@ -907,75 +1012,46 @@ InternalOpenFileDevicePath(
 \r
   if (!EFI_ERROR(Status)) {\r
     Handle1 = ConvertShellHandleToEfiFileProtocol(ShellHandle);\r
-    //\r
-    // chop off the begining part before the file system part...\r
-    //\r
-    ///@todo BlockIo?\r
-    Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,\r
-                                   &DevicePath,\r
-                                   &Handle);\r
-      if (!EFI_ERROR(Status)) {\r
+    if (Handle1 != NULL) {\r
       //\r
-      // To access as a file system, the file path should only\r
-      // contain file path components.  Follow the file path nodes\r
-      // and find the target file\r
+      // chop off the begining part before the file system part...\r
       //\r
-      for ( FilePathNode = (FILEPATH_DEVICE_PATH *)DevicePath\r
-          ; !IsDevicePathEnd (&FilePathNode->Header)\r
-          ; FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header)\r
-         ){\r
-        SHELL_FREE_NON_NULL(AlignedNode);\r
-        AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePathNode), FilePathNode);\r
-        //\r
-        // For file system access each node should be a file path component\r
-        //\r
-        if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
-            DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP\r
-           ) {\r
-          Status = EFI_UNSUPPORTED;\r
-          break;\r
-        }\r
-\r
-        //\r
-        // Open this file path node\r
-        //\r
-        Handle2 = Handle1;\r
-        Handle1 = NULL;\r
-\r
+      ///@todo BlockIo?\r
+      Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,\r
+                                     &DevicePath,\r
+                                     &Handle);\r
+        if (!EFI_ERROR(Status)) {\r
         //\r
-        // if this is the last node in the DevicePath always create (if that was requested).\r
+        // To access as a file system, the file path should only\r
+        // contain file path components.  Follow the file path nodes\r
+        // and find the target file\r
         //\r
-        if (IsDevicePathEnd ((NextDevicePathNode (&FilePathNode->Header)))) {\r
-          Status = Handle2->Open (\r
-                                Handle2,\r
-                                &Handle1,\r
-                                AlignedNode->PathName,\r
-                                OpenMode,\r
-                                Attributes\r
-                               );\r
-        } else {\r
-\r
+        for ( FilePathNode = (FILEPATH_DEVICE_PATH *)DevicePath\r
+            ; !IsDevicePathEnd (&FilePathNode->Header)\r
+            ; FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header)\r
+           ){\r
+          SHELL_FREE_NON_NULL(AlignedNode);\r
+          AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePathNode), FilePathNode);\r
           //\r
-          //  This is not the last node and we dont want to 'create' existing\r
-          //  directory entries...\r
+          // For file system access each node should be a file path component\r
           //\r
+          if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
+              DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP\r
+             ) {\r
+            Status = EFI_UNSUPPORTED;\r
+            break;\r
+          }\r
 \r
           //\r
-          // open without letting it create\r
-          // prevents error on existing files/directories\r
+          // Open this file path node\r
           //\r
-          Status = Handle2->Open (\r
-                                Handle2,\r
-                                &Handle1,\r
-                                AlignedNode->PathName,\r
-                                OpenMode &~EFI_FILE_MODE_CREATE,\r
-                                Attributes\r
-                               );\r
+          Handle2 = Handle1;\r
+          Handle1 = NULL;\r
+\r
           //\r
-          // if above failed now open and create the 'item'\r
-          // if OpenMode EFI_FILE_MODE_CREATE bit was on (but disabled above)\r
+          // if this is the last node in the DevicePath always create (if that was requested).\r
           //\r
-          if ((EFI_ERROR (Status)) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) {\r
+          if (IsDevicePathEnd ((NextDevicePathNode (&FilePathNode->Header)))) {\r
             Status = Handle2->Open (\r
                                   Handle2,\r
                                   &Handle1,\r
@@ -983,20 +1059,51 @@ InternalOpenFileDevicePath(
                                   OpenMode,\r
                                   Attributes\r
                                  );\r
+          } else {\r
+\r
+            //\r
+            //  This is not the last node and we dont want to 'create' existing\r
+            //  directory entries...\r
+            //\r
+\r
+            //\r
+            // open without letting it create\r
+            // prevents error on existing files/directories\r
+            //\r
+            Status = Handle2->Open (\r
+                                  Handle2,\r
+                                  &Handle1,\r
+                                  AlignedNode->PathName,\r
+                                  OpenMode &~EFI_FILE_MODE_CREATE,\r
+                                  Attributes\r
+                                 );\r
+            //\r
+            // if above failed now open and create the 'item'\r
+            // if OpenMode EFI_FILE_MODE_CREATE bit was on (but disabled above)\r
+            //\r
+            if ((EFI_ERROR (Status)) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) {\r
+              Status = Handle2->Open (\r
+                                    Handle2,\r
+                                    &Handle1,\r
+                                    AlignedNode->PathName,\r
+                                    OpenMode,\r
+                                    Attributes\r
+                                   );\r
+            }\r
           }\r
-        }\r
-        //\r
-        // Close the last node\r
-        //\r
-        ShellInfoObject.NewEfiShellProtocol->CloseFile (Handle2);\r
+          //\r
+          // Close the last node\r
+          //\r
+          ShellInfoObject.NewEfiShellProtocol->CloseFile (Handle2);\r
 \r
-        //\r
-        // If there's been an error, stop\r
-        //\r
-        if (EFI_ERROR (Status)) {\r
-          break;\r
-        }\r
-      } // for loop\r
+          //\r
+          // If there's been an error, stop\r
+          //\r
+          if (EFI_ERROR (Status)) {\r
+            break;\r
+          }\r
+        } // for loop\r
+      }\r
     }\r
   }\r
   SHELL_FREE_NON_NULL(AlignedNode);\r
@@ -1628,14 +1735,14 @@ InternalDuplicateShellFileInfo(
 {\r
   EFI_SHELL_FILE_INFO *NewNode;\r
 \r
-  NewNode = AllocatePool(sizeof(EFI_SHELL_FILE_INFO));\r
+  NewNode = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
   if (NewNode == NULL) {\r
     return (NULL);\r
   }\r
   NewNode->FullName = AllocateZeroPool(StrSize(Node->FullName));\r
 \r
   NewNode->FileName = AllocateZeroPool(StrSize(Node->FileName));\r
-  NewNode->Info     = AllocatePool((UINTN)Node->Info->Size);\r
+  NewNode->Info     = AllocateZeroPool((UINTN)Node->Info->Size);\r
   if ( NewNode->FullName == NULL\r
     || NewNode->FileName == NULL\r
     || NewNode->Info == NULL\r
@@ -1962,7 +2069,7 @@ ShellSearchHandle(
       } else {\r
         NewShellNode->Handle = NULL;\r
         if (*FileList == NULL) {\r
-          *FileList = AllocatePool(sizeof(EFI_SHELL_FILE_INFO));\r
+          *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
           InitializeListHead(&((*FileList)->Link));\r
         }\r
 \r
@@ -2001,7 +2108,7 @@ ShellSearchHandle(
               ShellInfoNode->FullName = NewFullName;\r
             }\r
           }\r
-          if (Directory && !EFI_ERROR(Status)){\r
+          if (Directory && !EFI_ERROR(Status) && ShellInfoNode->FullName != NULL && ShellInfoNode->FileName != NULL){\r
             //\r
             // should be a directory\r
             //\r
@@ -2015,7 +2122,6 @@ ShellSearchHandle(
               //\r
               //\r
               //\r
-              ASSERT_EFI_ERROR(Status);\r
               if (EFI_ERROR(Status)) {\r
                 break;\r
               }\r
@@ -2043,7 +2149,7 @@ ShellSearchHandle(
               Status = EFI_OUT_OF_RESOURCES;\r
             }\r
             if (*FileList == NULL) {\r
-              *FileList = AllocatePool(sizeof(EFI_SHELL_FILE_INFO));\r
+              *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
               InitializeListHead(&((*FileList)->Link));\r
             }\r
 \r
@@ -2120,7 +2226,7 @@ EfiShellFindFiles(
   RootDevicePath = NULL;\r
   RootFileHandle = NULL;\r
   MapName        = NULL;\r
-  PatternCopy = AllocatePool(StrSize(FilePattern));\r
+  PatternCopy = AllocateZeroPool(StrSize(FilePattern));\r
   if (PatternCopy == NULL) {\r
     return (EFI_OUT_OF_RESOURCES);\r
   }\r
@@ -2185,17 +2291,19 @@ EfiShellOpenFileList(
   CHAR16              *Path2;\r
   UINTN               Path2Size;\r
   CONST CHAR16        *CurDir;\r
+  BOOLEAN             Found;\r
 \r
   ShellCommandCleanPath(Path);\r
 \r
   Path2Size     = 0;\r
   Path2         = NULL;\r
 \r
-  ASSERT(FileList  != NULL);\r
-  ASSERT(*FileList != NULL);\r
+  if (FileList == NULL || *FileList == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
 \r
   if (*Path == L'.' && *(Path+1) == L'\\') {\r
-    Path++;\r
+    Path+=2;\r
   }\r
 \r
   //\r
@@ -2207,6 +2315,7 @@ EfiShellOpenFileList(
     StrnCatGrow(&Path2, &Path2Size, CurDir, 0);\r
     if (*Path == L'\\') {\r
       Path++;\r
+      while (ChopLastSlash(Path2)) ;\r
     }\r
     ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));\r
     StrnCatGrow(&Path2, &Path2Size, Path, 0);\r
@@ -2228,6 +2337,7 @@ EfiShellOpenFileList(
     return (Status);\r
   }\r
 \r
+  Found = FALSE;\r
   //\r
   // We had no errors so open all the files (that are not already opened...)\r
   //\r
@@ -2237,9 +2347,13 @@ EfiShellOpenFileList(
      ){\r
     if (ShellFileListItem->Status == 0 && ShellFileListItem->Handle == NULL) {\r
       ShellFileListItem->Status = EfiShellOpenFileByName (ShellFileListItem->FullName, &ShellFileListItem->Handle, OpenMode);\r
+      Found = TRUE;\r
     }\r
   }\r
 \r
+  if (!Found) {\r
+    return (EFI_NOT_FOUND);\r
+  }\r
   return(EFI_SUCCESS);\r
 }\r
 \r
@@ -3189,6 +3303,12 @@ CleanUpShellProtocol (
 \r
   Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle1);\r
   Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle2);\r
+  Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle3);\r
+  Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle4);\r
+  Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle1);\r
+  Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle2);\r
+  Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle3);\r
+  Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle4);\r
 \r
   return (Status);\r
 }\r
@@ -3206,10 +3326,20 @@ NotificationFunction(
   IN EFI_KEY_DATA *KeyData\r
   )\r
 {\r
-  if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {\r
-    return (EFI_UNSUPPORTED);\r
+//  ShellPrintEx(-1,-1,L"  <Notify>  ");\r
+   if ((KeyData->Key.UnicodeChar == L'c' || KeyData->Key.UnicodeChar == 3) &&\r
+      (KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState  == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))\r
+      ){ \r
+    if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {\r
+      return (EFI_UNSUPPORTED);\r
+    }\r
+    return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak));\r
+  } else if  ((KeyData->Key.UnicodeChar == L's') &&\r
+              (KeyData->KeyState.KeyShiftState  == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState  == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))\r
+              ){ \r
+    ShellInfoObject.HaltOutput = TRUE;\r
   }\r
-  return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak));\r
+  return (EFI_SUCCESS);\r
 }\r
 \r
 /**\r