]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/Shell.c
Update comments in DmpStore.c to be more suitable.
[mirror_edk2.git] / ShellPkg / Application / Shell / Shell.c
index 3401bc064446abb8bb2520e6061e451cabc2fc24..aa4dfd37ab6503c4c12bbaeb6e3dcd8d2917a80e 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   This is THE shell (application)\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2012, 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
@@ -52,10 +52,92 @@ SHELL_INFO ShellInfoObject = {
   NULL,\r
   {0,0,NULL,NULL},\r
   {0,0},\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  FALSE\r
 };\r
 \r
 STATIC CONST CHAR16 mScriptExtension[]      = L".NSH";\r
 STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";\r
+STATIC CONST CHAR16 mStartupScript[]        = L"startup.nsh";\r
+\r
+/**\r
+  Function to start monitoring for CTRL-S using SimpleTextInputEx.  This \r
+  feature's enabled state was not known when the shell initially launched.\r
+\r
+  @retval EFI_SUCCESS           The feature is enabled.\r
+  @retval EFI_OUT_OF_RESOURCES  There is not enough mnemory available.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalEfiShellStartCtrlSMonitor(\r
+  VOID\r
+  )\r
+{\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
+  EFI_KEY_DATA                      KeyData;\r
+  EFI_STATUS                        Status;\r
+\r
+  Status = gBS->OpenProtocol(\r
+    gST->ConsoleInHandle,\r
+    &gEfiSimpleTextInputExProtocolGuid,\r
+    (VOID**)&SimpleEx,\r
+    gImageHandle,\r
+    NULL,\r
+    EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+  if (EFI_ERROR(Status)) {\r
+    ShellPrintHiiEx(\r
+      -1, \r
+      -1, \r
+      NULL,\r
+      STRING_TOKEN (STR_SHELL_NO_IN_EX),\r
+      ShellInfoObject.HiiHandle);\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  KeyData.KeyState.KeyToggleState = 0;\r
+  KeyData.Key.ScanCode            = 0;\r
+  KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+  KeyData.Key.UnicodeChar         = L's';\r
+\r
+  Status = SimpleEx->RegisterKeyNotify(\r
+    SimpleEx,\r
+    &KeyData,\r
+    NotificationFunction,\r
+    &ShellInfoObject.CtrlSNotifyHandle1);\r
+  \r
+  KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = SimpleEx->RegisterKeyNotify(\r
+      SimpleEx,\r
+      &KeyData,\r
+      NotificationFunction,\r
+      &ShellInfoObject.CtrlSNotifyHandle2);\r
+  }\r
+  KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+  KeyData.Key.UnicodeChar         = 19;\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = SimpleEx->RegisterKeyNotify(\r
+      SimpleEx,\r
+      &KeyData,\r
+      NotificationFunction,\r
+      &ShellInfoObject.CtrlSNotifyHandle2);\r
+  }  \r
+  KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = SimpleEx->RegisterKeyNotify(\r
+      SimpleEx,\r
+      &KeyData,\r
+      NotificationFunction,\r
+      &ShellInfoObject.CtrlSNotifyHandle2);\r
+  }\r
+  return (Status);\r
+}\r
+\r
+\r
 \r
 /**\r
   The entry point for the application.\r
@@ -74,17 +156,11 @@ UefiMain (
   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
+  EFI_STATUS                      Status;\r
+  CHAR16                          *TempString;\r
+  UINTN                           Size;\r
+  EFI_HANDLE                      ConInHandle;\r
+  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *OldConIn;\r
 \r
   if (PcdGet8(PcdShellSupportLevel) > 3) {\r
     return (EFI_UNSUPPORTED);\r
@@ -94,7 +170,9 @@ UefiMain (
   // Clear the screen\r
   //\r
   Status = gST->ConOut->ClearScreen(gST->ConOut);\r
-  ASSERT_EFI_ERROR(Status);\r
+  if (EFI_ERROR(Status)) {\r
+    return (Status);\r
+  }\r
 \r
   //\r
   // Populate the global structure from PCDs\r
@@ -136,178 +214,206 @@ UefiMain (
   // 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
+  if (!EFI_ERROR(Status)) {\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
+    // 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
+    //\r
+    // install our (solitary) HII package\r
+    //\r
+    ShellInfoObject.HiiHandle = HiiAddPackages (&gEfiCallerIdGuid, gImageHandle, ShellStrings, NULL);\r
     if (ShellInfoObject.HiiHandle == NULL) {\r
-      return (EFI_NOT_STARTED);\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
-  //\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
+    // 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
-  Status = CommandInit();\r
-  ASSERT_EFI_ERROR(Status);\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
-  // Check the command line\r
-  //\r
-  Status = ProcessCommandLine();\r
+    //\r
+    // Now initialize the shell library (it requires Shell Parameters protocol)\r
+    //\r
+    Status = ShellInitialize();\r
+    ASSERT_EFI_ERROR(Status);\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
+    Status = CommandInit();\r
+    ASSERT_EFI_ERROR(Status);\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
+    // Check the command line\r
+    //\r
+    Status = ProcessCommandLine();\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
+    // If shell support level is >= 1 create the mappings and paths\r
+    //\r
+    if (PcdGet8(PcdShellSupportLevel) >= 1) {\r
+      Status = ShellCommandCreateInitialMappingsAndPaths();\r
+    }\r
 \r
-  //\r
-  // Display the mapping\r
-  //\r
-  if (PcdGet8(PcdShellSupportLevel) >= 2 && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap) {\r
-    Status = RunCommand(L"map");\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
-  //\r
-  // init all the built in alias'\r
-  //\r
-  Status = SetBuiltInAlias();\r
-  ASSERT_EFI_ERROR(Status);\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
-  // Initialize environment variables\r
-  //\r
-  if (ShellCommandGetProfileList() != NULL) {\r
-    Status = InternalEfiShellSetEnv(L"profiles", ShellCommandGetProfileList(), TRUE);\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
-  Size        = 100;\r
-  TempString  = AllocateZeroPool(Size);\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
-  UnicodeSPrint(TempString, Size, L"%d", PcdGet8(PcdShellSupportLevel));\r
-  Status = InternalEfiShellSetEnv(L"uefishellsupport", TempString, TRUE);\r
-  ASSERT_EFI_ERROR(Status);\r
+    Size        = 100;\r
+    TempString  = AllocateZeroPool(Size);\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
+    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", (gST->Hdr.Revision & 0xFFFF0000) >> 16, gST->Hdr.Revision & 0x0000FFFF);\r
-  Status = InternalEfiShellSetEnv(L"uefiversion", TempString, TRUE);\r
-  ASSERT_EFI_ERROR(Status);\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
-  FreePool(TempString);\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
-  if (!EFI_ERROR(Status)) {\r
-    if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {\r
-      //\r
-      // Set up the event for CTRL-C monitoring...\r
-      //\r
+    FreePool(TempString);\r
 \r
-      ///@todo add support for using SimpleInputEx here\r
-      //  if SimpleInputEx is not available display a warning.\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
+        Status = InernalEfiShellStartMonitor();\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
+      if (!EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
+        //\r
+        // Set up the event for CTRL-S monitoring...\r
+        //\r
+        Status = InternalEfiShellStartCtrlSMonitor();\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
+      if (!EFI_ERROR(Status) && ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
         //\r
-        // clean out all the memory allocated for CONST <something> * return values\r
-        // between each shell prompt presentation\r
+        // close off the gST->ConIn\r
         //\r
-        if (!IsListEmpty(&ShellInfoObject.BufferToFreeList.Link)){\r
-          FreeBufferList(&ShellInfoObject.BufferToFreeList);\r
-        }\r
+        OldConIn      = gST->ConIn;\r
+        ConInHandle   = gST->ConsoleInHandle;\r
+        gST->ConIn = CreateSimpleTextInOnFile((SHELL_FILE_HANDLE)&FileInterfaceNulFile, &gST->ConsoleInHandle);\r
+      } else {\r
+        OldConIn      = NULL;\r
+        ConInHandle   = NULL;\r
+      }\r
 \r
+      if (!EFI_ERROR(Status) && PcdGet8(PcdShellSupportLevel) >= 1) {\r
         //\r
-        // Reset page break back to default.\r
+        // process the startup script or launch the called app.\r
         //\r
-        ShellInfoObject.PageBreakEnabled        = PcdGetBool(PcdShellPageBreakDefault);\r
-        ShellInfoObject.ConsoleInfo->Enabled    = TRUE;\r
-        ShellInfoObject.ConsoleInfo->RowCounter = 0;\r
+        Status = DoStartupScript(ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
+      }\r
 \r
+      if (!ShellCommandGetExit() && (PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
         //\r
-        // Display Prompt\r
+        // begin the UI waiting loop\r
         //\r
-        Status = DoShellPrompt();\r
-      } while (!ShellCommandGetExit());\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
+          // Reset the CTRL-C event (yes we ignore the return values)\r
+          //\r
+          Status = gBS->CheckEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);\r
+\r
+          //\r
+          // Display Prompt\r
+          //\r
+          Status = DoShellPrompt();\r
+        } while (!ShellCommandGetExit());\r
+      }\r
+      if (OldConIn != NULL && ConInHandle != NULL) {\r
+        CloseSimpleTextInOnFile (gST->ConIn);\r
+        gST->ConIn            = OldConIn;\r
+        gST->ConsoleInHandle  = ConInHandle;\r
+      }\r
     }\r
   }\r
+\r
   //\r
   // uninstall protocols / free memory / etc...\r
   //\r
@@ -315,11 +421,6 @@ UefiMain (
     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
@@ -333,6 +434,9 @@ UefiMain (
     DEBUG_CODE(ShellInfoObject.NewShellParametersProtocol = NULL;);\r
   }\r
   if (ShellInfoObject.NewEfiShellProtocol != NULL){\r
+    if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){\r
+      ShellInfoObject.NewEfiShellProtocol->SetEnv(L"cwd", L"", TRUE);\r
+    }\r
     CleanUpShellProtocol(ShellInfoObject.NewEfiShellProtocol);\r
     DEBUG_CODE(ShellInfoObject.NewEfiShellProtocol = NULL;);\r
   }\r
@@ -342,7 +446,7 @@ UefiMain (
   }\r
 \r
   if (!IsListEmpty(&ShellInfoObject.SplitList.Link)){\r
-    ASSERT(FALSE);\r
+    ASSERT(FALSE); ///@todo finish this de-allocation.\r
   }\r
 \r
   if (ShellInfoObject.ShellInitSettings.FileName != NULL) {\r
@@ -371,6 +475,9 @@ UefiMain (
     DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;);\r
   }\r
 \r
+  if (ShellCommandGetExit()) {\r
+    return ((EFI_STATUS)ShellCommandGetExitCode());\r
+  }\r
   return (Status);\r
 }\r
 \r
@@ -456,16 +563,14 @@ IsScriptOnlyCommand(
   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
+  @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
@@ -506,6 +611,11 @@ GetDevicePathsForImageAndFile (
     if (!EFI_ERROR (Status)) {\r
       *DevPath  = DuplicateDevicePath (ImageDevicePath);\r
       *FilePath = DuplicateDevicePath (LoadedImage->FilePath);\r
+      gBS->CloseProtocol(\r
+                  LoadedImage->DeviceHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  gImageHandle,\r
+                  NULL);\r
     }\r
     gBS->CloseProtocol(\r
                 gImageHandle,\r
@@ -528,6 +638,7 @@ STATIC CONST SHELL_PARAM_ITEM mShellParamList[] = {
   {L"-delay",         TypeValue},\r
   {NULL, TypeMax}\r
   };\r
+\r
 /**\r
   Process all Uefi Shell 2.0 command line options.\r
 \r
@@ -568,6 +679,7 @@ ProcessCommandLine(
   UINTN         Count;\r
   UINTN         LoopVar;\r
   CHAR16        *ProblemParam;\r
+  UINT64        Intermediate;\r
 \r
   Package       = NULL;\r
   ProblemParam  = NULL;\r
@@ -578,7 +690,10 @@ ProcessCommandLine(
   Size = 0;\r
   TempConst = ShellCommandLineGetRawValue(Package, Count++);\r
   if (TempConst != NULL && StrLen(TempConst)) {\r
-    ShellInfoObject.ShellInitSettings.FileName = AllocatePool(StrSize(TempConst));\r
+    ShellInfoObject.ShellInitSettings.FileName = AllocateZeroPool(StrSize(TempConst));\r
+    if (ShellInfoObject.ShellInitSettings.FileName == NULL) {\r
+      return (EFI_OUT_OF_RESOURCES);\r
+    }\r
     StrCpy(ShellInfoObject.ShellInitSettings.FileName, TempConst);\r
     ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1;\r
     for (LoopVar = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {\r
@@ -593,10 +708,18 @@ ProcessCommandLine(
                       &Size,\r
                       L" ",\r
                       0);\r
+          if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {\r
+            SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);\r
+            return (EFI_OUT_OF_RESOURCES);\r
+          }\r
           StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
                       &Size,\r
                       gEfiShellParametersProtocol->Argv[LoopVar],\r
                       0);\r
+          if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {\r
+            SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);\r
+            return (EFI_OUT_OF_RESOURCES);\r
+          }\r
         }\r
       }\r
     }\r
@@ -621,17 +744,19 @@ ProcessCommandLine(
   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
+  ShellInfoObject.ShellInitSettings.Delay = 5;\r
+\r
+  if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {\r
+    ShellInfoObject.ShellInitSettings.Delay = 0;\r
+  } else 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
+    if (TempConst != NULL && *TempConst == L':') {\r
+      TempConst++;\r
+    }\r
+    if (TempConst != NULL && !EFI_ERROR(ShellConvertStringToUint64(TempConst, &Intermediate, FALSE, FALSE))) {\r
+      ShellInfoObject.ShellInitSettings.Delay = (UINTN)Intermediate;\r
     }\r
-  } else {\r
-    ShellInfoObject.ShellInitSettings.Delay = 5;\r
   }\r
-\r
   ShellCommandLineFreeVarList(Package);\r
 \r
   return (Status);\r
@@ -661,7 +786,9 @@ DoStartupScript(
   EFI_DEVICE_PATH_PROTOCOL      *NewPath;\r
   EFI_DEVICE_PATH_PROTOCOL      *NamePath;\r
   CHAR16                        *FileStringPath;\r
+  CHAR16                        *TempSpot;\r
   UINTN                         NewSize;\r
+  CONST CHAR16                  *MapName;\r
 \r
   Key.UnicodeChar = CHAR_NULL;\r
   Key.ScanCode    = 0;\r
@@ -676,9 +803,12 @@ DoStartupScript(
       NewSize += StrSize(ShellInfoObject.ShellInitSettings.FileOptions) + sizeof(CHAR16);\r
     }\r
     FileStringPath = AllocateZeroPool(NewSize);\r
+    if (FileStringPath == NULL) {\r
+      return (EFI_OUT_OF_RESOURCES);\r
+    }\r
     StrCpy(FileStringPath, ShellInfoObject.ShellInitSettings.FileName);\r
     if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {\r
-      StrCat (FileStringPath, L" ");\r
+      StrCat(FileStringPath, L" ");\r
       StrCat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions);\r
     }\r
     Status = RunCommand(FileStringPath);\r
@@ -697,18 +827,22 @@ DoStartupScript(
     return (EFI_SUCCESS);\r
   }\r
 \r
+  gST->ConOut->EnableCursor(gST->ConOut, FALSE);\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
+  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
+    if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
+      Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+    }\r
   }\r
   ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CRLF), ShellInfoObject.HiiHandle);\r
+  gST->ConOut->EnableCursor(gST->ConOut, TRUE);\r
 \r
   //\r
   // ESC was pressed\r
@@ -717,37 +851,59 @@ DoStartupScript(
     return (EFI_SUCCESS);\r
   }\r
 \r
-  NamePath = FileDevicePath (NULL, L"startup.nsh");\r
   //\r
-  // Try the first location\r
+  // Try the first location (must be file system)\r
   //\r
-  NewPath = AppendDevicePathNode (ImagePath, NamePath);\r
-  Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+  MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath(&ImagePath);\r
+  if (MapName != NULL) {\r
+    FileStringPath = NULL;\r
+    NewSize = 0;\r
+    FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, MapName, 0);\r
+    if (FileStringPath == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+    } else {\r
+      TempSpot = StrStr(FileStringPath, L";");\r
+      if (TempSpot != NULL) {\r
+        *TempSpot = CHAR_NULL;\r
+      }\r
+      FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, ((FILEPATH_DEVICE_PATH*)FilePath)->PathName, 0);\r
+      PathRemoveLastItem(FileStringPath);\r
+      FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, mStartupScript, 0);\r
+      Status = ShellInfoObject.NewEfiShellProtocol->OpenFileByName(FileStringPath, &FileHandle, EFI_FILE_MODE_READ);\r
+      FreePool(FileStringPath);\r
+    }\r
+  }\r
   if (EFI_ERROR(Status)) {\r
+    NamePath = FileDevicePath (NULL, mStartupScript);\r
+    NewPath = AppendDevicePathNode (ImagePath, NamePath);\r
+    FreePool(NamePath);\r
+\r
     //\r
-    // Try the second location\r
+    // Try the location\r
     //\r
-    FreePool(NewPath);\r
-    NewPath = AppendDevicePathNode (FilePath , NamePath);\r
     Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+    FreePool(NewPath);\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
+  if (!EFI_ERROR(Status) && FileHandle != NULL) {\r
+    Status = RunScriptFileHandle (FileHandle, mStartupScript);\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
+    FileStringPath = ShellFindFilePath(mStartupScript);\r
+    if (FileStringPath == NULL) {\r
+      //\r
+      // we return success since we dont need to have a startup script\r
+      //\r
+      Status = EFI_SUCCESS;\r
+      ASSERT(FileHandle == NULL);\r
+    } else {\r
+      Status = RunScriptFile(FileStringPath);\r
+      FreePool(FileStringPath);\r
+    }\r
   }\r
 \r
-  FreePool(NamePath);\r
-  FreePool(NewPath);\r
 \r
   return (Status);\r
 }\r
@@ -869,10 +1025,10 @@ AddLineToCommandHistory(
   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
+  @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
@@ -891,7 +1047,7 @@ ShellConvertAlias(
     return (EFI_SUCCESS);\r
   }\r
   FreePool(*CommandString);\r
-  *CommandString = AllocatePool(StrSize(NewString));\r
+  *CommandString = AllocateZeroPool(StrSize(NewString));\r
   if (*CommandString == NULL) {\r
     return (EFI_OUT_OF_RESOURCES);\r
   }\r
@@ -993,6 +1149,12 @@ ShellConvertVariables (
   NewCommandLine1 = AllocateZeroPool(NewSize);\r
   NewCommandLine2 = AllocateZeroPool(NewSize);\r
   ItemTemp        = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16)));\r
+  if (NewCommandLine1 == NULL || NewCommandLine2 == NULL || ItemTemp == NULL) {\r
+    SHELL_FREE_NON_NULL(NewCommandLine1);\r
+    SHELL_FREE_NON_NULL(NewCommandLine2);\r
+    SHELL_FREE_NON_NULL(ItemTemp);\r
+    return (NULL);\r
+  }\r
   StrCpy(NewCommandLine1, OriginalCommandLine);\r
   for (MasterEnvList = EfiShellGetEnv(NULL)\r
     ;  MasterEnvList != NULL && *MasterEnvList != CHAR_NULL //&& *(MasterEnvList+1) != CHAR_NULL\r
@@ -1059,7 +1221,16 @@ RunSplitCommand(
 \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
+\r
+  if (NextCommandLine == NULL || OurCommandLine == NULL) {\r
+    SHELL_FREE_NON_NULL(OurCommandLine);\r
+    SHELL_FREE_NON_NULL(NextCommandLine);\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  } else if (StrStr(OurCommandLine, L"|") != NULL || Size1 == 0 || Size2 == 0) {\r
+    SHELL_FREE_NON_NULL(OurCommandLine);\r
+    SHELL_FREE_NON_NULL(NextCommandLine);\r
+    return (EFI_INVALID_PARAMETER);\r
+  } else if (NextCommandLine[0] != CHAR_NULL &&\r
       NextCommandLine[0] == L'a' &&\r
       NextCommandLine[1] == L' '\r
      ){\r
@@ -1080,7 +1251,6 @@ RunSplitCommand(
   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
@@ -1150,12 +1320,13 @@ RunCommand(
   UINTN                     PostAliasSize;\r
   CHAR16                    *PostVariableCmdLine;\r
   CHAR16                    *CommandWithPath;\r
-  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+  CONST 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
+  SYSTEM_TABLE_INFO         OriginalSystemTableInfo;\r
   CHAR16                    *TempLocation3;\r
   UINTN                     Count;\r
   UINTN                     Count2;\r
@@ -1177,6 +1348,9 @@ RunCommand(
   Split               = NULL;\r
 \r
   CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0);\r
+  if (CleanOriginal == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
   while (CleanOriginal[StrLen(CleanOriginal)-1] == L' ') {\r
     CleanOriginal[StrLen(CleanOriginal)-1] = CHAR_NULL;\r
   }\r
@@ -1225,6 +1399,10 @@ RunCommand(
     PostAliasCmdLine = NULL;\r
   }\r
 \r
+  if (PostVariableCmdLine == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
   while (PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] == L' ') {\r
     PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] = CHAR_NULL;\r
   }\r
@@ -1258,6 +1436,9 @@ RunCommand(
     } else {\r
       Status = RunSplitCommand(PostVariableCmdLine, Split->SplitStdIn, Split->SplitStdOut);\r
     }\r
+    if (EFI_ERROR(Status)) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, PostVariableCmdLine);\r
+    }\r
   } else {\r
 \r
     //\r
@@ -1277,25 +1458,14 @@ RunCommand(
 \r
 \r
 \r
-    Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr);\r
+    Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);\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
+      if (Status == EFI_NOT_FOUND) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);\r
+      } else {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
       }\r
-\r
+    } else {\r
       while (PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] == L' ') {\r
         PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] = CHAR_NULL;\r
       }\r
@@ -1396,7 +1566,7 @@ RunCommand(
 \r
       RestoreArgcArgv(ShellInfoObject.NewShellParametersProtocol, &Argv, &Argc);\r
 \r
-      RestoreStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr);\r
+      RestoreStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);\r
     }\r
     if (CommandName != NULL) {\r
       if (ShellCommandGetCurrentScriptFile() != NULL &&  !IsScriptOnlyCommand(CommandName)) {\r
@@ -1412,7 +1582,6 @@ RunCommand(
   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
@@ -1473,21 +1642,29 @@ RunScriptFileHandle (
   SCRIPT_COMMAND_LIST *LastCommand;\r
   BOOLEAN             Ascii;\r
   BOOLEAN             PreScriptEchoState;\r
+  BOOLEAN             PreCommandEchoState;\r
   CONST CHAR16        *CurDir;\r
   UINTN               LineCount;\r
+  CHAR16              LeString[50];\r
 \r
   ASSERT(!ShellCommandGetScriptExit());\r
 \r
   PreScriptEchoState = ShellCommandGetEchoState();\r
 \r
   NewScriptFile = (SCRIPT_FILE*)AllocateZeroPool(sizeof(SCRIPT_FILE));\r
-  ASSERT(NewScriptFile != NULL);\r
+  if (NewScriptFile == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
 \r
   //\r
   // Set up the name\r
   //\r
   ASSERT(NewScriptFile->ScriptName == NULL);\r
   NewScriptFile->ScriptName = StrnCatGrow(&NewScriptFile->ScriptName, NULL, Name, 0);\r
+  if (NewScriptFile->ScriptName == NULL) {\r
+    DeleteScriptFileStruct(NewScriptFile);\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
 \r
   //\r
   // Save the parameters (used to replace %0 to %9 later on)\r
@@ -1495,10 +1672,17 @@ RunScriptFileHandle (
   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
+    if (NewScriptFile->Argv == NULL) {\r
+      DeleteScriptFileStruct(NewScriptFile);\r
+      return (EFI_OUT_OF_RESOURCES);\r
+    }\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
+      if (NewScriptFile->Argv[LoopVar] == NULL) {\r
+        DeleteScriptFileStruct(NewScriptFile);\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
     }\r
   } else {\r
     NewScriptFile->Argv = NULL;\r
@@ -1518,7 +1702,10 @@ RunScriptFileHandle (
       continue;\r
     }\r
     NewScriptFile->CurrentCommand = AllocateZeroPool(sizeof(SCRIPT_COMMAND_LIST));\r
-    ASSERT(NewScriptFile->CurrentCommand != NULL);\r
+    if (NewScriptFile->CurrentCommand == NULL) {\r
+      DeleteScriptFileStruct(NewScriptFile);\r
+      return (EFI_OUT_OF_RESOURCES);\r
+    }\r
 \r
     NewScriptFile->CurrentCommand->Cl   = CommandLine;\r
     NewScriptFile->CurrentCommand->Data = NULL;\r
@@ -1535,13 +1722,23 @@ RunScriptFileHandle (
   //\r
   // Now enumerate through the commands and run each one.\r
   //\r
-  CommandLine = AllocatePool(PcdGet16(PcdShellPrintBufferSize));\r
-  CommandLine2 = AllocatePool(PcdGet16(PcdShellPrintBufferSize));\r
+  CommandLine = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));\r
+  if (CommandLine == NULL) {\r
+    DeleteScriptFileStruct(NewScriptFile);\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+  CommandLine2 = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));\r
+  if (CommandLine2 == NULL) {\r
+    FreePool(CommandLine);\r
+    DeleteScriptFileStruct(NewScriptFile);\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\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
+    ASSERT(CommandLine2 != NULL);\r
     StrCpy(CommandLine2, NewScriptFile->CurrentCommand->Cl);\r
 \r
     //\r
@@ -1619,26 +1816,45 @@ RunScriptFileHandle (
 \r
       for (CommandLine3 = CommandLine2 ; CommandLine3[0] == L' ' ; CommandLine3++);\r
 \r
-      if (CommandLine3[0] == L':' ) {\r
+      if (CommandLine3 != NULL && 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
+          if (CommandLine3[0] == L'@') {\r
+            //\r
+            // We need to save the current echo state\r
+            // and disable echo for just this command.\r
+            //\r
+            PreCommandEchoState = ShellCommandGetEchoState();\r
+            ShellCommandSetEchoState(FALSE);\r
+            Status = RunCommand(CommandLine3+1);\r
+\r
+            //\r
+            // Now restore the pre-'@' echo state.\r
+            //\r
+            ShellCommandSetEchoState(PreCommandEchoState);\r
+          } else {\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
-            ShellPrintEx(-1, -1, L"%s\r\n", CommandLine2);\r
+            Status = RunCommand(CommandLine3);\r
           }\r
-          Status = RunCommand(CommandLine3);\r
         }\r
 \r
         if (ShellCommandGetScriptExit()) {\r
-          ShellCommandRegisterExit(FALSE);\r
+          UnicodeSPrint(LeString, sizeof(LeString)*sizeof(LeString[0]), L"0x%Lx", ShellCommandGetExitCode());\r
+          DEBUG_CODE(InternalEfiShellSetEnv(L"DebugLasterror", LeString, TRUE););\r
+          InternalEfiShellSetEnv(L"Lasterror", LeString, TRUE);\r
+\r
+          ShellCommandRegisterExit(FALSE, 0);\r
           Status = EFI_SUCCESS;\r
           break;\r
         }\r
@@ -1666,11 +1882,17 @@ RunScriptFileHandle (
     }\r
   }\r
 \r
-  ShellCommandSetEchoState(PreScriptEchoState);\r
 \r
   FreePool(CommandLine);\r
   FreePool(CommandLine2);\r
   ShellCommandSetNewScript (NULL);\r
+\r
+  //\r
+  // Only if this was the last script reset the state.\r
+  //\r
+  if (ShellCommandGetCurrentScriptFile()==NULL) {\r
+    ShellCommandSetEchoState(PreScriptEchoState);\r
+  }\r
   return (EFI_SUCCESS);\r
 }\r
 \r