udk2010.up2.shell initial release.
authorjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 14 Sep 2010 05:18:09 +0000 (05:18 +0000)
committerjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 14 Sep 2010 05:18:09 +0000 (05:18 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10874 6f19259b-4bc3-4df7-8a09-765794883524

102 files changed:
ShellPkg/Application/Shell/ConsoleLogger.c [new file with mode: 0644]
ShellPkg/Application/Shell/ConsoleLogger.h [new file with mode: 0644]
ShellPkg/Application/Shell/FileHandleInternal.h [new file with mode: 0644]
ShellPkg/Application/Shell/FileHandleWrappers.c [new file with mode: 0644]
ShellPkg/Application/Shell/FileHandleWrappers.h [new file with mode: 0644]
ShellPkg/Application/Shell/Shell.c [new file with mode: 0644]
ShellPkg/Application/Shell/Shell.h [new file with mode: 0644]
ShellPkg/Application/Shell/Shell.inf [new file with mode: 0644]
ShellPkg/Application/Shell/Shell.uni [new file with mode: 0644]
ShellPkg/Application/Shell/ShellEnvVar.c [new file with mode: 0644]
ShellPkg/Application/Shell/ShellEnvVar.h [new file with mode: 0644]
ShellPkg/Application/Shell/ShellManParser.c [new file with mode: 0644]
ShellPkg/Application/Shell/ShellManParser.h [new file with mode: 0644]
ShellPkg/Application/Shell/ShellParametersProtocol.c [new file with mode: 0644]
ShellPkg/Application/Shell/ShellParametersProtocol.h [new file with mode: 0644]
ShellPkg/Application/Shell/ShellProtocol.c [new file with mode: 0644]
ShellPkg/Application/Shell/ShellProtocol.h [new file with mode: 0644]
ShellPkg/Application/ShellLibTestApp/sa3.c
ShellPkg/Include/Guid/ShellAliasGuid.h [new file with mode: 0644]
ShellPkg/Include/Guid/ShellEnvironment2Ext.h
ShellPkg/Include/Guid/ShellMapGuid.h [new file with mode: 0644]
ShellPkg/Include/Guid/ShellVariableGuid.h [new file with mode: 0644]
ShellPkg/Include/Library/FileHandleLib.h
ShellPkg/Include/Library/HandleParsingLib.h [new file with mode: 0644]
ShellPkg/Include/Library/ShellCEntryLib.h
ShellPkg/Include/Library/ShellCommandLib.h [new file with mode: 0644]
ShellPkg/Include/Library/ShellLib.h
ShellPkg/Include/Library/SortLib.h
ShellPkg/Include/Protocol/EfiShell.h
ShellPkg/Include/Protocol/EfiShellEnvironment2.h
ShellPkg/Include/Protocol/EfiShellInterface.h
ShellPkg/Include/Protocol/EfiShellParameters.h
ShellPkg/Include/ShellBase.h
ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c
ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf
ShellPkg/Library/BaseSortLib/BaseSortLib.c
ShellPkg/Library/BaseSortLib/BaseSortLib.inf
ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c [new file with mode: 0644]
ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h [new file with mode: 0644]
ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf [new file with mode: 0644]
ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni [new file with mode: 0644]
ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c
ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c [new file with mode: 0644]
ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c [new file with mode: 0644]
ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h [new file with mode: 0644]
ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf [new file with mode: 0644]
ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.uni [new file with mode: 0644]
ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c [new file with mode: 0644]
ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c [new file with mode: 0644]
ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c [new file with mode: 0644]
ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c [new file with mode: 0644]
ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h [new file with mode: 0644]
ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf [new file with mode: 0644]
ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/For.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/If.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/NoOpScriptCommand.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni [new file with mode: 0644]
ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c [new file with mode: 0644]
ShellPkg/Library/UefiShellLib/UefiShellLib.c
ShellPkg/Library/UefiShellLib/UefiShellLib.inf
ShellPkg/Library/UefiSortLib/UefiSortLib.c
ShellPkg/Library/UefiSortLib/UefiSortLib.inf
ShellPkg/ShellPkg.dec
ShellPkg/ShellPkg.dsc
ShellPkg/UDK2010.UP2.Shell.txt [new file with mode: 0644]

diff --git a/ShellPkg/Application/Shell/ConsoleLogger.c b/ShellPkg/Application/Shell/ConsoleLogger.c
new file mode 100644 (file)
index 0000000..4b0d94d
--- /dev/null
@@ -0,0 +1,1151 @@
+/** @file\r
+  Provides interface to shell console logger.\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+**/\r
+\r
+#include "ConsoleLogger.h"\r
+#include "Shell.h"\r
+\r
+STATIC CONST CHAR16                     mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };\r
+\r
+/**\r
+  Install our intermediate ConOut into the system table to\r
+  keep a log of all the info that is displayed to the user.\r
+\r
+  @param[in] ScreensToSave  Sets how many screen-worths of data to save.\r
+  @param[out] ConsoleInfo   The object to pass into later functions.\r
+\r
+  @retval EFI_SUCCESS       The operation was successful.\r
+  @return other             The operation failed.\r
+\r
+  @sa ConsoleLoggerResetBuffers\r
+  @sa InstallProtocolInterface\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerInstall(\r
+  IN CONST UINTN ScreensToSave,\r
+  OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  ASSERT(ConsoleInfo != NULL);\r
+\r
+  *ConsoleInfo = AllocatePool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA));\r
+  ASSERT(ConsoleInfo != NULL);\r
+\r
+  (*ConsoleInfo)->Signature        = CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE;\r
+  (*ConsoleInfo)->OldConOut        = NULL;\r
+  (*ConsoleInfo)->OldConHandle     = NULL;\r
+  (*ConsoleInfo)->Buffer           = NULL;\r
+  (*ConsoleInfo)->BufferSize       = 0;\r
+  (*ConsoleInfo)->OriginalStartRow = 0;\r
+  (*ConsoleInfo)->CurrentStartRow  = 0;\r
+  (*ConsoleInfo)->RowsPerScreen    = 0;\r
+  (*ConsoleInfo)->ColsPerScreen    = 0;\r
+  (*ConsoleInfo)->Attributes       = NULL;\r
+  (*ConsoleInfo)->AttribSize       = 0;\r
+  (*ConsoleInfo)->ScreenCount      = ScreensToSave;\r
+  (*ConsoleInfo)->HistoryMode.MaxMode       = 1;\r
+  (*ConsoleInfo)->HistoryMode.Mode          = 0;\r
+  (*ConsoleInfo)->HistoryMode.Attribute     = 0;\r
+  (*ConsoleInfo)->HistoryMode.CursorColumn  = 0;\r
+  (*ConsoleInfo)->HistoryMode.CursorRow     = 0;\r
+  (*ConsoleInfo)->HistoryMode.CursorVisible = FALSE;\r
+  (*ConsoleInfo)->OurConOut.Reset           = ConsoleLoggerReset;\r
+  (*ConsoleInfo)->OurConOut.OutputString    = ConsoleLoggerOutputString;\r
+  (*ConsoleInfo)->OurConOut.TestString      = ConsoleLoggerTestString;\r
+  (*ConsoleInfo)->OurConOut.QueryMode       = ConsoleLoggerQueryMode;\r
+  (*ConsoleInfo)->OurConOut.SetMode         = ConsoleLoggerSetMode;\r
+  (*ConsoleInfo)->OurConOut.SetAttribute    = ConsoleLoggerSetAttribute;\r
+  (*ConsoleInfo)->OurConOut.ClearScreen     = ConsoleLoggerClearScreen;\r
+  (*ConsoleInfo)->OurConOut.SetCursorPosition = ConsoleLoggerSetCursorPosition;\r
+  (*ConsoleInfo)->OurConOut.EnableCursor    = ConsoleLoggerEnableCursor;\r
+  (*ConsoleInfo)->OurConOut.Mode            = NULL;\r
+  (*ConsoleInfo)->Enabled                   = TRUE;\r
+\r
+  Status = ConsoleLoggerResetBuffers(*ConsoleInfo);\r
+  if (EFI_ERROR(Status)) {\r
+    return (Status);\r
+  }\r
+\r
+  Status = gBS->InstallProtocolInterface(&gImageHandle, &gEfiSimpleTextOutProtocolGuid, EFI_NATIVE_INTERFACE, (VOID*)&((*ConsoleInfo)->OurConOut));\r
+\r
+  (*ConsoleInfo)->OldConOut = gST->ConOut;\r
+  (*ConsoleInfo)->OldConHandle = gST->ConsoleOutHandle;\r
+\r
+  gST->ConsoleOutHandle = gImageHandle;\r
+  gST->ConOut = &(*ConsoleInfo)->OurConOut;\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Return the system to the state it was before InstallConsoleLogger\r
+  was installed.\r
+\r
+  @param[in,out] ConsoleInfo   The object from the install function.\r
+\r
+  @retval EFI_SUCCESS     The operation was successful\r
+  @return other           The operation failed.  This was from UninstallProtocolInterface.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerUninstall(\r
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
+  )\r
+{\r
+  ASSERT(ConsoleInfo != NULL);\r
+  ASSERT(ConsoleInfo->OldConOut != NULL);\r
+\r
+  if (ConsoleInfo->Buffer != NULL) {\r
+    FreePool(ConsoleInfo->Buffer);\r
+    DEBUG_CODE(ConsoleInfo->Buffer     = NULL;);\r
+    DEBUG_CODE(ConsoleInfo->BufferSize = 0;);\r
+  }\r
+  if (ConsoleInfo->Attributes != NULL) {\r
+    FreePool(ConsoleInfo->Attributes);\r
+    DEBUG_CODE(ConsoleInfo->Attributes = NULL;);\r
+    DEBUG_CODE(ConsoleInfo->AttribSize = 0;);\r
+  }\r
+\r
+  gST->ConsoleOutHandle = ConsoleInfo->OldConHandle;\r
+  gST->ConOut = ConsoleInfo->OldConOut;\r
+\r
+  return (gBS->UninstallProtocolInterface(gImageHandle, &gEfiSimpleTextOutProtocolGuid, (VOID*)&ConsoleInfo->OurConOut));\r
+}\r
+\r
+/**\r
+  Displays previously logged output back to the screen.\r
+\r
+  This will scroll the screen forwards and backwards through the log of previous\r
+  output.  If Rows is 0 then the size of 1/2 the screen will be scrolled.  If Rows\r
+  is (UINTN)(-1) then the size of the screen will be scrolled.\r
+\r
+  @param[in] Forward      If TRUE then the log will be displayed forwards (scroll to newer).\r
+                          If FALSE then the log will be displayed backwards (scroll to older).\r
+  @param[in] Rows         Determines how many rows the log should scroll.\r
+  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerDisplayHistory(\r
+  IN CONST BOOLEAN  Forward,\r
+  IN CONST UINTN    Rows,\r
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
+  )\r
+{\r
+  UINTN   RowChange;\r
+\r
+  ASSERT(ConsoleInfo != NULL);\r
+\r
+  //\r
+  // Calculate the row number change\r
+  //\r
+  switch (Rows) {\r
+  case ((UINTN)(-1)):\r
+    RowChange = ConsoleInfo->RowsPerScreen;\r
+    break;\r
+  case (0):\r
+    RowChange = ConsoleInfo->RowsPerScreen / 2;\r
+    break;\r
+  default:\r
+    RowChange = Rows;\r
+    break;\r
+  }\r
+\r
+  //\r
+  // Do the math for direction\r
+  //\r
+  if (Forward) {\r
+    if ((ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow) < RowChange) {\r
+      RowChange = ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow;\r
+    }\r
+  } else {\r
+    if (ConsoleInfo->CurrentStartRow < RowChange) {\r
+      RowChange = ConsoleInfo->CurrentStartRow;\r
+    }\r
+  }\r
+\r
+  //\r
+  // If we are already at one end or the other\r
+  //\r
+  if (RowChange == 0) {\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  //\r
+  // Clear the screen\r
+  //\r
+  ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut);\r
+\r
+  //\r
+  // Set the new start row\r
+  //\r
+  if (Forward) {\r
+    ConsoleInfo->CurrentStartRow += RowChange;\r
+  } else {\r
+    ConsoleInfo->CurrentStartRow -= RowChange;\r
+  }\r
+\r
+  //\r
+  // Change the screen\r
+  //\r
+  return (UpdateDisplayFromHistory(ConsoleInfo));\r
+}\r
+\r
+/**\r
+  Function to return to normal output whent he scrolling is complete.\r
+  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.\r
+\r
+  @retval EFI_SUCCESS   The operation was successful.\r
+  @return other         The operation failed.  See UpdateDisplayFromHistory.\r
+\r
+  @sa UpdateDisplayFromHistory\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerStopHistory(\r
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
+  )\r
+{\r
+  ASSERT(ConsoleInfo != NULL);\r
+  if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {\r
+    return (EFI_SUCCESS);\r
+  }\r
+  ConsoleInfo->CurrentStartRow = ConsoleInfo->OriginalStartRow;\r
+  return (UpdateDisplayFromHistory(ConsoleInfo));\r
+}\r
+\r
+/**\r
+  Updates the hidden ConOut to be displaying the correct stuff.\r
+  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.\r
+\r
+  @retval EFI_SUCCESS     The operation was successful.\r
+  @return other           The operation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UpdateDisplayFromHistory(\r
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  EFI_STATUS      RetVal;\r
+  CHAR16          *Screen;\r
+  INT32           *Attributes;\r
+  UINTN           CurrentRow;\r
+  CHAR16          TempCharHolder;\r
+  UINTN           Column;\r
+  INT32           CurrentAttrib;\r
+  UINTN           CurrentColumn;\r
+  CHAR16          *StringSegment;\r
+  CHAR16          *StringSegmentEnd;\r
+  CHAR16          StringSegmentEndChar;\r
+\r
+  ASSERT(ConsoleInfo != NULL);\r
+  TempCharHolder = CHAR_NULL;\r
+  RetVal = EFI_SUCCESS;\r
+\r
+  //\r
+  // Disable cursor visibility and move it to the top left corner\r
+  //\r
+  ConsoleInfo->OldConOut->EnableCursor       (ConsoleInfo->OldConOut, FALSE);\r
+  ConsoleInfo->OldConOut->SetCursorPosition  (ConsoleInfo->OldConOut, 0, 0);\r
+\r
+  Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];\r
+  Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];\r
+  for ( CurrentRow = 0\r
+      ; CurrentRow < ConsoleInfo->RowsPerScreen\r
+      ; CurrentRow++\r
+      , Screen += (ConsoleInfo->ColsPerScreen + 2)\r
+      , Attributes += ConsoleInfo->ColsPerScreen\r
+     ){\r
+    //\r
+    // dont use the last char - prevents screen scroll\r
+    //\r
+    if (CurrentRow == (ConsoleInfo->RowsPerScreen-1)){\r
+      TempCharHolder = Screen[ConsoleInfo->ColsPerScreen - 1];\r
+      Screen[ConsoleInfo->ColsPerScreen - 1] = CHAR_NULL;\r
+    }\r
+\r
+    for ( Column = 0\r
+        ; Column < ConsoleInfo->ColsPerScreen\r
+        ; Column++\r
+       ){\r
+      if (Screen[Column] != CHAR_NULL) {\r
+        CurrentAttrib = Attributes[Column];\r
+        CurrentColumn = Column;\r
+        StringSegment = &Screen[Column];\r
+\r
+        //\r
+        // Find the first char with a different arrribute and make that temporarily NULL\r
+        // so we can do fewer printout statements.  (later) restore that one and we will\r
+        // start at that collumn on the next loop.\r
+        //\r
+        StringSegmentEndChar = CHAR_NULL;\r
+        for ( StringSegmentEnd = StringSegment\r
+            ; StringSegmentEnd != CHAR_NULL\r
+            ; StringSegmentEnd++\r
+            , Column++\r
+           ){\r
+          if (Attributes[Column] != CurrentAttrib) {\r
+            StringSegmentEndChar = *StringSegmentEnd;\r
+            *StringSegmentEnd    = CHAR_NULL;\r
+            break;\r
+          }\r
+        } // StringSegmentEnd loop\r
+\r
+        //\r
+        // Now write out as much as had the same Attributes\r
+        //\r
+\r
+        ConsoleInfo->OldConOut->SetAttribute(ConsoleInfo->OldConOut, CurrentAttrib);\r
+        ConsoleInfo->OldConOut->SetCursorPosition(ConsoleInfo->OldConOut, CurrentColumn, CurrentRow);\r
+        Status = ConsoleInfo->OldConOut->OutputString(ConsoleInfo->OldConOut, StringSegment);\r
+\r
+        if (EFI_ERROR(Status)) {\r
+          ASSERT(FALSE);\r
+          RetVal = Status;\r
+        }\r
+\r
+        //\r
+        // If we found a change in attribute put the character back and decrement the column\r
+        // so when it increments it will point at that character and we will start printing\r
+        // a segment with that new attribute\r
+        //\r
+        if (StringSegmentEndChar != CHAR_NULL) {\r
+          *StringSegmentEnd = StringSegmentEndChar;\r
+          StringSegmentEndChar = CHAR_NULL;\r
+          Column--;\r
+        }\r
+      }\r
+    } // column for loop\r
+\r
+    //\r
+    // If we removed the last char and this was the last row put it back\r
+    //\r
+    if (TempCharHolder != CHAR_NULL) {\r
+      Screen[ConsoleInfo->ColsPerScreen - 1] = TempCharHolder;\r
+      TempCharHolder = CHAR_NULL;\r
+    }\r
+  } // row for loop\r
+\r
+  //\r
+  // If we are setting the screen back to original turn on the cursor and make it visible\r
+  // and set the attributes back to what they were\r
+  //\r
+  if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {\r
+    ConsoleInfo->OldConOut->SetAttribute (\r
+                                ConsoleInfo->OldConOut,\r
+                                ConsoleInfo->HistoryMode.Attribute\r
+                               );\r
+    ConsoleInfo->OldConOut->SetCursorPosition (\r
+                                ConsoleInfo->OldConOut,\r
+                                ConsoleInfo->HistoryMode.CursorColumn,\r
+                                ConsoleInfo->HistoryMode.CursorRow - ConsoleInfo->OriginalStartRow\r
+                               );\r
+\r
+    Status = ConsoleInfo->OldConOut->EnableCursor (\r
+                                ConsoleInfo->OldConOut,\r
+                                ConsoleInfo->HistoryMode.CursorVisible\r
+                               );\r
+    if (EFI_ERROR (Status)) {\r
+      RetVal = Status;\r
+    }\r
+  }\r
+\r
+  return (RetVal);\r
+}\r
+\r
+/**\r
+  Reset the text output device hardware and optionaly run diagnostics\r
+\r
+  @param  This                pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
+  @param ExtendedVerification Indicates that a more extensive test may be performed\r
+\r
+  @retval EFI_SUCCESS         The text output device was reset.\r
+  @retval EFI_DEVICE_ERROR    The text output device is not functioning correctly and\r
+                              could not be reset.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerReset (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+  IN  BOOLEAN                         ExtendedVerification\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
+  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);\r
+\r
+  //\r
+  // Forward the request to the original ConOut\r
+  //\r
+  Status = ConsoleInfo->OldConOut->Reset (ConsoleInfo->OldConOut, ExtendedVerification);\r
+\r
+  //\r
+  // Check that the buffers are still correct for logging\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    ConsoleLoggerResetBuffers(ConsoleInfo);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Appends a string to the history buffer.  If the buffer is full then the oldest\r
+  information in the buffer will be dropped.  Information is added in a line by\r
+  line manner such that an empty line takes up just as much space as a full line.\r
+\r
+  @param[in] String       String pointer to add.\r
+  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AppendStringToHistory(\r
+  IN CONST CHAR16 *String,\r
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
+  )\r
+{\r
+  CONST CHAR16  *Walker;\r
+  UINTN         CopySize;\r
+  UINTN         PrintIndex;\r
+  UINTN         Index;\r
+\r
+  ASSERT(ConsoleInfo != NULL);\r
+\r
+  for ( Walker = String\r
+      ; Walker != NULL && *Walker != CHAR_NULL\r
+      ; Walker++\r
+     ){\r
+    switch (*Walker) {\r
+    case (CHAR_BACKSPACE):\r
+      if (ConsoleInfo->HistoryMode.CursorColumn > 0) {\r
+        ConsoleInfo->HistoryMode.CursorColumn--;\r
+      }\r
+      break;\r
+    case (CHAR_LINEFEED):\r
+      if (ConsoleInfo->HistoryMode.CursorRow >= (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1)) {\r
+        //\r
+        // Should never be bigger\r
+        //\r
+        ASSERT(ConsoleInfo->HistoryMode.CursorRow == (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1));\r
+\r
+        //\r
+        // scroll history attributes 'up' 1 row and set the last row to default attribute\r
+        //\r
+        CopySize = ConsoleInfo->ColsPerScreen\r
+                 * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)\r
+                 * sizeof(ConsoleInfo->Attributes[0]);\r
+        ASSERT(CopySize < ConsoleInfo->AttribSize);\r
+        CopyMem(\r
+          ConsoleInfo->Attributes,\r
+          ConsoleInfo->Attributes + ConsoleInfo->ColsPerScreen,\r
+          CopySize\r
+         );\r
+\r
+        for ( Index = 0\r
+            ; Index < ConsoleInfo->ColsPerScreen\r
+            ; Index++\r
+           ){\r
+          *(ConsoleInfo->Attributes + (CopySize/sizeof(ConsoleInfo->Attributes)) + Index) = ConsoleInfo->HistoryMode.Attribute;\r
+        }\r
+\r
+        //\r
+        // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')\r
+        //\r
+        CopySize = (ConsoleInfo->ColsPerScreen + 2)\r
+                 * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)\r
+                 * sizeof(ConsoleInfo->Buffer[0]);\r
+        ASSERT(CopySize < ConsoleInfo->BufferSize);\r
+        CopyMem(\r
+          ConsoleInfo->Buffer,\r
+          ConsoleInfo->Buffer + (ConsoleInfo->ColsPerScreen + 2),\r
+          CopySize\r
+         );\r
+\r
+        //\r
+        // Set that last row of chars to spaces\r
+        //\r
+        SetMem16(((UINT8*)ConsoleInfo->Buffer)+CopySize, ConsoleInfo->ColsPerScreen*sizeof(CHAR16), L' ');\r
+      } else {\r
+        //\r
+        // we are not on the last row\r
+        //\r
+\r
+        //\r
+        // We should not be scrolling history\r
+        //\r
+        ASSERT (ConsoleInfo->OriginalStartRow == ConsoleInfo->CurrentStartRow);\r
+        //\r
+        // are we at the end of a row?\r
+        //\r
+        if (ConsoleInfo->HistoryMode.CursorRow == (INT32) (ConsoleInfo->OriginalStartRow + ConsoleInfo->RowsPerScreen - 1)) {\r
+          ConsoleInfo->OriginalStartRow++;\r
+          ConsoleInfo->CurrentStartRow++;\r
+        }\r
+        ConsoleInfo->HistoryMode.CursorRow++;\r
+      }\r
+      break;\r
+    case (CHAR_CARRIAGE_RETURN):\r
+      //\r
+      // Move the cursor to the beginning of the current row.\r
+      //\r
+      ConsoleInfo->HistoryMode.CursorColumn = 0;\r
+      break;\r
+    default:\r
+      //\r
+      // Acrtually print characters into the history buffer\r
+      //\r
+\r
+      PrintIndex = ConsoleInfo->HistoryMode.CursorRow * ConsoleInfo->ColsPerScreen + ConsoleInfo->HistoryMode.CursorColumn;\r
+\r
+      for ( // no initializer needed\r
+          ; ConsoleInfo->HistoryMode.CursorColumn < (INT32) ConsoleInfo->ColsPerScreen\r
+          ; ConsoleInfo->HistoryMode.CursorColumn++\r
+          , PrintIndex++\r
+          , Walker++\r
+         ){\r
+        if (*Walker == CHAR_NULL\r
+          ||*Walker == CHAR_BACKSPACE\r
+          ||*Walker == CHAR_LINEFEED\r
+          ||*Walker == CHAR_CARRIAGE_RETURN\r
+         ){\r
+            Walker--;\r
+            break;\r
+        }\r
+        //\r
+        // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.\r
+        //\r
+\r
+        ASSERT(PrintIndex + ConsoleInfo->HistoryMode.CursorRow < ConsoleInfo->BufferSize);\r
+        ConsoleInfo->Buffer[PrintIndex + (2*ConsoleInfo->HistoryMode.CursorRow)] = *Walker;\r
+        ASSERT(PrintIndex < ConsoleInfo->AttribSize);\r
+        ConsoleInfo->Attributes[PrintIndex] = ConsoleInfo->HistoryMode.Attribute;\r
+      } // for loop\r
+\r
+      //\r
+      // Add the carriage return and line feed at the end of the lines\r
+      //\r
+      if (ConsoleInfo->HistoryMode.CursorColumn >= (INT32)ConsoleInfo->ColsPerScreen) {\r
+        AppendStringToHistory(L"\r\n", ConsoleInfo);\r
+        Walker--;\r
+      }\r
+\r
+      break;\r
+    } // switch for character\r
+  } // for loop\r
+\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Worker function to handle printing the output to the screen\r
+  and the history buffer\r
+\r
+  @param[in] String               The string to output\r
+  @param[in] ConsoleInfo          The pointer to the instance of the console logger information.\r
+\r
+  @retval EFI_SUCCESS             The string was printed\r
+  @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output\r
+                                  the text.\r
+  @retval EFI_UNSUPPORTED         The output device's mode is not currently in a\r
+                                  defined text mode.\r
+  @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the\r
+                                  characters in the Unicode string could not be\r
+                                  rendered and were skipped.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerOutputStringSplit(\r
+  IN CONST CHAR16   *String,\r
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  //\r
+  // Forward the request to the original ConOut\r
+  //\r
+  Status = ConsoleInfo->OldConOut->OutputString (ConsoleInfo->OldConOut, (CHAR16*)String);\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    return (Status);\r
+  }\r
+\r
+  return (AppendStringToHistory(String, ConsoleInfo));\r
+}\r
+\r
+/**\r
+  Function to handle page break mode.\r
+\r
+  This function will prompt for continue or break.\r
+\r
+  @retval EFI_SUCCESS   Continue was choosen\r
+  @return other         Break was choosen\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerDoPageBreak(\r
+  VOID\r
+  )\r
+{\r
+  SHELL_PROMPT_RESPONSE *Resp;\r
+  EFI_STATUS            Status;\r
+\r
+  Resp = NULL;\r
+  ASSERT(ShellInfoObject.PageBreakEnabled);\r
+  ShellInfoObject.PageBreakEnabled = FALSE;\r
+  Status = ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue, STRING_TOKEN(STR_SHELL_QUIT_CONT), ShellInfoObject.HiiHandle, (VOID**)&Resp);\r
+  ShellInfoObject.PageBreakEnabled = TRUE;\r
+  ASSERT(Resp != NULL);\r
+  if (Resp == NULL) {\r
+    return (EFI_NOT_FOUND);\r
+  }\r
+  if (EFI_ERROR(Status)) {\r
+    if (Resp != NULL) {\r
+      FreePool(Resp);\r
+    }\r
+    return (Status);\r
+  }\r
+  if (*Resp == ShellPromptResponseContinue) {\r
+    FreePool(Resp);\r
+    ShellInfoObject.ConsoleInfo->RowCounter = 0;\r
+    return (EFI_SUCCESS);\r
+  } else if (*Resp == ShellPromptResponseQuit) {\r
+    FreePool(Resp);\r
+    ShellInfoObject.ConsoleInfo->Enabled = FALSE;\r
+    return (EFI_DEVICE_ERROR);\r
+  } else {\r
+    ASSERT(FALSE);\r
+  }\r
+  return (EFI_SUCCESS);\r
+}\r
+/**\r
+  Worker function to handle printing the output with page breaks.\r
+\r
+  @param[in] String               The string to output\r
+  @param[in] ConsoleInfo          The pointer to the instance of the console logger information.\r
+\r
+  @retval EFI_SUCCESS             The string was printed\r
+  @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output\r
+                                  the text.\r
+  @retval EFI_UNSUPPORTED         The output device's mode is not currently in a\r
+                                  defined text mode.\r
+  @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the\r
+                                  characters in the Unicode string could not be\r
+                                  rendered and were skipped.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerPrintWithPageBreak(\r
+  IN CHAR16   *String,\r
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
+  )\r
+{\r
+  CONST CHAR16  *Walker;\r
+  CONST CHAR16  *LineStart;\r
+  CHAR16        TempChar;\r
+\r
+  for ( Walker = String\r
+      , LineStart = String\r
+      ; Walker != NULL && *Walker != CHAR_NULL\r
+      ; Walker++\r
+     ){\r
+    switch (*Walker) {\r
+    case (CHAR_BACKSPACE):\r
+      if (ConsoleInfo->OurConOut.Mode->CursorColumn > 0) {\r
+        ConsoleInfo->OurConOut.Mode->CursorColumn--;\r
+      }\r
+      break;\r
+    case (CHAR_LINEFEED):\r
+      //\r
+      // add a temp NULL terminator\r
+      //\r
+      TempChar = *(Walker + 1);\r
+      *((CHAR16*)(Walker+1)) = CHAR_NULL;\r
+\r
+      //\r
+      // output the string\r
+      //\r
+      ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);\r
+\r
+      //\r
+      // restore the temp NULL terminator to it's original character\r
+      //\r
+      *((CHAR16*)(Walker+1)) = TempChar;\r
+\r
+      //\r
+      // Update LineStart Variable\r
+      //\r
+      LineStart = Walker + 1;\r
+\r
+      //\r
+      // increment row count\r
+      //\r
+      ShellInfoObject.ConsoleInfo->RowCounter++;\r
+      ConsoleInfo->OurConOut.Mode->CursorRow++;\r
+\r
+      break;\r
+    case (CHAR_CARRIAGE_RETURN):\r
+      //\r
+      // Move the cursor to the beginning of the current row.\r
+      //\r
+      ConsoleInfo->OurConOut.Mode->CursorColumn = 0;\r
+      break;\r
+    default:\r
+      //\r
+      // increment column count\r
+      //\r
+      ConsoleInfo->OurConOut.Mode->CursorColumn++;\r
+      //\r
+      // check if that is the last column\r
+      //\r
+      if ((INTN)ConsoleInfo->ColsPerScreen == ConsoleInfo->OurConOut.Mode->CursorColumn - 1) {\r
+        //\r
+        // output a line similar to the linefeed character.\r
+        //\r
+\r
+        //\r
+        // add a temp NULL terminator\r
+        //\r
+        TempChar = *(Walker + 1);\r
+        *((CHAR16*)(Walker+1)) = CHAR_NULL;\r
+\r
+        //\r
+        // output the string\r
+        //\r
+        ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);\r
+\r
+        //\r
+        // restore the temp NULL terminator to it's original character\r
+        //\r
+        *((CHAR16*)(Walker+1)) = TempChar;\r
+\r
+        //\r
+        // Update LineStart Variable\r
+        //\r
+        LineStart = Walker;\r
+\r
+        //\r
+        // increment row count and zero the column\r
+        //\r
+        ShellInfoObject.ConsoleInfo->RowCounter++;\r
+        ConsoleInfo->OurConOut.Mode->CursorRow++;\r
+        ConsoleInfo->OurConOut.Mode->CursorColumn = 0;\r
+      } // last column on line\r
+      break;\r
+    } // switch for character\r
+\r
+    //\r
+    // check if that was the last printable row.  If yes handle PageBreak mode\r
+    //\r
+    if ((ConsoleInfo->RowsPerScreen) -1 == ShellInfoObject.ConsoleInfo->RowCounter) {\r
+      if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {\r
+        //\r
+        // We got an error which means 'break' and halt the printing\r
+        //\r
+        return (EFI_DEVICE_ERROR);\r
+      }\r
+    }\r
+  } // for loop\r
+\r
+  if (LineStart != NULL && *LineStart != CHAR_NULL) {\r
+    ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);\r
+  }\r
+\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Write a Unicode string to the output device.\r
+\r
+  @param[in] This                 Protocol instance pointer.\r
+  @param[in] WString              The NULL-terminated Unicode string to be displayed on the output\r
+                                  device(s). All output devices must also support the Unicode\r
+                                  drawing defined in this file.\r
+  @retval EFI_SUCCESS             The string was output to the device.\r
+  @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output\r
+                                  the text.\r
+  @retval EFI_UNSUPPORTED         The output device's mode is not currently in a\r
+                                  defined text mode.\r
+  @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the\r
+                                  characters in the Unicode string could not be\r
+                                  rendered and were skipped.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerOutputString (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+  IN  CHAR16                          *WString\r
+  )\r
+{\r
+  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
+  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);\r
+  ASSERT(ShellInfoObject.ConsoleInfo == ConsoleInfo);\r
+  if (!ShellInfoObject.ConsoleInfo->Enabled) {\r
+    return (EFI_DEVICE_ERROR);\r
+  } else if (ShellInfoObject.PageBreakEnabled) {\r
+    return (ConsoleLoggerPrintWithPageBreak(WString, ConsoleInfo));\r
+  } else {\r
+    return (ConsoleLoggerOutputStringSplit(WString, ConsoleInfo));\r
+  }\r
+}\r
+\r
+/**\r
+  Verifies that all characters in a Unicode string can be output to the\r
+  target device.\r
+\r
+  @param[in] This     Protocol instance pointer.\r
+  @param[in] WString  The NULL-terminated Unicode string to be examined for the output\r
+                      device(s).\r
+\r
+  @retval EFI_SUCCESS           The device(s) are capable of rendering the output string.\r
+  @retval EFI_UNSUPPORTED       Some of the characters in the Unicode string cannot be\r
+                                rendered by one or more of the output devices mapped\r
+                                by the EFI handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerTestString (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
+  IN  CHAR16                        *WString\r
+  )\r
+{\r
+  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
+  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);\r
+  //\r
+  // Forward the request to the original ConOut\r
+  //\r
+  return (ConsoleInfo->OldConOut->TestString (ConsoleInfo->OldConOut, WString));\r
+}\r
+\r
+/**\r
+  Returns information for an available text mode that the output device(s)\r
+  supports.\r
+\r
+  @param[in] This               Protocol instance pointer.\r
+  @param[in] ModeNumber         The mode number to return information on.\r
+  @param[out] Columns           Upon return, the number of columns in the selected geometry\r
+  @param[out] Rows              Upon return, the number of rows in the selected geometry\r
+\r
+  @retval EFI_SUCCESS           The requested mode information was returned.\r
+  @retval EFI_DEVICE_ERROR      The device had an error and could not\r
+                                complete the request.\r
+  @retval EFI_UNSUPPORTED       The mode number was not valid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerQueryMode (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
+  IN  UINTN                         ModeNumber,\r
+  OUT UINTN                         *Columns,\r
+  OUT UINTN                         *Rows\r
+  )\r
+{\r
+  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
+  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);\r
+  //\r
+  // Forward the request to the original ConOut\r
+  //\r
+  return (ConsoleInfo->OldConOut->QueryMode (\r
+    ConsoleInfo->OldConOut,\r
+    ModeNumber,\r
+    Columns,\r
+    Rows\r
+   ));\r
+}\r
+\r
+/**\r
+  Sets the output device(s) to a specified mode.\r
+\r
+  @param[in] This               Protocol instance pointer.\r
+  @param[in] ModeNumber         The mode number to set.\r
+\r
+\r
+  @retval EFI_SUCCESS           The requested text mode was set.\r
+  @retval EFI_DEVICE_ERROR      The device had an error and\r
+                                could not complete the request.\r
+  @retval EFI_UNSUPPORTED       The mode number was not valid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerSetMode (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
+  IN  UINTN                         ModeNumber\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+\r
+  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
+  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);\r
+\r
+  //\r
+  // Forward the request to the original ConOut\r
+  //\r
+  Status = ConsoleInfo->OldConOut->SetMode (ConsoleInfo->OldConOut, ModeNumber);\r
+\r
+  //\r
+  // Check that the buffers are still correct for logging\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    ConsoleLoggerResetBuffers(ConsoleInfo);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Sets the background and foreground colors for the OutputString () and\r
+  ClearScreen () functions.\r
+\r
+  @param[in] This               Protocol instance pointer.\r
+  @param[in] Attribute          The attribute to set. Bits 0..3 are the foreground color, and\r
+                                bits 4..6 are the background color. All other bits are undefined\r
+                                and must be zero. The valid Attributes are defined in this file.\r
+\r
+  @retval EFI_SUCCESS           The attribute was set.\r
+  @retval EFI_DEVICE_ERROR      The device had an error and\r
+                                could not complete the request.\r
+  @retval EFI_UNSUPPORTED       The attribute requested is not defined.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerSetAttribute (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+  IN  UINTN                           Attribute\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+\r
+  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
+  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);\r
+\r
+  //\r
+  // Forward the request to the original ConOut\r
+  //\r
+  Status = ConsoleInfo->OldConOut->SetAttribute (ConsoleInfo->OldConOut, Attribute);\r
+\r
+  //\r
+  // Record console output history\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    ConsoleInfo->HistoryMode.Attribute = (INT32) Attribute;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Clears the output device(s) display to the currently selected background\r
+  color.\r
+\r
+  @param[in] This               Protocol instance pointer.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR      The device had an error and\r
+                                could not complete the request.\r
+  @retval EFI_UNSUPPORTED       The output device is not in a valid text mode.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerClearScreen (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  CHAR16            *Screen;\r
+  INT32             *Attributes;\r
+  UINTN             Row;\r
+  UINTN             Column;\r
+\r
+\r
+  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
+  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);\r
+\r
+  //\r
+  // Forward the request to the original ConOut\r
+  //\r
+  Status = ConsoleInfo->OldConOut->ClearScreen (ConsoleInfo->OldConOut);\r
+\r
+  //\r
+  // Record console output history\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 1) * ConsoleInfo->CurrentStartRow];\r
+    Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];\r
+    for ( Row = ConsoleInfo->OriginalStartRow\r
+        ; Row < (ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)\r
+        ; Row++\r
+       ){\r
+      for ( Column = 0\r
+          ; Column < ConsoleInfo->ColsPerScreen\r
+          ; Column++\r
+          , Screen++\r
+          , Attributes++\r
+         ){\r
+        *Screen = L' ';\r
+        *Attributes = ConsoleInfo->OldConOut->Mode->Attribute;\r
+      }\r
+      //\r
+      // Skip the NULL on each column end in text buffer only\r
+      //\r
+      Screen++;\r
+    }\r
+    ConsoleInfo->HistoryMode.CursorColumn = 0;\r
+    ConsoleInfo->HistoryMode.CursorRow    = 0;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Sets the current coordinates of the cursor position\r
+\r
+  @param[in] This               Protocol instance pointer.\r
+  @param[in] Column             Column to put the cursor in.  Must be between zero and Column returned from QueryMode\r
+  @param[in] Row                Row to put the cursor in.  Must be between zero and Row returned from QueryMode\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR      The device had an error and\r
+                                could not complete the request.\r
+  @retval EFI_UNSUPPORTED       The output device is not in a valid text mode, or the\r
+                                cursor position is invalid for the current mode.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerSetCursorPosition (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
+  IN  UINTN                         Column,\r
+  IN  UINTN                         Row\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+\r
+  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
+  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);\r
+  //\r
+  // Forward the request to the original ConOut\r
+  //\r
+  Status = ConsoleInfo->OldConOut->SetCursorPosition (\r
+    ConsoleInfo->OldConOut,\r
+    Column,\r
+    Row\r
+   );\r
+\r
+  //\r
+  // Record console output history\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    ConsoleInfo->HistoryMode.CursorColumn = (INT32)Column;\r
+    ConsoleInfo->HistoryMode.CursorRow    = (INT32)(ConsoleInfo->OriginalStartRow + Row);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Makes the cursor visible or invisible\r
+\r
+  @param[in] This       Protocol instance pointer.\r
+  @param[in] Visible    If TRUE, the cursor is set to be visible. If FALSE, the cursor is\r
+                        set to be invisible.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR      The device had an error and could not complete the\r
+                                request, or the device does not support changing\r
+                                the cursor mode.\r
+  @retval EFI_UNSUPPORTED       The output device is not in a valid text mode.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerEnableCursor (\r
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
+  IN  BOOLEAN                       Visible\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+\r
+  CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;\r
+  ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);\r
+  //\r
+  // Forward the request to the original ConOut\r
+  //\r
+  Status = ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, Visible);\r
+\r
+  //\r
+  // Record console output history\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    ConsoleInfo->HistoryMode.CursorVisible = Visible;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Function to update and verify that the current buffers are correct.\r
+\r
+  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.\r
+\r
+  This will be used when a mode has changed or a reset ocurred to verify all\r
+  history buffers.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConsoleLoggerResetBuffers(\r
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  if (ConsoleInfo->Buffer != NULL) {\r
+    FreePool(ConsoleInfo->Buffer);\r
+    ConsoleInfo->Buffer     = NULL;\r
+    ConsoleInfo->BufferSize = 0;\r
+  }\r
+  if (ConsoleInfo->Attributes != NULL) {\r
+    FreePool(ConsoleInfo->Attributes);\r
+    ConsoleInfo->Attributes = NULL;\r
+    ConsoleInfo->AttribSize = 0;\r
+  }\r
+\r
+  Status = gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &ConsoleInfo->ColsPerScreen, &ConsoleInfo->RowsPerScreen);\r
+  if (EFI_ERROR(Status)){\r
+    return (Status);\r
+  }\r
+\r
+  ConsoleInfo->BufferSize = (ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Buffer[0]);\r
+  ConsoleInfo->AttribSize = ConsoleInfo->ColsPerScreen * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Attributes[0]);\r
+\r
+  ConsoleInfo->Buffer = (CHAR16*)AllocateZeroPool(ConsoleInfo->BufferSize);\r
+\r
+  if (ConsoleInfo->Buffer == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  ConsoleInfo->Attributes = (INT32*)AllocateZeroPool(ConsoleInfo->AttribSize);\r
+  if (ConsoleInfo->Attributes == NULL) {\r
+    FreePool(ConsoleInfo->Buffer);\r
+    ConsoleInfo->Buffer     = NULL;\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  ConsoleInfo->OurConOut.Mode = gST->ConOut->Mode;\r
+  ConsoleInfo->OldConOut = gST->ConOut;\r
+  CopyMem (&ConsoleInfo->HistoryMode, ConsoleInfo->OldConOut->Mode, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE));\r
+\r
+  return (EFI_SUCCESS);\r
+}\r
diff --git a/ShellPkg/Application/Shell/ConsoleLogger.h b/ShellPkg/Application/Shell/ConsoleLogger.h
new file mode 100644 (file)
index 0000000..847c64c
--- /dev/null
@@ -0,0 +1,341 @@
+/** @file
+  Provides interface to shell console logger.
+
+  Copyright (c) 2009 - 2010, 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 _CONSOLE_LOGGER_HEADER_
+#define _CONSOLE_LOGGER_HEADER_
+
+#include <Uefi.h>
+
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+
+#include <Library/Debuglib.h>
+#include <Library/Baselib.h>
+#include <Library/BaseMemorylib.h>
+#include <Library/MemoryAllocationlib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/ShellLib.h>
+
+#define CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('c', 'o', 'P', 'D')
+
+typedef struct _CONSOLE_LOGGER_PRIVATE_DATA{
+  UINTN                             Signature;
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   OurConOut;        ///< the protocol we installed onto the system table
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *OldConOut;       ///< old protocol to reinstall upon exiting
+  EFI_HANDLE                        OldConHandle;     ///< old protocol handle
+  UINTN                             ScreenCount;      ///< How many screens worth of data to save
+  CHAR16                            *Buffer;          ///< Buffer to save data
+  UINTN                             BufferSize;       ///< size of buffer in bytes
+
+                                                      //  start row is the top of the screen
+  UINTN                             OriginalStartRow; ///< What the originally visible start row was
+  UINTN                             CurrentStartRow;  ///< what the currently visible start row is
+
+  UINTN                             RowsPerScreen;    ///< how many rows the screen can display
+  UINTN                             ColsPerScreen;    ///< how many columns the screen can display
+
+  INT32                             *Attributes;      ///< Buffer for Attribute to be saved for each character
+  UINTN                             AttribSize;       ///< Size of Attributes in bytes
+
+  EFI_SIMPLE_TEXT_OUTPUT_MODE       HistoryMode;      ///< mode of the history log
+  BOOLEAN                           Enabled;          ///< Set to FALSE when a break is requested.
+  UINTN                             RowCounter;       ///< Initial row of each print job.
+} CONSOLE_LOGGER_PRIVATE_DATA;
+
+#define CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(a) CR (a, CONSOLE_LOGGER_PRIVATE_DATA, OurConOut, CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE)
+
+/**
+  Install our intermediate ConOut into the system table to
+  keep a log of all the info that is displayed to the user.
+
+  @param[in] ScreensToSave  Sets how many screen-worths of data to save.
+  @param[out] ConsoleInfo   The object to pass into later functions.
+
+  @retval EFI_SUCCESS       The operation was successful.
+  @return other             The operation failed.
+
+  @sa ConsoleLoggerResetBuffers
+  @sa InstallProtocolInterface
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerInstall(
+  IN CONST UINTN ScreensToSave,
+  OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo
+  );
+
+/**
+  Return the system to the state it was before InstallConsoleLogger
+  was installed.
+
+  @param[in,out] ConsoleInfo   The object from the install function.
+
+  @retval EFI_SUCCESS     The operation was successful
+  @return other           The operation failed.  This was from UninstallProtocolInterface.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerUninstall(
+  IN OUT CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+  );
+
+/**
+  Displays previously logged output back to the screen.
+
+  This will scroll the screen forwards and backwards through the log of previous
+  output.  If Rows is 0 then the size of 1/2 the screen will be scrolled.  If Rows
+  is (UINTN)(-1) then the size of the screen will be scrolled.
+
+  @param[in] Forward      If TRUE then the log will be displayed forwards (scroll to newer).
+                          If FALSE then the log will be displayed backwards (scroll to older).
+  @param[in] Rows         Determines how many rows the log should scroll.
+  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerDisplayHistory(
+  IN CONST BOOLEAN  Forward,
+  IN CONST UINTN    Rows,
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+  );
+
+/**
+  Function to return to normal output whent he scrolling is complete.
+  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
+
+  @retval EFI_SUCCESS   The operation was successful.
+  @return other         The operation failed.  See UpdateDisplayFromHistory.
+
+  @sa UpdateDisplayFromHistory
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerStopHistory(
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+  );
+
+/**
+  Updates the hidden ConOut to be displaying the correct stuff.
+  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
+
+  @retval EFI_SUCCESS     The operation was successful.
+  @return other           The operation failed.
+**/
+EFI_STATUS
+EFIAPI
+UpdateDisplayFromHistory(
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+  );
+
+/**
+  Reset the text output device hardware and optionaly run diagnostics
+
+  @param This                 Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
+  @param ExtendedVerification Indicates that a more extensive test may be performed
+
+  @retval EFI_SUCCESS         The text output device was reset.
+  @retval EFI_DEVICE_ERROR    The text output device is not functioning correctly and
+                              could not be reset.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerReset (
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+  IN  BOOLEAN                         ExtendedVerification
+  );
+
+/**
+  Write a Unicode string to the output device.
+
+  @param[in] This                 Protocol instance pointer.
+  @param[in] WString              The NULL-terminated Unicode string to be displayed on the output
+                                  device(s). All output devices must also support the Unicode
+                                  drawing defined in this file.
+  @retval EFI_SUCCESS             The string was output to the device.
+  @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output
+                                  the text.
+  @retval EFI_UNSUPPORTED         The output device's mode is not currently in a
+                                  defined text mode.
+  @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the
+                                  characters in the Unicode string could not be
+                                  rendered and were skipped.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerOutputString(
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+  IN  CHAR16                          *WString
+  );
+
+/**
+  Verifies that all characters in a Unicode string can be output to the
+  target device.
+
+  @param[in] This     Protocol instance pointer.
+  @param[in] WString  The NULL-terminated Unicode string to be examined for the output
+                      device(s).
+
+  @retval EFI_SUCCESS           The device(s) are capable of rendering the output string.
+  @retval EFI_UNSUPPORTED       Some of the characters in the Unicode string cannot be
+                                rendered by one or more of the output devices mapped
+                                by the EFI handle.
+
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerTestString (
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+  IN  CHAR16                          *WString
+  );
+
+/**
+  Returns information for an available text mode that the output device(s)
+  supports.
+
+  @param[in] This               Protocol instance pointer.
+  @param[in] ModeNumber         The mode number to return information on.
+  @param[out] Columns           Upon return, the number of columns in the selected geometry
+  @param[out] Rows              Upon return, the number of rows in the selected geometry
+
+  @retval EFI_SUCCESS           The requested mode information was returned.
+  @retval EFI_DEVICE_ERROR      The device had an error and could not
+                                complete the request.
+  @retval EFI_UNSUPPORTED       The mode number was not valid.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerQueryMode (
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
+  IN  UINTN                            ModeNumber,
+  OUT UINTN                            *Columns,
+  OUT UINTN                            *Rows
+  );
+
+/**
+  Sets the output device(s) to a specified mode.
+
+  @param[in] This               Protocol instance pointer.
+  @param[in] ModeNumber         The mode number to set.
+
+
+  @retval EFI_SUCCESS           The requested text mode was set.
+  @retval EFI_DEVICE_ERROR      The device had an error and
+                                could not complete the request.
+  @retval EFI_UNSUPPORTED       The mode number was not valid.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerSetMode (
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
+  IN  UINTN                            ModeNumber
+  );
+
+/**
+  Sets the background and foreground colors for the OutputString () and
+  ClearScreen () functions.
+
+  @param[in] This               Protocol instance pointer.
+  @param[in] Attribute          The attribute to set. Bits 0..3 are the foreground color, and
+                                bits 4..6 are the background color. All other bits are undefined
+                                and must be zero. The valid Attributes are defined in this file.
+
+  @retval EFI_SUCCESS           The attribute was set.
+  @retval EFI_DEVICE_ERROR      The device had an error and
+                                could not complete the request.
+  @retval EFI_UNSUPPORTED       The attribute requested is not defined.
+
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerSetAttribute (
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+  IN  UINTN                           Attribute
+  );
+
+/**
+  Clears the output device(s) display to the currently selected background
+  color.
+
+  @param[in] This               Protocol instance pointer.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_DEVICE_ERROR      The device had an error and
+                                could not complete the request.
+  @retval EFI_UNSUPPORTED       The output device is not in a valid text mode.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerClearScreen (
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This
+  );
+
+/**
+  Sets the current coordinates of the cursor position.
+
+  @param[in] This               Protocol instance pointer.
+  @param[in] Column             Column to put the cursor in.  Must be between zero and Column returned from QueryMode
+  @param[in] Row                Row to put the cursor in.  Must be between zero and Row returned from QueryMode
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_DEVICE_ERROR      The device had an error and
+                                could not complete the request.
+  @retval EFI_UNSUPPORTED       The output device is not in a valid text mode, or the
+                                cursor position is invalid for the current mode.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerSetCursorPosition (
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
+  IN  UINTN                         Column,
+  IN  UINTN                         Row
+  );
+
+/**
+    Makes the cursor visible or invisible
+
+  @param[in] This       Protocol instance pointer.
+  @param[in] Visible    If TRUE, the cursor is set to be visible. If FALSE, the cursor is
+                        set to be invisible.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_DEVICE_ERROR      The device had an error and could not complete the
+                                request, or the device does not support changing
+                                the cursor mode.
+  @retval EFI_UNSUPPORTED       The output device is not in a valid text mode.
+
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerEnableCursor (
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
+  IN  BOOLEAN                          Visible
+  );
+
+/**
+  Function to update and verify that the current buffers are correct.
+
+  @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
+
+  This will be used when a mode has changed or a reset ocurred to verify all
+  history buffers.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerResetBuffers(
+  IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+  );
+
+#endif //_CONSOLE_LOGGER_HEADER_
+
diff --git a/ShellPkg/Application/Shell/FileHandleInternal.h b/ShellPkg/Application/Shell/FileHandleInternal.h
new file mode 100644 (file)
index 0000000..ec55a6e
--- /dev/null
@@ -0,0 +1,68 @@
+/** @file
+  internal worker functions for FileHandleWrappers to use
+
+  Copyright (c) 2009 - 2010, 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_HANDLE_INTERNAL_HEADER_
+#define _FILE_HANDLE_INTERNAL_HEADER_
+
+/**
+  Move the cursor position one character backward.
+
+  @param[in] LineLength       Length of a line. Get it by calling QueryMode
+  @param[in,out] Column      Current column of the cursor position
+  @param[in,out] Row         Current row of the cursor position
+**/
+VOID
+EFIAPI
+MoveCursorBackward (
+  IN     UINTN                   LineLength,
+  IN OUT UINTN                   *Column,
+  IN OUT UINTN                   *Row
+  );
+
+/**
+  Move the cursor position one character forward.
+
+  @param[in] LineLength       Length of a line.
+  @param[in] TotalRow         Total row of a screen
+  @param[in,out] Column      Current column of the cursor position
+  @param[in,out] Row         Current row of the cursor position
+**/
+VOID
+EFIAPI
+MoveCursorForward (
+  IN     UINTN                   LineLength,
+  IN     UINTN                   TotalRow,
+  IN OUT UINTN                   *Column,
+  IN OUT UINTN                   *Row
+  );
+
+/**
+  Prints out each previously typed command in the command list history log.
+
+  When each screen is full it will pause for a key before continuing.
+
+  @param[in] TotalCols    How many columns are on the screen
+  @param[in] TotalRows    How many rows are on the screen
+  @param[in] StartColumn  which column to start at
+**/
+VOID
+EFIAPI
+PrintCommandHistory (
+  IN CONST UINTN TotalCols,
+  IN CONST UINTN TotalRows,
+  IN CONST UINTN StartColumn
+  );
+
+#endif //_FILE_HANDLE_INTERNAL_HEADER_
+
diff --git a/ShellPkg/Application/Shell/FileHandleWrappers.c b/ShellPkg/Application/Shell/FileHandleWrappers.c
new file mode 100644 (file)
index 0000000..02e42e3
--- /dev/null
@@ -0,0 +1,1563 @@
+/** @file\r
+  EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables,\r
+  StdIn, StdOut, StdErr, etc...).\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#include "Shell.h"\r
+#include "FileHandleInternal.h"\r
+\r
+/**\r
+  File style interface for console (Open).  \r
+  \r
+  @param[in] This       Ignored.\r
+  @param[out] NewHandle Ignored.\r
+  @param[in] FileName   Ignored.\r
+  @param[in] OpenMode   Ignored.\r
+  @param[in] Attributes Ignored.\r
+  \r
+  @retval EFI_NOT_FOUND\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceOpenNotFound(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  OUT EFI_FILE_PROTOCOL **NewHandle,\r
+  IN CHAR16 *FileName,\r
+  IN UINT64 OpenMode,\r
+  IN UINT64 Attributes\r
+  )\r
+{\r
+  return (EFI_NOT_FOUND);\r
+}\r
+\r
+/**\r
+  File style interface for console (Close, Delete, & Flush)\r
+  \r
+  @param[in] This       Ignored.\r
+  \r
+  @retval EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceNopGeneric(\r
+  IN EFI_FILE_PROTOCOL *This\r
+  )\r
+{\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  File style interface for console (GetPosition).\r
+\r
+  @param[in] This       Ignored.\r
+  @param[out] Position  Ignored.\r
+  \r
+  @retval EFI_UNSUPPORTED\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceNopGetPosition(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  OUT UINT64 *Position\r
+  )\r
+{\r
+  return (EFI_UNSUPPORTED);\r
+}\r
+\r
+/**\r
+  File style interface for console (SetPosition).\r
+  \r
+  @param[in] This       Ignored.\r
+  @param[in] Position   Ignored.\r
+  \r
+  @retval EFI_UNSUPPORTED\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceNopSetPosition(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN UINT64 Position\r
+  )\r
+{\r
+  return (EFI_UNSUPPORTED);\r
+}\r
+\r
+/**\r
+  File style interface for console (GetInfo).\r
+  \r
+  @param[in] This             Ignored.\r
+  @param[in] InformationType  Ignored.\r
+  @param[in,out] BufferSize   Ignored.\r
+  @param[out] Buffer          Ignored.\r
+  \r
+  @retval EFI_UNSUPPORTED\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceNopGetInfo(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN EFI_GUID *InformationType,\r
+  IN OUT UINTN *BufferSize,\r
+  OUT VOID *Buffer\r
+  )\r
+{\r
+  return (EFI_UNSUPPORTED);\r
+}\r
+\r
+/**\r
+  File style interface for console (SetInfo).\r
+  \r
+  @param[in] This       Ignored.\r
+  @param[in] InformationType   Ignored.\r
+  @param[in] BufferSize Ignored.\r
+  @param[in] Buffer     Ignored.\r
+  \r
+  @retval EFI_UNSUPPORTED\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceNopSetInfo(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN EFI_GUID *InformationType,\r
+  IN UINTN BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  return (EFI_UNSUPPORTED);\r
+}\r
+\r
+/**\r
+  File style interface for StdOut (Write).\r
+\r
+  Writes data to the screen.\r
+  \r
+  @param[in] This             The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[in,out] BufferSize   Size in bytes of Buffer.\r
+  @param[in] Buffer           The pointer to the buffer to write.\r
+  \r
+  @retval EFI_UNSUPPORTED No output console is supported.\r
+  @return A return value from gST->ConOut->OutputString.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceStdOutWrite(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {\r
+    return (EFI_UNSUPPORTED);\r
+  } else {\r
+    return (gST->ConOut->OutputString(gST->ConOut, Buffer));\r
+  }\r
+}\r
+\r
+/**\r
+  File style interface for StdIn (Write).\r
+  \r
+  @param[in] This       Ignored.\r
+  @param[in] BufferSize Ignored.\r
+  @param[in] Buffer     Ignored.\r
+  \r
+  @retval EFI_UNSUPPORTED\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceStdInWrite(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  return (EFI_UNSUPPORTED);\r
+}\r
+\r
+/**\r
+  File style interface for console StdErr (Write).\r
+\r
+  Writes error to the error output.\r
+  \r
+  @param[in] This             The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[in,out] BufferSize   Size in bytes of Buffer.\r
+  @param[in] Buffer           The pointer to the buffer to write.\r
+  \r
+  @return A return value from gST->StdErr->OutputString.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceStdErrWrite(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  return (gST->StdErr->OutputString(gST->StdErr, Buffer));\r
+}\r
+\r
+/**\r
+  File style interface for console StdOut (Read).\r
+  \r
+  @param[in] This             Ignored.\r
+  @param[in,out] BufferSize   Ignored.\r
+  @param[out] Buffer          Ignored.\r
+  \r
+  @retval EFI_UNSUPPORTED\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceStdOutRead(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  OUT VOID *Buffer\r
+  )\r
+{\r
+  return (EFI_UNSUPPORTED);\r
+}\r
+\r
+/**\r
+  File style interface for console StdErr (Read).\r
+  \r
+  @param[in] This             Ignored.\r
+  @param[in,out] BufferSize   Ignored.\r
+  @param[out] Buffer          Ignored.\r
+  \r
+  @retval EFI_UNSUPPORTED\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceStdErrRead(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  OUT VOID *Buffer\r
+  )\r
+{\r
+  return (EFI_UNSUPPORTED);\r
+}\r
+\r
+/**\r
+  File style interface for NUL file (Read).\r
+  \r
+  @param[in] This             Ignored.\r
+  @param[in,out] BufferSize   Ignored.\r
+  @param[in] Buffer           Ignored.\r
+  \r
+  @retval EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceNulRead(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  OUT VOID *Buffer\r
+  )\r
+{\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  File style interface for NUL file (Write).\r
+  \r
+  @param[in] This             Ignored.\r
+  @param[in,out] BufferSize   Ignored.\r
+  @param[in] Buffer           Ignored.\r
+  \r
+  @retval EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceNulWrite(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  File style interface for console (Read).\r
+\r
+  This will return a single line of input from the console.\r
+\r
+  @param This           A pointer to the EFI_FILE_PROTOCOL instance that is the\r
+                        file handle to read data from. Not used.\r
+  @param BufferSize     On input, the size of the Buffer. On output, the amount\r
+                        of data returned in Buffer. In both cases, the size is\r
+                        measured in bytes.\r
+  @param Buffer         The buffer into which the data is read.\r
+\r
+\r
+  @retval EFI_SUCCESS           The data was read.\r
+  @retval EFI_NO_MEDIA          The device has no medium.\r
+  @retval EFI_DEVICE_ERROR      The device reported an error.\r
+  @retval EFI_DEVICE_ERROR      An attempt was made to read from a deleted file.\r
+  @retval EFI_DEVICE_ERROR      On entry, the current file position is beyond the end of the file.\r
+  @retval EFI_VOLUME_CORRUPTED  The file system structures are corrupted.\r
+  @retval EFI_BUFFER_TOO_SMALL  The BufferSize is too small to read the current directory\r
+                                entry. BufferSize has been updated with the size\r
+                                needed to complete the request.\r
+  @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceStdInRead(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  OUT VOID *Buffer\r
+  )\r
+{\r
+  CHAR16              *CurrentString;\r
+  BOOLEAN             Done;\r
+  UINTN               Column;         // Column of current cursor\r
+  UINTN               Row;            // Row of current cursor\r
+  UINTN               StartColumn;    // Column at the beginning of the line\r
+  UINTN               Update;         // Line index for update\r
+  UINTN               Delete;         // Num of chars to delete from console after update\r
+  UINTN               StringLen;      // Total length of the line\r
+  UINTN               StringCurPos;   // Line index corresponding to the cursor\r
+  UINTN               MaxStr;         // Maximum possible line length\r
+  UINTN               Index;\r
+  UINTN               TotalColumn;     // Num of columns in the console\r
+  UINTN               TotalRow;       // Num of rows in the console\r
+  UINTN               SkipLength;\r
+  UINTN               OutputLength;   // Length of the update string\r
+  UINTN               TailRow;        // Row of end of line\r
+  UINTN               TailColumn;     // Column of end of line\r
+  EFI_INPUT_KEY       Key;\r
+\r
+  BUFFER_LIST         *LinePos;\r
+  BUFFER_LIST         *NewPos;\r
+  BOOLEAN             InScrolling;\r
+  EFI_STATUS          Status;\r
+  BOOLEAN             InTabScrolling; // Whether in TAB-completion state\r
+  EFI_SHELL_FILE_INFO *FoundFileList;\r
+  EFI_SHELL_FILE_INFO *TabLinePos;\r
+  EFI_SHELL_FILE_INFO *TempPos;\r
+  CHAR16              *TabStr;\r
+  CHAR16              *TabOutputStr;\r
+  BOOLEAN             InQuotationMode;\r
+  CHAR16              *TempStr;\r
+  UINTN               TabPos;         // Start index of the string to search for TAB completion.\r
+  UINTN               TabUpdatePos;   // Start index of the string updated by TAB stroke\r
+//  UINTN               Count;\r
+  UINTN               EventIndex;\r
+  CONST CHAR16        *Cwd;\r
+\r
+  //\r
+  // If buffer is not large enough to hold a CHAR16, return minimum buffer size\r
+  //\r
+  if (*BufferSize < sizeof (CHAR16) * 2) {\r
+    *BufferSize = sizeof (CHAR16) * 2;\r
+    return (EFI_BUFFER_TOO_SMALL);\r
+  }\r
+\r
+  Done              = FALSE;\r
+  CurrentString     = Buffer;\r
+  StringLen         = 0;\r
+  StringCurPos      = 0;\r
+  OutputLength      = 0;\r
+  Update            = 0;\r
+  Delete            = 0;\r
+  LinePos           = NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory);\r
+  InScrolling       = FALSE;\r
+  InTabScrolling    = FALSE;\r
+  Status            = EFI_SUCCESS;\r
+  TabLinePos        = NULL;\r
+  FoundFileList     = NULL;\r
+  TempPos           = NULL;\r
+  TabPos            = 0;\r
+  TabUpdatePos      = 0;\r
+\r
+  //\r
+  // Allocate buffers\r
+  //\r
+  TabStr            = AllocateZeroPool (*BufferSize);\r
+  if (TabStr == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  TabOutputStr      = AllocateZeroPool (*BufferSize);\r
+  if (TabOutputStr == NULL) {\r
+    FreePool(TabStr);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Get the screen setting and the current cursor location\r
+  //\r
+  Column      = StartColumn = gST->ConOut->Mode->CursorColumn;\r
+  Row         = gST->ConOut->Mode->CursorRow;\r
+  gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &TotalColumn, &TotalRow);\r
+\r
+  //\r
+  // Limit the line length to the buffer size or the minimun size of the\r
+  // screen. (The smaller takes effect)\r
+  //\r
+  MaxStr = TotalColumn * (TotalRow - 1) - StartColumn;\r
+  if (MaxStr > *BufferSize / sizeof (CHAR16)) {\r
+    MaxStr = *BufferSize / sizeof (CHAR16);\r
+  }\r
+  ZeroMem (CurrentString, MaxStr * sizeof (CHAR16));\r
+  do {\r
+    //\r
+    // Read a key\r
+    //\r
+    gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Press PageUp or PageDown to scroll the history screen up or down.\r
+    // Press any other key to quit scrolling.\r
+    //\r
+    if (Key.UnicodeChar == 0 && (Key.ScanCode == SCAN_PAGE_UP || Key.ScanCode == SCAN_PAGE_DOWN)) {\r
+      if (Key.ScanCode == SCAN_PAGE_UP) {\r
+        ConsoleLoggerDisplayHistory(FALSE, 0, ShellInfoObject.ConsoleInfo);\r
+      } else if (Key.ScanCode == SCAN_PAGE_DOWN) {\r
+        ConsoleLoggerDisplayHistory(TRUE, 0, ShellInfoObject.ConsoleInfo);\r
+      }\r
+\r
+      InScrolling = TRUE;\r
+    } else {\r
+      if (InScrolling) {\r
+        ConsoleLoggerStopHistory(ShellInfoObject.ConsoleInfo);\r
+        InScrolling = FALSE;\r
+      }\r
+    }\r
+\r
+    //\r
+    // If we are quitting TAB scrolling...\r
+    //\r
+    if (InTabScrolling && Key.UnicodeChar != CHAR_TAB) {\r
+        if (FoundFileList != NULL) {\r
+          ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);\r
+          DEBUG_CODE(FoundFileList = NULL;);\r
+        }\r
+        InTabScrolling = FALSE;\r
+    }\r
+\r
+    switch (Key.UnicodeChar) {\r
+    case CHAR_CARRIAGE_RETURN:\r
+      //\r
+      // All done, print a newline at the end of the string\r
+      //\r
+      TailRow     = Row + (StringLen - StringCurPos + Column) / TotalColumn;\r
+      TailColumn  = (StringLen - StringCurPos + Column) % TotalColumn;\r
+      ShellPrintEx ((INT32)TailColumn, (INT32)TailRow, L"%N\n");\r
+      Done = TRUE;\r
+      break;\r
+\r
+    case CHAR_BACKSPACE:\r
+      if (StringCurPos != 0) {\r
+        //\r
+        // If not move back beyond string beginning, move all characters behind\r
+        // the current position one character forward\r
+        //\r
+        StringCurPos--;\r
+        Update  = StringCurPos;\r
+        Delete  = 1;\r
+        CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos));\r
+\r
+        //\r
+        // Adjust the current column and row\r
+        //\r
+        MoveCursorBackward (TotalColumn, &Column, &Row);\r
+      }\r
+      break;\r
+\r
+    case CHAR_TAB:\r
+      //\r
+      // handle auto complete of file and directory names...\r
+      //\r
+      if (InTabScrolling) {\r
+        ASSERT(FoundFileList != NULL);\r
+        ASSERT(TabLinePos != NULL);\r
+        TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);\r
+        if (IsNull(&(FoundFileList->Link), &TabLinePos->Link)) {\r
+          TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);\r
+        }\r
+      } else {\r
+        TabPos          = 0;\r
+        TabUpdatePos    = 0;\r
+        InQuotationMode = FALSE;\r
+        for (Index = 0; Index < StringLen; Index++) {\r
+          if (CurrentString[Index] == L'\"') {\r
+            InQuotationMode = (BOOLEAN)(!InQuotationMode);\r
+          }\r
+          if (CurrentString[Index] == L' ' && !InQuotationMode) {\r
+            TabPos = Index + 1;\r
+            TabUpdatePos = Index + 1;\r
+          }\r
+          if (CurrentString[Index] == L'\\') {\r
+            TabUpdatePos = Index + 1;\r
+          }\r
+        }\r
+        if (StrStr(CurrentString + TabPos, L":") == NULL) {\r
+          Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL);\r
+          if (Cwd != NULL) {\r
+            StrCpy(TabStr, Cwd);\r
+            if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) == L'\\' ) {\r
+              TabStr[StrLen(TabStr)-1] = CHAR_NULL;\r
+            }\r
+            StrnCat(TabStr, CurrentString + TabPos, (StringLen - TabPos) * sizeof (CHAR16));\r
+          } else {\r
+            StrCpy(TabStr, L"");\r
+            StrnCat(TabStr, CurrentString + TabPos, (StringLen - TabPos) * sizeof (CHAR16));\r
+          }\r
+        } else {\r
+          StrCpy(TabStr, CurrentString + TabPos);\r
+        }\r
+        StrCat(TabStr, L"*");\r
+        FoundFileList = NULL;\r
+//        TabStr = CleanPath(TabStr);\r
+        Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FoundFileList);\r
+        for ( TempStr = CurrentString\r
+            ; *TempStr == L' '\r
+            ; TempStr++); // note the ';'... empty for loop\r
+        //\r
+        // make sure we have a list before we do anything more...\r
+        //\r
+        if (EFI_ERROR (Status) || FoundFileList == NULL) {\r
+          InTabScrolling = FALSE;\r
+          TabLinePos = NULL;\r
+          continue;\r
+        } else {\r
+          //\r
+          // enumerate through the list of files\r
+          //\r
+          for ( TempPos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(FoundFileList->Link))\r
+              ; !IsNull(&FoundFileList->Link, &TempPos->Link)\r
+              ; TempPos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &(TempPos->Link))\r
+             ){\r
+            //\r
+            // If "cd" is typed, only directory name will be auto-complete filled\r
+            // in either case . and .. will be removed.\r
+            //\r
+            if ((((TempStr[0] == L'c' || TempStr[0] == L'C') &&\r
+                (TempStr[1] == L'd' || TempStr[1] == L'D')\r
+               ) && ((ShellIsDirectory(TempPos->FullName) != EFI_SUCCESS)\r
+                ||(StrCmp(TempPos->FileName, L".") == 0)\r
+                ||(StrCmp(TempPos->FileName, L"..") == 0)\r
+               )) || ((StrCmp(TempPos->FileName, L".") == 0)\r
+                ||(StrCmp(TempPos->FileName, L"..") == 0))){\r
+                TabLinePos = TempPos;\r
+                TempPos = (EFI_SHELL_FILE_INFO*)(RemoveEntryList(&(TempPos->Link))->BackLink);\r
+                InternalFreeShellFileInfoNode(TabLinePos);\r
+            }\r
+          }\r
+          if (FoundFileList != NULL && !IsListEmpty(&FoundFileList->Link)) {\r
+            TabLinePos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FoundFileList->Link);\r
+            InTabScrolling = TRUE;\r
+          } else {\r
+            FreePool(FoundFileList);\r
+            FoundFileList = NULL;\r
+          }\r
+        }\r
+      }\r
+      break;\r
+\r
+    default:\r
+      if (Key.UnicodeChar >= ' ') {\r
+        //\r
+        // If we are at the buffer's end, drop the key\r
+        //\r
+        if (StringLen == MaxStr - 1 && (ShellInfoObject.ViewingSettings.InsertMode || StringCurPos == StringLen)) {\r
+          break;\r
+        }\r
+        //\r
+        // If in insert mode, make space by moving each other character 1\r
+        // space higher in the array\r
+        //\r
+        if (ShellInfoObject.ViewingSettings.InsertMode) {\r
+          CopyMem(CurrentString + StringCurPos + 1, CurrentString + StringCurPos, (StringLen - StringCurPos)*sizeof(CurrentString[0]));\r
+        }\r
+\r
+        CurrentString[StringCurPos] = Key.UnicodeChar;\r
+        Update      = StringCurPos;\r
+\r
+        StringCurPos += 1;\r
+        OutputLength = 1;\r
+      }\r
+      break;\r
+\r
+    case 0:\r
+      switch (Key.ScanCode) {\r
+      case SCAN_DELETE:\r
+        //\r
+        // Move characters behind current position one character forward\r
+        //\r
+        if (StringLen != 0) {\r
+          Update  = StringCurPos;\r
+          Delete  = 1;\r
+          CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos));\r
+        }\r
+        break;\r
+\r
+      case SCAN_UP:\r
+        //\r
+        // Prepare to print the previous command\r
+        //\r
+        NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);\r
+        if (IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link)) {\r
+          NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);\r
+        }\r
+        break;\r
+\r
+      case SCAN_DOWN:\r
+        //\r
+        // Prepare to print the next command\r
+        //\r
+        NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);\r
+        if (NewPos == (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) {\r
+          NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);\r
+        }\r
+        break;\r
+\r
+      case SCAN_LEFT:\r
+        //\r
+        // Adjust current cursor position\r
+        //\r
+        if (StringCurPos != 0) {\r
+          --StringCurPos;\r
+          MoveCursorBackward (TotalColumn, &Column, &Row);\r
+        }\r
+        break;\r
+\r
+      case SCAN_RIGHT:\r
+        //\r
+        // Adjust current cursor position\r
+        //\r
+        if (StringCurPos < StringLen) {\r
+          ++StringCurPos;\r
+          MoveCursorForward (TotalColumn, TotalRow, &Column, &Row);\r
+        }\r
+        break;\r
+\r
+      case SCAN_HOME:\r
+        //\r
+        // Move current cursor position to the beginning of the command line\r
+        //\r
+        Row -= (StringCurPos + StartColumn) / TotalColumn;\r
+        Column  = StartColumn;\r
+        StringCurPos  = 0;\r
+        break;\r
+\r
+      case SCAN_END:\r
+        //\r
+        // Move current cursor position to the end of the command line\r
+        //\r
+        TailRow       = Row + (StringLen - StringCurPos + Column) / TotalColumn;\r
+        TailColumn    = (StringLen - StringCurPos + Column) % TotalColumn;\r
+        Row           = TailRow;\r
+        Column        = TailColumn;\r
+        StringCurPos  = StringLen;\r
+        break;\r
+\r
+      case SCAN_ESC:\r
+        //\r
+        // Prepare to clear the current command line\r
+        //\r
+        CurrentString[0]  = 0;\r
+        Update  = 0;\r
+        Delete  = StringLen;\r
+        Row -= (StringCurPos + StartColumn) / TotalColumn;\r
+        Column        = StartColumn;\r
+        OutputLength  = 0;\r
+        break;\r
+\r
+      case SCAN_INSERT:\r
+        //\r
+        // Toggle the SEnvInsertMode flag\r
+        //\r
+        ShellInfoObject.ViewingSettings.InsertMode = (BOOLEAN)!ShellInfoObject.ViewingSettings.InsertMode;\r
+        break;\r
+\r
+      case SCAN_F7:\r
+        //\r
+        // Print command history\r
+        //\r
+        PrintCommandHistory (TotalColumn, TotalRow, 4);\r
+        *CurrentString  = CHAR_NULL;\r
+        Done  = TRUE;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Done) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // If we are in auto-complete mode, we are preparing to print\r
+    // the next file or directory name\r
+    //\r
+    if (InTabScrolling) {\r
+      //\r
+      // Adjust the column and row to the start of TAB-completion string.\r
+      //\r
+      Column = (StartColumn + TabUpdatePos) % TotalColumn;\r
+      Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn;\r
+      OutputLength = StrLen (TabLinePos->FileName);\r
+      //\r
+      // if the output string contains  blank space, quotation marks L'\"'\r
+      // should be added to the output.\r
+      //\r
+      if (StrStr(TabLinePos->FileName, L" ") != NULL){\r
+        TabOutputStr[0] = L'\"';\r
+        CopyMem (TabOutputStr + 1, TabLinePos->FileName, OutputLength * sizeof (CHAR16));\r
+        TabOutputStr[OutputLength + 1] = L'\"';\r
+        TabOutputStr[OutputLength + 2] = CHAR_NULL;\r
+      } else {\r
+        CopyMem (TabOutputStr, TabLinePos->FileName, OutputLength * sizeof (CHAR16));\r
+        TabOutputStr[OutputLength] = CHAR_NULL;\r
+      }\r
+      OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1;\r
+      CopyMem (CurrentString + TabUpdatePos, TabOutputStr, OutputLength * sizeof (CHAR16));\r
+      CurrentString[TabUpdatePos + OutputLength] = CHAR_NULL;\r
+      StringCurPos = TabUpdatePos + OutputLength;\r
+      Update = TabUpdatePos;\r
+      if (StringLen > TabUpdatePos + OutputLength) {\r
+        Delete = StringLen - TabUpdatePos - OutputLength;\r
+      }\r
+    }\r
+\r
+    //\r
+    // If we have a new position, we are preparing to print a previous or\r
+    // next command.\r
+    //\r
+    if (NewPos != (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) {\r
+      Column = StartColumn;\r
+      Row -= (StringCurPos + StartColumn) / TotalColumn;\r
+\r
+      LinePos       = NewPos;\r
+      NewPos        = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory);\r
+\r
+      OutputLength  = StrLen (LinePos->Buffer) < MaxStr - 1 ? StrLen (LinePos->Buffer) : MaxStr - 1;\r
+      CopyMem (CurrentString, LinePos->Buffer, OutputLength * sizeof (CHAR16));\r
+      CurrentString[OutputLength] = CHAR_NULL;\r
+\r
+      StringCurPos            = OutputLength;\r
+\r
+      //\r
+      // Draw new input string\r
+      //\r
+      Update = 0;\r
+      if (StringLen > OutputLength) {\r
+        //\r
+        // If old string was longer, blank its tail\r
+        //\r
+        Delete = StringLen - OutputLength;\r
+      }\r
+    }\r
+    //\r
+    // If we need to update the output do so now\r
+    //\r
+    if (Update != (UINTN) -1) {\r
+      ShellPrintEx ((INT32)Column, (INT32)Row, L"%s%.*s", CurrentString + Update, Delete, L"");\r
+      StringLen = StrLen (CurrentString);\r
+\r
+      if (Delete != 0) {\r
+        SetMem (CurrentString + StringLen, Delete * sizeof (CHAR16), CHAR_NULL);\r
+      }\r
+\r
+      if (StringCurPos > StringLen) {\r
+        StringCurPos = StringLen;\r
+      }\r
+\r
+      Update = (UINTN) -1;\r
+\r
+      //\r
+      // After using print to reflect newly updates, if we're not using\r
+      // BACKSPACE and DELETE, we need to move the cursor position forward,\r
+      // so adjust row and column here.\r
+      //\r
+      if (Key.UnicodeChar != CHAR_BACKSPACE && !(Key.UnicodeChar == 0 && Key.ScanCode == SCAN_DELETE)) {\r
+        //\r
+        // Calulate row and column of the tail of current string\r
+        //\r
+        TailRow     = Row + (StringLen - StringCurPos + Column + OutputLength) / TotalColumn;\r
+        TailColumn  = (StringLen - StringCurPos + Column + OutputLength) % TotalColumn;\r
+\r
+        //\r
+        // If the tail of string reaches screen end, screen rolls up, so if\r
+        // Row does not equal TailRow, Row should be decremented\r
+        //\r
+        // (if we are recalling commands using UPPER and DOWN key, and if the\r
+        // old command is too long to fit the screen, TailColumn must be 79.\r
+        //\r
+        if (TailColumn == 0 && TailRow >= TotalRow && Row != TailRow) {\r
+          Row--;\r
+        }\r
+        //\r
+        // Calculate the cursor position after current operation. If cursor\r
+        // reaches line end, update both row and column, otherwise, only\r
+        // column will be changed.\r
+        //\r
+        if (Column + OutputLength >= TotalColumn) {\r
+          SkipLength = OutputLength - (TotalColumn - Column);\r
+\r
+          Row += SkipLength / TotalColumn + 1;\r
+          if (Row > TotalRow - 1) {\r
+            Row = TotalRow - 1;\r
+          }\r
+\r
+          Column = SkipLength % TotalColumn;\r
+        } else {\r
+          Column += OutputLength;\r
+        }\r
+      }\r
+\r
+      Delete = 0;\r
+    }\r
+    //\r
+    // Set the cursor position for this key\r
+    //\r
+    gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);\r
+  } while (!Done);\r
+\r
+  if (CurrentString != NULL && StrLen(CurrentString) > 0) {\r
+    //\r
+    // add the line to the history buffer\r
+    //\r
+    AddLineToCommandHistory(CurrentString);\r
+  }\r
+\r
+  FreePool (TabStr);\r
+  FreePool (TabOutputStr);\r
+  //\r
+  // Return the data to the caller\r
+  //\r
+  *BufferSize = StringLen * sizeof (CHAR16);\r
+\r
+  //\r
+  // if this was used it should be deallocated by now...\r
+  // prevent memory leaks...\r
+  //\r
+  ASSERT(FoundFileList == NULL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// FILE sytle interfaces for StdIn/StdOut/StdErr\r
+//\r
+EFI_FILE_PROTOCOL FileInterfaceStdIn = {\r
+  EFI_FILE_REVISION,\r
+  FileInterfaceOpenNotFound,\r
+  FileInterfaceNopGeneric,\r
+  FileInterfaceNopGeneric,\r
+  FileInterfaceStdInRead,\r
+  FileInterfaceStdInWrite,\r
+  FileInterfaceNopGetPosition,\r
+  FileInterfaceNopSetPosition,\r
+  FileInterfaceNopGetInfo,\r
+  FileInterfaceNopSetInfo,\r
+  FileInterfaceNopGeneric\r
+};\r
+\r
+EFI_FILE_PROTOCOL FileInterfaceStdOut = {\r
+  EFI_FILE_REVISION,\r
+  FileInterfaceOpenNotFound,\r
+  FileInterfaceNopGeneric,\r
+  FileInterfaceNopGeneric,\r
+  FileInterfaceStdOutRead,\r
+  FileInterfaceStdOutWrite,\r
+  FileInterfaceNopGetPosition,\r
+  FileInterfaceNopSetPosition,\r
+  FileInterfaceNopGetInfo,\r
+  FileInterfaceNopSetInfo,\r
+  FileInterfaceNopGeneric\r
+};\r
+\r
+EFI_FILE_PROTOCOL FileInterfaceStdErr = {\r
+  EFI_FILE_REVISION,\r
+  FileInterfaceOpenNotFound,\r
+  FileInterfaceNopGeneric,\r
+  FileInterfaceNopGeneric,\r
+  FileInterfaceStdErrRead,\r
+  FileInterfaceStdErrWrite,\r
+  FileInterfaceNopGetPosition,\r
+  FileInterfaceNopSetPosition,\r
+  FileInterfaceNopGetInfo,\r
+  FileInterfaceNopSetInfo,\r
+  FileInterfaceNopGeneric\r
+};\r
+\r
+EFI_FILE_PROTOCOL FileInterfaceNulFile = {\r
+  EFI_FILE_REVISION,\r
+  FileInterfaceOpenNotFound,\r
+  FileInterfaceNopGeneric,\r
+  FileInterfaceNopGeneric,\r
+  FileInterfaceNulRead,\r
+  FileInterfaceNulWrite,\r
+  FileInterfaceNopGetPosition,\r
+  FileInterfaceNopSetPosition,\r
+  FileInterfaceNopGetInfo,\r
+  FileInterfaceNopSetInfo,\r
+  FileInterfaceNopGeneric\r
+};\r
+\r
+\r
+\r
+\r
+//\r
+// This is identical to EFI_FILE_PROTOCOL except for the additional member\r
+// for the name.\r
+//\r
+\r
+typedef struct {\r
+  UINT64                Revision;\r
+  EFI_FILE_OPEN         Open;\r
+  EFI_FILE_CLOSE        Close;\r
+  EFI_FILE_DELETE       Delete;\r
+  EFI_FILE_READ         Read;\r
+  EFI_FILE_WRITE        Write;\r
+  EFI_FILE_GET_POSITION GetPosition;\r
+  EFI_FILE_SET_POSITION SetPosition;\r
+  EFI_FILE_GET_INFO     GetInfo;\r
+  EFI_FILE_SET_INFO     SetInfo;\r
+  EFI_FILE_FLUSH        Flush;\r
+  CHAR16                Name[1];\r
+} EFI_FILE_PROTOCOL_ENVIRONMENT;\r
+//ANSI compliance helper to get size of the struct.\r
+#define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name)\r
+\r
+/**\r
+  File style interface for Environment Variable (Close).\r
+\r
+  Frees the memory for this object.\r
+  \r
+  @param[in] This       The pointer to the EFI_FILE_PROTOCOL object.\r
+  \r
+  @retval EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceEnvClose(\r
+  IN EFI_FILE_PROTOCOL *This\r
+  )\r
+{\r
+  FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT*)This);\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  File style interface for Environment Variable (Delete).\r
+  \r
+  @param[in] This       The pointer to the EFI_FILE_PROTOCOL object.\r
+  \r
+  @retval The return value from FileInterfaceEnvClose().\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceEnvDelete(\r
+  IN EFI_FILE_PROTOCOL *This\r
+  )\r
+{\r
+  SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name);\r
+  return (FileInterfaceEnvClose(This));\r
+}\r
+\r
+/**\r
+  File style interface for Environment Variable (Read).\r
+  \r
+  @param[in] This             The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[in,out] BufferSize   Size in bytes of Buffer.\r
+  @param[out] Buffer          The pointer to the buffer to fill.\r
+  \r
+  @retval EFI_SUCCESS   The data was read.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceEnvRead(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  OUT VOID *Buffer\r
+  )\r
+{\r
+  return (SHELL_GET_ENVIRONMENT_VARIABLE(\r
+    ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,\r
+    BufferSize,\r
+    Buffer));\r
+}\r
+\r
+/**\r
+  File style interface for Volatile Environment Variable (Write).\r
+  \r
+  @param[in] This             The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[in,out] BufferSize   Size in bytes of Buffer.\r
+  @param[in] Buffer           The pointer to the buffer to write.\r
+  \r
+  @retval EFI_SUCCESS   The data was read.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceEnvVolWrite(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  VOID*       NewBuffer;\r
+  UINTN       NewSize;\r
+  EFI_STATUS  Status;\r
+\r
+  NewBuffer   = NULL;\r
+  NewSize     = 0;\r
+\r
+  Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
+  if (Status == EFI_BUFFER_TOO_SMALL){\r
+    NewBuffer = AllocateZeroPool(NewSize + *BufferSize + sizeof(CHAR16));\r
+    Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
+  }\r
+  if (!EFI_ERROR(Status) && NewBuffer != NULL) {\r
+    while (((CHAR16*)NewBuffer)[NewSize/2] == CHAR_NULL) {\r
+      //\r
+      // We want to overwrite the CHAR_NULL\r
+      //\r
+      NewSize -= 2;\r
+    }\r
+    CopyMem((UINT8*)NewBuffer + NewSize + 2, Buffer, *BufferSize);\r
+    Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);\r
+    FreePool(NewBuffer);\r
+    return (Status);\r
+  } else {\r
+    SHELL_FREE_NON_NULL(NewBuffer);\r
+    return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, *BufferSize, Buffer));\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  File style interface for Non Volatile Environment Variable (Write).\r
+  \r
+  @param[in] This             The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[in,out] BufferSize   Size in bytes of Buffer.\r
+  @param[in] Buffer           The pointer to the buffer to write.\r
+  \r
+  @retval EFI_SUCCESS   The data was read.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceEnvNonVolWrite(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  VOID*       NewBuffer;\r
+  UINTN       NewSize;\r
+  EFI_STATUS  Status;\r
+\r
+  NewBuffer   = NULL;\r
+  NewSize     = 0;\r
+\r
+  Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
+  if (Status == EFI_BUFFER_TOO_SMALL){\r
+    NewBuffer = AllocateZeroPool(NewSize + *BufferSize);\r
+    Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);\r
+  }\r
+  if (!EFI_ERROR(Status)) {\r
+    CopyMem((UINT8*)NewBuffer + NewSize, Buffer, *BufferSize);\r
+    return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(\r
+    ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,\r
+    NewSize + *BufferSize,\r
+    NewBuffer));\r
+  } else {\r
+    return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(\r
+    ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,\r
+    *BufferSize,\r
+    Buffer));\r
+  }\r
+}\r
+\r
+/**\r
+  Creates a EFI_FILE_PROTOCOL (almost) object for using to access\r
+  environment variables through file operations.\r
+\r
+  @param EnvName    The name of the Environment Variable to be operated on.\r
+\r
+  @retval NULL      Memory could not be allocated.\r
+  @return other     a pointer to an EFI_FILE_PROTOCOL structure\r
+**/\r
+EFI_FILE_PROTOCOL*\r
+EFIAPI\r
+CreateFileInterfaceEnv(\r
+  IN CONST CHAR16 *EnvName\r
+  )\r
+{\r
+  EFI_FILE_PROTOCOL_ENVIRONMENT  *EnvFileInterface;\r
+\r
+  if (EnvName == NULL) {\r
+    return (NULL);\r
+  }\r
+\r
+  //\r
+  // Get some memory\r
+  //\r
+  EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+StrSize(EnvName));\r
+  if (EnvFileInterface == NULL){\r
+    return (NULL);\r
+  }\r
+\r
+  //\r
+  // Assign the generic members\r
+  //\r
+  EnvFileInterface->Revision    = EFI_FILE_REVISION;\r
+  EnvFileInterface->Open        = FileInterfaceOpenNotFound;\r
+  EnvFileInterface->Close       = FileInterfaceEnvClose;\r
+  EnvFileInterface->GetPosition = FileInterfaceNopGetPosition;\r
+  EnvFileInterface->SetPosition = FileInterfaceNopSetPosition;\r
+  EnvFileInterface->GetInfo     = FileInterfaceNopGetInfo;\r
+  EnvFileInterface->SetInfo     = FileInterfaceNopSetInfo;\r
+  EnvFileInterface->Flush       = FileInterfaceNopGeneric;\r
+  EnvFileInterface->Delete      = FileInterfaceEnvDelete;\r
+  EnvFileInterface->Read        = FileInterfaceEnvRead;\r
+\r
+  StrCpy(EnvFileInterface->Name, EnvName);\r
+\r
+  //\r
+  // Assign the different members for Volatile and Non-Volatile variables\r
+  //\r
+  if (IsVolatileEnv(EnvName)) {\r
+    EnvFileInterface->Write       = FileInterfaceEnvVolWrite;\r
+  } else {\r
+    EnvFileInterface->Write       = FileInterfaceEnvNonVolWrite;\r
+  }\r
+  return ((EFI_FILE_PROTOCOL *)EnvFileInterface);\r
+}\r
+\r
+/**\r
+  Move the cursor position one character backward.\r
+\r
+  @param[in] LineLength       Length of a line. Get it by calling QueryMode\r
+  @param[in,out] Column      Current column of the cursor position\r
+  @param[in,out] Row         Current row of the cursor position\r
+**/\r
+VOID\r
+EFIAPI\r
+MoveCursorBackward (\r
+  IN     UINTN                   LineLength,\r
+  IN OUT UINTN                   *Column,\r
+  IN OUT UINTN                   *Row\r
+  )\r
+{\r
+  //\r
+  // If current column is 0, move to the last column of the previous line,\r
+  // otherwise, just decrement column.\r
+  //\r
+  if (*Column == 0) {\r
+    *Column = LineLength - 1;\r
+    if (*Row > 0) {\r
+      (*Row)--;\r
+    }\r
+    return;\r
+  }\r
+  (*Column)--;\r
+}\r
+\r
+/**\r
+  Move the cursor position one character forward.\r
+\r
+  @param[in] LineLength       Length of a line.\r
+  @param[in] TotalRow         Total row of a screen\r
+  @param[in,out] Column      Current column of the cursor position\r
+  @param[in,out] Row         Current row of the cursor position\r
+**/\r
+VOID\r
+EFIAPI\r
+MoveCursorForward (\r
+  IN     UINTN                   LineLength,\r
+  IN     UINTN                   TotalRow,\r
+  IN OUT UINTN                   *Column,\r
+  IN OUT UINTN                   *Row\r
+  )\r
+{\r
+  //\r
+  // Increment Column.\r
+  // If this puts column past the end of the line, move to first column\r
+  // of the next row.\r
+  //\r
+  (*Column)++;\r
+  if (*Column >= LineLength) {\r
+    (*Column) = 0;\r
+    if ((*Row) < TotalRow - 1) {\r
+      (*Row)++;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Prints out each previously typed command in the command list history log.\r
+\r
+  When each screen is full it will pause for a key before continuing.\r
+\r
+  @param[in] TotalCols    How many columns are on the screen\r
+  @param[in] TotalRows    How many rows are on the screen\r
+  @param[in] StartColumn  which column to start at\r
+**/\r
+VOID\r
+EFIAPI\r
+PrintCommandHistory (\r
+  IN CONST UINTN TotalCols,\r
+  IN CONST UINTN TotalRows,\r
+  IN CONST UINTN StartColumn\r
+  )\r
+{\r
+  BUFFER_LIST     *Node;\r
+  UINTN           Index;\r
+  UINTN           LineNumber;\r
+  UINTN           LineCount;\r
+\r
+  ShellPrintEx (-1, -1, L"\n");\r
+  Index       = 0;\r
+  LineNumber  = 0;\r
+  //\r
+  // go through history list...\r
+  //\r
+  for ( Node = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link)\r
+      ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)\r
+      ; Node = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)\r
+   ){\r
+    Index++;\r
+    LineCount = ((StrLen (Node->Buffer) + StartColumn + 1) / TotalCols) + 1;\r
+\r
+    if (LineNumber + LineCount >= TotalRows) {\r
+      ShellPromptForResponseHii(\r
+        ShellPromptResponseTypeEnterContinue,\r
+        STRING_TOKEN (STR_SHELL_ENTER_TO_CONT),\r
+        ShellInfoObject.HiiHandle,\r
+        NULL\r
+       );\r
+      LineNumber = 0;\r
+    }\r
+    ShellPrintEx (-1, -1, L"%2d. %s\n", Index, Node->Buffer);\r
+    LineNumber += LineCount;\r
+  }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+//\r
+// This is identical to EFI_FILE_PROTOCOL except for the additional members\r
+// for the buffer, size, and position.\r
+//\r
+\r
+typedef struct {\r
+  UINT64                Revision;\r
+  EFI_FILE_OPEN         Open;\r
+  EFI_FILE_CLOSE        Close;\r
+  EFI_FILE_DELETE       Delete;\r
+  EFI_FILE_READ         Read;\r
+  EFI_FILE_WRITE        Write;\r
+  EFI_FILE_GET_POSITION GetPosition;\r
+  EFI_FILE_SET_POSITION SetPosition;\r
+  EFI_FILE_GET_INFO     GetInfo;\r
+  EFI_FILE_SET_INFO     SetInfo;\r
+  EFI_FILE_FLUSH        Flush;\r
+  VOID                  *Buffer;\r
+  UINT64                Position;\r
+  UINT64                BufferSize;\r
+  BOOLEAN               Unicode;\r
+} EFI_FILE_PROTOCOL_MEM;\r
+\r
+/**\r
+  File style interface for Mem (SetPosition).\r
+  \r
+  @param[in] This       The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[out] Position  The position to set.\r
+  \r
+  @retval EFI_SUCCESS             The position was successfully changed.\r
+  @retval EFI_INVALID_PARAMETER   The Position was invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceMemSetPosition(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  OUT UINT64 Position\r
+  )\r
+{\r
+  if (Position <= ((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) {\r
+    ((EFI_FILE_PROTOCOL_MEM*)This)->Position = Position;\r
+    return (EFI_SUCCESS);\r
+  } else {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+}\r
+\r
+/**\r
+  File style interface for Mem (GetPosition).\r
+  \r
+  @param[in] This       The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[out] Position  The pointer to the position.\r
+  \r
+  @retval EFI_SUCCESS   The position was retrieved.\r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceMemGetPosition(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  OUT UINT64 *Position\r
+  )\r
+{\r
+  *Position = ((EFI_FILE_PROTOCOL_MEM*)This)->Position;\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  File style interface for Mem (Write).\r
+  \r
+  @param[in] This             The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[in,out] BufferSize   Size in bytes of Buffer.\r
+  @param[in] Buffer           The pointer to the buffer to write.\r
+  \r
+  @retval EFI_SUCCESS   The data was written.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceMemWrite(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  CHAR8 *AsciiBuffer;\r
+  if (((EFI_FILE_PROTOCOL_MEM*)This)->Unicode) {\r
+    //\r
+    // Unicode\r
+    //\r
+    if ((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position + (*BufferSize)) > (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize)) {\r
+      ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer = ReallocatePool((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize), (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) + (*BufferSize) + 10, ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);\r
+      ((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize += (*BufferSize) + 10;\r
+    }\r
+    CopyMem(((UINT8*)((EFI_FILE_PROTOCOL_MEM*)This)->Buffer) + ((EFI_FILE_PROTOCOL_MEM*)This)->Position, Buffer, *BufferSize);\r
+    ((EFI_FILE_PROTOCOL_MEM*)This)->Position += (*BufferSize);\r
+    return (EFI_SUCCESS);\r
+  } else {\r
+    //\r
+    // Ascii\r
+    //\r
+    AsciiBuffer = AllocatePool(*BufferSize);\r
+    AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);\r
+    if ((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize)) {\r
+      ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer = ReallocatePool((UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize), (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) + AsciiStrSize(AsciiBuffer) + 10, ((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);\r
+      ((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize += AsciiStrSize(AsciiBuffer) + 10;\r
+    }\r
+    CopyMem(((UINT8*)((EFI_FILE_PROTOCOL_MEM*)This)->Buffer) + ((EFI_FILE_PROTOCOL_MEM*)This)->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer));\r
+    ((EFI_FILE_PROTOCOL_MEM*)This)->Position += AsciiStrSize(AsciiBuffer);\r
+    FreePool(AsciiBuffer);\r
+    return (EFI_SUCCESS);\r
+  }\r
+}\r
+\r
+/**\r
+  File style interface for Mem (Read).\r
+  \r
+  @param[in] This             The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[in,out] BufferSize   Size in bytes of Buffer.\r
+  @param[in] Buffer           The pointer to the buffer to fill.\r
+  \r
+  @retval EFI_SUCCESS   The data was read.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceMemRead(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  if (*BufferSize > (UINTN)((((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) - (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position))) {\r
+    (*BufferSize) = (UINTN)((((EFI_FILE_PROTOCOL_MEM*)This)->BufferSize) - (UINTN)(((EFI_FILE_PROTOCOL_MEM*)This)->Position));\r
+  }\r
+  CopyMem(Buffer, ((UINT8*)((EFI_FILE_PROTOCOL_MEM*)This)->Buffer) + ((EFI_FILE_PROTOCOL_MEM*)This)->Position, (*BufferSize));\r
+  ((EFI_FILE_PROTOCOL_MEM*)This)->Position = ((EFI_FILE_PROTOCOL_MEM*)This)->Position + (*BufferSize);\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  File style interface for Mem (Close).\r
+\r
+  Frees all memory associated with this object.\r
+  \r
+  @param[in] This       The pointer to the EFI_FILE_PROTOCOL object.\r
+  \r
+  @retval EFI_SUCCESS   The 'file' was closed.\r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceMemClose(\r
+  IN EFI_FILE_PROTOCOL *This\r
+  )\r
+{\r
+  SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);\r
+  SHELL_FREE_NON_NULL((EFI_FILE_PROTOCOL_MEM*)This);\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Creates a EFI_FILE_PROTOCOL (almost) object for using to access\r
+  a file entirely in memory through file operations.\r
+\r
+  @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.\r
+\r
+  @retval NULL      Memory could not be allocated.\r
+  @return other     A pointer to an EFI_FILE_PROTOCOL structure.\r
+**/\r
+EFI_FILE_PROTOCOL*\r
+EFIAPI\r
+CreateFileInterfaceMem(\r
+  IN CONST BOOLEAN Unicode\r
+  )\r
+{\r
+  EFI_FILE_PROTOCOL_MEM  *FileInterface;\r
+\r
+  //\r
+  // Get some memory\r
+  //\r
+  FileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM));\r
+  if (FileInterface == NULL){\r
+    return (NULL);\r
+  }\r
+\r
+  //\r
+  // Assign the generic members\r
+  //\r
+  FileInterface->Revision    = EFI_FILE_REVISION;\r
+  FileInterface->Open        = FileInterfaceOpenNotFound;\r
+  FileInterface->Close       = FileInterfaceMemClose;\r
+  FileInterface->GetPosition = FileInterfaceMemGetPosition;\r
+  FileInterface->SetPosition = FileInterfaceMemSetPosition;\r
+  FileInterface->GetInfo     = FileInterfaceNopGetInfo;\r
+  FileInterface->SetInfo     = FileInterfaceNopSetInfo;\r
+  FileInterface->Flush       = FileInterfaceNopGeneric;\r
+  FileInterface->Delete      = FileInterfaceNopGeneric;\r
+  FileInterface->Read        = FileInterfaceMemRead;\r
+  FileInterface->Write       = FileInterfaceMemWrite;\r
+  FileInterface->Unicode     = Unicode;\r
+\r
+  ASSERT(FileInterface->Buffer      == NULL);\r
+  ASSERT(FileInterface->BufferSize  == 0);\r
+  ASSERT(FileInterface->Position    == 0);\r
+\r
+  return ((EFI_FILE_PROTOCOL *)FileInterface);\r
+}\r
+\r
+typedef struct {\r
+  UINT64                Revision;\r
+  EFI_FILE_OPEN         Open;\r
+  EFI_FILE_CLOSE        Close;\r
+  EFI_FILE_DELETE       Delete;\r
+  EFI_FILE_READ         Read;\r
+  EFI_FILE_WRITE        Write;\r
+  EFI_FILE_GET_POSITION GetPosition;\r
+  EFI_FILE_SET_POSITION SetPosition;\r
+  EFI_FILE_GET_INFO     GetInfo;\r
+  EFI_FILE_SET_INFO     SetInfo;\r
+  EFI_FILE_FLUSH        Flush;\r
+  BOOLEAN               Unicode;\r
+  EFI_FILE_PROTOCOL     *Orig;\r
+} EFI_FILE_PROTOCOL_FILE;\r
+\r
+/**\r
+  File style interface for File (Close).\r
+  \r
+  @param[in] This       The pointer to the EFI_FILE_PROTOCOL object.\r
+  \r
+  @retval EFI_SUCCESS   The file was closed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceFileClose(\r
+  IN EFI_FILE_PROTOCOL *This\r
+  )\r
+{\r
+  ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Close(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);\r
+  FreePool(This);\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  File style interface for File (Write).\r
+\r
+  If the file was opened with ASCII mode the data will be processed through \r
+  AsciiSPrint before writing.\r
+  \r
+  @param[in] This       The pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[in] BufferSize Size in bytes of Buffer.\r
+  @param[in] Buffer     The pointer to the buffer to write.\r
+  \r
+  @retval EFI_SUCCESS   The data was written.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileInterfaceFileWrite(\r
+  IN EFI_FILE_PROTOCOL *This,\r
+  IN OUT UINTN *BufferSize,\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  CHAR8       *AsciiBuffer;\r
+  UINTN       Size;\r
+  EFI_STATUS  Status;\r
+  if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {\r
+    //\r
+    // Unicode\r
+    //\r
+    return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));\r
+  } else {\r
+    //\r
+    // Ascii\r
+    //\r
+    AsciiBuffer = AllocatePool(*BufferSize);\r
+    AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);\r
+    Size = AsciiStrSize(AsciiBuffer) - 1; // (we dont need the null terminator)\r
+    Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiBuffer));\r
+    FreePool(AsciiBuffer);\r
+    return (Status);\r
+  }\r
+}\r
+\r
+/**\r
+  Create a file interface with unicode information.\r
+\r
+  This will create a new EFI_FILE_PROTOCOL identical to the Templace\r
+  except that the new one has Unicode and Ascii knowledge.\r
+  \r
+  @param[in] Template   A pointer to the EFI_FILE_PROTOCOL object.\r
+  @param[in] Unicode    TRUE for UCS-2, FALSE for ASCII.\r
+  \r
+  @return a new EFI_FILE_PROTOCOL object to be used instead of the template.\r
+**/\r
+EFI_FILE_PROTOCOL*\r
+CreateFileInterfaceFile(\r
+  IN CONST EFI_FILE_PROTOCOL  *Template,\r
+  IN CONST BOOLEAN            Unicode\r
+  )\r
+{\r
+  EFI_FILE_PROTOCOL_FILE *NewOne;\r
+\r
+  NewOne = AllocatePool(sizeof(EFI_FILE_PROTOCOL_FILE));\r
+  CopyMem(NewOne, Template, sizeof(EFI_FILE_PROTOCOL_FILE));\r
+  NewOne->Orig    = (EFI_FILE_PROTOCOL *)Template;\r
+  NewOne->Unicode = Unicode;\r
+  NewOne->Close   = FileInterfaceFileClose;\r
+  NewOne->Write   = FileInterfaceFileWrite;\r
+\r
+  return ((EFI_FILE_PROTOCOL *)NewOne);\r
+}\r
diff --git a/ShellPkg/Application/Shell/FileHandleWrappers.h b/ShellPkg/Application/Shell/FileHandleWrappers.h
new file mode 100644 (file)
index 0000000..af133b0
--- /dev/null
@@ -0,0 +1,95 @@
+/** @file\r
+  EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables, StdIn, StdOut, StdErr, etc...)\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#ifndef _SHELL_FILE_HANDLE_WRAPPERS_HEADER_\r
+#define _SHELL_FILE_HANDLE_WRAPPERS_HEADER_\r
+\r
+typedef struct {\r
+  LIST_ENTRY        Link;\r
+  CHAR16*           Buffer;\r
+} SHELL_LINE_LIST;\r
+\r
+typedef struct {\r
+  UINTN             LogCount;\r
+  SHELL_LINE_LIST   *Log;\r
+} SHELL_LINE_LOG;\r
+\r
+///\r
+/// FILE sytle interfaces for StdIn.\r
+///\r
+extern EFI_FILE_PROTOCOL FileInterfaceStdIn;\r
+\r
+///\r
+/// FILE sytle interfaces for StdOut.\r
+///\r
+extern EFI_FILE_PROTOCOL FileInterfaceStdOut;\r
+\r
+///\r
+/// FILE sytle interfaces for StdErr.\r
+///\r
+extern EFI_FILE_PROTOCOL FileInterfaceStdErr;\r
+\r
+///\r
+/// FILE style interface for NUL file.\r
+///\r
+extern EFI_FILE_PROTOCOL FileInterfaceNulFile;\r
+\r
+/**\r
+  Creates a EFI_FILE_PROTOCOL (almost) object for using to access\r
+  environment variables through file operations.\r
+\r
+  @param EnvName    The name of the Environment Variable to be operated on.\r
+\r
+  @retval NULL      Memory could not be allocated.\r
+  @return other     a pointer to an EFI_FILE_PROTOCOL structure\r
+**/\r
+EFI_FILE_PROTOCOL*\r
+EFIAPI\r
+CreateFileInterfaceEnv(\r
+  CONST CHAR16 *EnvName\r
+  );\r
+\r
+/**\r
+  Creates a EFI_FILE_PROTOCOL (almost) object for using to access\r
+  a file entirely in memory through file operations.\r
+\r
+  @param[in] Unicode  TRUE if the data is UNICODE, FALSE otherwise.\r
+\r
+  @retval NULL      Memory could not be allocated.\r
+  @return other     a pointer to an EFI_FILE_PROTOCOL structure\r
+**/\r
+EFI_FILE_PROTOCOL*\r
+EFIAPI\r
+CreateFileInterfaceMem(\r
+  IN CONST BOOLEAN Unicode\r
+  );\r
+\r
+/**\r
+  Creates a EFI_FILE_PROTOCOL (almost) object for using to access\r
+  a file entirely with unicode awareness through file operations.\r
+\r
+  @param[in] Template The pointer to the handle to start with.\r
+  @param[in] Unicode  TRUE if the data is UNICODE, FALSE otherwise.\r
+\r
+  @retval NULL      Memory could not be allocated.\r
+  @return other     a pointer to an EFI_FILE_PROTOCOL structure\r
+**/\r
+EFI_FILE_PROTOCOL*\r
+CreateFileInterfaceFile(\r
+  IN CONST EFI_FILE_PROTOCOL  *Template,\r
+  IN CONST BOOLEAN            Unicode\r
+  );\r
+\r
+#endif //_SHELL_FILE_HANDLE_WRAPPERS_HEADER_\r
+\r
diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c
new file mode 100644 (file)
index 0000000..3401bc0
--- /dev/null
@@ -0,0 +1,1707 @@
+/** @file\r
+  This is THE shell (application)\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#include "Shell.h"\r
+\r
+//\r
+// Initialize the global structure\r
+//\r
+SHELL_INFO ShellInfoObject = {\r
+  NULL,\r
+  NULL,\r
+  FALSE,\r
+  FALSE,\r
+  {\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    0,\r
+    NULL,\r
+    NULL\r
+  },\r
+  {0,0},\r
+  {\r
+    {0,0},\r
+    0,\r
+    0,\r
+    TRUE\r
+  },\r
+  NULL,\r
+  0,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  {0,0,NULL,NULL},\r
+  {0,0},\r
+};\r
+\r
+STATIC CONST CHAR16 mScriptExtension[]      = L".NSH";\r
+STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";\r
+\r
+/**\r
+  The entry point for the application.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS       The entry point is executed successfully.\r
+  @retval other             Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UefiMain (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  CHAR16      *TempString;\r
+  UINTN       Size;\r
+//    EFI_INPUT_KEY                 Key;\r
+\r
+//  gST->ConOut->OutputString(gST->ConOut, L"ReadKeyStroke Calling\r\n");\r
+//\r
+//  Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+//\r
+//  gST->ConOut->OutputString(gST->ConOut, L"ReadKeyStroke Done\r\n");\r
+//  gBS->Stall (1000000);\r
+\r
+  if (PcdGet8(PcdShellSupportLevel) > 3) {\r
+    return (EFI_UNSUPPORTED);\r
+  }\r
+\r
+  //\r
+  // Clear the screen\r
+  //\r
+  Status = gST->ConOut->ClearScreen(gST->ConOut);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // Populate the global structure from PCDs\r
+  //\r
+  ShellInfoObject.ImageDevPath                = NULL;\r
+  ShellInfoObject.FileDevPath                 = NULL;\r
+  ShellInfoObject.PageBreakEnabled            = PcdGetBool(PcdShellPageBreakDefault);\r
+  ShellInfoObject.ViewingSettings.InsertMode  = PcdGetBool(PcdShellInsertModeDefault);\r
+  ShellInfoObject.LogScreenCount              = PcdGet8   (PcdShellScreenLogCount  );\r
+\r
+  //\r
+  // verify we dont allow for spec violation\r
+  //\r
+  ASSERT(ShellInfoObject.LogScreenCount >= 3);\r
+\r
+  //\r
+  // Initialize the LIST ENTRY objects...\r
+  //\r
+  InitializeListHead(&ShellInfoObject.BufferToFreeList.Link);\r
+  InitializeListHead(&ShellInfoObject.ViewingSettings.CommandHistory.Link);\r
+  InitializeListHead(&ShellInfoObject.SplitList.Link);\r
+\r
+  //\r
+  // Check PCDs for optional features that are not implemented yet.\r
+  //\r
+  if (   PcdGetBool(PcdShellSupportOldProtocols)\r
+      || !FeaturePcdGet(PcdShellRequireHiiPlatform)\r
+      || FeaturePcdGet(PcdShellSupportFrameworkHii)\r
+   ) {\r
+    return (EFI_UNSUPPORTED);\r
+  }\r
+\r
+  //\r
+  // turn off the watchdog timer\r
+  //\r
+  gBS->SetWatchdogTimer (0, 0, 0, NULL);\r
+\r
+  //\r
+  // install our console logger.  This will keep a log of the output for back-browsing\r
+  //\r
+  Status = ConsoleLoggerInstall(ShellInfoObject.LogScreenCount, &ShellInfoObject.ConsoleInfo);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // Enable the cursor to be visible\r
+  //\r
+  gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+  //\r
+  // If supporting EFI 1.1 we need to install HII protocol\r
+  // only do this if PcdShellRequireHiiPlatform == FALSE\r
+  //\r
+  // remove EFI_UNSUPPORTED check above when complete.\r
+  ///@todo add support for Framework HII\r
+\r
+  //\r
+  // install our (solitary) HII package\r
+  //\r
+  ShellInfoObject.HiiHandle = HiiAddPackages (&gEfiCallerIdGuid, gImageHandle, ShellStrings, NULL);\r
+  if (ShellInfoObject.HiiHandle == NULL) {\r
+    if (PcdGetBool(PcdShellSupportFrameworkHii)) {\r
+      ///@todo Add our package into Framework HII\r
+    }\r
+    if (ShellInfoObject.HiiHandle == NULL) {\r
+      return (EFI_NOT_STARTED);\r
+    }\r
+  }\r
+\r
+  //\r
+  // create and install the EfiShellParametersProtocol\r
+  //\r
+  Status = CreatePopulateInstallShellParametersProtocol(&ShellInfoObject.NewShellParametersProtocol, &ShellInfoObject.RootShellInstance);\r
+  ASSERT_EFI_ERROR(Status);\r
+  ASSERT(ShellInfoObject.NewShellParametersProtocol != NULL);\r
+\r
+  //\r
+  // create and install the EfiShellProtocol\r
+  //\r
+  Status = CreatePopulateInstallShellProtocol(&ShellInfoObject.NewEfiShellProtocol);\r
+  ASSERT_EFI_ERROR(Status);\r
+  ASSERT(ShellInfoObject.NewEfiShellProtocol != NULL);\r
+\r
+  //\r
+  // Now initialize the shell library (it requires Shell Parameters protocol)\r
+  //\r
+  Status = ShellInitialize();\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  Status = CommandInit();\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // Check the command line\r
+  //\r
+  Status = ProcessCommandLine();\r
+\r
+  //\r
+  // If shell support level is >= 1 create the mappings and paths\r
+  //\r
+  if (PcdGet8(PcdShellSupportLevel) >= 1) {\r
+    Status = ShellCommandCreateInitialMappingsAndPaths();\r
+  }\r
+\r
+  //\r
+  // save the device path for the loaded image and the device path for the filepath (under loaded image)\r
+  // These are where to look for the startup.nsh file\r
+  //\r
+  Status = GetDevicePathsForImageAndFile(&ShellInfoObject.ImageDevPath, &ShellInfoObject.FileDevPath);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // Display the version\r
+  //\r
+  if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion) {\r
+    ShellPrintHiiEx (\r
+      0,\r
+      gST->ConOut->Mode->CursorRow,\r
+      NULL,\r
+      STRING_TOKEN (STR_VER_OUTPUT_MAIN),\r
+      ShellInfoObject.HiiHandle,\r
+      SupportLevel[PcdGet8(PcdShellSupportLevel)],\r
+      gEfiShellProtocol->MajorVersion,\r
+      gEfiShellProtocol->MinorVersion,\r
+      (gST->Hdr.Revision&0xffff0000)>>16,\r
+      (gST->Hdr.Revision&0x0000ffff),\r
+      gST->FirmwareVendor,\r
+      gST->FirmwareRevision\r
+     );\r
+  }\r
+\r
+  //\r
+  // Display the mapping\r
+  //\r
+  if (PcdGet8(PcdShellSupportLevel) >= 2 && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap) {\r
+    Status = RunCommand(L"map");\r
+    ASSERT_EFI_ERROR(Status);\r
+  }\r
+\r
+  //\r
+  // init all the built in alias'\r
+  //\r
+  Status = SetBuiltInAlias();\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // Initialize environment variables\r
+  //\r
+  if (ShellCommandGetProfileList() != NULL) {\r
+    Status = InternalEfiShellSetEnv(L"profiles", ShellCommandGetProfileList(), TRUE);\r
+    ASSERT_EFI_ERROR(Status);\r
+  }\r
+\r
+  Size        = 100;\r
+  TempString  = AllocateZeroPool(Size);\r
+\r
+  UnicodeSPrint(TempString, Size, L"%d", PcdGet8(PcdShellSupportLevel));\r
+  Status = InternalEfiShellSetEnv(L"uefishellsupport", TempString, TRUE);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  UnicodeSPrint(TempString, Size, L"%d.%d", ShellInfoObject.NewEfiShellProtocol->MajorVersion, ShellInfoObject.NewEfiShellProtocol->MinorVersion);\r
+  Status = InternalEfiShellSetEnv(L"uefishellversion", TempString, TRUE);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  UnicodeSPrint(TempString, Size, L"%d.%d", (gST->Hdr.Revision & 0xFFFF0000) >> 16, gST->Hdr.Revision & 0x0000FFFF);\r
+  Status = InternalEfiShellSetEnv(L"uefiversion", TempString, TRUE);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  FreePool(TempString);\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {\r
+      //\r
+      // Set up the event for CTRL-C monitoring...\r
+      //\r
+\r
+      ///@todo add support for using SimpleInputEx here\r
+      //  if SimpleInputEx is not available display a warning.\r
+    }\r
+\r
+    if (!EFI_ERROR(Status) && PcdGet8(PcdShellSupportLevel) >= 1) {\r
+      //\r
+      // process the startup script or launch the called app.\r
+      //\r
+      Status = DoStartupScript(ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
+    }\r
+\r
+    if ((PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
+      //\r
+      // begin the UI waiting loop\r
+      //\r
+      do {\r
+        //\r
+        // clean out all the memory allocated for CONST <something> * return values\r
+        // between each shell prompt presentation\r
+        //\r
+        if (!IsListEmpty(&ShellInfoObject.BufferToFreeList.Link)){\r
+          FreeBufferList(&ShellInfoObject.BufferToFreeList);\r
+        }\r
+\r
+        //\r
+        // Reset page break back to default.\r
+        //\r
+        ShellInfoObject.PageBreakEnabled        = PcdGetBool(PcdShellPageBreakDefault);\r
+        ShellInfoObject.ConsoleInfo->Enabled    = TRUE;\r
+        ShellInfoObject.ConsoleInfo->RowCounter = 0;\r
+\r
+        //\r
+        // Display Prompt\r
+        //\r
+        Status = DoShellPrompt();\r
+      } while (!ShellCommandGetExit());\r
+    }\r
+  }\r
+  //\r
+  // uninstall protocols / free memory / etc...\r
+  //\r
+  if (ShellInfoObject.UserBreakTimer != NULL) {\r
+    gBS->CloseEvent(ShellInfoObject.UserBreakTimer);\r
+    DEBUG_CODE(ShellInfoObject.UserBreakTimer = NULL;);\r
+  }\r
+\r
+  if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){\r
+    ShellInfoObject.NewEfiShellProtocol->SetEnv(L"cwd", L"", TRUE);\r
+  }\r
+\r
+  if (ShellInfoObject.ImageDevPath != NULL) {\r
+    FreePool(ShellInfoObject.ImageDevPath);\r
+    DEBUG_CODE(ShellInfoObject.ImageDevPath = NULL;);\r
+  }\r
+  if (ShellInfoObject.FileDevPath != NULL) {\r
+    FreePool(ShellInfoObject.FileDevPath);\r
+    DEBUG_CODE(ShellInfoObject.FileDevPath = NULL;);\r
+  }\r
+  if (ShellInfoObject.NewShellParametersProtocol != NULL) {\r
+    CleanUpShellParametersProtocol(ShellInfoObject.NewShellParametersProtocol);\r
+    DEBUG_CODE(ShellInfoObject.NewShellParametersProtocol = NULL;);\r
+  }\r
+  if (ShellInfoObject.NewEfiShellProtocol != NULL){\r
+    CleanUpShellProtocol(ShellInfoObject.NewEfiShellProtocol);\r
+    DEBUG_CODE(ShellInfoObject.NewEfiShellProtocol = NULL;);\r
+  }\r
+\r
+  if (!IsListEmpty(&ShellInfoObject.BufferToFreeList.Link)){\r
+    FreeBufferList(&ShellInfoObject.BufferToFreeList);\r
+  }\r
+\r
+  if (!IsListEmpty(&ShellInfoObject.SplitList.Link)){\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  if (ShellInfoObject.ShellInitSettings.FileName != NULL) {\r
+    FreePool(ShellInfoObject.ShellInitSettings.FileName);\r
+    DEBUG_CODE(ShellInfoObject.ShellInitSettings.FileName = NULL;);\r
+  }\r
+\r
+  if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {\r
+    FreePool(ShellInfoObject.ShellInitSettings.FileOptions);\r
+    DEBUG_CODE(ShellInfoObject.ShellInitSettings.FileOptions = NULL;);\r
+  }\r
+\r
+  if (ShellInfoObject.HiiHandle != NULL) {\r
+    HiiRemovePackages(ShellInfoObject.HiiHandle);\r
+    DEBUG_CODE(ShellInfoObject.HiiHandle = NULL;);\r
+  }\r
+\r
+  if (!IsListEmpty(&ShellInfoObject.ViewingSettings.CommandHistory.Link)){\r
+    FreeBufferList(&ShellInfoObject.ViewingSettings.CommandHistory);\r
+  }\r
+\r
+  ASSERT(ShellInfoObject.ConsoleInfo != NULL);\r
+  if (ShellInfoObject.ConsoleInfo != NULL) {\r
+    ConsoleLoggerUninstall(ShellInfoObject.ConsoleInfo);\r
+    FreePool(ShellInfoObject.ConsoleInfo);\r
+    DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;);\r
+  }\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Sets all the alias' that were registered with the ShellCommandLib library.\r
+\r
+  @retval EFI_SUCCESS           all init commands were run sucessfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBuiltInAlias(\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  CONST ALIAS_LIST    *List;\r
+  ALIAS_LIST          *Node;\r
+\r
+  //\r
+  // Get all the commands we want to run\r
+  //\r
+  List = ShellCommandGetInitAliasList();\r
+\r
+  //\r
+  // for each command in the List\r
+  //\r
+  for ( Node = (ALIAS_LIST*)GetFirstNode(&List->Link)\r
+      ; !IsNull (&List->Link, &Node->Link)\r
+      ; Node = (ALIAS_LIST *)GetNextNode(&List->Link, &Node->Link)\r
+   ){\r
+    //\r
+    // install the alias'\r
+    //\r
+    Status = InternalSetAlias(Node->CommandString, Node->Alias, TRUE);\r
+    ASSERT_EFI_ERROR(Status);\r
+  }\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Internal function to determine if 2 command names are really the same.\r
+\r
+  @param[in] Command1       The pointer to the first command name.\r
+  @param[in] Command2       The pointer to the second command name.\r
+\r
+  @retval TRUE              The 2 command names are the same.\r
+  @retval FALSE             The 2 command names are not the same.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsCommand(\r
+  IN CONST CHAR16 *Command1,\r
+  IN CONST CHAR16 *Command2\r
+  )\r
+{\r
+  if (StringNoCaseCompare(&Command1, &Command2) == 0) {\r
+    return (TRUE);\r
+  }\r
+  return (FALSE);\r
+}\r
+\r
+/**\r
+  Internal function to determine if a command is a script only command.\r
+\r
+  @param[in] CommandName    The pointer to the command name.\r
+\r
+  @retval TRUE              The command is a script only command.\r
+  @retval FALSE             The command is not a script only command.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsScriptOnlyCommand(\r
+  IN CONST CHAR16 *CommandName\r
+  )\r
+{\r
+  if (IsCommand(CommandName, L"for")\r
+    ||IsCommand(CommandName, L"endfor")\r
+    ||IsCommand(CommandName, L"if")\r
+    ||IsCommand(CommandName, L"else")\r
+    ||IsCommand(CommandName, L"endif")\r
+    ||IsCommand(CommandName, L"goto")) {\r
+    return (TRUE);\r
+  }\r
+  return (FALSE);\r
+}\r
+\r
+\r
+\r
+/**\r
+  This function will populate the 2 device path protocol parameters based on the\r
+  global gImageHandle.  The DevPath will point to the device path for the handle that has\r
+  loaded image protocol installed on it.  The FilePath will point to the device path\r
+  for the file that was loaded.\r
+\r
+  @param[in,out] DevPath       On a sucessful return the device path to the loaded image.\r
+  @param[in,out] FilePath      On a sucessful return the device path to the file.\r
+\r
+  @retval EFI_SUCCESS           The 2 device paths were sucessfully returned.\r
+  @retval other                 A error from gBS->HandleProtocol.\r
+\r
+  @sa HandleProtocol\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDevicePathsForImageAndFile (\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath,\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ImageDevicePath;\r
+\r
+  ASSERT(DevPath  != NULL);\r
+  ASSERT(FilePath != NULL);\r
+\r
+  Status = gBS->OpenProtocol (\r
+                gImageHandle,\r
+                &gEfiLoadedImageProtocolGuid,\r
+                (VOID**)&LoadedImage,\r
+                gImageHandle,\r
+                NULL,\r
+                EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+               );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->OpenProtocol (\r
+                  LoadedImage->DeviceHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID**)&ImageDevicePath,\r
+                  gImageHandle,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                 );\r
+    if (!EFI_ERROR (Status)) {\r
+      *DevPath  = DuplicateDevicePath (ImageDevicePath);\r
+      *FilePath = DuplicateDevicePath (LoadedImage->FilePath);\r
+    }\r
+    gBS->CloseProtocol(\r
+                gImageHandle,\r
+                &gEfiLoadedImageProtocolGuid,\r
+                gImageHandle,\r
+                NULL);\r
+  }\r
+  return (Status);\r
+}\r
+\r
+STATIC CONST SHELL_PARAM_ITEM mShellParamList[] = {\r
+  {L"-nostartup",     TypeFlag},\r
+  {L"-startup",       TypeFlag},\r
+  {L"-noconsoleout",  TypeFlag},\r
+  {L"-noconsolein",   TypeFlag},\r
+  {L"-nointerrupt",   TypeFlag},\r
+  {L"-nomap",         TypeFlag},\r
+  {L"-noversion",     TypeFlag},\r
+  {L"-startup",       TypeFlag},\r
+  {L"-delay",         TypeValue},\r
+  {NULL, TypeMax}\r
+  };\r
+/**\r
+  Process all Uefi Shell 2.0 command line options.\r
+\r
+  see Uefi Shell 2.0 section 3.2 for full details.\r
+\r
+  the command line must resemble the following:\r
+\r
+  shell.efi [ShellOpt-options] [options] [file-name [file-name-options]]\r
+\r
+  ShellOpt-options  Options which control the initialization behavior of the shell.\r
+                    These options are read from the EFI global variable "ShellOpt"\r
+                    and are processed before options or file-name.\r
+\r
+  options           Options which control the initialization behavior of the shell.\r
+\r
+  file-name         The name of a UEFI shell application or script to be executed\r
+                    after initialization is complete. By default, if file-name is\r
+                    specified, then -nostartup is implied. Scripts are not supported\r
+                    by level 0.\r
+\r
+  file-name-options The command-line options that are passed to file-name when it\r
+                    is invoked.\r
+\r
+  This will initialize the ShellInfoObject.ShellInitSettings global variable.\r
+\r
+  @retval EFI_SUCCESS           The variable is initialized.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProcessCommandLine(\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  LIST_ENTRY    *Package;\r
+  UINTN         Size;\r
+  CONST CHAR16  *TempConst;\r
+  UINTN         Count;\r
+  UINTN         LoopVar;\r
+  CHAR16        *ProblemParam;\r
+\r
+  Package       = NULL;\r
+  ProblemParam  = NULL;\r
+  \r
+  Status = ShellCommandLineParse (mShellParamList, &Package, NULL, FALSE);\r
+\r
+  Count = 1;\r
+  Size = 0;\r
+  TempConst = ShellCommandLineGetRawValue(Package, Count++);\r
+  if (TempConst != NULL && StrLen(TempConst)) {\r
+    ShellInfoObject.ShellInitSettings.FileName = AllocatePool(StrSize(TempConst));\r
+    StrCpy(ShellInfoObject.ShellInitSettings.FileName, TempConst);\r
+    ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1;\r
+    for (LoopVar = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {\r
+      if (StrCmp(gEfiShellParametersProtocol->Argv[LoopVar], ShellInfoObject.ShellInitSettings.FileName)==0) {\r
+        LoopVar++;\r
+        //\r
+        // We found the file... add the rest of the params...\r
+        //\r
+        for ( ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {\r
+          ASSERT((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL));\r
+          StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
+                      &Size,\r
+                      L" ",\r
+                      0);\r
+          StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
+                      &Size,\r
+                      gEfiShellParametersProtocol->Argv[LoopVar],\r
+                      0);\r
+        }\r
+      }\r
+    }\r
+  } else {\r
+    ShellCommandLineFreeVarList(Package);\r
+    Package = NULL;\r
+    Status = ShellCommandLineParse (mShellParamList, &Package, &ProblemParam, FALSE);\r
+    if (EFI_ERROR(Status)) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), ShellInfoObject.HiiHandle, ProblemParam);\r
+      FreePool(ProblemParam);\r
+      ShellCommandLineFreeVarList(Package);\r
+      return (EFI_INVALID_PARAMETER);\r
+    }\r
+  }\r
+\r
+  ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup      = ShellCommandLineGetFlag(Package, L"-startup");\r
+  ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup    = ShellCommandLineGetFlag(Package, L"-nostartup");\r
+  ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = ShellCommandLineGetFlag(Package, L"-noconsoleout");\r
+  ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn  = ShellCommandLineGetFlag(Package, L"-noconsolein");\r
+  ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt  = ShellCommandLineGetFlag(Package, L"-nointerrupt");\r
+  ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap        = ShellCommandLineGetFlag(Package, L"-nomap");\r
+  ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion    = ShellCommandLineGetFlag(Package, L"-noversion");\r
+  ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay        = ShellCommandLineGetFlag(Package, L"-delay");\r
+\r
+  if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay) {\r
+    TempConst = ShellCommandLineGetValue(Package, L"-delay");\r
+    if (TempConst != NULL) {\r
+      ShellInfoObject.ShellInitSettings.Delay = StrDecimalToUintn (TempConst);\r
+    } else {\r
+      ShellInfoObject.ShellInitSettings.Delay = 5;\r
+    }\r
+  } else {\r
+    ShellInfoObject.ShellInitSettings.Delay = 5;\r
+  }\r
+\r
+  ShellCommandLineFreeVarList(Package);\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Handles all interaction with the default startup script.\r
+\r
+  this will check that the correct command line parameters were passed, handle the delay, and then start running the script.\r
+\r
+  @param ImagePath              the path to the image for shell.  first place to look for the startup script\r
+  @param FilePath               the path to the file for shell.  second place to look for the startup script.\r
+\r
+  @retval EFI_SUCCESS           the variable is initialized.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DoStartupScript(\r
+  EFI_DEVICE_PATH_PROTOCOL *ImagePath,\r
+  EFI_DEVICE_PATH_PROTOCOL *FilePath\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Delay;\r
+  EFI_INPUT_KEY                 Key;\r
+  SHELL_FILE_HANDLE             FileHandle;\r
+  EFI_DEVICE_PATH_PROTOCOL      *NewPath;\r
+  EFI_DEVICE_PATH_PROTOCOL      *NamePath;\r
+  CHAR16                        *FileStringPath;\r
+  UINTN                         NewSize;\r
+\r
+  Key.UnicodeChar = CHAR_NULL;\r
+  Key.ScanCode    = 0;\r
+  FileHandle      = NULL;\r
+\r
+  if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup && ShellInfoObject.ShellInitSettings.FileName != NULL) {\r
+    //\r
+    // launch something else instead\r
+    //\r
+    NewSize = StrSize(ShellInfoObject.ShellInitSettings.FileName);\r
+    if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {\r
+      NewSize += StrSize(ShellInfoObject.ShellInitSettings.FileOptions) + sizeof(CHAR16);\r
+    }\r
+    FileStringPath = AllocateZeroPool(NewSize);\r
+    StrCpy(FileStringPath, ShellInfoObject.ShellInitSettings.FileName);\r
+    if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {\r
+      StrCat (FileStringPath, L" ");\r
+      StrCat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions);\r
+    }\r
+    Status = RunCommand(FileStringPath);\r
+    FreePool(FileStringPath);\r
+    return (Status);\r
+\r
+  }\r
+\r
+  //\r
+  // for shell level 0 we do no scripts\r
+  // Without the Startup bit overriding we allow for nostartup to prevent scripts\r
+  //\r
+  if ( (PcdGet8(PcdShellSupportLevel) < 1)\r
+    || (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup)\r
+   ){\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  //\r
+  // print out our warning and see if they press a key\r
+  //\r
+  for ( Status = EFI_UNSUPPORTED, Delay = (ShellInfoObject.ShellInitSettings.Delay * 10)\r
+      ; Delay > 0 && EFI_ERROR(Status)\r
+      ; Delay--\r
+     ){\r
+    ShellPrintHiiEx(0, gST->ConOut->Mode->CursorRow, NULL, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION), ShellInfoObject.HiiHandle, Delay/10);\r
+    gBS->Stall (100000);\r
+    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+  }\r
+  ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CRLF), ShellInfoObject.HiiHandle);\r
+\r
+  //\r
+  // ESC was pressed\r
+  //\r
+  if (Status == EFI_SUCCESS && Key.UnicodeChar == 0 && Key.ScanCode == SCAN_ESC) {\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  NamePath = FileDevicePath (NULL, L"startup.nsh");\r
+  //\r
+  // Try the first location\r
+  //\r
+  NewPath = AppendDevicePathNode (ImagePath, NamePath);\r
+  Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+  if (EFI_ERROR(Status)) {\r
+    //\r
+    // Try the second location\r
+    //\r
+    FreePool(NewPath);\r
+    NewPath = AppendDevicePathNode (FilePath , NamePath);\r
+    Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+  }\r
+\r
+  //\r
+  // If we got a file, run it\r
+  //\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = RunScriptFileHandle (FileHandle, L"startup.nsh");\r
+    ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);\r
+  } else {\r
+    //\r
+    // we return success since we dont need to have a startup script\r
+    //\r
+    Status = EFI_SUCCESS;\r
+    ASSERT(FileHandle == NULL);\r
+  }\r
+\r
+  FreePool(NamePath);\r
+  FreePool(NewPath);\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Function to perform the shell prompt looping.  It will do a single prompt,\r
+  dispatch the result, and then return.  It is expected that the caller will\r
+  call this function in a loop many times.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval RETURN_ABORTED\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DoShellPrompt (\r
+  VOID\r
+  )\r
+{\r
+  UINTN         Column;\r
+  UINTN         Row;\r
+  CHAR16        *CmdLine;\r
+  CONST CHAR16  *CurDir;\r
+  UINTN         BufferSize;\r
+  EFI_STATUS    Status;\r
+\r
+  CurDir  = NULL;\r
+\r
+  //\r
+  // Get screen setting to decide size of the command line buffer\r
+  //\r
+  gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Column, &Row);\r
+  BufferSize  = Column * Row * sizeof (CHAR16);\r
+  CmdLine     = AllocateZeroPool (BufferSize);\r
+  if (CmdLine == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");\r
+\r
+  //\r
+  // Prompt for input\r
+  //\r
+  gST->ConOut->SetCursorPosition (gST->ConOut, 0, gST->ConOut->Mode->CursorRow);\r
+\r
+  if (CurDir != NULL && StrLen(CurDir) > 1) {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir);\r
+  } else {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle);\r
+  }\r
+\r
+  //\r
+  // Read a line from the console\r
+  //\r
+  Status = ShellInfoObject.NewEfiShellProtocol->ReadFile(ShellInfoObject.NewShellParametersProtocol->StdIn, &BufferSize, CmdLine);\r
+\r
+  //\r
+  // Null terminate the string and parse it\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL;\r
+    Status = RunCommand(CmdLine);\r
+  }\r
+\r
+  //\r
+  // Done with this command\r
+  //\r
+  FreePool (CmdLine);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Add a buffer to the Buffer To Free List for safely returning buffers to other\r
+  places without risking letting them modify internal shell information.\r
+\r
+  @param Buffer   Something to pass to FreePool when the shell is exiting.\r
+**/\r
+VOID*\r
+EFIAPI\r
+AddBufferToFreeList(\r
+  VOID *Buffer\r
+  )\r
+{\r
+  BUFFER_LIST   *BufferListEntry;\r
+\r
+  if (Buffer == NULL) {\r
+    return (NULL);\r
+  }\r
+\r
+  BufferListEntry = AllocateZeroPool(sizeof(BUFFER_LIST));\r
+  ASSERT(BufferListEntry != NULL);\r
+  BufferListEntry->Buffer = Buffer;\r
+  InsertTailList(&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link);\r
+  return (Buffer);\r
+}\r
+\r
+/**\r
+  Add a buffer to the Line History List\r
+\r
+  @param Buffer     The line buffer to add.\r
+**/\r
+VOID\r
+EFIAPI\r
+AddLineToCommandHistory(\r
+  IN CONST CHAR16 *Buffer\r
+  )\r
+{\r
+  BUFFER_LIST *Node;\r
+\r
+  Node = AllocateZeroPool(sizeof(BUFFER_LIST));\r
+  ASSERT(Node != NULL);\r
+  Node->Buffer = AllocateZeroPool(StrSize(Buffer));\r
+  ASSERT(Node->Buffer != NULL);\r
+  StrCpy(Node->Buffer, Buffer);\r
+\r
+  InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);\r
+}\r
+\r
+/**\r
+  Checks if a string is an alias for another command.  If yes, then it replaces the alias name\r
+  with the correct command name.\r
+\r
+  @param[in,out] CommandString    Upon entry the potential alias.  Upon return the\r
+                                  command name if it was an alias.  If it was not\r
+                                  an alias it will be unchanged.  This function may\r
+                                  change the buffer to fit the command name.\r
+\r
+  @retval EFI_SUCCESS             The name was changed.\r
+  @retval EFI_SUCCESS             The name was not an alias.\r
+  @retval EFI_OUT_OF_RESOURCES    A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellConvertAlias(\r
+  IN OUT CHAR16 **CommandString\r
+  )\r
+{\r
+  CONST CHAR16  *NewString;\r
+\r
+  NewString = ShellInfoObject.NewEfiShellProtocol->GetAlias(*CommandString, NULL);\r
+  if (NewString == NULL) {\r
+    return (EFI_SUCCESS);\r
+  }\r
+  FreePool(*CommandString);\r
+  *CommandString = AllocatePool(StrSize(NewString));\r
+  if (*CommandString == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+  StrCpy(*CommandString, NewString);\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Function allocates a new command line and replaces all instances of environment\r
+  variable names that are correctly preset to their values.\r
+\r
+  If the return value is not NULL the memory must be caller freed.\r
+\r
+  @param[in] OriginalCommandLine    The original command line\r
+\r
+  @retval NULL                      An error ocurred.\r
+  @return                           The new command line with no environment variables present.\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+ShellConvertVariables (\r
+  IN CONST CHAR16 *OriginalCommandLine\r
+  )\r
+{\r
+  CONST CHAR16        *MasterEnvList;\r
+  UINTN               NewSize;\r
+  CHAR16              *NewCommandLine1;\r
+  CHAR16              *NewCommandLine2;\r
+  CHAR16              *Temp;\r
+  UINTN               ItemSize;\r
+  CHAR16              *ItemTemp;\r
+  SCRIPT_FILE         *CurrentScriptFile;\r
+  ALIAS_LIST          *AliasListNode;\r
+\r
+  ASSERT(OriginalCommandLine != NULL);\r
+\r
+  ItemSize          = 0;\r
+  NewSize           = StrSize(OriginalCommandLine);\r
+  CurrentScriptFile = ShellCommandGetCurrentScriptFile();\r
+  Temp              = NULL;\r
+\r
+  ///@todo update this to handle the %0 - %9 for scripting only (borrow from line 1256 area) ? ? ?\r
+\r
+  //\r
+  // calculate the size required for the post-conversion string...\r
+  //\r
+  if (CurrentScriptFile != NULL) {\r
+    for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList)\r
+      ;  !IsNull(&CurrentScriptFile->SubstList, &AliasListNode->Link)\r
+      ;  AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link)\r
+   ){\r
+      for (Temp = StrStr(OriginalCommandLine, AliasListNode->Alias)\r
+        ;  Temp != NULL\r
+        ;  Temp = StrStr(Temp+1, AliasListNode->Alias)\r
+       ){\r
+        //\r
+        // we need a preceeding and if there is space no ^ preceeding (if no space ignore)\r
+        //\r
+        if ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2)) {\r
+          NewSize += StrSize(AliasListNode->CommandString);\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  for (MasterEnvList = EfiShellGetEnv(NULL)\r
+    ;  MasterEnvList != NULL && *MasterEnvList != CHAR_NULL //&& *(MasterEnvList+1) != CHAR_NULL\r
+    ;  MasterEnvList += StrLen(MasterEnvList) + 1\r
+   ){\r
+    if (StrSize(MasterEnvList) > ItemSize) {\r
+      ItemSize = StrSize(MasterEnvList);\r
+    }\r
+    for (Temp = StrStr(OriginalCommandLine, MasterEnvList)\r
+      ;  Temp != NULL\r
+      ;  Temp = StrStr(Temp+1, MasterEnvList)\r
+     ){\r
+      //\r
+      // we need a preceeding and following % and if there is space no ^ preceeding (if no space ignore)\r
+      //\r
+      if (*(Temp-1) == L'%' && *(Temp+StrLen(MasterEnvList)) == L'%' &&\r
+        ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2))) {\r
+        NewSize+=StrSize(EfiShellGetEnv(MasterEnvList));\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Quick out if none were found...\r
+  //\r
+  if (NewSize == StrSize(OriginalCommandLine)) {\r
+    ASSERT(Temp == NULL);\r
+    Temp = StrnCatGrow(&Temp, NULL, OriginalCommandLine, 0);\r
+    return (Temp);\r
+  }\r
+\r
+  //\r
+  // now do the replacements...\r
+  //\r
+  NewCommandLine1 = AllocateZeroPool(NewSize);\r
+  NewCommandLine2 = AllocateZeroPool(NewSize);\r
+  ItemTemp        = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16)));\r
+  StrCpy(NewCommandLine1, OriginalCommandLine);\r
+  for (MasterEnvList = EfiShellGetEnv(NULL)\r
+    ;  MasterEnvList != NULL && *MasterEnvList != CHAR_NULL //&& *(MasterEnvList+1) != CHAR_NULL\r
+    ;  MasterEnvList += StrLen(MasterEnvList) + 1\r
+   ){\r
+    StrCpy(ItemTemp, L"%");\r
+    StrCat(ItemTemp, MasterEnvList);\r
+    StrCat(ItemTemp, L"%");\r
+    ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE);\r
+    StrCpy(NewCommandLine1, NewCommandLine2);\r
+  }\r
+  if (CurrentScriptFile != NULL) {\r
+    for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList)\r
+      ;  !IsNull(&CurrentScriptFile->SubstList, &AliasListNode->Link)\r
+      ;  AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link)\r
+   ){\r
+    ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE);\r
+    StrCpy(NewCommandLine1, NewCommandLine2);\r
+    }\r
+  }\r
+\r
+  FreePool(NewCommandLine2);\r
+  FreePool(ItemTemp);\r
+\r
+  return (NewCommandLine1);\r
+}\r
+\r
+/**\r
+  Internal function to run a command line with pipe usage.\r
+\r
+  @param[in] CmdLine        The pointer to the command line.\r
+  @param[in] StdIn          The pointer to the Standard input.\r
+  @param[in] StdOut         The pointer to the Standard output.\r
+\r
+  @retval EFI_SUCCESS       The split command is executed successfully.\r
+  @retval other             Some error occurs when executing the split command.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunSplitCommand(\r
+  IN CONST CHAR16             *CmdLine,\r
+  IN       SHELL_FILE_HANDLE  *StdIn,\r
+  IN       SHELL_FILE_HANDLE  *StdOut\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  CHAR16            *NextCommandLine;\r
+  CHAR16            *OurCommandLine;\r
+  UINTN             Size1;\r
+  UINTN             Size2;\r
+  SPLIT_LIST        *Split;\r
+  SHELL_FILE_HANDLE *TempFileHandle;\r
+  BOOLEAN           Unicode;\r
+\r
+  ASSERT(StdOut == NULL);\r
+\r
+  ASSERT(StrStr(CmdLine, L"|") != NULL);\r
+\r
+  Status          = EFI_SUCCESS;\r
+  NextCommandLine = NULL;\r
+  OurCommandLine  = NULL;\r
+  Size1           = 0;\r
+  Size2           = 0;\r
+\r
+  NextCommandLine = StrnCatGrow(&NextCommandLine, &Size1, StrStr(CmdLine, L"|")+1, 0);\r
+  OurCommandLine  = StrnCatGrow(&OurCommandLine , &Size2, CmdLine                , StrStr(CmdLine, L"|") - CmdLine);\r
+  if (NextCommandLine[0] != CHAR_NULL &&\r
+      NextCommandLine[0] == L'a' &&\r
+      NextCommandLine[1] == L' '\r
+     ){\r
+    CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0]));\r
+    Unicode = FALSE;\r
+  } else {\r
+    Unicode = TRUE;\r
+  }\r
+\r
+\r
+  //\r
+  // make a SPLIT_LIST item and add to list\r
+  //\r
+  Split = AllocateZeroPool(sizeof(SPLIT_LIST));\r
+  ASSERT(Split != NULL);\r
+  Split->SplitStdIn   = StdIn;\r
+  Split->SplitStdOut  = ConvertEfiFileProtocolToShellHandle(CreateFileInterfaceMem(Unicode), NULL);\r
+  ASSERT(Split->SplitStdOut != NULL);\r
+  InsertHeadList(&ShellInfoObject.SplitList.Link, &Split->Link);\r
+\r
+  ASSERT(StrStr(OurCommandLine, L"|") == NULL);\r
+  Status = RunCommand(OurCommandLine);\r
+\r
+  //\r
+  // move the output from the first to the in to the second.\r
+  //\r
+  TempFileHandle      = Split->SplitStdOut;\r
+  if (Split->SplitStdIn == StdIn) {\r
+    Split->SplitStdOut = NULL;\r
+  } else {\r
+    Split->SplitStdOut  = Split->SplitStdIn;\r
+  }\r
+  Split->SplitStdIn   = TempFileHandle;\r
+  ShellInfoObject.NewEfiShellProtocol->SetFilePosition(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn), 0);\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = RunCommand(NextCommandLine);\r
+  }\r
+\r
+  //\r
+  // remove the top level from the ScriptList\r
+  //\r
+  ASSERT((SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link) == Split);\r
+  RemoveEntryList(&Split->Link);\r
+\r
+  //\r
+  // Note that the original StdIn is now the StdOut...\r
+  //\r
+  if (Split->SplitStdOut != NULL && Split->SplitStdOut != StdIn) {\r
+    ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdOut));\r
+  }\r
+  if (Split->SplitStdIn != NULL) {\r
+    ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn));\r
+  }\r
+\r
+  FreePool(Split);\r
+  FreePool(NextCommandLine);\r
+  FreePool(OurCommandLine);\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Function will process and run a command line.\r
+\r
+  This will determine if the command line represents an internal shell \r
+  command or dispatch an external application.\r
+\r
+  @param[in] CmdLine      The command line to parse.\r
+\r
+  @retval EFI_SUCCESS     The command was completed.\r
+  @retval EFI_ABORTED     The command's operation was aborted.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunCommand(\r
+  IN CONST CHAR16   *CmdLine\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  CHAR16                    *CommandName;\r
+  SHELL_STATUS              ShellStatus;\r
+  UINTN                     Argc;\r
+  CHAR16                    **Argv;\r
+  BOOLEAN                   LastError;\r
+  CHAR16                    LeString[11];\r
+  CHAR16                    *PostAliasCmdLine;\r
+  UINTN                     PostAliasSize;\r
+  CHAR16                    *PostVariableCmdLine;\r
+  CHAR16                    *CommandWithPath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+  CONST CHAR16              *TempLocation;\r
+  CONST CHAR16              *TempLocation2;\r
+  SHELL_FILE_HANDLE         OriginalStdIn;\r
+  SHELL_FILE_HANDLE         OriginalStdOut;\r
+  SHELL_FILE_HANDLE         OriginalStdErr;\r
+  CHAR16                    *TempLocation3;\r
+  UINTN                     Count;\r
+  UINTN                     Count2;\r
+  CHAR16                    *CleanOriginal;\r
+  SPLIT_LIST                *Split;\r
+\r
+  ASSERT(CmdLine != NULL);\r
+  if (StrLen(CmdLine) == 0) {\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  CommandName         = NULL;\r
+  PostVariableCmdLine = NULL;\r
+  PostAliasCmdLine    = NULL;\r
+  CommandWithPath     = NULL;\r
+  DevPath             = NULL;\r
+  Status              = EFI_SUCCESS;\r
+  CleanOriginal       = NULL;\r
+  Split               = NULL;\r
+\r
+  CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0);\r
+  while (CleanOriginal[StrLen(CleanOriginal)-1] == L' ') {\r
+    CleanOriginal[StrLen(CleanOriginal)-1] = CHAR_NULL;\r
+  }\r
+  while (CleanOriginal[0] == L' ') {\r
+    CopyMem(CleanOriginal, CleanOriginal+1, StrSize(CleanOriginal) - sizeof(CleanOriginal[0]));\r
+  }\r
+\r
+  CommandName = NULL;\r
+  if (StrStr(CleanOriginal, L" ") == NULL){\r
+    StrnCatGrow(&CommandName, NULL, CleanOriginal, 0);\r
+  } else {\r
+    StrnCatGrow(&CommandName, NULL, CleanOriginal, StrStr(CleanOriginal, L" ") - CleanOriginal);\r
+  }\r
+\r
+  ASSERT(PostAliasCmdLine == NULL);\r
+  if (!ShellCommandIsCommandOnList(CommandName)) {\r
+    //\r
+    // Convert via alias\r
+    //\r
+    Status = ShellConvertAlias(&CommandName);\r
+    PostAliasSize = 0;\r
+    PostAliasCmdLine = StrnCatGrow(&PostAliasCmdLine, &PostAliasSize, CommandName, 0);\r
+    PostAliasCmdLine = StrnCatGrow(&PostAliasCmdLine, &PostAliasSize, StrStr(CleanOriginal, L" "), 0);\r
+    ASSERT_EFI_ERROR(Status);\r
+  } else {\r
+    PostAliasCmdLine = StrnCatGrow(&PostAliasCmdLine, NULL, CleanOriginal, 0);\r
+  }\r
+\r
+  if (CleanOriginal != NULL) {\r
+    FreePool(CleanOriginal);\r
+    CleanOriginal = NULL;\r
+  }\r
+\r
+  if (CommandName != NULL) {\r
+    FreePool(CommandName);\r
+    CommandName = NULL;\r
+  }\r
+\r
+  PostVariableCmdLine = ShellConvertVariables(PostAliasCmdLine);\r
+\r
+  //\r
+  // we can now free the modified by alias command line\r
+  //\r
+  if (PostAliasCmdLine != NULL) {\r
+    FreePool(PostAliasCmdLine);\r
+    PostAliasCmdLine = NULL;\r
+  }\r
+\r
+  while (PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] == L' ') {\r
+    PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] = CHAR_NULL;\r
+  }\r
+  while (PostVariableCmdLine[0] == L' ') {\r
+    CopyMem(PostVariableCmdLine, PostVariableCmdLine+1, StrSize(PostVariableCmdLine) - sizeof(PostVariableCmdLine[0]));\r
+  }\r
+\r
+  //\r
+  // We dont do normal processing with a split command line (output from one command input to another)\r
+  //\r
+  TempLocation3 = NULL;\r
+  if (StrStr(PostVariableCmdLine, L"|") != NULL) {\r
+    for (TempLocation3 = PostVariableCmdLine ; TempLocation3 != NULL && *TempLocation3 != CHAR_NULL ; TempLocation3++) {\r
+      if (*TempLocation3 == L'^' && *(TempLocation3+1) == L'|') {\r
+        TempLocation3++;\r
+      } else if (*TempLocation3 == L'|') {\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  if (TempLocation3 != NULL && *TempLocation3 != CHAR_NULL) {\r
+    //\r
+    // are we in an existing split???\r
+    //\r
+    if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
+      Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
+    }\r
+\r
+    if (Split == NULL) {\r
+      Status = RunSplitCommand(PostVariableCmdLine, NULL, NULL);\r
+    } else {\r
+      Status = RunSplitCommand(PostVariableCmdLine, Split->SplitStdIn, Split->SplitStdOut);\r
+    }\r
+  } else {\r
+\r
+    //\r
+    // If this is a mapped drive change handle that...\r
+    //\r
+    if (PostVariableCmdLine[(StrLen(PostVariableCmdLine)-1)] == L':' && StrStr(PostVariableCmdLine, L" ") == NULL) {\r
+      Status = ShellInfoObject.NewEfiShellProtocol->SetCurDir(NULL, PostVariableCmdLine);\r
+      if (EFI_ERROR(Status)) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_MAPPING), ShellInfoObject.HiiHandle, PostVariableCmdLine);\r
+      }\r
+      FreePool(PostVariableCmdLine);\r
+      return (Status);\r
+    }\r
+\r
+    ///@todo update this section to divide into 3 ways - run internal command, run split (above), and run an external file...\r
+    ///      We waste a lot of time doing processing like StdIn,StdOut,Argv,Argc for things that are external files...\r
+\r
+\r
+\r
+    Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr);\r
+    if (EFI_ERROR(Status)) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
+    } else {\r
+      //\r
+      // remove the < and/or > from the command line now\r
+      //\r
+      for (TempLocation3 = PostVariableCmdLine ; TempLocation3 != NULL && *TempLocation3 != CHAR_NULL ; TempLocation3++) {\r
+        if (*TempLocation3 == L'^') {\r
+          if (*(TempLocation3+1) == L'<' || *(TempLocation3+1) == L'>') {\r
+            CopyMem(TempLocation3, TempLocation3+1, StrSize(TempLocation3) - sizeof(TempLocation3[0]));\r
+          }\r
+        } else if (*TempLocation3 == L'>') {\r
+          *TempLocation3 = CHAR_NULL;\r
+        } else if ((*TempLocation3 == L'1' || *TempLocation3 == L'2')&&(*(TempLocation3+1) == L'>')) {\r
+          *TempLocation3 = CHAR_NULL;\r
+        }\r
+      }\r
+\r
+      while (PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] == L' ') {\r
+        PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] = CHAR_NULL;\r
+      }\r
+      while (PostVariableCmdLine[0] == L' ') {\r
+        CopyMem(PostVariableCmdLine, PostVariableCmdLine+1, StrSize(PostVariableCmdLine) - sizeof(PostVariableCmdLine[0]));\r
+      }\r
+\r
+      //\r
+      // get the argc and argv updated for internal commands\r
+      //\r
+      Status = UpdateArgcArgv(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &Argv, &Argc);\r
+      ASSERT_EFI_ERROR(Status);\r
+\r
+      for (Count = 0 ; Count < ShellInfoObject.NewShellParametersProtocol->Argc ; Count++) {\r
+        if (StrStr(ShellInfoObject.NewShellParametersProtocol->Argv[Count], L"-?") == ShellInfoObject.NewShellParametersProtocol->Argv[Count]\r
+        ||  (ShellInfoObject.NewShellParametersProtocol->Argv[0][0] == L'?' && ShellInfoObject.NewShellParametersProtocol->Argv[0][1] == CHAR_NULL)\r
+          ) {\r
+          //\r
+          // We need to redo the arguments since a parameter was -?\r
+          // move them all down 1 to the end, then up one then replace the first with help\r
+          //\r
+          FreePool(ShellInfoObject.NewShellParametersProtocol->Argv[Count]);\r
+          ShellInfoObject.NewShellParametersProtocol->Argv[Count] = NULL;\r
+          for (Count2 = Count ; (Count2 + 1) < ShellInfoObject.NewShellParametersProtocol->Argc ; Count2++) {\r
+            ShellInfoObject.NewShellParametersProtocol->Argv[Count2] = ShellInfoObject.NewShellParametersProtocol->Argv[Count2+1];\r
+          }\r
+          ShellInfoObject.NewShellParametersProtocol->Argv[Count2] = NULL;\r
+          for (Count2 = ShellInfoObject.NewShellParametersProtocol->Argc -1 ; Count2 > 0 ; Count2--) {\r
+            ShellInfoObject.NewShellParametersProtocol->Argv[Count2] = ShellInfoObject.NewShellParametersProtocol->Argv[Count2-1];\r
+          }\r
+          ShellInfoObject.NewShellParametersProtocol->Argv[0] = NULL;\r
+          ShellInfoObject.NewShellParametersProtocol->Argv[0] = StrnCatGrow(&ShellInfoObject.NewShellParametersProtocol->Argv[0], NULL, L"help", 0);\r
+          break;\r
+        }\r
+      }\r
+\r
+      //\r
+      // command or file?\r
+      //\r
+      if (ShellCommandIsCommandOnList(ShellInfoObject.NewShellParametersProtocol->Argv[0])) {\r
+        //\r
+        // Run the command (which was converted if it was an alias)\r
+        //\r
+        if (!EFI_ERROR(Status))  {\r
+          Status = ShellCommandRunCommandHandler(ShellInfoObject.NewShellParametersProtocol->Argv[0], &ShellStatus, &LastError);\r
+          ASSERT_EFI_ERROR(Status);\r
+          UnicodeSPrint(LeString, sizeof(LeString)*sizeof(LeString[0]), L"0x%08x", ShellStatus);\r
+          DEBUG_CODE(InternalEfiShellSetEnv(L"DebugLasterror", LeString, TRUE););\r
+          if (LastError) {\r
+            InternalEfiShellSetEnv(L"Lasterror", LeString, TRUE);\r
+          }\r
+          //\r
+          // Pass thru the exitcode from the app.\r
+          //\r
+          if (ShellCommandGetExit()) {\r
+            Status = ShellStatus;\r
+          } else if (ShellStatus != 0 && IsScriptOnlyCommand(ShellInfoObject.NewShellParametersProtocol->Argv[0])) {\r
+            Status = EFI_ABORTED;\r
+          }\r
+        }\r
+      } else {\r
+        //\r
+        // run an external file (or script)\r
+        //\r
+        if (StrStr(ShellInfoObject.NewShellParametersProtocol->Argv[0], L":") != NULL) {\r
+          ASSERT (CommandWithPath == NULL);\r
+          if (ShellIsFile(ShellInfoObject.NewShellParametersProtocol->Argv[0]) == EFI_SUCCESS) {\r
+            CommandWithPath = StrnCatGrow(&CommandWithPath, NULL, ShellInfoObject.NewShellParametersProtocol->Argv[0], 0);\r
+          }\r
+        }\r
+        if (CommandWithPath == NULL) {\r
+          CommandWithPath = ShellFindFilePathEx(ShellInfoObject.NewShellParametersProtocol->Argv[0], mExecutableExtensions);\r
+        }\r
+        if (CommandWithPath == NULL || ShellIsDirectory(CommandWithPath) == EFI_SUCCESS) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, ShellInfoObject.NewShellParametersProtocol->Argv[0]);\r
+        } else {\r
+          //\r
+          // Check if it's a NSH (script) file.\r
+          //\r
+          TempLocation = CommandWithPath+StrLen(CommandWithPath)-4;\r
+          TempLocation2 = mScriptExtension;\r
+          if ((StrLen(CommandWithPath) > 4) && (StringNoCaseCompare((VOID*)(&TempLocation), (VOID*)(&TempLocation2)) == 0)) {\r
+            Status = RunScriptFile (CommandWithPath);\r
+          } else {\r
+            DevPath = ShellInfoObject.NewEfiShellProtocol->GetDevicePathFromFilePath(CommandWithPath);\r
+            ASSERT(DevPath != NULL);\r
+            Status = InternalShellExecuteDevicePath(\r
+              &gImageHandle,\r
+              DevPath,\r
+              PostVariableCmdLine,\r
+              NULL,\r
+              NULL\r
+             );\r
+          }\r
+        }\r
+      }\r
+      CommandName = StrnCatGrow(&CommandName, NULL, ShellInfoObject.NewShellParametersProtocol->Argv[0], 0);\r
+\r
+      RestoreArgcArgv(ShellInfoObject.NewShellParametersProtocol, &Argv, &Argc);\r
+\r
+      RestoreStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr);\r
+    }\r
+    if (CommandName != NULL) {\r
+      if (ShellCommandGetCurrentScriptFile() != NULL &&  !IsScriptOnlyCommand(CommandName)) {\r
+        //\r
+        // if this is NOT a scipt only command return success so the script won't quit.\r
+        // prevent killing the script - this is the only place where we know the actual command name (after alias and variable replacement...)\r
+        //\r
+        Status = EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  SHELL_FREE_NON_NULL(CommandName);\r
+  SHELL_FREE_NON_NULL(CommandWithPath);\r
+  SHELL_FREE_NON_NULL(PostVariableCmdLine);\r
+  SHELL_FREE_NON_NULL(DevPath);\r
+\r
+  return (Status);\r
+}\r
+\r
+STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"', 0x0001, 0x0002};\r
+/**\r
+  Function determins if the CommandName COULD be a valid command.  It does not determine whether\r
+  this is a valid command.  It only checks for invalid characters.\r
+\r
+  @param[in] CommandName    The name to check\r
+\r
+  @retval TRUE              CommandName could be a command name\r
+  @retval FALSE             CommandName could not be a valid command name\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsValidCommandName(\r
+  IN CONST CHAR16     *CommandName\r
+  )\r
+{\r
+  UINTN Count;\r
+  if (CommandName == NULL) {\r
+    ASSERT(FALSE);\r
+    return (FALSE);\r
+  }\r
+  for ( Count = 0\r
+      ; Count < sizeof(InvalidChars) / sizeof(InvalidChars[0])\r
+      ; Count++\r
+     ){\r
+    if (ScanMem16(CommandName, StrSize(CommandName), InvalidChars[Count]) != NULL) {\r
+      return (FALSE);\r
+    }\r
+  }\r
+  return (TRUE);\r
+}\r
+\r
+/**\r
+  Function to process a NSH script file via SHELL_FILE_HANDLE.\r
+\r
+  @param[in] Handle             The handle to the already opened file.\r
+  @param[in] Name               The name of the script file.\r
+\r
+  @retval EFI_SUCCESS           the script completed sucessfully\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunScriptFileHandle (\r
+  IN SHELL_FILE_HANDLE  Handle,\r
+  IN CONST CHAR16       *Name\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  SCRIPT_FILE         *NewScriptFile;\r
+  UINTN               LoopVar;\r
+  CHAR16              *CommandLine;\r
+  CHAR16              *CommandLine2;\r
+  CHAR16              *CommandLine3;\r
+  SCRIPT_COMMAND_LIST *LastCommand;\r
+  BOOLEAN             Ascii;\r
+  BOOLEAN             PreScriptEchoState;\r
+  CONST CHAR16        *CurDir;\r
+  UINTN               LineCount;\r
+\r
+  ASSERT(!ShellCommandGetScriptExit());\r
+\r
+  PreScriptEchoState = ShellCommandGetEchoState();\r
+\r
+  NewScriptFile = (SCRIPT_FILE*)AllocateZeroPool(sizeof(SCRIPT_FILE));\r
+  ASSERT(NewScriptFile != NULL);\r
+\r
+  //\r
+  // Set up the name\r
+  //\r
+  ASSERT(NewScriptFile->ScriptName == NULL);\r
+  NewScriptFile->ScriptName = StrnCatGrow(&NewScriptFile->ScriptName, NULL, Name, 0);\r
+\r
+  //\r
+  // Save the parameters (used to replace %0 to %9 later on)\r
+  //\r
+  NewScriptFile->Argc = ShellInfoObject.NewShellParametersProtocol->Argc;\r
+  if (NewScriptFile->Argc != 0) {\r
+    NewScriptFile->Argv = (CHAR16**)AllocateZeroPool(NewScriptFile->Argc * sizeof(CHAR16*));\r
+    ASSERT(NewScriptFile->Argv != NULL);\r
+    for (LoopVar = 0 ; LoopVar < 10 && LoopVar < NewScriptFile->Argc; LoopVar++) {\r
+      ASSERT(NewScriptFile->Argv[LoopVar] == NULL);\r
+      NewScriptFile->Argv[LoopVar] = StrnCatGrow(&NewScriptFile->Argv[LoopVar], NULL, ShellInfoObject.NewShellParametersProtocol->Argv[LoopVar], 0);\r
+    }\r
+  } else {\r
+    NewScriptFile->Argv = NULL;\r
+  }\r
+\r
+  InitializeListHead(&NewScriptFile->CommandList);\r
+  InitializeListHead(&NewScriptFile->SubstList);\r
+\r
+  //\r
+  // Now build the list of all script commands.\r
+  //\r
+  LineCount = 0;\r
+  while(!ShellFileHandleEof(Handle)) {\r
+    CommandLine = ShellFileHandleReturnLine(Handle, &Ascii);\r
+    LineCount++;\r
+    if (CommandLine == NULL || StrLen(CommandLine) == 0) {\r
+      continue;\r
+    }\r
+    NewScriptFile->CurrentCommand = AllocateZeroPool(sizeof(SCRIPT_COMMAND_LIST));\r
+    ASSERT(NewScriptFile->CurrentCommand != NULL);\r
+\r
+    NewScriptFile->CurrentCommand->Cl   = CommandLine;\r
+    NewScriptFile->CurrentCommand->Data = NULL;\r
+    NewScriptFile->CurrentCommand->Line = LineCount;\r
+\r
+    InsertTailList(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link);\r
+  }\r
+\r
+  //\r
+  // Add this as the topmost script file\r
+  //\r
+  ShellCommandSetNewScript (NewScriptFile);\r
+\r
+  //\r
+  // Now enumerate through the commands and run each one.\r
+  //\r
+  CommandLine = AllocatePool(PcdGet16(PcdShellPrintBufferSize));\r
+  CommandLine2 = AllocatePool(PcdGet16(PcdShellPrintBufferSize));\r
+\r
+  for ( NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode(&NewScriptFile->CommandList)\r
+      ; !IsNull(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)\r
+      ; // conditional increment in the body of the loop\r
+  ){\r
+    StrCpy(CommandLine2, NewScriptFile->CurrentCommand->Cl);\r
+\r
+    //\r
+    // NULL out comments\r
+    //\r
+    for (CommandLine3 = CommandLine2 ; CommandLine3 != NULL && *CommandLine3 != CHAR_NULL ; CommandLine3++) {\r
+      if (*CommandLine3 == L'^') {\r
+        if (*(CommandLine3+1) == L'#' || *(CommandLine3+1) == L':') {\r
+          CopyMem(CommandLine3, CommandLine3+1, StrSize(CommandLine3) - sizeof(CommandLine3[0]));\r
+        }\r
+      } else if (*CommandLine3 == L'#') {\r
+        *CommandLine3 = CHAR_NULL;\r
+      }\r
+    }\r
+\r
+    if (CommandLine2 != NULL && StrLen(CommandLine2) >= 1) {\r
+      //\r
+      // Due to variability in starting the find and replace action we need to have both buffers the same.\r
+      //\r
+      StrCpy(CommandLine, CommandLine2);\r
+\r
+      //\r
+      // Remove the %0 to %9 from the command line (if we have some arguments)\r
+      //\r
+      if (NewScriptFile->Argv != NULL) {\r
+        switch (NewScriptFile->Argc) {\r
+          default:\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+          case 9:\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+          case 8:\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+          case 7:\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+          case 6:\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+          case 5:\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+          case 4:\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+          case 3:\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+          case 2:\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+          case 1:\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE, TRUE);\r
+            ASSERT_EFI_ERROR(Status);\r
+            break;\r
+          case 0:\r
+            break;\r
+        }\r
+      }\r
+      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", L"\"\"", FALSE, FALSE);\r
+\r
+      StrCpy(CommandLine2, CommandLine);\r
+\r
+      LastCommand = NewScriptFile->CurrentCommand;\r
+\r
+      for (CommandLine3 = CommandLine2 ; CommandLine3[0] == L' ' ; CommandLine3++);\r
+\r
+      if (CommandLine3[0] == L':' ) {\r
+        //\r
+        // This line is a goto target / label\r
+        //\r
+      } else {\r
+        if (CommandLine3 != NULL && StrLen(CommandLine3) > 0) {\r
+          if (ShellCommandGetEchoState()) {\r
+            CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");\r
+            if (CurDir != NULL && StrLen(CurDir) > 1) {\r
+              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir);\r
+            } else {\r
+              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle);\r
+            }\r
+            ShellPrintEx(-1, -1, L"%s\r\n", CommandLine2);\r
+          }\r
+          Status = RunCommand(CommandLine3);\r
+        }\r
+\r
+        if (ShellCommandGetScriptExit()) {\r
+          ShellCommandRegisterExit(FALSE);\r
+          Status = EFI_SUCCESS;\r
+          break;\r
+        }\r
+        if (EFI_ERROR(Status)) {\r
+          break;\r
+        }\r
+        if (ShellCommandGetExit()) {\r
+          break;\r
+        }\r
+      }\r
+      //\r
+      // If that commend did not update the CurrentCommand then we need to advance it...\r
+      //\r
+      if (LastCommand == NewScriptFile->CurrentCommand) {\r
+        NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link);\r
+        if (!IsNull(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)) {\r
+          NewScriptFile->CurrentCommand->Reset = TRUE;\r
+        }\r
+      }\r
+    } else {\r
+      NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link);\r
+      if (!IsNull(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)) {\r
+        NewScriptFile->CurrentCommand->Reset = TRUE;\r
+      }\r
+    }\r
+  }\r
+\r
+  ShellCommandSetEchoState(PreScriptEchoState);\r
+\r
+  FreePool(CommandLine);\r
+  FreePool(CommandLine2);\r
+  ShellCommandSetNewScript (NULL);\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Function to process a NSH script file.\r
+\r
+  @param[in] ScriptPath         Pointer to the script file name (including file system path).\r
+\r
+  @retval EFI_SUCCESS           the script completed sucessfully\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunScriptFile (\r
+  IN CONST CHAR16 *ScriptPath\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  SHELL_FILE_HANDLE   FileHandle;\r
+\r
+  if (ShellIsFile(ScriptPath) != EFI_SUCCESS) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  Status = ShellOpenFileByName(ScriptPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+  if (EFI_ERROR(Status)) {\r
+    return (Status);\r
+  }\r
+\r
+  Status = RunScriptFileHandle(FileHandle, ScriptPath);\r
+\r
+  ShellCloseFile(&FileHandle);\r
+\r
+  return (Status);\r
+}\r
diff --git a/ShellPkg/Application/Shell/Shell.h b/ShellPkg/Application/Shell/Shell.h
new file mode 100644 (file)
index 0000000..6f165e5
--- /dev/null
@@ -0,0 +1,292 @@
+/** @file\r
+  function definitions for internal to shell functions.\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#ifndef _SHELL_INTERNAL_HEADER_\r
+#define _SHELL_INTERNAL_HEADER_\r
+\r
+#include <Uefi.h>\r
+#include <ShellBase.h>\r
+\r
+#include <Guid/ShellVariableGuid.h>\r
+\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/EfiShell.h>\r
+#include <Protocol/EfiShellInterface.h>\r
+#include <Protocol/EfiShellEnvironment2.h>\r
+#include <Protocol/EfiShellParameters.h>\r
+#include <Protocol/BlockIo.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiApplicationEntryPoint.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/ShellCommandLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/ShellLib.h>\r
+#include <Library/SortLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HandleParsingLib.h>\r
+\r
+#include "ShellParametersProtocol.h"\r
+#include "ShellProtocol.h"\r
+#include "ShellEnvVar.h"\r
+#include "ConsoleLogger.h"\r
+#include "ShellManParser.h"\r
+\r
+typedef struct {\r
+  LIST_ENTRY        Link;           ///< Standard linked list handler.\r
+  SHELL_FILE_HANDLE *SplitStdOut;   ///< ConsoleOut for use in the split.\r
+  SHELL_FILE_HANDLE *SplitStdIn;    ///< ConsoleIn for use in the split.\r
+} SPLIT_LIST;\r
+\r
+typedef struct {\r
+  UINT32  Startup:1;      ///< Was "-startup"       found on command line.\r
+  UINT32  NoStartup:1;    ///< Was "-nostartup"     found on command line.\r
+  UINT32  NoConsoleOut:1; ///< Was "-noconsoleout"  found on command line.\r
+  UINT32  NoConsoleIn:1;  ///< Was "-noconsolein"   found on command line.\r
+  UINT32  NoInterrupt:1;  ///< Was "-nointerrupt"   found on command line.\r
+  UINT32  NoMap:1;        ///< Was "-nomap"         found on command line.\r
+  UINT32  NoVersion:1;    ///< Was "-noversion"     found on command line.\r
+  UINT32  Delay:1;        ///< Was "-delay[:n]      found on command line\r
+  UINT32  Reserved:8;     ///< Extra bits\r
+} SHELL_BITS;\r
+\r
+typedef union {\r
+  SHELL_BITS  Bits;\r
+  UINT16      AllBits;\r
+} SHELL_BIT_UNION;\r
+\r
+typedef struct {\r
+  SHELL_BIT_UNION BitUnion;\r
+  UINTN           Delay;          ///< Seconds of delay default:5.\r
+  CHAR16          *FileName;      ///< Filename to run upon successful initialization.\r
+  CHAR16          *FileOptions;   ///< Options to pass to FileName.\r
+} SHELL_INIT_SETTINGS;\r
+\r
+typedef struct {\r
+  BUFFER_LIST                 CommandHistory;\r
+  UINTN                       VisibleRowNumber;\r
+  UINTN                       OriginalVisibleRowNumber;\r
+  BOOLEAN                     InsertMode;           ///< Is the current typing mode insert (FALSE = overwrite).\r
+} SHELL_VIEWING_SETTINGS;\r
+\r
+typedef struct {\r
+  EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParametersProtocol;\r
+  EFI_SHELL_PROTOCOL            *NewEfiShellProtocol;\r
+  BOOLEAN                       PageBreakEnabled;\r
+  BOOLEAN                       RootShellInstance;\r
+  SHELL_INIT_SETTINGS           ShellInitSettings;\r
+  BUFFER_LIST                   BufferToFreeList;     ///< List of buffers that were returned to the user to free.\r
+  SHELL_VIEWING_SETTINGS        ViewingSettings;\r
+  EFI_HII_HANDLE                HiiHandle;            ///< Handle from HiiLib.\r
+  UINTN                         LogScreenCount;       ///< How many screens of log information to save.\r
+  EFI_EVENT                     UserBreakTimer;       ///< Timer event for polling for CTRL-C.\r
+  EFI_DEVICE_PATH_PROTOCOL      *ImageDevPath;        ///< DevicePath for ourselves.\r
+  EFI_DEVICE_PATH_PROTOCOL      *FileDevPath;         ///< DevicePath for ourselves.\r
+  CONSOLE_LOGGER_PRIVATE_DATA   *ConsoleInfo;         ///< Pointer for ConsoleInformation.\r
+  EFI_SHELL_PARAMETERS_PROTOCOL *OldShellParameters;  ///< old shell parameters to reinstall upon exiting.\r
+  SHELL_PROTOCOL_HANDLE_LIST    OldShellList;         ///< List of other instances to reinstall when closing.\r
+  SPLIT_LIST                    SplitList;            ///< List of Splits in FILO stack.\r
+} SHELL_INFO;\r
+\r
+extern SHELL_INFO ShellInfoObject;\r
+\r
+/**\r
+  Sets all the alias' that were registered with the ShellCommandLib library.\r
+\r
+  @retval EFI_SUCCESS           all init commands were run sucessfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetBuiltInAlias(\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function will populate the 2 device path protocol parameters based on the\r
+  global gImageHandle.  the DevPath will point to the device path for the handle that has\r
+  loaded image protocol installed on it.  the FilePath will point to the device path\r
+  for the file that was loaded.\r
+\r
+  @param[in,out] DevPath       on a sucessful return the device path to the loaded image\r
+  @param[in,out] FilePath      on a sucessful return the device path to the file\r
+\r
+  @retval EFI_SUCCESS           the 2 device paths were sucessfully returned.\r
+  @return other                 a error from gBS->HandleProtocol\r
+\r
+  @sa HandleProtocol\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDevicePathsForImageAndFile (\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath,\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath\r
+  );\r
+\r
+/**\r
+  Process all Uefi Shell 2.0 command line options.\r
+\r
+  see Uefi Shell 2.0 section 3.2 for full details.\r
+\r
+  the command line should resemble the following:\r
+\r
+  shell.efi [ShellOpt-options] [options] [file-name [file-name-options]]\r
+\r
+  ShellOpt options  Options which control the initialization behavior of the shell.\r
+                    These options are read from the EFI global variable "ShellOpt"\r
+                    and are processed before options or file-name.\r
+\r
+  options           Options which control the initialization behavior of the shell.\r
+\r
+  file-name         The name of a UEFI shell application or script to be executed\r
+                    after initialization is complete. By default, if file-name is\r
+                    specified, then -nostartup is implied. Scripts are not supported\r
+                    by level 0.\r
+\r
+  file-nameoptions  The command-line options that are passed to file-name when it\r
+                    is invoked.\r
+\r
+  This will initialize the ShellInitSettings global variable.\r
+\r
+  @retval EFI_SUCCESS           the variable is initialized.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProcessCommandLine(\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Handles all interaction with the default startup script.\r
+\r
+  this will check that the correct command line parameters were passed, handle the delay, and then start running the script.\r
+\r
+  @param[in] ImagePath          The path to the image for shell.  The first place to look for the startup script.\r
+  @param[in] FilePath           The path to the file for shell.  The second place to look for the startup script.\r
+\r
+  @retval EFI_SUCCESS           The variable is initialized.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DoStartupScript(\r
+  IN EFI_DEVICE_PATH_PROTOCOL *ImagePath,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
+  );\r
+\r
+/**\r
+  Function to perform the shell prompt looping.  It will do a single prompt,\r
+  dispatch the result, and then return.  It is expected that the caller will\r
+  call this function in a loop many times.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval RETURN_ABORTED\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DoShellPrompt (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Add a buffer to the Buffer To Free List for safely returning buffers to other\r
+  places without risking letting them modify internal shell information.\r
+\r
+  @param Buffer   Something to pass to FreePool when the shell is exiting.\r
+**/\r
+VOID*\r
+EFIAPI\r
+AddBufferToFreeList(\r
+  VOID *Buffer\r
+  );\r
+\r
+/**\r
+  Add a buffer to the Command History List.\r
+\r
+  @param Buffer[in]     The line buffer to add.\r
+**/\r
+VOID\r
+EFIAPI\r
+AddLineToCommandHistory(\r
+  IN CONST CHAR16 *Buffer\r
+  );\r
+\r
+/**\r
+  Function will process and run a command line.\r
+\r
+  This will determine if the command line represents an internal shell command or dispatch an external application.\r
+\r
+  @param[in] CmdLine  the command line to parse\r
+\r
+  @retval EFI_SUCCESS     the command was completed\r
+  @retval EFI_ABORTED     the command's operation was aborted\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunCommand(\r
+  IN CONST CHAR16   *CmdLine\r
+  );\r
+\r
+/**\r
+  Function determins if the CommandName COULD be a valid command.  It does not determine whether\r
+  this is a valid command.  It only checks for invalid characters.\r
+\r
+  @param[in] CommandName    The name to check\r
+\r
+  @retval TRUE              CommandName could be a command name\r
+  @retval FALSE             CommandName could not be a valid command name\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsValidCommandName(\r
+  IN CONST CHAR16     *CommandName\r
+  );\r
+\r
+/**\r
+  Function to process a NSH script file via SHELL_FILE_HANDLE.\r
+\r
+  @param[in] Handle             The handle to the already opened file.\r
+  @param[in] Name               The name of the script file.\r
+\r
+  @retval EFI_SUCCESS           the script completed sucessfully\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunScriptFileHandle (\r
+  IN SHELL_FILE_HANDLE  Handle,\r
+  IN CONST CHAR16       *Name\r
+  );\r
+\r
+/**\r
+  Function to process a NSH script file.\r
+\r
+  @param[in] ScriptPath         Pointer to the script file name (including file system path).\r
+\r
+  @retval EFI_SUCCESS           the script completed sucessfully\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunScriptFile (\r
+  IN CONST CHAR16 *ScriptPath\r
+  );\r
+\r
+\r
+#endif //_SHELL_INTERNAL_HEADER_\r
+\r
diff --git a/ShellPkg/Application/Shell/Shell.inf b/ShellPkg/Application/Shell/Shell.inf
new file mode 100644 (file)
index 0000000..c50e560
--- /dev/null
@@ -0,0 +1,105 @@
+##  @file\r
+#  This is the shell application\r
+#\r
+#  Copyright (c) 2009-2010, Intel Corporation.  All rights reserved.<BR>\r
+#\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
+#  http://opensource.org/licenses/bsd-license.php\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
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010006\r
+  BASE_NAME                      = Shell\r
+  FILE_GUID                      = 7C04A583-9E3E-4f1c-AD65-E05268D0B4D1\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = UefiMain\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  Shell.c\r
+  Shell.h\r
+  ShellParametersProtocol.c\r
+  ShellParametersProtocol.h\r
+  ShellProtocol.c\r
+  ShellProtocol.h\r
+  FileHandleWrappers.c\r
+  FileHandleWrappers.h\r
+  FileHandleInternal.h\r
+  ShellEnvVar.c\r
+  ShellEnvVar.h\r
+  ShellManParser.c\r
+  ShellManParser.h\r
+  Shell.uni\r
+  ConsoleLogger.c\r
+  ConsoleLogger.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  ShellPkg/ShellPkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  UefiApplicationEntryPoint\r
+  UefiLib\r
+  DebugLib\r
+  MemoryAllocationLib\r
+  ShellCommandLib\r
+  UefiRuntimeServicesTableLib\r
+  UefiBootServicesTableLib\r
+  DevicePathLib\r
+  BaseMemoryLib\r
+  PcdLib\r
+  FileHandleLib\r
+  PrintLib\r
+  HiiLib\r
+  SortLib\r
+  HandleParsingLib\r
+\r
+[Guids]\r
+  gShellVariableGuid                                      # ALWAYS_CONSUMED\r
+  gShellMapGuid                                           # ALWAYS_CONSUMED\r
+  gShellAliasGuid                                         # ALWAYS_CONSUMED\r
+\r
+[Protocols]\r
+  gEfiShellProtocolGuid                                   # ALWAYS_PRODUCED\r
+  gEfiShellParametersProtocolGuid                         # ALWAYS_PRODUCED\r
+  gEfiShellEnvironment2Guid                               # SOMETIMES_PRODUCED\r
+  gEfiShellInterfaceGuid                                  # SOMETIMES_PRODUCED\r
+\r
+  gEfiLoadedImageProtocolGuid                             # ALWAYS_CONSUMED\r
+  gEfiSimpleTextInputExProtocolGuid                       # ALWAYS_CONSUMED\r
+  gEfiSimpleTextOutProtocolGuid                           # ALWAYS_CONSUMED\r
+  gEfiSimpleFileSystemProtocolGuid                        # ALWAYS_CONSUMED\r
+  gEfiLoadedImageProtocolGuid                             # ALWAYS_CONSUMED\r
+  gEfiComponentName2ProtocolGuid                          # ALWAYS_CONSUMED\r
+  gEfiUnicodeCollation2ProtocolGuid                       # ALWAYS_CONSUMED\r
+  gEfiDevicePathProtocolGuid                              # ALWAYS_CONSUMED\r
+  gEfiDevicePathToTextProtocolGuid                        # ALWAYS_CONSUMED\r
+\r
+[Pcd]\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel         # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellSupportOldProtocols  # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellRequireHiiPlatform   # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellSupportFrameworkHii  # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellPageBreakDefault     # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize    # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellInsertModeDefault    # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellScreenLogCount       # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength        # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize      # ALWAYS_CONSUMED\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellForceConsole         # ALWAYS_CONSUMED\r
+\r
diff --git a/ShellPkg/Application/Shell/Shell.uni b/ShellPkg/Application/Shell/Shell.uni
new file mode 100644 (file)
index 0000000..82a87ae
Binary files /dev/null and b/ShellPkg/Application/Shell/Shell.uni differ
diff --git a/ShellPkg/Application/Shell/ShellEnvVar.c b/ShellPkg/Application/Shell/ShellEnvVar.c
new file mode 100644 (file)
index 0000000..ff353c4
--- /dev/null
@@ -0,0 +1,326 @@
+/** @file\r
+  function declarations for shell environment functions.\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Guid/ShellVariableGuid.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+#include "ShellEnvVar.h"\r
+\r
+\r
+/**\r
+  Reports whether an environment variable is Volatile or Non-Volatile.\r
+\r
+  @param EnvVarName             The name of the environment variable in question\r
+\r
+  @retval TRUE                  This environment variable is Volatile\r
+  @retval FALSE                 This environment variable is NON-Volatile\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsVolatileEnv (\r
+  IN CONST CHAR16 *EnvVarName\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Size;\r
+  VOID        *Buffer;\r
+  UINT32      Attribs;\r
+\r
+  Size = 0;\r
+  Buffer = NULL;\r
+\r
+  //\r
+  // get the variable\r
+  //\r
+  Status = gRT->GetVariable((CHAR16*)EnvVarName,\r
+                            &gShellVariableGuid,\r
+                            &Attribs,\r
+                            &Size,\r
+                            Buffer);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    Buffer = AllocatePool(Size);\r
+    ASSERT(Buffer != NULL);\r
+    Status = gRT->GetVariable((CHAR16*)EnvVarName,\r
+                              &gShellVariableGuid,\r
+                              &Attribs,\r
+                              &Size,\r
+                              Buffer);\r
+    FreePool(Buffer);\r
+  }\r
+  //\r
+  // not found means volatile\r
+  //\r
+  if (Status == EFI_NOT_FOUND) {\r
+    return (TRUE);\r
+  }\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // check for the Non Volatile bit\r
+  //\r
+  if ((Attribs & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE) {\r
+    return (FALSE);\r
+  }\r
+\r
+  //\r
+  // everything else is volatile\r
+  //\r
+  return (TRUE);\r
+}\r
+\r
+/**\r
+  free function for ENV_VAR_LIST objects.\r
+\r
+  @param[in] List               The pointer to pointer to list.\r
+**/\r
+VOID\r
+EFIAPI\r
+FreeEnvironmentVariableList(\r
+  IN LIST_ENTRY *List\r
+  )\r
+{\r
+  ENV_VAR_LIST *Node;\r
+\r
+  ASSERT (List != NULL);\r
+  if (List == NULL) {\r
+    return;\r
+  }\r
+\r
+  for ( Node = (ENV_VAR_LIST*)GetFirstNode(List)\r
+      ; IsListEmpty(List)\r
+      ; Node = (ENV_VAR_LIST*)GetFirstNode(List)\r
+     ){\r
+    ASSERT(Node != NULL);\r
+    RemoveEntryList(&Node->Link);\r
+    if (Node->Key != NULL) {\r
+      FreePool(Node->Key);\r
+    }\r
+    if (Node->Val != NULL) {\r
+      FreePool(Node->Val);\r
+    }\r
+    FreePool(Node);\r
+  }\r
+}\r
+\r
+/**\r
+  Creates a list of all Shell-Guid-based environment variables.\r
+\r
+  @param[in,out] ListHead       The pointer to pointer to LIST ENTRY object for\r
+                                storing this list.\r
+\r
+  @retval EFI_SUCCESS           the list was created sucessfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetEnvironmentVariableList(\r
+  IN OUT LIST_ENTRY *ListHead\r
+  )\r
+{\r
+  CHAR16            *VariableName;\r
+  UINTN             NameSize;\r
+  UINT64            MaxStorSize;\r
+  UINT64            RemStorSize;\r
+  UINT64            MaxVarSize;\r
+  EFI_STATUS        Status;\r
+  EFI_GUID          Guid;\r
+  UINTN             ValSize;\r
+  ENV_VAR_LIST      *VarList;\r
+\r
+  ASSERT(ListHead != NULL);\r
+\r
+  Status = gRT->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS, &MaxStorSize, &RemStorSize, &MaxVarSize);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  NameSize = (UINTN)MaxVarSize;\r
+  VariableName = AllocatePool(NameSize);\r
+  StrCpy(VariableName, L"");\r
+\r
+  while (TRUE) {\r
+    NameSize = (UINTN)MaxVarSize;\r
+    Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);\r
+    if (Status == EFI_NOT_FOUND){\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    }\r
+    ASSERT_EFI_ERROR(Status);\r
+    if (EFI_ERROR(Status)) {\r
+      break;\r
+    }\r
+    if (CompareGuid(&Guid, &gShellVariableGuid)){\r
+      VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));\r
+      ValSize = 0;\r
+      Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);\r
+      if (Status == EFI_BUFFER_TOO_SMALL){\r
+        VarList->Val = AllocatePool(ValSize);\r
+        ASSERT(VarList->Val != NULL);\r
+        Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);\r
+      }\r
+      ASSERT_EFI_ERROR(Status);\r
+      VarList->Key = AllocatePool(StrSize(VariableName));\r
+      ASSERT(VarList->Key != NULL);\r
+      StrCpy(VarList->Key, VariableName);\r
+\r
+      InsertTailList(ListHead, &VarList->Link);\r
+    } // compare guid\r
+  } // while\r
+  FreePool(VariableName);\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    FreeEnvironmentVariableList(ListHead);\r
+  }\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Sets a list of all Shell-Guid-based environment variables.  this will\r
+  also eliminate all existing shell environment variables (even if they\r
+  are not on the list).\r
+\r
+  This function will also deallocate the memory from List.\r
+\r
+  @param[in] ListHead           The pointer to LIST_ENTRY from\r
+                                GetShellEnvVarList().\r
+\r
+  @retval EFI_SUCCESS           the list was Set sucessfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetEnvironmentVariableList(\r
+  IN LIST_ENTRY *ListHead\r
+  )\r
+{\r
+  ENV_VAR_LIST      VarList;\r
+  ENV_VAR_LIST      *Node;\r
+  EFI_STATUS        Status;\r
+  UINTN             Size;\r
+\r
+  InitializeListHead(&VarList.Link);\r
+\r
+  //\r
+  // Delete all the current environment variables\r
+  //\r
+  Status = GetEnvironmentVariableList(&VarList.Link);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  for ( Node = (ENV_VAR_LIST*)GetFirstNode(&VarList.Link)\r
+      ; !IsNull(&VarList.Link, &Node->Link)\r
+      ; Node = (ENV_VAR_LIST*)GetNextNode(&VarList.Link, &Node->Link)\r
+     ){\r
+    if (Node->Key != NULL) {\r
+      Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Node->Key);\r
+    }\r
+    ASSERT_EFI_ERROR(Status);\r
+  }\r
+\r
+  FreeEnvironmentVariableList(&VarList.Link);\r
+\r
+  //\r
+  // set all the variables fron the list\r
+  //\r
+  for ( Node = (ENV_VAR_LIST*)GetFirstNode(ListHead)\r
+      ; !IsNull(ListHead, &Node->Link)\r
+      ; Node = (ENV_VAR_LIST*)GetNextNode(ListHead, &Node->Link)\r
+     ){\r
+    Size = StrSize(Node->Val);\r
+    if (Node->Atts & EFI_VARIABLE_NON_VOLATILE) {\r
+      Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(Node->Key, Size, Node->Val);\r
+    } else {\r
+      Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (Node->Key, Size, Node->Val);\r
+    }\r
+    ASSERT_EFI_ERROR(Status);\r
+  }\r
+  FreeEnvironmentVariableList(ListHead);\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  sets a list of all Shell-Guid-based environment variables.\r
+\r
+  @param Environment        Points to a NULL-terminated array of environment\r
+                            variables with the format 'x=y', where x is the\r
+                            environment variable name and y is the value.\r
+\r
+  @retval EFI_SUCCESS       The command executed successfully.\r
+  @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES Out of resources.\r
+\r
+  @sa SetEnvironmentVariableList\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetEnvironmentVariables(\r
+  IN CONST CHAR16 **Environment\r
+  )\r
+{\r
+  CONST CHAR16  *CurrentString;\r
+  UINTN         CurrentCount;\r
+  ENV_VAR_LIST  *VarList;\r
+  ENV_VAR_LIST  *Node;\r
+  UINTN         NewSize;\r
+\r
+  VarList = NULL;\r
+\r
+  if (Environment == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // Build a list identical to the ones used for get/set list functions above\r
+  //\r
+  for ( CurrentCount = 0\r
+      ;\r
+      ; CurrentCount++\r
+     ){\r
+    CurrentString = Environment[CurrentCount];\r
+    if (CurrentString == NULL) {\r
+      break;\r
+    }\r
+    ASSERT(StrStr(CurrentString, L"=") != NULL);\r
+    Node = AllocatePool(sizeof(ENV_VAR_LIST));\r
+    ASSERT(Node != NULL);\r
+    Node->Key = AllocateZeroPool((StrStr(CurrentString, L"=") - CurrentString + 1) * sizeof(CHAR16));\r
+    ASSERT(Node->Key != NULL);\r
+    StrnCpy(Node->Key, CurrentString, StrStr(CurrentString, L"=") - CurrentString);\r
+    NewSize = StrSize(CurrentString);\r
+    NewSize -= StrLen(Node->Key) - 1;\r
+    Node->Val = AllocateZeroPool(NewSize);\r
+    ASSERT(Node->Val != NULL);\r
+    StrCpy(Node->Val, CurrentString + StrLen(Node->Key) + 1);\r
+    Node->Atts = EFI_VARIABLE_BOOTSERVICE_ACCESS;\r
+\r
+    if (VarList == NULL) {\r
+      VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));\r
+      ASSERT(VarList != NULL);\r
+      InitializeListHead(&VarList->Link);\r
+    }\r
+    InsertTailList(&VarList->Link, &Node->Link);\r
+\r
+  } // for loop\r
+\r
+  //\r
+  // set this new list as the set of all environment variables.\r
+  // this function also frees the memory and deletes all pre-existing\r
+  // shell-guid based environment variables.\r
+  //\r
+  return (SetEnvironmentVariableList(&VarList->Link));\r
+}\r
diff --git a/ShellPkg/Application/Shell/ShellEnvVar.h b/ShellPkg/Application/Shell/ShellEnvVar.h
new file mode 100644 (file)
index 0000000..2778959
--- /dev/null
@@ -0,0 +1,210 @@
+/** @file\r
+  function definitions for shell environment functions.\r
+\r
+  the following includes are required:\r
+//#include <Guid/ShellVariableGuid.h>\r
+//#include <Library/UefiRuntimeServicesTableLib.h>\r
+\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#ifndef _SHELL_ENVIRONMENT_VARIABLE_HEADER_\r
+#define _SHELL_ENVIRONMENT_VARIABLE_HEADER_\r
+\r
+typedef struct {\r
+  LIST_ENTRY  Link;\r
+  CHAR16      *Key;\r
+  CHAR16      *Val;\r
+  UINT32      Atts;\r
+} ENV_VAR_LIST;\r
+\r
+/**\r
+  Reports whether an environment variable is Volatile or Non-Volatile\r
+\r
+  This will use the Runtime Services call GetVariable to to search for the variable.\r
+\r
+  @param EnvVarName             The name of the environment variable in question\r
+\r
+  @retval TRUE                  This environment variable is Volatile\r
+  @retval FALSE                 This environment variable is NON-Volatile\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsVolatileEnv (\r
+  IN CONST CHAR16 *EnvVarName\r
+  );\r
+\r
+/**\r
+  Delete a Non-Violatile environment variable.\r
+\r
+  This will use the Runtime Services call SetVariable to remove a non-violatile variable.\r
+\r
+  @param EnvVarName             The name of the environment variable in question\r
+\r
+  @retval EFI_SUCCESS           The variable was deleted sucessfully\r
+  @retval other                 An error ocurred\r
+  @sa SetVariable\r
+**/\r
+#define SHELL_DELETE_ENVIRONMENT_VARIABLE(EnvVarName) \\r
+  (gRT->SetVariable((CHAR16*)EnvVarName, \\r
+  &gShellVariableGuid,          \\r
+  0,                            \\r
+  0,                            \\r
+  NULL))\r
+\r
+/**\r
+  Set a Non-Violatile environment variable.\r
+\r
+  This will use the Runtime Services call SetVariable to set a non-violatile variable.\r
+\r
+  @param EnvVarName             The name of the environment variable in question\r
+  @param BufferSize             UINTN size of Buffer\r
+  @param Buffer                 Pointer to value to set variable to\r
+\r
+  @retval EFI_SUCCESS           The variable was changed sucessfully\r
+  @retval other                 An error ocurred\r
+  @sa SetVariable\r
+**/\r
+#define SHELL_SET_ENVIRONMENT_VARIABLE_NV(EnvVarName,BufferSize,Buffer)  \\r
+  (gRT->SetVariable((CHAR16*)EnvVarName,                          \\r
+  &gShellVariableGuid,                                            \\r
+  EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS,      \\r
+  BufferSize,                                                     \\r
+  (VOID*)Buffer))\r
+\r
+/**\r
+  Get an environment variable.\r
+\r
+  This will use the Runtime Services call GetVariable to get a variable.\r
+\r
+  @param EnvVarName             The name of the environment variable in question\r
+  @param BufferSize             Pointer to the UINTN size of Buffer\r
+  @param Buffer                 Pointer buffer to get variable value into\r
+\r
+  @retval EFI_SUCCESS           The variable's value was retrieved sucessfully\r
+  @retval other                 An error ocurred\r
+  @sa SetVariable\r
+**/\r
+#define SHELL_GET_ENVIRONMENT_VARIABLE(EnvVarName,BufferSize,Buffer)    \\r
+  (gRT->GetVariable((CHAR16*)EnvVarName,                        \\r
+  &gShellVariableGuid,                                          \\r
+  0,                                                            \\r
+  BufferSize,                                                   \\r
+  Buffer))\r
+\r
+/**\r
+  Get an environment variable.\r
+\r
+  This will use the Runtime Services call GetVariable to get a variable.\r
+\r
+  @param EnvVarName             The name of the environment variable in question\r
+  @param Atts                   Pointer to the UINT32 for attributes (or NULL)\r
+  @param BufferSize             Pointer to the UINTN size of Buffer\r
+  @param Buffer                 Pointer buffer to get variable value into\r
+\r
+  @retval EFI_SUCCESS           The variable's value was retrieved sucessfully\r
+  @retval other                 An error ocurred\r
+  @sa SetVariable\r
+**/\r
+#define SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(EnvVarName,Atts,BufferSize,Buffer)    \\r
+  (gRT->GetVariable((CHAR16*)EnvVarName,                        \\r
+  &gShellVariableGuid,                                          \\r
+  Atts,                                                            \\r
+  BufferSize,                                                   \\r
+  Buffer))\r
+\r
+/**\r
+  Set a Violatile environment variable.\r
+\r
+  This will use the Runtime Services call SetVariable to set a violatile variable.\r
+\r
+  @param EnvVarName             The name of the environment variable in question\r
+  @param BufferSize             UINTN size of Buffer\r
+  @param Buffer                 Pointer to value to set variable to\r
+\r
+  @retval EFI_SUCCESS           The variable was changed sucessfully\r
+  @retval other                 An error ocurred\r
+  @sa SetVariable\r
+**/\r
+#define SHELL_SET_ENVIRONMENT_VARIABLE_V(EnvVarName,BufferSize,Buffer) \\r
+  (gRT->SetVariable((CHAR16*)EnvVarName,                      \\r
+  &gShellVariableGuid,                                        \\r
+  EFI_VARIABLE_BOOTSERVICE_ACCESS,                            \\r
+  BufferSize,                                                 \\r
+  (VOID*)Buffer))\r
+\r
+/**\r
+  Creates a list of all Shell-Guid-based environment variables.\r
+\r
+  @param[in,out] List           The pointer to pointer to LIST_ENTRY object for\r
+                                storing this list.\r
+\r
+  @retval EFI_SUCCESS           the list was created sucessfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetEnvironmentVariableList(\r
+  IN OUT LIST_ENTRY *List\r
+  );\r
+\r
+/**\r
+  Sets a list of all Shell-Guid-based environment variables.  this will\r
+  also eliminate all pre-existing shell environment variables (even if they\r
+  are not on the list).\r
+\r
+  This function will also deallocate the memory from List.\r
+\r
+  @param[in] List               The pointer to LIST_ENTRY from\r
+                                GetShellEnvVarList().\r
+\r
+  @retval EFI_SUCCESS           The list was Set sucessfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetEnvironmentVariableList(\r
+  IN LIST_ENTRY *List\r
+  );\r
+\r
+/**\r
+  sets all Shell-Guid-based environment variables.  this will\r
+  also eliminate all pre-existing shell environment variables (even if they\r
+  are not on the list).\r
+\r
+  @param[in] Environment    Points to a NULL-terminated array of environment\r
+                            variables with the format 'x=y', where x is the\r
+                            environment variable name and y is the value.\r
+\r
+  @retval EFI_SUCCESS       The command executed successfully.\r
+  @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES Out of resources.\r
+\r
+  @sa SetEnvironmentVariableList\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetEnvironmentVariables(\r
+  IN CONST CHAR16 **Environment\r
+  );\r
+\r
+/**\r
+  free function for ENV_VAR_LIST objects.\r
+\r
+  @param[in] List               The pointer to pointer to list.\r
+**/\r
+VOID\r
+EFIAPI\r
+FreeEnvironmentVariableList(\r
+  IN LIST_ENTRY *List\r
+  );\r
+\r
+#endif //_SHELL_ENVIRONMENT_VARIABLE_HEADER_\r
+\r
diff --git a/ShellPkg/Application/Shell/ShellManParser.c b/ShellPkg/Application/Shell/ShellManParser.c
new file mode 100644 (file)
index 0000000..fe9facb
--- /dev/null
@@ -0,0 +1,615 @@
+/** @file\r
+  Provides interface to shell MAN file parser.\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#include "Shell.h"\r
+\r
+/**\r
+  Verifies that the filename has .MAN on the end.\r
+\r
+  allocates a new buffer and copies the name (appending .MAN if necessary)\r
+\r
+  ASSERT if ManFileName is NULL\r
+\r
+  @param[in] ManFileName            original filename\r
+\r
+  @return the new filename with .man as the extension.\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+GetManFileName(\r
+  IN CONST CHAR16 *ManFileName\r
+  )\r
+{\r
+  CHAR16 *Buffer;\r
+  ASSERT(ManFileName != NULL);\r
+  //\r
+  // Fix the file name\r
+  //\r
+  if (StrnCmp(ManFileName+StrLen(ManFileName)-4, L".man", 4)==0) {\r
+    Buffer = AllocateZeroPool(StrSize(ManFileName));\r
+    StrCpy(Buffer, ManFileName);\r
+  } else {\r
+    Buffer = AllocateZeroPool(StrSize(ManFileName) + 4*sizeof(CHAR16));\r
+    StrCpy(Buffer, ManFileName);\r
+    StrCat(Buffer, L".man");\r
+  }\r
+  return (Buffer);\r
+}\r
+\r
+/**\r
+  Search the path environment variable for possible locations and test for\r
+  which one contains a man file with the name specified.  If a valid file is found\r
+  stop searching and return the (opened) SHELL_FILE_HANDLE for that file.\r
+\r
+  @param[in] FileName           Name of the file to find and open.\r
+  @param[out] Handle            Pointer to the handle of the found file.  The\r
+                                value of this is undefined for return values\r
+                                except EFI_SUCCESS.\r
+\r
+  @retval EFI_SUCCESS           The file was found.  Handle is a valid SHELL_FILE_HANDLE\r
+  @retval EFI_INVALID_PARAMETER A parameter had an invalid value.\r
+  @retval EFI_NOT_FOUND         The file was not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SearchPathForFile(\r
+  IN CONST CHAR16             *FileName,\r
+  OUT SHELL_FILE_HANDLE       *Handle\r
+  )\r
+{\r
+  CHAR16          *FullFileName;\r
+  EFI_STATUS      Status;\r
+\r
+  if ( FileName     == NULL\r
+    || Handle       == NULL\r
+    || StrLen(FileName) == 0\r
+   ){\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  FullFileName = ShellFindFilePath(FileName);\r
+  if (FullFileName == NULL) {\r
+    return (EFI_NOT_FOUND);\r
+  }\r
+\r
+  //\r
+  // now open that file\r
+  //\r
+  Status = EfiShellOpenFileByName(FullFileName, Handle, EFI_FILE_MODE_READ);\r
+  FreePool(FullFileName);\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  parses through Buffer (which is MAN file formatted) and returns the\r
+  detailed help for any sub section specified in the comma seperated list of\r
+  sections provided.  If the end of the file or a .TH section is found then\r
+  return.\r
+\r
+  Upon a sucessful return the caller is responsible to free the memory in *HelpText\r
+\r
+  @param[in] Buffer             Buffer to read from\r
+  @param[in] Sections           name of command's sub sections to find\r
+  @param[in] HelpText           pointer to pointer to string where text goes.\r
+  @param[in] HelpSize           pointer to size of allocated HelpText (may be updated)\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
+  @retval EFI_SUCCESS           the section was found and its description sotred in\r
+                                an alloceted buffer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ManBufferFindSections(\r
+  IN CONST CHAR16 *Buffer,\r
+  IN CONST CHAR16 *Sections,\r
+  IN CHAR16       **HelpText,\r
+  IN UINTN        *HelpSize\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  CONST CHAR16        *CurrentLocation;\r
+  BOOLEAN             CurrentlyReading;\r
+  CHAR16              *SectionName;\r
+  UINTN               SectionLen;\r
+  BOOLEAN             Found;\r
+  CHAR16              *TempString;\r
+  CHAR16              *TempString2;\r
+\r
+  if ( Buffer     == NULL\r
+    || HelpText   == NULL\r
+    || HelpSize   == NULL\r
+   ){\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  Status            = EFI_SUCCESS;\r
+  CurrentlyReading  = FALSE;\r
+  Found             = FALSE;\r
+\r
+  for (CurrentLocation = Buffer,TempString = NULL\r
+    ;  CurrentLocation != NULL && *CurrentLocation != CHAR_NULL\r
+    ;  CurrentLocation=StrStr(CurrentLocation, L"\r\n"),TempString = NULL\r
+   ){\r
+    while(CurrentLocation[0] == L'\r' || CurrentLocation[0] == L'\n') {\r
+      CurrentLocation++;\r
+    }\r
+    if (CurrentLocation[0] == L'#') {\r
+      //\r
+      // Skip comment lines\r
+      //\r
+      continue;\r
+    }\r
+    if (StrnCmp(CurrentLocation, L".TH", 3) == 0) {\r
+      //\r
+      // we hit the end of this commands section so stop.\r
+      //\r
+      break;\r
+    }\r
+    if (StrnCmp(CurrentLocation, L".SH ", 4) == 0) {\r
+      if (Sections == NULL) {\r
+        CurrentlyReading = TRUE;\r
+        continue;\r
+      } else if (CurrentlyReading) {\r
+        CurrentlyReading = FALSE;\r
+      }\r
+      CurrentLocation += 4;\r
+      //\r
+      // is this a section we want to read in?\r
+      //\r
+      if (StrLen(CurrentLocation)!=0) {\r
+        TempString2 = StrStr(CurrentLocation, L" ");\r
+        TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\r"));\r
+        TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\n"));\r
+        ASSERT(TempString == NULL);\r
+        TempString = StrnCatGrow(&TempString, NULL, CurrentLocation, TempString2==NULL?0:TempString2 - CurrentLocation);\r
+        SectionName = TempString;\r
+        SectionLen = StrLen(SectionName);\r
+        SectionName = StrStr(Sections, SectionName);\r
+        if (SectionName == NULL) {\r
+          continue;\r
+        }\r
+        if (*(SectionName + SectionLen) == CHAR_NULL || *(SectionName + SectionLen) == L',') {\r
+          CurrentlyReading = TRUE;\r
+        }\r
+      }\r
+    } else if (CurrentlyReading) {\r
+      Found = TRUE;\r
+      if (StrLen(CurrentLocation)!=0) {\r
+        TempString2 = StrStr(CurrentLocation, L"\r");\r
+        TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\n"));\r
+        ASSERT(TempString == NULL);\r
+        TempString = StrnCatGrow(&TempString, NULL, CurrentLocation, TempString2==NULL?0:TempString2 - CurrentLocation);\r
+        //\r
+        // copy and save the current line.\r
+        //\r
+        ASSERT((*HelpText == NULL && *HelpSize == 0) || (*HelpText != NULL));\r
+        StrnCatGrow (HelpText, HelpSize, TempString, 0);\r
+        StrnCatGrow (HelpText, HelpSize, L"\r\n", 0);\r
+      }\r
+    }\r
+    SHELL_FREE_NON_NULL(TempString);\r
+  }\r
+  if (!Found && !EFI_ERROR(Status)) {\r
+    return (EFI_NOT_FOUND);\r
+  }\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  parses through the MAN file specified by SHELL_FILE_HANDLE and returns the\r
+  detailed help for any sub section specified in the comma seperated list of\r
+  sections provided.  If the end of the file or a .TH section is found then\r
+  return.\r
+\r
+  Upon a sucessful return the caller is responsible to free the memory in *HelpText\r
+\r
+  @param[in] Handle             FileHandle to read from\r
+  @param[in] Sections           name of command's sub sections to find\r
+  @param[out] HelpText          pointer to pointer to string where text goes.\r
+  @param[out] HelpSize          pointer to size of allocated HelpText (may be updated)\r
+  @param[in] Ascii              TRUE if the file is ASCII, FALSE otherwise.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
+  @retval EFI_SUCCESS           the section was found and its description sotred in\r
+                                an alloceted buffer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ManFileFindSections(\r
+  IN SHELL_FILE_HANDLE  Handle,\r
+  IN CONST CHAR16       *Sections,\r
+  OUT CHAR16            **HelpText,\r
+  OUT UINTN             *HelpSize,\r
+  IN BOOLEAN            Ascii\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  CHAR16              *ReadLine;\r
+  UINTN               Size;\r
+  BOOLEAN             CurrentlyReading;\r
+  CHAR16              *SectionName;\r
+  UINTN               SectionLen;\r
+  BOOLEAN             Found;\r
+\r
+  if ( Handle     == NULL\r
+    || HelpText   == NULL\r
+    || HelpSize   == NULL\r
+   ){\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  Status            = EFI_SUCCESS;\r
+  CurrentlyReading  = FALSE;\r
+  Size              = 1024;\r
+  Found             = FALSE;\r
+\r
+  ReadLine          = AllocateZeroPool(Size);\r
+  if (ReadLine == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  for (;!ShellFileHandleEof(Handle);Size = 1024) {\r
+    Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, &Ascii);\r
+    if (ReadLine[0] == L'#') {\r
+      //\r
+      // Skip comment lines\r
+      //\r
+      continue;\r
+    }\r
+    //\r
+    // ignore too small of buffer...\r
+    //\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      Status = EFI_SUCCESS;\r
+    }\r
+    if (EFI_ERROR(Status)) {\r
+      break;\r
+    } else if (StrnCmp(ReadLine, L".TH", 3) == 0) {\r
+      //\r
+      // we hit the end of this commands section so stop.\r
+      //\r
+      break;\r
+    } else if (StrnCmp(ReadLine, L".SH", 3) == 0) {\r
+      if (Sections == NULL) {\r
+        CurrentlyReading = TRUE;\r
+        continue;\r
+      }\r
+      //\r
+      // we found a section\r
+      //\r
+      if (CurrentlyReading) {\r
+        CurrentlyReading = FALSE;\r
+      }\r
+      //\r
+      // is this a section we want to read in?\r
+      //\r
+      for ( SectionName = ReadLine + 3\r
+          ; *SectionName == L' '\r
+          ; SectionName++);\r
+      SectionLen = StrLen(SectionName);\r
+      SectionName = StrStr(Sections, SectionName);\r
+      if (SectionName == NULL) {\r
+        continue;\r
+      }\r
+      if (*(SectionName + SectionLen) == CHAR_NULL || *(SectionName + SectionLen) == L',') {\r
+        CurrentlyReading = TRUE;\r
+      }\r
+    } else if (CurrentlyReading) {\r
+      Found = TRUE;\r
+      //\r
+      // copy and save the current line.\r
+      //\r
+      ASSERT((*HelpText == NULL && *HelpSize == 0) || (*HelpText != NULL));\r
+      StrnCatGrow (HelpText, HelpSize, ReadLine, 0);\r
+      StrnCatGrow (HelpText, HelpSize, L"\r\n", 0);\r
+    }\r
+  }\r
+  FreePool(ReadLine);\r
+  if (!Found && !EFI_ERROR(Status)) {\r
+    return (EFI_NOT_FOUND);\r
+  }\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  parses through the MAN file formatted Buffer and returns the\r
+  "Brief Description" for the .TH section as specified by Command.  If the\r
+  command section is not found return EFI_NOT_FOUND.\r
+\r
+  Upon a sucessful return the caller is responsible to free the memory in *BriefDesc\r
+\r
+  @param[in] Handle             Buffer to read from\r
+  @param[in] Command            name of command's section to find\r
+  @param[in] BriefDesc          pointer to pointer to string where description goes.\r
+  @param[in] BriefSize          pointer to size of allocated BriefDesc\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
+  @retval EFI_SUCCESS           the section was found and its description sotred in\r
+                                an alloceted buffer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ManBufferFindTitleSection(\r
+  IN CHAR16         **Buffer,\r
+  IN CONST CHAR16   *Command,\r
+  IN CHAR16         **BriefDesc,\r
+  IN UINTN          *BriefSize\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  CHAR16        *TitleString;\r
+  CHAR16        *TitleEnd;\r
+  CHAR16        *CurrentLocation;\r
+\r
+  if ( Buffer     == NULL\r
+    || Command    == NULL\r
+    || (BriefDesc != NULL && BriefSize == NULL)\r
+   ){\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  Status    = EFI_SUCCESS;\r
+\r
+  TitleString = AllocatePool((7*sizeof(CHAR16)) + StrSize(Command));\r
+  if (TitleString == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+  StrCpy(TitleString, L".TH ");\r
+  StrCat(TitleString, Command);\r
+  StrCat(TitleString, L" 0 ");\r
+\r
+  CurrentLocation = StrStr(*Buffer, TitleString);\r
+  if (CurrentLocation == NULL){\r
+    Status = EFI_NOT_FOUND;\r
+  } else {\r
+    //\r
+    // we found it so copy out the rest of the line into BriefDesc\r
+    // After skipping any spaces or zeroes\r
+    //\r
+    for (CurrentLocation += StrLen(TitleString)\r
+      ;  *CurrentLocation == L' ' || *CurrentLocation == L'0' || *CurrentLocation == L'1' || *CurrentLocation == L'\"'\r
+      ;  CurrentLocation++);\r
+\r
+    TitleEnd = StrStr(CurrentLocation, L"\"");\r
+    ASSERT(TitleEnd != NULL);\r
+    if (BriefDesc != NULL) {\r
+      *BriefSize = StrSize(TitleEnd);\r
+      *BriefDesc = AllocateZeroPool(*BriefSize);\r
+      if (*BriefDesc == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+      } else {\r
+        StrnCpy(*BriefDesc, CurrentLocation, TitleEnd-CurrentLocation);\r
+      }\r
+    }\r
+\r
+    for (CurrentLocation = TitleEnd\r
+      ;  *CurrentLocation != L'\n'\r
+      ;  CurrentLocation++);\r
+    for (\r
+      ;  *CurrentLocation == L' ' || *CurrentLocation == L'\n' || *CurrentLocation == L'\r'\r
+      ;  CurrentLocation++);\r
+    *Buffer = CurrentLocation;\r
+  }\r
+\r
+  FreePool(TitleString);\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  parses through the MAN file specified by SHELL_FILE_HANDLE and returns the\r
+  "Brief Description" for the .TH section as specified by Command.  if the\r
+  command section is not found return EFI_NOT_FOUND.\r
+\r
+  Upon a sucessful return the caller is responsible to free the memory in *BriefDesc\r
+\r
+  @param[in] Handle             FileHandle to read from\r
+  @param[in] Command            name of command's section to find\r
+  @param[out] BriefDesc         pointer to pointer to string where description goes.\r
+  @param[out] BriefSize         pointer to size of allocated BriefDesc\r
+  @param[in,out] Ascii          TRUE if the file is ASCII, FALSE otherwise, will be\r
+                                set if the file handle is at the 0 position.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
+  @retval EFI_SUCCESS           the section was found and its description sotred in\r
+                                an alloceted buffer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ManFileFindTitleSection(\r
+  IN SHELL_FILE_HANDLE  Handle,\r
+  IN CONST CHAR16       *Command,\r
+  OUT CHAR16            **BriefDesc OPTIONAL,\r
+  OUT UINTN             *BriefSize OPTIONAL,\r
+  IN OUT BOOLEAN        *Ascii\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  CHAR16      *TitleString;\r
+  CHAR16      *ReadLine;\r
+  UINTN       Size;\r
+  CHAR16      *TitleEnd;\r
+  UINTN       TitleLen;\r
+  BOOLEAN     Found;\r
+\r
+  if ( Handle     == NULL\r
+    || Command    == NULL\r
+    || (BriefDesc != NULL && BriefSize == NULL)\r
+   ){\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  Status    = EFI_SUCCESS;\r
+  Size      = 1024;\r
+  Found     = FALSE;\r
+\r
+  ReadLine  = AllocateZeroPool(Size);\r
+  if (ReadLine == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  TitleString = AllocatePool((4*sizeof(CHAR16)) + StrSize(Command));\r
+  if (TitleString == NULL) {\r
+    FreePool(ReadLine);\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+  StrCpy(TitleString, L".TH ");\r
+  StrCat(TitleString, Command);\r
+  TitleLen = StrLen(TitleString);\r
+  for (;!ShellFileHandleEof(Handle);Size = 1024) {\r
+   Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, Ascii);\r
+    if (ReadLine[0] == L'#') {\r
+      //\r
+      // Skip comment lines\r
+      //\r
+      continue;\r
+    }\r
+    //\r
+    // ignore too small of buffer...\r
+    //\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      Status = EFI_SUCCESS;\r
+    }\r
+    if (EFI_ERROR(Status)) {\r
+      break;\r
+    }\r
+    if (StrnCmp(ReadLine, TitleString, TitleLen) == 0) {\r
+      Found = TRUE;\r
+      //\r
+      // we found it so copy out the rest of the line into BriefDesc\r
+      // After skipping any spaces or zeroes\r
+      //\r
+      for ( TitleEnd = ReadLine+TitleLen\r
+          ; *TitleEnd == L' ' || *TitleEnd == L'0' || *TitleEnd == L'1'\r
+          ; TitleEnd++);\r
+      if (BriefDesc != NULL) {\r
+        *BriefSize = StrSize(TitleEnd);\r
+        *BriefDesc = AllocateZeroPool(*BriefSize);\r
+        if (*BriefDesc == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          break;\r
+        }\r
+        StrCpy(*BriefDesc, TitleEnd);\r
+      }\r
+      break;\r
+    }\r
+  }\r
+  FreePool(ReadLine);\r
+  FreePool(TitleString);\r
+  if (!Found && !EFI_ERROR(Status)) {\r
+    return (EFI_NOT_FOUND);\r
+  }\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  This function returns the help information for the specified command. The help text\r
+  will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B)\r
+\r
+  If Sections is specified, then each section name listed will be compared in a casesensitive\r
+  manner, to the section names described in Appendix B. If the section exists,\r
+  it will be appended to the returned help text. If the section does not exist, no\r
+  information will be returned. If Sections is NULL, then all help text information\r
+  available will be returned.\r
+\r
+  if BriefDesc is NULL, then the breif description will not be savedd seperatly,\r
+  but placed first in the main HelpText.\r
+\r
+  @param[in] ManFileName        Points to the NULL-terminated UEFI Shell MAN file name.\r
+  @param[in] Command            Points to the NULL-terminated UEFI Shell command name.\r
+  @param[in] Sections           Points to the NULL-terminated comma-delimited\r
+                                section names to return. If NULL, then all\r
+                                sections will be returned.\r
+  @param[out] BriefDesc         On return, points to a callee-allocated buffer\r
+                                containing brief description text.\r
+  @param[out] HelpText          On return, points to a callee-allocated buffer\r
+                                containing all specified help text.\r
+\r
+  @retval EFI_SUCCESS           The help text was returned.\r
+  @retval EFI_OUT_OF_RESOURCES  The necessary buffer could not be allocated to hold the\r
+                                returned help text.\r
+  @retval EFI_INVALID_PARAMETER HelpText is NULL\r
+  @retval EFI_NOT_FOUND         There is no help text available for Command.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProcessManFile(\r
+  IN CONST CHAR16 *ManFileName,\r
+  IN CONST CHAR16 *Command,\r
+  IN CONST CHAR16 *Sections OPTIONAL,\r
+  OUT CHAR16      **BriefDesc OPTIONAL,\r
+  OUT CHAR16      **HelpText\r
+  )\r
+{\r
+  CHAR16            *TempString;\r
+  SHELL_FILE_HANDLE FileHandle;\r
+  EFI_STATUS        Status;\r
+  UINTN             HelpSize;\r
+  UINTN             BriefSize;\r
+  BOOLEAN           Ascii;\r
+  CHAR16            *TempString2;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FileDevPath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+\r
+  if ( ManFileName == NULL\r
+    || Command     == NULL\r
+    || HelpText    == NULL\r
+   ){\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  HelpSize    = 0;\r
+  BriefSize   = 0;\r
+  TempString  = NULL;\r
+  //\r
+  // See if it's in HII first\r
+  //\r
+  TempString = ShellCommandGetCommandHelp(Command);\r
+  if (TempString != NULL) {\r
+    TempString2 = TempString;\r
+    Status = ManBufferFindTitleSection(&TempString2, Command, BriefDesc, &BriefSize);\r
+    if (!EFI_ERROR(Status) && HelpText != NULL){\r
+      Status = ManBufferFindSections(TempString2, Sections, HelpText, &HelpSize);\r
+    }\r
+  } else {\r
+    FileHandle    = NULL;\r
+    TempString  = GetManFileName(ManFileName);\r
+\r
+    Status = SearchPathForFile(TempString, &FileHandle);\r
+    if (EFI_ERROR(Status)) {\r
+      FileDevPath = FileDevicePath(NULL, TempString);\r
+      DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, FileDevPath);\r
+      Status = InternalOpenFileDevicePath(DevPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+      FreePool(FileDevPath);\r
+      FreePool(DevPath);\r
+    }\r
+\r
+    if (!EFI_ERROR(Status)) {\r
+      HelpSize  = 0;\r
+      BriefSize = 0;\r
+      Status = ManFileFindTitleSection(FileHandle, Command, BriefDesc, &BriefSize, &Ascii);\r
+      if (!EFI_ERROR(Status) && HelpText != NULL){\r
+        Status = ManFileFindSections(FileHandle, Sections, HelpText, &HelpSize, Ascii);\r
+      }\r
+      ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);\r
+    } else {\r
+      *HelpText = NULL;\r
+    }\r
+  }\r
+  if (TempString != NULL) {\r
+    FreePool(TempString);\r
+  }\r
+\r
+  return (Status);\r
+}\r
diff --git a/ShellPkg/Application/Shell/ShellManParser.h b/ShellPkg/Application/Shell/ShellManParser.h
new file mode 100644 (file)
index 0000000..3807eec
--- /dev/null
@@ -0,0 +1,86 @@
+/** @file\r
+  Provides interface to shell MAN file parser.\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#ifndef _SHELL_MAN_FILE_PARSER_HEADER_\r
+#define _SHELL_MAN_FILE_PARSER_HEADER_\r
+\r
+/**\r
+  This function returns the help information for the specified command. The help text\r
+  will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B)\r
+\r
+  If Sections is specified, then each section name listed will be compared in a casesensitive\r
+  manner, to the section names described in Appendix B. If the section exists,\r
+  it will be appended to the returned help text. If the section does not exist, no\r
+  information will be returned. If Sections is NULL, then all help text information\r
+  available will be returned.\r
+\r
+  if BriefDesc is NULL, then the breif description will not be savedd seperatly,\r
+  but placed first in the main HelpText.\r
+\r
+  @param[in] ManFileName        Points to the NULL-terminated UEFI Shell MAN file name.\r
+  @param[in] Command            Points to the NULL-terminated UEFI Shell command name.\r
+  @param[in] Sections           Points to the NULL-terminated comma-delimited\r
+                                section names to return. If NULL, then all\r
+                                sections will be returned.\r
+  @param[out] BriefDesc         On return, points to a callee-allocated buffer\r
+                                containing brief description text.\r
+  @param[out] HelpText          On return, points to a callee-allocated buffer\r
+                                containing all specified help text.\r
+\r
+  @retval EFI_SUCCESS           The help text was returned.\r
+  @retval EFI_OUT_OF_RESOURCES  The necessary buffer could not be allocated to hold the\r
+                                returned help text.\r
+  @retval EFI_INVALID_PARAMETER HelpText is NULL\r
+  @retval EFI_NOT_FOUND         There is no help text available for Command.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProcessManFile(\r
+  IN CONST CHAR16 *ManFileName,\r
+  IN CONST CHAR16 *Command,\r
+  IN CONST CHAR16 *Sections OPTIONAL,\r
+  OUT CHAR16      **BriefDesc,\r
+  OUT CHAR16      **HelpText\r
+  );\r
+\r
+/**\r
+  parses through the MAN file specified by SHELL_FILE_HANDLE and returns the\r
+  detailed help for any sub section specified in the comma seperated list of\r
+  sections provided.  If the end of the file or a .TH section is found then\r
+  return.\r
+\r
+  Upon a sucessful return the caller is responsible to free the memory in *HelpText\r
+\r
+  @param[in] Handle             FileHandle to read from\r
+  @param[in] Sections           name of command's sub sections to find\r
+  @param[out] HelpText          pointer to pointer to string where text goes.\r
+  @param[out] HelpSize          pointer to size of allocated HelpText (may be updated)\r
+  @param[in] Ascii              TRUE if the file is ASCII, FALSE otherwise.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
+  @retval EFI_SUCCESS           the section was found and its description sotred in\r
+                                an alloceted buffer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ManFileFindSections(\r
+  IN SHELL_FILE_HANDLE  Handle,\r
+  IN CONST CHAR16       *Sections,\r
+  OUT CHAR16            **HelpText,\r
+  OUT UINTN             *HelpSize,\r
+  IN BOOLEAN            Ascii\r
+  );\r
+\r
+#endif //_SHELL_MAN_FILE_PARSER_HEADER_\r
+\r
diff --git a/ShellPkg/Application/Shell/ShellParametersProtocol.c b/ShellPkg/Application/Shell/ShellParametersProtocol.c
new file mode 100644 (file)
index 0000000..914853f
--- /dev/null
@@ -0,0 +1,949 @@
+/** @file\r
+  Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,\r
+  manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#include "ShellParametersProtocol.h"\r
+\r
+/**\r
+  return the next parameter from a command line string;\r
+\r
+  This function moves the next parameter from Walker into TempParameter and moves\r
+  Walker up past that parameter for recursive calling.  When the final parameter\r
+  is moved *Walker will be set to NULL;\r
+\r
+  Temp Parameter must be large enough to hold the parameter before calling this\r
+  function.\r
+\r
+  @param[in,out] Walker        pointer to string of command line.  Adjusted to\r
+                                reminaing command line on return\r
+  @param[in,out] TempParameter pointer to string of command line item extracted.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+GetNextParameter(\r
+  CHAR16 **Walker,\r
+  CHAR16 **TempParameter\r
+  )\r
+{\r
+  CHAR16 *NextDelim;\r
+  CHAR16 *TempLoc;\r
+\r
+  ASSERT(Walker           != NULL);\r
+  ASSERT(*Walker          != NULL);\r
+  ASSERT(TempParameter    != NULL);\r
+  ASSERT(*TempParameter   != NULL);\r
+\r
+  //\r
+  // make sure we dont have any leading spaces\r
+  //\r
+  while ((*Walker)[0] == L' ') {\r
+      (*Walker)++;\r
+  }\r
+\r
+  //\r
+  // make sure we still have some params now...\r
+  //\r
+  if (StrLen(*Walker) == 0) {\r
+    ASSERT((*Walker)[0] == CHAR_NULL);\r
+    *Walker = NULL;\r
+    return;\r
+  }\r
+\r
+  //\r
+  // we have a quoted parameter\r
+  // could be the last parameter, but SHOULD have a trailing quote\r
+  //\r
+  if ((*Walker)[0] == L'\"') {\r
+    NextDelim = NULL;\r
+    for (TempLoc = *Walker + 1 ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
+      if (*TempLoc == L'^' && *(TempLoc+1) == L'^') {\r
+        TempLoc++;\r
+      } else if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
+        TempLoc++;\r
+      } else if (*TempLoc == L'^' && *(TempLoc+1) == L'|') {\r
+        TempLoc++;\r
+      } else if (*TempLoc == L'^') {\r
+        *TempLoc = L' ';\r
+      } else if (*TempLoc == L'\"') {\r
+        NextDelim = TempLoc;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (NextDelim - ((*Walker)+1) == 0) {\r
+      //\r
+      // found ""\r
+      //\r
+      StrCpy(*TempParameter, L"");\r
+      *Walker = NextDelim + 1;\r
+    } else if (NextDelim != NULL) {\r
+      StrnCpy(*TempParameter, (*Walker)+1, NextDelim - ((*Walker)+1));\r
+      *Walker = NextDelim + 1;\r
+    } else {\r
+      //\r
+      // last one... someone forgot the training quote!\r
+      //\r
+      StrCpy(*TempParameter, *Walker);\r
+      *Walker = NULL;\r
+    }\r
+    for (TempLoc = *TempParameter ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
+      if ((*TempLoc == L'^' && *(TempLoc+1) == L'^')\r
+       || (*TempLoc == L'^' && *(TempLoc+1) == L'|')\r
+       || (*TempLoc == L'^' && *(TempLoc+1) == L'\"')\r
+      ){\r
+        CopyMem(TempLoc, TempLoc+1, StrSize(TempLoc) - sizeof(TempLoc[0]));\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // we have a regular parameter (no quote) OR\r
+    // we have the final parameter (no trailing space)\r
+    //\r
+    NextDelim = StrStr((*Walker), L" ");\r
+    if (NextDelim != NULL) {\r
+      StrnCpy(*TempParameter, *Walker, NextDelim - (*Walker));\r
+      (*TempParameter)[NextDelim - (*Walker)] = CHAR_NULL;\r
+      *Walker = NextDelim+1;\r
+    } else {\r
+      //\r
+      // last one.\r
+      //\r
+      StrCpy(*TempParameter, *Walker);\r
+      *Walker = NULL;\r
+    }\r
+    for (NextDelim = *TempParameter ; NextDelim != NULL && *NextDelim != CHAR_NULL ; NextDelim++) {\r
+      if (*NextDelim == L'^' && *(NextDelim+1) == L'^') {\r
+        CopyMem(NextDelim, NextDelim+1, StrSize(NextDelim) - sizeof(NextDelim[0]));\r
+      } else if (*NextDelim == L'^') {\r
+        *NextDelim = L' ';\r
+      }\r
+    }\r
+    while ((*TempParameter)[StrLen(*TempParameter)-1] == L' ') {\r
+      (*TempParameter)[StrLen(*TempParameter)-1] = CHAR_NULL;\r
+    }\r
+    while ((*TempParameter)[0] == L' ') {\r
+      CopyMem(*TempParameter, (*TempParameter)+1, StrSize(*TempParameter) - sizeof((*TempParameter)[0]));\r
+    }\r
+  }\r
+  return;\r
+}\r
+\r
+/**\r
+  function to populate Argc and Argv.\r
+\r
+  This function parses the CommandLine and divides it into standard C style Argc/Argv\r
+  parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL.  this supports space\r
+  delimited and quote surrounded parameter definition.\r
+\r
+  @param[in] CommandLine        String of command line to parse\r
+  @param[in,out] Argv           pointer to array of strings; one for each parameter\r
+  @param[in,out] Argc           pointer to number of strings in Argv array\r
+\r
+  @return EFI_SUCCESS           the operation was sucessful\r
+  @return EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ParseCommandLineToArgs(\r
+  IN CONST CHAR16 *CommandLine,\r
+  IN OUT CHAR16 ***Argv,\r
+  IN OUT UINTN *Argc\r
+  )\r
+{\r
+  UINTN       Count;\r
+  CHAR16      *TempParameter;\r
+  CHAR16      *Walker;\r
+  CHAR16      *NewParam;\r
+  UINTN       Size;\r
+\r
+  ASSERT(Argc != NULL);\r
+  ASSERT(Argv != NULL);\r
+\r
+  if (CommandLine == NULL || StrLen(CommandLine)==0) {\r
+    (*Argc) = 0;\r
+    (*Argv) = NULL;\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  Size = StrSize(CommandLine);\r
+  TempParameter = AllocateZeroPool(Size);\r
+  if (TempParameter == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  for ( Count = 0\r
+      , Walker = (CHAR16*)CommandLine\r
+      ; Walker != NULL && *Walker != CHAR_NULL\r
+      ; GetNextParameter(&Walker, &TempParameter)\r
+      , Count++\r
+     );\r
+\r
+/*  Count = 0;\r
+  Walker = (CHAR16*)CommandLine;\r
+  while(Walker != NULL) {\r
+    GetNextParameter(&Walker, &TempParameter);\r
+    Count++;\r
+  }\r
+*/\r
+  //\r
+  // lets allocate the pointer array\r
+  //\r
+  (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));\r
+  if (*Argv == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  *Argc = 0;\r
+  Walker = (CHAR16*)CommandLine;\r
+  while(Walker != NULL && *Walker != CHAR_NULL) {\r
+    SetMem16(TempParameter, Size, CHAR_NULL);\r
+    GetNextParameter(&Walker, &TempParameter);\r
+    NewParam = AllocateZeroPool(StrSize(TempParameter));\r
+    ASSERT(NewParam != NULL);\r
+    StrCpy(NewParam, TempParameter);\r
+    ((CHAR16**)(*Argv))[(*Argc)] = NewParam;\r
+    (*Argc)++;\r
+  }\r
+  ASSERT(Count >= (*Argc));\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then\r
+  installs it on our handle and if there is an existing version of the protocol\r
+  that one is cached for removal later.\r
+\r
+  @param[in,out] NewShellParameters on a successful return, a pointer to pointer\r
+                                     to the newly installed interface.\r
+  @param[in,out] RootShellInstance  on a successful return, pointer to boolean.\r
+                                     TRUE if this is the root shell instance.\r
+\r
+  @retval EFI_SUCCESS               the operation completed successfully.\r
+  @return other                     the operation failed.\r
+  @sa ReinstallProtocolInterface\r
+  @sa InstallProtocolInterface\r
+  @sa ParseCommandLineToArgs\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreatePopulateInstallShellParametersProtocol (\r
+  IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  **NewShellParameters,\r
+  IN OUT BOOLEAN                        *RootShellInstance\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+  CHAR16                    *FullCommandLine;\r
+  UINTN                     Size;\r
+\r
+  Size = 0;\r
+  FullCommandLine = NULL;\r
+  LoadedImage = NULL;\r
+\r
+  //\r
+  // Assert for valid parameters\r
+  //\r
+  ASSERT(NewShellParameters != NULL);\r
+  ASSERT(RootShellInstance  != NULL);\r
+\r
+  //\r
+  // See if we have a shell parameters placed on us\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                gImageHandle,\r
+                &gEfiShellParametersProtocolGuid,\r
+                (VOID **) &ShellInfoObject.OldShellParameters,\r
+                gImageHandle,\r
+                NULL,\r
+                EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+               );\r
+  //\r
+  // if we don't then we must be the root shell (error is expected)\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    *RootShellInstance = TRUE;\r
+  }\r
+\r
+  //\r
+  // Allocate the new structure\r
+  //\r
+  *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
+  ASSERT(NewShellParameters != NULL);\r
+\r
+  //\r
+  // get loaded image protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                gImageHandle,\r
+                &gEfiLoadedImageProtocolGuid,\r
+                (VOID **) &LoadedImage,\r
+                gImageHandle,\r
+                NULL,\r
+                EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+               );\r
+  ASSERT_EFI_ERROR(Status);\r
+  //\r
+  // Build the full command line\r
+  //\r
+  Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
+    Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
+  }\r
+  if (Status == EFI_NOT_FOUND) {\r
+    //\r
+    // no parameters via environment... ok\r
+    //\r
+  } else {\r
+    ASSERT_EFI_ERROR(Status);\r
+  }\r
+  if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
+    //\r
+    // Now we need to include a NULL terminator in the size.\r
+    //\r
+    Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);\r
+    FullCommandLine = AllocateZeroPool(Size);\r
+  }\r
+  if (LoadedImage->LoadOptionsSize != 0){\r
+    StrCpy(FullCommandLine, LoadedImage->LoadOptions);\r
+  }\r
+  if (FullCommandLine != NULL) {\r
+    //\r
+    // Populate Argc and Argv\r
+    //\r
+    Status = ParseCommandLineToArgs(FullCommandLine,\r
+                                    &(*NewShellParameters)->Argv,\r
+                                    &(*NewShellParameters)->Argc);\r
+\r
+    FreePool(FullCommandLine);\r
+\r
+    ASSERT_EFI_ERROR(Status);\r
+  } else {\r
+    (*NewShellParameters)->Argv = NULL;\r
+    (*NewShellParameters)->Argc = 0;\r
+  }\r
+\r
+  //\r
+  // Populate the 3 faked file systems...\r
+  //\r
+  if (*RootShellInstance) {\r
+    (*NewShellParameters)->StdIn  = &FileInterfaceStdIn;\r
+    (*NewShellParameters)->StdOut = &FileInterfaceStdOut;\r
+    (*NewShellParameters)->StdErr = &FileInterfaceStdErr;\r
+    Status = gBS->InstallProtocolInterface(&gImageHandle,\r
+                                           &gEfiShellParametersProtocolGuid,\r
+                                           EFI_NATIVE_INTERFACE,\r
+                                           (VOID*)(*NewShellParameters));\r
+  } else {\r
+    //\r
+    // copy from the existing ones\r
+    //\r
+    (*NewShellParameters)->StdIn  = ShellInfoObject.OldShellParameters->StdIn;\r
+    (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;\r
+    (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;\r
+    Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
+                                             &gEfiShellParametersProtocolGuid,\r
+                                             (VOID*)ShellInfoObject.OldShellParameters,\r
+                                             (VOID*)(*NewShellParameters));\r
+  }\r
+\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  frees all memory used by createion and installation of shell parameters protocol\r
+  and if there was an old version installed it will restore that one.\r
+\r
+  @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
+  being cleaned up.\r
+\r
+  @retval EFI_SUCCESS     the cleanup was successful\r
+  @return other           the cleanup failed\r
+  @sa ReinstallProtocolInterface\r
+  @sa UninstallProtocolInterface\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CleanUpShellParametersProtocol (\r
+  IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *NewShellParameters\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINTN LoopCounter;\r
+\r
+  //\r
+  // If the old exists we need to restore it\r
+  //\r
+  if (ShellInfoObject.OldShellParameters != NULL) {\r
+    Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
+                                             &gEfiShellParametersProtocolGuid,\r
+                                             (VOID*)NewShellParameters,\r
+                                             (VOID*)ShellInfoObject.OldShellParameters);\r
+    DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);\r
+  } else {\r
+    //\r
+    // No old one, just uninstall us...\r
+    //\r
+    Status = gBS->UninstallProtocolInterface(gImageHandle,\r
+                                             &gEfiShellParametersProtocolGuid,\r
+                                             (VOID*)NewShellParameters);\r
+  }\r
+  if (NewShellParameters->Argv != NULL) {\r
+    for ( LoopCounter = 0\r
+        ; LoopCounter < NewShellParameters->Argc\r
+        ; LoopCounter++\r
+       ){\r
+      FreePool(NewShellParameters->Argv[LoopCounter]);\r
+    }\r
+    FreePool(NewShellParameters->Argv);\r
+  }\r
+  FreePool(NewShellParameters);\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
+  structure by parsing NewCommandLine.  The current values are returned to the\r
+  user.\r
+\r
+  If OldStdIn or OldStdOut is NULL then that value is not returned.\r
+\r
+  @param[in,out] ShellParameters        Pointer to parameter structure to modify.\r
+  @param[in] NewCommandLine             The new command line to parse and use.\r
+  @param[out] OldStdIn                  Pointer to old StdIn.\r
+  @param[out] OldStdOut                 Pointer to old StdOut.\r
+  @param[out] OldStdErr                 Pointer to old StdErr.\r
+\r
+  @retval   EFI_SUCCESS                 Operation was sucessful, Argv and Argc are valid.\r
+  @retval   EFI_OUT_OF_RESOURCES        A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UpdateStdInStdOutStdErr(\r
+  IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
+  IN CONST CHAR16                       *NewCommandLine,\r
+  OUT SHELL_FILE_HANDLE                 *OldStdIn,\r
+  OUT SHELL_FILE_HANDLE                 *OldStdOut,\r
+  OUT SHELL_FILE_HANDLE                 *OldStdErr\r
+  )\r
+{\r
+  CHAR16            *CommandLineCopy;\r
+  CHAR16            *CommandLineWalker;\r
+  CHAR16            *StdErrFileName;\r
+  CHAR16            *StdOutFileName;\r
+  CHAR16            *StdInFileName;\r
+  CHAR16            *StdInVarName;\r
+  CHAR16            *StdOutVarName;\r
+  CHAR16            *StdErrVarName;\r
+  EFI_STATUS        Status;\r
+  SHELL_FILE_HANDLE TempHandle;\r
+  UINT64            FileSize;\r
+  BOOLEAN           OutUnicode;\r
+  BOOLEAN           InUnicode;\r
+  BOOLEAN           ErrUnicode;\r
+  BOOLEAN           OutAppend;\r
+  BOOLEAN           ErrAppend;\r
+  UINTN             Size;\r
+  CHAR16            TagBuffer[2];\r
+  SPLIT_LIST        *Split;\r
+\r
+  ASSERT(ShellParameters != NULL);\r
+  OutUnicode      = TRUE;\r
+  InUnicode       = TRUE;\r
+  ErrUnicode      = TRUE;\r
+  StdInVarName    = NULL;\r
+  StdOutVarName   = NULL;\r
+  StdErrVarName   = NULL;\r
+  StdErrFileName  = NULL;\r
+  StdInFileName   = NULL;\r
+  StdOutFileName  = NULL;\r
+  ErrAppend       = FALSE;\r
+  OutAppend       = FALSE;\r
+  CommandLineCopy = NULL;\r
+\r
+  if (OldStdIn != NULL) {\r
+    *OldStdIn = ShellParameters->StdIn;\r
+  }\r
+  if (OldStdOut != NULL) {\r
+    *OldStdOut = ShellParameters->StdOut;\r
+  }\r
+  if (OldStdErr != NULL) {\r
+    *OldStdErr = ShellParameters->StdErr;\r
+  }\r
+\r
+  if (NewCommandLine == NULL) {\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
+  Status          = EFI_SUCCESS;\r
+  Split           = NULL;\r
+\r
+  if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
+    Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
+    if (Split != NULL && Split->SplitStdIn != NULL) {\r
+      ShellParameters->StdIn  = Split->SplitStdIn;\r
+    }\r
+    if (Split != NULL && Split->SplitStdOut != NULL) {\r
+      ShellParameters->StdOut = Split->SplitStdOut;\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
+    StdErrVarName   = CommandLineWalker += 6;\r
+    ErrAppend       = TRUE;\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
+    StdOutVarName   = CommandLineWalker += 6;\r
+    OutAppend       = TRUE;\r
+  } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
+    StdOutVarName   = CommandLineWalker += 5;\r
+    OutAppend       = TRUE;\r
+  } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
+    StdOutVarName   = CommandLineWalker += 4;\r
+    OutAppend       = FALSE;\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
+    StdOutFileName  = CommandLineWalker += 6;\r
+    OutAppend       = TRUE;\r
+    OutUnicode      = FALSE;\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
+    if (StdOutFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdOutFileName  = CommandLineWalker += 5;\r
+      OutAppend       = TRUE;\r
+    }\r
+  } \r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
+    if (StdOutFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdOutFileName  = CommandLineWalker += 4;\r
+      OutAppend       = TRUE;\r
+    }\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
+    if (StdOutFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdOutFileName  = CommandLineWalker += 5;\r
+      OutAppend       = TRUE;\r
+      OutUnicode      = FALSE;\r
+    }\r
+  } \r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
+    if (StdOutFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdOutFileName  = CommandLineWalker += 5;\r
+      OutAppend       = FALSE;\r
+      OutUnicode      = FALSE;\r
+    }\r
+  } \r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
+    if (StdOutFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdOutFileName  = CommandLineWalker += 4;\r
+      OutAppend       = FALSE;\r
+      OutUnicode      = FALSE;\r
+    }\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
+    if (StdErrFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdErrFileName  = CommandLineWalker += 5;\r
+      ErrAppend       = TRUE;\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
+    if (StdErrVarName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdErrVarName   = CommandLineWalker += 5;\r
+      ErrAppend       = FALSE;\r
+    }\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
+    if (StdOutVarName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdOutVarName   = CommandLineWalker += 5;\r
+      OutAppend       = FALSE;\r
+    }\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
+    if (StdErrFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdErrFileName  = CommandLineWalker += 5;\r
+      ErrAppend       = FALSE;\r
+      ErrUnicode      = FALSE;\r
+    }\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
+    if (StdErrFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdErrFileName  = CommandLineWalker += 4;\r
+      ErrAppend       = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
+    if (StdOutFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdOutFileName  = CommandLineWalker += 4;\r
+      OutAppend       = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
+    if (StdOutFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdOutFileName  = CommandLineWalker += 3;\r
+      OutAppend       = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
+    if (StdInFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdInFileName  = CommandLineWalker += 3;\r
+      OutAppend       = FALSE;\r
+    }\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
+    if (StdInFileName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdInFileName  = CommandLineWalker += 4;\r
+      OutAppend       = FALSE;\r
+    }\r
+  }\r
+  if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
+    if (StdInVarName != NULL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      StdInVarName  = CommandLineWalker += 4;\r
+      OutAppend       = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    if (StdErrFileName != NULL && (CommandLineWalker = StrStr(StdErrFileName, L" ")) != NULL) {\r
+      CommandLineWalker[0] = CHAR_NULL;\r
+    }\r
+    if (StdOutFileName != NULL && (CommandLineWalker = StrStr(StdOutFileName, L" ")) != NULL) {\r
+      CommandLineWalker[0] = CHAR_NULL;\r
+    }\r
+    if (StdInFileName  != NULL && (CommandLineWalker = StrStr(StdInFileName , L" ")) != NULL) {\r
+      CommandLineWalker[0] = CHAR_NULL;\r
+    }\r
+    if (StdErrVarName  != NULL && (CommandLineWalker = StrStr(StdErrVarName , L" ")) != NULL) {\r
+      CommandLineWalker[0] = CHAR_NULL;\r
+    }\r
+    if (StdOutVarName  != NULL && (CommandLineWalker = StrStr(StdOutVarName , L" ")) != NULL) {\r
+      CommandLineWalker[0] = CHAR_NULL;\r
+    }\r
+    if (StdInVarName   != NULL && (CommandLineWalker = StrStr(StdInVarName  , L" ")) != NULL) {\r
+      CommandLineWalker[0] = CHAR_NULL;\r
+    }\r
+\r
+    //\r
+    // Verify not the same and not duplicating something from a split\r
+    //\r
+    if ((StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
+      ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
+      ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
+      ||(StdErrVarName  != NULL && StdInVarName  != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName  ) == 0)\r
+      ||(StdOutVarName  != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName  ) == 0)\r
+      ||(StdErrVarName  != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
+      ||(Split != NULL && Split->SplitStdIn  != NULL && (StdInVarName  != NULL || StdInFileName  != NULL))\r
+      ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
+      ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
+      ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
+      ||(StdInFileName  != NULL && StdInVarName  != NULL)\r
+      ||(StdErrVarName  != NULL && !IsVolatileEnv(StdErrVarName))\r
+      ||(StdOutVarName  != NULL && !IsVolatileEnv(StdOutVarName))\r
+      ){\r
+      Status = EFI_INVALID_PARAMETER;\r
+    } else {\r
+      //\r
+      // Open the Std<Whatever> and we should not have conflicts here...\r
+      //\r
+\r
+      //\r
+      // StdErr to a file\r
+      //\r
+      if (StdErrFileName != NULL) {\r
+        if (!ErrAppend) {\r
+          //\r
+          // delete existing file.\r
+          //\r
+          ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
+        }\r
+        Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
+        ASSERT(TempHandle != NULL);\r
+        if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
+          //\r
+          // Write out the UnicodeFileTag\r
+          //\r
+          Size = sizeof(CHAR16);\r
+          TagBuffer[0] = UnicodeFileTag;\r
+          TagBuffer[1] = CHAR_NULL;\r
+          ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
+        }\r
+        if (!ErrUnicode && !EFI_ERROR(Status)) {\r
+          TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
+          ASSERT(TempHandle != NULL);\r
+        }\r
+        if (!EFI_ERROR(Status)) {\r
+          ShellParameters->StdErr = TempHandle;\r
+        }\r
+      }\r
+\r
+      //\r
+      // StdOut to a file\r
+      //\r
+      if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
+        if (!OutAppend) {\r
+          //\r
+          // delete existing file.\r
+          //\r
+          ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
+        }\r
+        Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
+        ASSERT(TempHandle != NULL);\r
+        if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
+          //\r
+          // Write out the UnicodeFileTag\r
+          //\r
+          Size = sizeof(CHAR16);\r
+          TagBuffer[0] = UnicodeFileTag;\r
+          TagBuffer[1] = CHAR_NULL;\r
+          ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
+        } else if (OutAppend) {\r
+          //\r
+          // Move to end of file\r
+          //\r
+          Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
+          if (!EFI_ERROR(Status)) {\r
+            Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);\r
+          }\r
+        }\r
+        if (!OutUnicode && !EFI_ERROR(Status)) {\r
+          TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
+          ASSERT(TempHandle != NULL);\r
+        }\r
+        if (!EFI_ERROR(Status)) {\r
+          ShellParameters->StdOut = TempHandle;\r
+        }\r
+      }\r
+\r
+      //\r
+      // StdOut to a var\r
+      //\r
+      if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
+        if (!OutAppend) {\r
+          //\r
+          // delete existing variable.\r
+          //\r
+          SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
+        }\r
+        TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
+        ASSERT(TempHandle != NULL);\r
+        if (!OutUnicode) {\r
+          TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
+          ASSERT(TempHandle != NULL);\r
+        }\r
+        ShellParameters->StdOut = TempHandle;\r
+      }\r
+\r
+      //\r
+      // StdErr to a var\r
+      //\r
+      if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
+        if (!ErrAppend) {\r
+          //\r
+          // delete existing variable.\r
+          //\r
+          SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
+        }\r
+        TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
+        ASSERT(TempHandle != NULL);\r
+        if (!ErrUnicode) {\r
+          TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
+          ASSERT(TempHandle != NULL);\r
+        }\r
+        ShellParameters->StdErr = TempHandle;\r
+      }\r
+\r
+      //\r
+      // StdIn from a var\r
+      //\r
+      if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
+        TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
+        if (!InUnicode) {\r
+          TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
+        }\r
+        Size = 0;\r
+        ASSERT(TempHandle != NULL);\r
+        if (((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
+          Status = EFI_INVALID_PARAMETER;\r
+        } else {\r
+          ShellParameters->StdIn = TempHandle;\r
+        }\r
+      }\r
+\r
+      //\r
+      // StdIn from a file\r
+      //\r
+      if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
+        Status = ShellOpenFileByName(\r
+          StdInFileName,\r
+          &TempHandle,\r
+          EFI_FILE_MODE_READ,\r
+          0);\r
+        if (!InUnicode && !EFI_ERROR(Status)) {\r
+          TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
+        }\r
+        if (!EFI_ERROR(Status)) {\r
+          ShellParameters->StdIn = TempHandle;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  FreePool(CommandLineCopy);\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
+  structure with StdIn and StdOut.  The current values are de-allocated.\r
+\r
+  @param[in,out] ShellParameters       pointer to parameter structure to modify\r
+  @param[out] OldStdIn                 Pointer to old StdIn.\r
+  @param[out] OldStdOut                Pointer to old StdOut.\r
+  @param[out] OldStdErr                Pointer to old StdErr.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RestoreStdInStdOutStdErr (\r
+  IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
+  OUT SHELL_FILE_HANDLE                 *OldStdIn OPTIONAL,\r
+  OUT SHELL_FILE_HANDLE                 *OldStdOut OPTIONAL,\r
+  OUT SHELL_FILE_HANDLE                 *OldStdErr OPTIONAL\r
+  )\r
+{\r
+  SPLIT_LIST        *Split;\r
+  if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
+    Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
+  } else {\r
+    Split = NULL;\r
+  }\r
+  if (OldStdIn  != NULL && ShellParameters->StdIn  != *OldStdIn) {\r
+    if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
+      gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
+    }\r
+    ShellParameters->StdIn = OldStdIn==NULL?NULL:*OldStdIn;\r
+  }\r
+  if (OldStdOut != NULL && ShellParameters->StdOut != *OldStdOut) {\r
+    if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
+      gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
+    }\r
+    ShellParameters->StdOut = OldStdOut==NULL?NULL:*OldStdOut;\r
+  }\r
+  return (EFI_SUCCESS);\r
+}\r
+/**\r
+  Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
+  structure by parsing NewCommandLine.  The current values are returned to the\r
+  user.\r
+\r
+  If OldArgv or OldArgc is NULL then that value is not returned.\r
+\r
+  @param[in,out] ShellParameters        Pointer to parameter structure to modify.\r
+  @param[in] NewCommandLine             The new command line to parse and use.\r
+  @param[out] OldArgv                   Pointer to old list of parameters.\r
+  @param[out] OldArgc                   Pointer to old number of items in Argv list.\r
+\r
+  @retval   EFI_SUCCESS                 Operation was sucessful, Argv and Argc are valid.\r
+  @retval   EFI_OUT_OF_RESOURCES        A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UpdateArgcArgv(\r
+  IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
+  IN CONST CHAR16                       *NewCommandLine,\r
+  OUT CHAR16                            ***OldArgv OPTIONAL,\r
+  OUT UINTN                             *OldArgc OPTIONAL\r
+  )\r
+{\r
+  ASSERT(ShellParameters != NULL);\r
+\r
+  if (OldArgc != NULL) {\r
+    *OldArgc = ShellParameters->Argc;\r
+  }\r
+  if (OldArgc != NULL) {\r
+    *OldArgv = ShellParameters->Argv;\r
+  }\r
+\r
+  return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
+}\r
+\r
+/**\r
+  Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
+  structure with Argv and Argc.  The current values are de-allocated and the\r
+  OldArgv must not be deallocated by the caller.\r
+\r
+  @param[in,out] ShellParameters       pointer to parameter structure to modify\r
+  @param[in] OldArgv                   pointer to old list of parameters\r
+  @param[in] OldArgc                   pointer to old number of items in Argv list\r
+**/\r
+VOID\r
+EFIAPI\r
+RestoreArgcArgv(\r
+  IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
+  IN CHAR16                             ***OldArgv,\r
+  IN UINTN                              *OldArgc\r
+  )\r
+{\r
+  UINTN LoopCounter;\r
+  ASSERT(ShellParameters != NULL);\r
+  ASSERT(OldArgv         != NULL);\r
+  ASSERT(OldArgc         != NULL);\r
+\r
+  if (ShellParameters->Argv != NULL) {\r
+    for ( LoopCounter = 0\r
+        ; LoopCounter < ShellParameters->Argc\r
+        ; LoopCounter++\r
+       ){\r
+      FreePool(ShellParameters->Argv[LoopCounter]);\r
+    }\r
+    FreePool(ShellParameters->Argv);\r
+  }\r
+  ShellParameters->Argv = *OldArgv;\r
+  *OldArgv = NULL;\r
+  ShellParameters->Argc = *OldArgc;\r
+  *OldArgc = 0;\r
+}\r
diff --git a/ShellPkg/Application/Shell/ShellParametersProtocol.h b/ShellPkg/Application/Shell/ShellParametersProtocol.h
new file mode 100644 (file)
index 0000000..3a5fc30
--- /dev/null
@@ -0,0 +1,208 @@
+/** @file\r
+  Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,\r
+  manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.\r
+\r
+  Copyright (c) 2009 - 2010, 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
+  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
+\r
+**/\r
+\r
+#ifndef _SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_\r
+#define _SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/EfiShellParameters.h>\r
+#include <Protocol/LoadedImage.h>\r
+\r
+#include <Guid/ShellVariableGuid.h>\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/ShellLib.h>\r
+#include <Library/FileHandleLib.h>\r
+\r
+#include "ShellEnvVar.h"\r
+#include "FileHandleWrappers.h"\r
+#include "Shell.h"\r
+\r
+/**\r
+  creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then\r
+  installs it on our handle and if there is an existing version of the protocol\r
+  that one is cached for removal later.\r
+\r
+  @param[in,out] NewShellParameters on a successful return, a pointer to pointer\r
+                                     to the newly installed interface.\r
+  @param[in,out] RootShellInstance  on a successful return, pointer to boolean.\r
+                                     TRUE if this is the root shell instance.\r
+\r
+  @retval EFI_SUCCESS               the operation completed successfully.\r
+  @return other                     the operation failed.\r
+  @sa ReinstallProtocolInterface\r
+  @sa InstallProtocolInterface\r
+  @sa ParseCommandLineToArgs\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreatePopulateInstallShellParametersProtocol (\r
+  IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  **NewShellParameters,\r
+  IN OUT BOOLEAN                        *RootShellInstance\r
+  );\r
+\r
+/**\r
+  frees all memory used by createion and installation of shell parameters protocol\r
+  and if there was an old version installed it will restore that one.\r
+\r
+  @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
+  being cleaned up.\r
+\r
+  @retval EFI_SUCCESS     the cleanup was successful\r
+